Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bounds accepts HTMLElement like react-re-resizable does #890

Merged
merged 1 commit into from
Dec 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,13 @@ The `cancel` property disables specifies a selector to be used to prevent drag i

The direction of allowed movement (dragging) allowed ('x','y','both','none').

#### `bounds?: string;`
#### `bounds?: string; | Element`

Specifies movement boundaries. Accepted values:
- `parent` restricts movement within the node's offsetParent
(nearest node with position relative or absolute)
- `window`, `body`, or
- Selector, like `.fooClassName`.
- `window`, `body`, Selector like `.fooClassName` or
- `Element`.


#### `enableUserSelectHack?: boolean;`
Expand Down
38 changes: 38 additions & 0 deletions src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,44 @@ test("should clamped by selector size", async (t) => {
t.is((rnd.childAt(0).childAt(0).getDOMNode() as HTMLElement).style.height, "800px");
});

test("should clamped by boundary element size", async (t) => {
const rnd = mount(
<div className="target" style={{ width: "800px", height: "600px" }}>
<div style={{ width: "800px", height: "600px" }}>
<Rnd
default={{ x: 0, y: 0, width: 100, height: 100 }}
resizeHandleClasses={{
top: "handler",
right: "handler",
bottom: "handler",
left: "handler",
topRight: "handler",
bottomRight: "handler",
bottomLeft: "handler",
topLeft: "handler",
}}
bounds={document.querySelector(".target")!}
enableResizing={{
top: false,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight: true,
bottomLeft: false,
topLeft: false,
}}
/>
</div>
</div>,
{ attachTo: document.querySelector("div") },
);
rnd.find("div.handler").at(0).simulate("mousedown", { clientX: 0, clientY: 0 });
mouseMove(1200, 1200);
t.is((rnd.childAt(0).getDOMNode() as HTMLElement).style.width, "800px");
t.is((rnd.childAt(0).getDOMNode() as HTMLElement).style.height, "600px");
});

test("should get rnd updated when updatePosition invoked", async (t) => {
const rnd = mount<Rnd>(<Rnd default={{ x: 100, y: 100, width: 100, height: 100 }} />);
rnd.instance().updatePosition({ x: 200, y: 300 });
Expand Down
11 changes: 7 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export interface Props {
};
size?: Size;
resizeGrid?: Grid;
bounds?: string;
bounds?: string | Element;
onMouseDown?: (e: MouseEvent) => void;
onMouseUp?: (e: MouseEvent) => void;
onResizeStart?: RndResizeStartCallback;
Expand Down Expand Up @@ -330,8 +330,10 @@ export class Rnd extends React.PureComponent<Props, State> {
const right = (window.innerWidth - this.resizable.size.width * scale) / scale + left;
const bottom = (window.innerHeight - this.resizable.size.height * scale) / scale + top;
return this.setState({ bounds: { top, right, bottom, left } });
} else {
} else if (typeof this.props.bounds === "string") {
boundary = document.querySelector(this.props.bounds);
} else if (this.props.bounds instanceof HTMLElement) {
boundary = this.props.bounds;
}
if (!(boundary instanceof HTMLElement) || !(parent instanceof HTMLElement)) {
return;
Expand Down Expand Up @@ -405,8 +407,10 @@ export class Rnd extends React.PureComponent<Props, State> {
boundary = document.body;
} else if (this.props.bounds === "window") {
boundary = window;
} else {
} else if (typeof this.props.bounds === "string") {
boundary = document.querySelector(this.props.bounds);
} else if (this.props.bounds instanceof HTMLElement) {
boundary = this.props.bounds;
}

const self = this.getSelfElement();
Expand Down Expand Up @@ -566,7 +570,6 @@ export class Rnd extends React.PureComponent<Props, State> {
left: selfRect.left - parentLeft + scrollLeft - position.x * scale,
top: selfRect.top - parentTop + scrollTop - position.y * scale,
};

}

refDraggable = (c: $TODO) => {
Expand Down
50 changes: 50 additions & 0 deletions stories/bounds/element-controlled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import { Rnd } from "../../src";
import { style, parentBoundary } from "../styles";

type State = {
x: number;
y: number;
width: number;
height: number;
};

const Example: React.FC = () => {
const [state, setState] = React.useState<State>({
width: 200,
height: 200,
x: 0,
y: 0,
});
const [boundaryElm, setBoundaryElm] = React.useState<HTMLDivElement>();
return (
<div style={parentBoundary} ref={(elm) => setBoundaryElm(elm!)}>
<Rnd
style={style}
bounds={boundaryElm}
size={{
width: state.width,
height: state.height,
}}
position={{
x: state.x,
y: state.y,
}}
onDragStop={(e: any, d: any) => {
setState({ ...state, x: d.x, y: d.y });
}}
onResize={(e, direction, ref, delta, position) => {
setState({
width: ref.offsetWidth,
height: ref.offsetHeight,
...position,
});
}}
>
001
</Rnd>
</div>
);
};

export default Example;
25 changes: 25 additions & 0 deletions stories/bounds/element-uncontrolled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { Rnd } from "../../src";
import { style, parentBoundary } from "../styles";

export default () => {
const [boundaryElm, setBoundaryElm] = React.useState<HTMLDivElement>();
return (
<div style={parentBoundary} ref={(ref) => setBoundaryElm(ref!)}>
{boundaryElm && (
<Rnd
style={style}
bounds={boundaryElm}
default={{
width: 200,
height: 200,
x: 0,
y: 0,
}}
>
001
</Rnd>
)}
</div>
);
};
6 changes: 5 additions & 1 deletion stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import BoundsSelectorUncontrolled from "./bounds/selector-uncontrolled";
import BoundsSelectorControlled from "./bounds/selector-controlled";
import BoundsWindowControlled from "./bounds/window-controlled";
import BoundsBodyControlled from "./bounds/body-controlled";
import BoundsElementControlled from "./bounds/element-controlled";
import BoundsElementUncontrolled from "./bounds/element-uncontrolled";

import SizePercentUncontrolled from "./size/size-percent-uncontrolled";
import SizePercentControlled from "./size/size-percent-controlled";
Expand Down Expand Up @@ -63,7 +65,9 @@ storiesOf("bounds", module)
.add("selector uncontrolled", () => <BoundsSelectorUncontrolled />)
.add("selector controlled", () => <BoundsSelectorControlled />)
.add("window controlled", () => <BoundsWindowControlled />)
.add("body controlled", () => <BoundsBodyControlled />);
.add("body controlled", () => <BoundsBodyControlled />)
.add("element controlled", () => <BoundsElementControlled />)
.add("element uncontrolled", () => <BoundsElementUncontrolled />)

storiesOf("scale", module)
.add("with parent boundary", () => <ScaleParentUnControlled />)
Expand Down