From e5a09eee8d7db7449ff579189aea97758f52ea51 Mon Sep 17 00:00:00 2001 From: David <75678655+David-Werth@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:48:38 +0100 Subject: [PATCH 1/2] feat: implement percentage based positioning --- README.md | 9 + src/index.js.flow | 3 + src/index.tsx | 165 +++++++++++++++--- stories/index.tsx | 7 + .../position/position-percent-controlled.tsx | 61 +++++++ .../position-percent-uncontrolled.tsx | 30 ++++ 6 files changed, 254 insertions(+), 21 deletions(-) create mode 100644 stories/position/position-percent-controlled.tsx create mode 100644 stories/position/position-percent-uncontrolled.tsx diff --git a/README.md b/README.md index 7accde5a..da7e1d3c 100755 --- a/README.md +++ b/README.md @@ -125,6 +125,15 @@ Use `size` if you need to control size state by yourself. The `position` property is used to set position of the component. Use `position` if you need to control size state by yourself. +When `positionUnit` is `'%'`, `x` and `y` are in 0–100 (percentage of parent size). + +#### `positionUnit?: 'px' | '%';` + +When `'%'`, positioning uses percentages of the parent size instead of pixels: +- `position` and `default` `x`/`y` are in 0–100. +- `onDrag`, `onDragStop`, `onResize`, and `onResizeStop` receive position as 0–100. +- `updatePosition()` expects `{ x, y }` in 0–100. +Default is `'px'`. see, following example. diff --git a/src/index.js.flow b/src/index.js.flow index 8b930c5e..e27bc85a 100755 --- a/src/index.js.flow +++ b/src/index.js.flow @@ -104,6 +104,8 @@ export type HandleComponent = { topLeft?: React.ReactElement; } +export type PositionUnit = 'px' | '%'; + export type Props = { dragGrid?: Grid, default?: { @@ -114,6 +116,7 @@ export type Props = { x: number, y: number, }, + positionUnit?: PositionUnit, size?: Size, resizeGrid?: Grid, bounds?: string, diff --git a/src/index.tsx b/src/index.tsx index 9920e199..244bf83f 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -50,6 +50,8 @@ type Size = { height: string | number; }; +export type PositionUnit = "px" | "%"; + type State = { resizing: boolean; bounds: { @@ -60,6 +62,7 @@ type State = { }; maxWidth?: number | string; maxHeight?: number | string; + parentSize: { width: number; height: number } | null; }; type MaxSize = { @@ -158,6 +161,8 @@ export interface Props { dragPositionOffset?: DraggableProps["positionOffset"]; allowAnyClick?: boolean; scale?: number; + /** When '%', position and default x/y are in 0–100; callbacks and updatePosition use the same unit. Default 'px'. */ + positionUnit?: PositionUnit; [key: string]: any; } @@ -181,6 +186,27 @@ const getEnableResizingByFlag = (flag: boolean): Enable => ({ topRight: flag, }); +function positionPercentToPx( + percent: Position, + parentSize: { width: number; height: number }, +): Position { + return { + x: (percent.x / 100) * parentSize.width, + y: (percent.y / 100) * parentSize.height, + }; +} + +function positionPxToPercent( + px: Position, + parentSize: { width: number; height: number }, +): Position { + const { width, height } = parentSize; + return { + x: width <= 0 ? 0 : (px.x / width) * 100, + y: height <= 0 ? 0 : (px.y / height) * 100, + }; +} + interface DefaultProps { maxWidth: number; maxHeight: number; @@ -224,6 +250,7 @@ export class Rnd extends React.PureComponent { }, maxWidth: props.maxWidth, maxHeight: props.maxHeight, + parentSize: null, }; this.onResizeStart = this.onResizeStart.bind(this); @@ -236,17 +263,58 @@ export class Rnd extends React.PureComponent { } componentDidMount() { + this.updateParentSize(); this.updateOffsetFromParent(); const { left, top } = this.offsetFromParent; - const { x, y } = this.getDraggablePosition(); - this.draggable.setState({ - x: x - left, - y: y - top, - }); + const positionUnit = this.props.positionUnit ?? "px"; + const defaultValue = this.props.default; + let parentSize: { width: number; height: number } | null = null; + if (this.resizable) { + try { + parentSize = this.getParentSize(); + } catch { + // refs may not be ready + } + } + + if (positionUnit === "%" && defaultValue && parentSize) { + const px = positionPercentToPx( + { x: defaultValue.x, y: defaultValue.y }, + parentSize, + ); + this.draggable.setState({ + x: px.x - left, + y: px.y - top, + }); + } else { + const { x, y } = this.getDraggablePosition(); + this.draggable.setState({ + x: x - left, + y: y - top, + }); + } // HACK: Apply position adjustment this.forceUpdate(); } + componentDidUpdate() { + this.updateParentSize(); + } + + updateParentSize() { + const parent = this.getParent(); + if (!parent || !this.resizable) return; + try { + const { width, height } = this.getParentSize(); + const prev = this.state.parentSize; + if (!prev || prev.width !== width || prev.height !== height) { + this.setState({ parentSize: { width, height } }); + } + } catch { + // getParentSize may throw before refs are ready + } + } + // HACK: To get `react-draggable` state x and y. getDraggablePosition(): { x: number; y: number } { const { x, y } = (this.draggable as any).state; @@ -356,27 +424,58 @@ export class Rnd extends React.PureComponent { }); } + getPositionForCallback(px: Position): Position { + const positionUnit = this.props.positionUnit ?? "px"; + if (positionUnit === "%") { + try { + const parentSize = this.getParentSize(); + return positionPxToPercent(px, parentSize); + } catch { + return px; + } + } + return px; + } + onDrag(e: RndDragEvent, data: DraggableData) { if (!this.props.onDrag) return; const { left, top } = this.offsetFromParent; + let pos: Position; if (!this.props.dragAxis || this.props.dragAxis === "both") { - return this.props.onDrag(e, { ...data, x: data.x + left, y: data.y + top }); + pos = { x: data.x + left, y: data.y + top }; } else if (this.props.dragAxis === "x") { - return this.props.onDrag(e, { ...data, x: data.x + left, y: this.originalPosition.y + top, deltaY: 0 }); + pos = { x: data.x + left, y: this.originalPosition.y + top }; + } else { + pos = { x: this.originalPosition.x + left, y: data.y + top }; + } + const position = this.getPositionForCallback(pos); + if (!this.props.dragAxis || this.props.dragAxis === "both") { + return this.props.onDrag(e, { ...data, ...position }); + } else if (this.props.dragAxis === "x") { + return this.props.onDrag(e, { ...data, ...position, deltaY: 0 }); } else if (this.props.dragAxis === "y") { - return this.props.onDrag(e, { ...data, x: this.originalPosition.x + left, y: data.y + top, deltaX: 0 }); + return this.props.onDrag(e, { ...data, ...position, deltaX: 0 }); } } onDragStop(e: RndDragEvent, data: DraggableData) { if (!this.props.onDragStop) return; const { left, top } = this.offsetFromParent; + let pos: Position; if (!this.props.dragAxis || this.props.dragAxis === "both") { - return this.props.onDragStop(e, { ...data, x: data.x + left, y: data.y + top }); + pos = { x: data.x + left, y: data.y + top }; } else if (this.props.dragAxis === "x") { - return this.props.onDragStop(e, { ...data, x: data.x + left, y: this.originalPosition.y + top, deltaY: 0 }); + pos = { x: data.x + left, y: this.originalPosition.y + top }; + } else { + pos = { x: this.originalPosition.x + left, y: data.y + top }; + } + const position = this.getPositionForCallback(pos); + if (!this.props.dragAxis || this.props.dragAxis === "both") { + return this.props.onDragStop(e, { ...data, ...position }); + } else if (this.props.dragAxis === "x") { + return this.props.onDragStop(e, { ...data, ...position, deltaY: 0 }); } else if (this.props.dragAxis === "y") { - return this.props.onDragStop(e, { ...data, x: this.originalPosition.x + left, y: data.y + top, deltaX: 0 }); + return this.props.onDragStop(e, { ...data, ...position, deltaX: 0 }); } } @@ -518,10 +617,8 @@ export class Rnd extends React.PureComponent { this.resizingPosition = { x, y }; if (!this.props.onResize) return; - this.props.onResize(e, direction, elementRef, delta, { - x, - y, - }); + const position = this.getPositionForCallback({ x, y }); + this.props.onResize(e, direction, elementRef, delta, position); } onResizeStop( @@ -536,7 +633,8 @@ export class Rnd extends React.PureComponent { const { maxWidth, maxHeight } = this.getMaxSizesFromProps(); this.setState({ maxWidth, maxHeight }); if (this.props.onResizeStop) { - this.props.onResizeStop(e, direction, elementRef, delta, this.resizingPosition); + const position = this.getPositionForCallback(this.resizingPosition); + this.props.onResizeStop(e, direction, elementRef, delta, position); } } @@ -546,7 +644,19 @@ export class Rnd extends React.PureComponent { } updatePosition(position: Position) { - this.draggable.setState(position); + const positionUnit = this.props.positionUnit ?? "px"; + if (positionUnit === "%") { + try { + const parentSize = this.getParentSize(); + const px = positionPercentToPx(position, parentSize); + const { left, top } = this.offsetFromParent; + this.draggable.setState({ x: px.x - left, y: px.y - top }); + } catch { + this.draggable.setState(position); + } + } else { + this.draggable.setState(position); + } } updateOffsetFromParent() { @@ -602,6 +712,7 @@ export class Rnd extends React.PureComponent { scale, allowAnyClick, dragPositionOffset, + positionUnit = "px", ...resizableProps } = this.props; const defaultValue = this.props.default ? { ...this.props.default } : undefined; @@ -615,13 +726,25 @@ export class Rnd extends React.PureComponent { ...style, }; const { left, top } = this.offsetFromParent; - let draggablePosition; + let draggablePosition: { x: number; y: number } | undefined; if (position) { + let positionPx: Position; + if (positionUnit === "%" && this.state.parentSize) { + positionPx = positionPercentToPx(position, this.state.parentSize); + } else { + positionPx = position; + } draggablePosition = { - x: position.x - left, - y: position.y - top, + x: positionPx.x - left, + y: positionPx.y - top, }; } + + // In % mode, default x/y are applied in componentDidMount; pass 0,0 so Draggable gets numeric values + const defaultPositionForDraggable = + defaultValue && positionUnit === "%" && typeof defaultValue.x === "number" && typeof defaultValue.y === "number" + ? { ...defaultValue, x: 0, y: 0 } + : defaultValue; // INFO: Make uncontorolled component when resizing to control position by setPostion. const pos = this.state.resizing ? undefined : draggablePosition; const dragAxisOrUndefined = this.state.resizing ? "both" : dragAxis; @@ -633,7 +756,7 @@ export class Rnd extends React.PureComponent { this.draggable = c; }} handle={dragHandleClassName ? `.${dragHandleClassName}` : undefined} - defaultPosition={defaultValue} + defaultPosition={defaultPositionForDraggable} onMouseDown={onMouseDown} // @ts-expect-error onMouseUp={onMouseUp} diff --git a/stories/index.tsx b/stories/index.tsx index e54836ce..f02d7c4e 100644 --- a/stories/index.tsx +++ b/stories/index.tsx @@ -31,6 +31,9 @@ import BoundsElementUncontrolled from "./bounds/element-uncontrolled"; import SizePercentUncontrolled from "./size/size-percent-uncontrolled"; import SizePercentControlled from "./size/size-percent-controlled"; +import PositionPercentUncontrolled from "./position/position-percent-uncontrolled"; +import PositionPercentControlled from "./position/position-percent-controlled"; + import Callbacks from "./callback/callbacks"; import Cancel from "./cancel/cancel"; @@ -82,6 +85,10 @@ storiesOf("size", module) .add("percent uncontrolled", () => ) .add("percent controlled", () => ); +storiesOf("position", module) + .add("percent uncontrolled", () => ) + .add("percent controlled", () => ); + storiesOf("callbacks", module).add("callback", () => ); storiesOf("cancel", module).add("cancel", () => ); diff --git a/stories/position/position-percent-controlled.tsx b/stories/position/position-percent-controlled.tsx new file mode 100644 index 00000000..8a3ea359 --- /dev/null +++ b/stories/position/position-percent-controlled.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import { Rnd } from "../../src"; +import { style } from "../styles"; + +type State = { + x: number; + y: number; + width: number; + height: number; +}; + +const containerStyle: React.CSSProperties = { + width: 400, + height: 300, + position: "relative", + background: "#e8e8e8", + border: "1px solid #ccc", +}; + +export default class Example extends React.Component<{}, State> { + constructor(props: {}) { + super(props); + this.state = { + width: 120, + height: 80, + x: 10, + y: 20, + }; + } + + render() { + return ( +
+ { + this.setState({ x: d.x, y: d.y }); + }} + onResizeStop={(e, direction, ref, delta, position) => { + this.setState({ + width: ref.offsetWidth, + height: ref.offsetHeight, + ...position, + }); + }} + > + Position in % (x: {this.state.x.toFixed(1)}, y: {this.state.y.toFixed(1)}) + +
+ ); + } +} diff --git a/stories/position/position-percent-uncontrolled.tsx b/stories/position/position-percent-uncontrolled.tsx new file mode 100644 index 00000000..db3f9a3d --- /dev/null +++ b/stories/position/position-percent-uncontrolled.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { Rnd } from "../../src"; +import { style } from "../styles"; + +const containerStyle: React.CSSProperties = { + width: 400, + height: 300, + position: "relative", + background: "#e8e8e8", + border: "1px solid #ccc", +}; + +export default function Example() { + return ( +
+ + Default at 25%, 30% (uncontrolled) + +
+ ); +} From 4419ea818bc6e813019fbde53109c67cc23de159 Mon Sep 17 00:00:00 2001 From: dwrth Date: Wed, 11 Mar 2026 13:13:21 +0100 Subject: [PATCH 2/2] Align percentual positioning with percentual sizing, remove positionUnit approach --- README.md | 21 ++- src/index.tsx | 135 ++++++++---------- .../position/position-percent-controlled.tsx | 22 ++- .../position-percent-uncontrolled.tsx | 5 +- 4 files changed, 82 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 8db1cf8d..67348475 100755 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ yarn add react-rnd ## Props -#### `default: { x: number; y: number; width?: number | string; height?: number | string; };` +#### `default: { x: number | string; y: number | string; width?: number | string; height?: number | string; };` The `width` and `height` property is used to set the default size of the component. For example, you can set `300`, `'300px'`, `50%`. @@ -121,19 +121,14 @@ For example, you can set 300, '300px', 50%. Use `size` if you need to control size state by yourself. -#### `position?: { x: number, y: number };` +#### `position?: { x: (number | string), y: (number | string) };` The `position` property is used to set position of the component. -Use `position` if you need to control size state by yourself. -When `positionUnit` is `'%'`, `x` and `y` are in 0–100 (percentage of parent size). - -#### `positionUnit?: 'px' | '%';` - -When `'%'`, positioning uses percentages of the parent size instead of pixels: -- `position` and `default` `x`/`y` are in 0–100. -- `onDrag`, `onDragStop`, `onResize`, and `onResizeStop` receive position as 0–100. -- `updatePosition()` expects `{ x, y }` in 0–100. -Default is `'px'`. +Use `position` if you need to control position state by yourself. +You can pass: +- numbers (treated as pixels), e.g. `x: 100` +- strings with `'px'`, e.g. `'300px'` +- strings with `'%'`, e.g. `'50%'` (percentage of the parent size) see, following example. @@ -473,7 +468,7 @@ class YourComponent extends Component { } ``` -#### `updatePosition({ x: number, y: number }): void` +#### `updatePosition({ x: number | string, y: number | string }): void` Update component position. `grid` `bounds` props is ignored, when this method called. diff --git a/src/index.tsx b/src/index.tsx index 244bf83f..e6bce079 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -50,8 +50,6 @@ type Size = { height: string | number; }; -export type PositionUnit = "px" | "%"; - type State = { resizing: boolean; bounds: { @@ -119,12 +117,12 @@ export type HandleComponent = { export interface Props { dragGrid?: Grid; default?: { - x: number; - y: number; + x: number | string; + y: number | string; } & Size; position?: { - x: number; - y: number; + x: number | string; + y: number | string; }; size?: Size; resizeGrid?: Grid; @@ -161,8 +159,6 @@ export interface Props { dragPositionOffset?: DraggableProps["positionOffset"]; allowAnyClick?: boolean; scale?: number; - /** When '%', position and default x/y are in 0–100; callbacks and updatePosition use the same unit. Default 'px'. */ - positionUnit?: PositionUnit; [key: string]: any; } @@ -186,25 +182,28 @@ const getEnableResizingByFlag = (flag: boolean): Enable => ({ topRight: flag, }); -function positionPercentToPx( - percent: Position, - parentSize: { width: number; height: number }, -): Position { - return { - x: (percent.x / 100) * parentSize.width, - y: (percent.y / 100) * parentSize.height, - }; -} - -function positionPxToPercent( - px: Position, - parentSize: { width: number; height: number }, -): Position { - const { width, height } = parentSize; - return { - x: width <= 0 ? 0 : (px.x / width) * 100, - y: height <= 0 ? 0 : (px.y / height) * 100, - }; +function parsePositionValue( + value: number | string, + axisSize: number | null, +): number { + if (typeof value === "number") { + return value; + } + const str = value.toString().trim(); + if (str.endsWith("%")) { + const n = Number(str.slice(0, -1)); + if (Number.isNaN(n) || axisSize == null) return 0; + return (n / 100) * axisSize; + } + if (str.endsWith("px")) { + const n = Number(str.slice(0, -2)); + return Number.isNaN(n) ? 0 : n; + } + const n = Number(str); + if (!Number.isNaN(n)) { + return n; + } + return 0; } interface DefaultProps { @@ -266,7 +265,6 @@ export class Rnd extends React.PureComponent { this.updateParentSize(); this.updateOffsetFromParent(); const { left, top } = this.offsetFromParent; - const positionUnit = this.props.positionUnit ?? "px"; const defaultValue = this.props.default; let parentSize: { width: number; height: number } | null = null; if (this.resizable) { @@ -277,14 +275,12 @@ export class Rnd extends React.PureComponent { } } - if (positionUnit === "%" && defaultValue && parentSize) { - const px = positionPercentToPx( - { x: defaultValue.x, y: defaultValue.y }, - parentSize, - ); + if (defaultValue && parentSize) { + const x = parsePositionValue(defaultValue.x, parentSize.width); + const y = parsePositionValue(defaultValue.y, parentSize.height); this.draggable.setState({ - x: px.x - left, - y: px.y - top, + x: x - left, + y: y - top, }); } else { const { x, y } = this.getDraggablePosition(); @@ -424,19 +420,6 @@ export class Rnd extends React.PureComponent { }); } - getPositionForCallback(px: Position): Position { - const positionUnit = this.props.positionUnit ?? "px"; - if (positionUnit === "%") { - try { - const parentSize = this.getParentSize(); - return positionPxToPercent(px, parentSize); - } catch { - return px; - } - } - return px; - } - onDrag(e: RndDragEvent, data: DraggableData) { if (!this.props.onDrag) return; const { left, top } = this.offsetFromParent; @@ -448,7 +431,7 @@ export class Rnd extends React.PureComponent { } else { pos = { x: this.originalPosition.x + left, y: data.y + top }; } - const position = this.getPositionForCallback(pos); + const position = pos; if (!this.props.dragAxis || this.props.dragAxis === "both") { return this.props.onDrag(e, { ...data, ...position }); } else if (this.props.dragAxis === "x") { @@ -469,7 +452,7 @@ export class Rnd extends React.PureComponent { } else { pos = { x: this.originalPosition.x + left, y: data.y + top }; } - const position = this.getPositionForCallback(pos); + const position = pos; if (!this.props.dragAxis || this.props.dragAxis === "both") { return this.props.onDragStop(e, { ...data, ...position }); } else if (this.props.dragAxis === "x") { @@ -617,7 +600,7 @@ export class Rnd extends React.PureComponent { this.resizingPosition = { x, y }; if (!this.props.onResize) return; - const position = this.getPositionForCallback({ x, y }); + const position = { x, y }; this.props.onResize(e, direction, elementRef, delta, position); } @@ -633,7 +616,7 @@ export class Rnd extends React.PureComponent { const { maxWidth, maxHeight } = this.getMaxSizesFromProps(); this.setState({ maxWidth, maxHeight }); if (this.props.onResizeStop) { - const position = this.getPositionForCallback(this.resizingPosition); + const position = this.resizingPosition; this.props.onResizeStop(e, direction, elementRef, delta, position); } } @@ -643,20 +626,19 @@ export class Rnd extends React.PureComponent { this.resizable.updateSize({ width: size.width, height: size.height }); } - updatePosition(position: Position) { - const positionUnit = this.props.positionUnit ?? "px"; - if (positionUnit === "%") { - try { - const parentSize = this.getParentSize(); - const px = positionPercentToPx(position, parentSize); - const { left, top } = this.offsetFromParent; - this.draggable.setState({ x: px.x - left, y: px.y - top }); - } catch { - this.draggable.setState(position); - } - } else { - this.draggable.setState(position); + updatePosition(position: { x: number | string; y: number | string }) { + let parentSize: { width: number; height: number } | null = null; + try { + parentSize = this.getParentSize(); + } catch { + parentSize = null; } + const axisWidth = parentSize ? parentSize.width : null; + const axisHeight = parentSize ? parentSize.height : null; + const { left, top } = this.offsetFromParent; + const x = parsePositionValue(position.x, axisWidth); + const y = parsePositionValue(position.y, axisHeight); + this.draggable.setState({ x: x - left, y: y - top }); } updateOffsetFromParent() { @@ -712,7 +694,6 @@ export class Rnd extends React.PureComponent { scale, allowAnyClick, dragPositionOffset, - positionUnit = "px", ...resizableProps } = this.props; const defaultValue = this.props.default ? { ...this.props.default } : undefined; @@ -728,23 +709,21 @@ export class Rnd extends React.PureComponent { const { left, top } = this.offsetFromParent; let draggablePosition: { x: number; y: number } | undefined; if (position) { - let positionPx: Position; - if (positionUnit === "%" && this.state.parentSize) { - positionPx = positionPercentToPx(position, this.state.parentSize); - } else { - positionPx = position; - } + const parentSize = this.state.parentSize; + const width = parentSize ? parentSize.width : null; + const height = parentSize ? parentSize.height : null; + const xPx = parsePositionValue(position.x, width); + const yPx = parsePositionValue(position.y, height); draggablePosition = { - x: positionPx.x - left, - y: positionPx.y - top, + x: xPx - left, + y: yPx - top, }; } - // In % mode, default x/y are applied in componentDidMount; pass 0,0 so Draggable gets numeric values const defaultPositionForDraggable = - defaultValue && positionUnit === "%" && typeof defaultValue.x === "number" && typeof defaultValue.y === "number" - ? { ...defaultValue, x: 0, y: 0 } - : defaultValue; + defaultValue && typeof defaultValue.x === "number" && typeof defaultValue.y === "number" + ? { x: defaultValue.x, y: defaultValue.y } + : undefined; // INFO: Make uncontorolled component when resizing to control position by setPostion. const pos = this.state.resizing ? undefined : draggablePosition; const dragAxisOrUndefined = this.state.resizing ? "both" : dragAxis; diff --git a/stories/position/position-percent-controlled.tsx b/stories/position/position-percent-controlled.tsx index 8a3ea359..b145e63d 100644 --- a/stories/position/position-percent-controlled.tsx +++ b/stories/position/position-percent-controlled.tsx @@ -3,8 +3,8 @@ import { Rnd } from "../../src"; import { style } from "../styles"; type State = { - x: number; - y: number; + x: number; // percentage of container width + y: number; // percentage of container height width: number; height: number; }; @@ -33,23 +33,31 @@ export default class Example extends React.Component<{}, State> {
{ - this.setState({ x: d.x, y: d.y }); + const containerWidth = containerStyle.width as number; + const containerHeight = containerStyle.height as number; + const x = (d.x / containerWidth) * 100; + const y = (d.y / containerHeight) * 100; + this.setState({ x, y }); }} onResizeStop={(e, direction, ref, delta, position) => { + const containerWidth = containerStyle.width as number; + const containerHeight = containerStyle.height as number; + const x = (position.x / containerWidth) * 100; + const y = (position.y / containerHeight) * 100; this.setState({ width: ref.offsetWidth, height: ref.offsetHeight, - ...position, + x, + y, }); }} > diff --git a/stories/position/position-percent-uncontrolled.tsx b/stories/position/position-percent-uncontrolled.tsx index db3f9a3d..2aaba998 100644 --- a/stories/position/position-percent-uncontrolled.tsx +++ b/stories/position/position-percent-uncontrolled.tsx @@ -15,10 +15,9 @@ export default function Example() {