react-rnd
react-rnd copied to clipboard
Add a default position x,y of "center"
Hey there,
I want to make a dialog that sizes to the elements within it but am having trouble doing that AND getting the dialog to be centered on the page.
It would be awesome if we could pass something like:
default={{x:"center", y:"center"}}
That way the dialog could be centered and that expands to fit the elements inside (up to its specified bounds).
Thanks @bokuweb !
@bokuweb can you please update to react-draggable 3.2.0 or higher ? That will fix this issue!
Thanks!
@bokuweb it looks like there are some failing tests with the latest react-rnd:
https://github.com/bokuweb/react-rnd/pull/510
https://circleci.com/gh/bokuweb/react-rnd/1340?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link
I'm not sure why that is. I'll ask @STRML if he knows..?
It appears there was an inadvertent breaking change in 3.2.0.
Prior to 3.2.0, if a defaultPosition were present, it became the x
and y
present in the callback on the initial drag and subsequent to that.
In 3.2.0, the x
and y
received in the callback is relative to the defaultPosition already passed. So if you pass a defaultPosition of
x: 100, y:100and initiate
onDragStart, the callback will contain
{x: 0, y: 0}in the data. This makes sense if you consider
defaultPositionto be something more like
initialOffset, and is required if your offset is something like, for example,
{x: '10%', y: '10%'}`.
I'm going to pull the release for now and work out how to fix this. I may end up renaming defaultPosition
and issue a 4.0.
I've added my comments here: https://github.com/mzabriskie/react-draggable/issues/391
@bokuweb I believe this is now possible thanks to this PR: https://github.com/mzabriskie/react-draggable/pull/393
We can now set a positionOffset using percentages
<Draggable positionOffset={{x: '-10%', y: '-10%'}} {...dragHandlers}>
<div className="box">
{'I have a default position based on percents {x: \'-10%\', y: \'-10%\'}, so I\'m slightly offset.'}
</div>
</Draggable>
Hello, Do you know where I come from
板凳宽板凳长
@tnrich Thanks :) Is it enough to update to react-draggable3.3? If you are ok could you please create PR with new storybook story??(Please add your story here https://github.com/bokuweb/react-rnd/tree/master/stories)
Hi @bokuweb So I tried updating react-rnd to version 3.3 of react-draggable but it wasn't enough to just do that. I think because react-rnd calculates a position offset from the parent, the initial % translation from the positionOffset prop gets canceled out. You'll need to take a look at the code I think and tinker with it a bit. I tried editing the react-rnd position offset code but was a little stumped as to how to get it to work perfectly.
@tnrich Thanks for your investigation :) I'll try it later. Unfortunately I can not have enough time to fix it(I have a lot of tasks 😭 ) Please wait ...
@bokuweb any chance you could find some time to tackle this one? Thank you!
Hi @bokuweb Any updates on this? Thank you!
Here's a link to the hand rolled solution I came up with (in dialog form) to get around this: https://teselagen.github.io/teselagen-react-components/#/ResizableDraggableDialog
And here's a link to the source code: https://github.com/TeselaGen/teselagen-react-components/blob/master/src/ResizableDraggableDialog/index.js
Basically I ended up controlling all the state and do manual checks of the window size and the contents of the dialog:
import React from "react";
import { Dialog, Classes } from "@blueprintjs/core";
import { Rnd } from "react-rnd";
import "./style.css";
const defaultDialogWidth = 400;
const defaultDialogHeight = 450;
export default class ResizableDraggableDialog extends React.Component {
componentDidMount() {
window.addEventListener("resize", this.onWindowResize);
this.setDefaults();
setTimeout(() => {
this.setDefaults();
}, 0);
}
state = {
x: 0,
y: 0,
width: defaultDialogWidth,
height: defaultDialogHeight
};
setDefaults = () => {
const { width, height } = this.props;
const { windowWidth, windowHeight } = this.getWindowWidthAndHeight();
let heightToUse;
if (height) {
heightToUse = height;
} else {
heightToUse = (document.querySelector(".bp3-dialog-body") || {})
.scrollHeight;
if (heightToUse) {
heightToUse = heightToUse + 60;
} else {
heightToUse = defaultDialogHeight;
}
}
let widthToUse;
if (width) {
widthToUse = width;
} else {
widthToUse = defaultDialogWidth;
}
this.setState({
x: Math.round(Math.max((windowWidth - widthToUse) / 2, 0)),
y: Math.round(Math.max((windowHeight - heightToUse) / 2, 0)),
width: Math.min(widthToUse, windowWidth),
height: Math.min(Math.max(defaultDialogHeight, heightToUse), windowHeight)
});
};
onWindowResize = () => {
this.setDefaults();
};
componentWillUnmount() {
window.removeEventListener("resize", this.onWindowResize);
}
getWindowWidthAndHeight = () => {
const w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName("body")[0],
windowWidth = w.innerWidth || e.clientWidth || g.clientWidth,
windowHeight = w.innerHeight || e.clientHeight || g.clientHeight;
return {
windowWidth,
windowHeight: windowHeight - 20 //add a small correction here
};
};
render() {
const { width, height, RndProps, ...rest } = this.props;
const { windowWidth, windowHeight } = this.getWindowWidthAndHeight();
return (
<div
className="tg-bp3-dialog-resizable-draggable"
style={{ top: 0, left: 0, position: "fixed" }}
>
<Rnd
enableResizing={{
bottomLeft: true,
bottomRight: true,
topLeft: true,
topRight: true
}}
maxHeight={windowHeight}
maxWidth={windowWidth}
bounds="window"
size={{ width: this.state.width, height: this.state.height }}
position={{ x: this.state.x, y: this.state.y }}
onDragStop={(e, d) => {
this.setState({ x: d.x, y: d.y });
}}
onResizeStop={(e, direction, ref, delta, position) => {
this.setState({
width: ref.style.width,
height: ref.style.height,
...position
});
}}
dragHandleClassName={Classes.DIALOG_HEADER}
{...RndProps}
>
<Dialog
enforceFocus={false}
hasBackdrop={false}
usePortal={false}
canEscapeKeyClose={true}
{...rest}
/>
</Rnd>
</div>
);
}
}