Skip to content
Closed
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
156 changes: 132 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [Install](#install)
* [Usage](#usage)
* [Props](#props)
* [Grid system](#grid-system)
* [Instance API](#instance-api)
* [updateSize(size: { width: number | string, height: number | string }): void](#updateSize-void)
* [updatePosition({ x: number, y: number }): void](#updatePosition-void)
Expand Down Expand Up @@ -106,25 +107,39 @@ yarn add react-rnd

## Props

#### `default: { x: number; y: number; width?: number | string; height?: number | string; };`
#### `default: { x: number; y: number; width?: number | string; height?: number | string; } | RndDefaultGrid;`

The `width` and `height` property is used to set the default size of the component.
For example, you can set `300`, `'300px'`, `50%`.
If omitted, set `'auto'`.

The `x` and `y` property is used to set the default position of the component.

#### `size?: { width: (number | string), height: (number | string) };`
When using grid units (`positionUnit="grid"` / `sizeUnit="grid"`), use `RndDefaultGrid`: `{ columnStart, rowStart, columnSpan, rowSpan }`. Requires `gridConfig`.

#### `size?: { width: (number | string), height: (number | string) } | GridSize;`

The `size` property is used to set size of the component.
For example, you can set 300, '300px', 50%.
When `sizeUnit` is `'grid'`, use `GridSize`: `{ columnSpan: number, rowSpan: number }`.

Use `size` if you need to control size state by yourself.
Use `size` if you need to control size state yourself.

#### `position?: { x: number, y: number };`
#### `position?: { x: number, y: number } | GridPosition;`

The `position` property is used to set position of the component.
Use `position` if you need to control size state by yourself.
Use `position` if you need to control position state yourself.
When `positionUnit` is `'%'`, `x` and `y` are in 0–100 (percentage of parent size).
When `positionUnit` is `'grid'`, use `GridPosition`: `{ columnStart: number, rowStart: number }`.

#### `positionUnit?: 'px' | '%' | 'grid';`

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.

When `'grid'`, position and size use **grid units** (see [Grid system](#grid-system)). You must set `gridConfig`. Position is `{ columnStart, rowStart }`; callbacks receive `gridPlacement` and optionally grid position. Default is `'px'`.

see, following example.

Expand Down Expand Up @@ -173,13 +188,25 @@ For example, you can set `300`, `'300px'`, `50%`.
The `maxHeight` property is used to set the maximum height of the component.
For example, you can set `300`, `'300px'`, `50%`.

#### `gridConfig?: { columns: number; rowHeight: number };`

Required when using `positionUnit="grid"` or `sizeUnit="grid"`. Defines the grid: `columns` is the number of columns; `rowHeight` is the height of each row in pixels. Column width is derived from the parent width (`parentWidth / columns`). Drag and resize automatically snap to grid lines when in grid mode.

#### `sizeUnit?: 'px' | '%' | 'grid';`

When `'grid'`, `size` is in grid spans: `{ columnSpan, rowSpan }`. Requires `gridConfig`. Default is `'px'`. See [Grid system](#grid-system).

#### `layoutMode?: 'absolute' | 'grid';`

When `'grid'`, the Rnd wrapper uses CSS `grid-column` and `grid-row` instead of `position`/`left`/`top`, so the component participates in a CSS Grid parent. The parent must use `display: grid` with matching column/row setup. Default is `'absolute'`.

#### `resizeGrid?: [number, number];`

The `resizeGrid` property is used to specify the increments that resizing should snap to. Defaults to `[1, 1]`.
The `resizeGrid` property is used to specify the increments that resizing should snap to. Defaults to `[1, 1]`. When `sizeUnit="grid"` (or `positionUnit="grid"`), this is set automatically from `gridConfig`.

#### `dragGrid?: [number, number];`

The `dragGrid` property is used to specify the increments that moving should snap to. Defaults to `[1, 1]`.
The `dragGrid` property is used to specify the increments that moving should snap to. Defaults to `[1, 1]`. When `positionUnit="grid"`, this is set automatically from `gridConfig`.

#### `lockAspectRatio?: boolean | number;`

Expand Down Expand Up @@ -320,16 +347,95 @@ Specifies movement boundaries. Accepted values:

#### `enableUserSelectHack?: boolean;`

By default, we add 'user-select:none' attributes to the document body
to prevent ugly text selection during drag. If this is causing problems
for your app, set this to `false`.
By default, we add 'user-select:none' attributes to the document body to prevent ugly text selection during drag. If this is causing problems for your app, set this to `false`.

#### `scale?: number;`

Specifies the scale of the canvas your are resizing and dragging this element on. This allows
you to, for example, get the correct resize and drag deltas while you are zoomed in or out via
a transform or matrix in the parent of this element.
If omitted, set `1`.
Specifies the scale of the canvas you are resizing and dragging this element on. This allows you to, for example, get the correct resize and drag deltas while you are zoomed in or out via a transform or matrix in the parent of this element. If omitted, set `1`.

## Grid system

Rnd can use **grid units** for position and size so you can persist and control layout by column/row indices (e.g. for page builders or Fluid-style editors). No manual conversion between pixels and grid is needed.

### Setup

1. Set **`gridConfig`**: `{ columns: number, rowHeight: number }`. For example, 24 columns and 8px row height.
2. Set **`positionUnit="grid"`** and/or **`sizeUnit="grid"`**.
3. Use **`position`** as `{ columnStart, rowStart }` and **`size`** as `{ columnSpan, rowSpan }` (0-based indices).

Column width is computed from the parent width (`parentWidth / columns`). Row height is fixed (e.g. `grid-auto-rows: 8px` on the container). Drag and resize snap to grid lines automatically.

### Types

```javascript
// Grid configuration (required when using grid units)
type GridConfig = { columns: number; rowHeight: number };

// Position in grid: start cell
type GridPosition = { columnStart: number; rowStart: number };

// Size in grid: number of cells
type GridSize = { columnSpan: number; rowSpan: number };

// Full placement (0-based line indices; columnEnd/rowEnd are exclusive)
type GridPlacement = {
columnStart: number;
rowStart: number;
columnEnd: number;
rowEnd: number;
};
```

### Example: controlled grid

```javascript
<Rnd
gridConfig={{ columns: 24, rowHeight: 8 }}
positionUnit="grid"
sizeUnit="grid"
position={{ columnStart: 2, rowStart: 3 }}
size={{ columnSpan: 6, rowSpan: 4 }}
onDragStop={(e, d) => {
if (d.gridPlacement) {
setPosition({ columnStart: d.columnStart, rowStart: d.rowStart });
}
}}
onResizeStop={(e, dir, ref, delta, position, gridPlacement) => {
if (gridPlacement) {
setPosition({ columnStart: gridPlacement.columnStart, rowStart: gridPlacement.rowStart });
setSize({
columnSpan: gridPlacement.columnEnd - gridPlacement.columnStart,
rowSpan: gridPlacement.rowEnd - gridPlacement.rowStart,
});
}
}}
/>
```

### Callbacks in grid mode

- **`onDragStop`**: The second argument includes **`gridPlacement`** when `positionUnit="grid"`: `{ columnStart, rowStart, columnEnd, rowEnd }`. Position is also provided as `{ columnStart, rowStart }`.
- **`onResizeStop`**: The sixth argument is **`gridPlacement`** when using grid units, so you can persist the new grid placement directly.

### Acting as a grid child

Set **`layoutMode="grid"`** so the Rnd wrapper uses `grid-column` and `grid-row` instead of `position`/`left`/`top`. The parent must be `display: grid` with the same grid (e.g. same column count and row height). Useful when the DOM should be pure CSS Grid for layout.

### Instance API in grid mode

- **`updatePosition(position)`** accepts **`GridPosition`** when `positionUnit="grid"`: `{ columnStart, rowStart }`.
- **`updateSize(size)`** accepts **`GridSize`** when `sizeUnit="grid"`: `{ columnSpan, rowSpan }`.

### Exported helpers

You can use these for custom logic or persistence:

- `getGridCellDimensions(parentSize, gridConfig)` → `{ columnWidth, rowHeight }`
- `gridPositionToPx(gridPosition, cellDimensions)`
- `gridSizeToPx(gridSize, cellDimensions)`
- `pxToGridPosition(pxPosition, cellDimensions)`
- `pxToGridSize(pxSize, cellDimensions)`
- `pxToGridPlacement(position, size, cellDimensions)` → `GridPlacement`

## Callback

Expand Down Expand Up @@ -365,15 +471,16 @@ Calls when resizable component resizing.

#### `onResizeStop?: RndResizeCallback;`

`RndResizeCallback` type is below.
`RndResizeCallback` type is below. When using [grid units](#grid-system), a sixth argument `gridPlacement?: GridPlacement` is passed.

``` javascript
export type RndResizeCallback = (
e: MouseEvent | TouchEvent,
dir: ResizeDirection,
refToElement: React.ElementRef<'div'>,
delta: ResizableDelta,
position: Position,
position: Position | GridPosition,
gridPlacement?: GridPlacement,
) => void;
```

Expand Down Expand Up @@ -417,8 +524,7 @@ type DraggableEventHandler = (

#### `onDragStop: DraggableEventHandler;`

`onDragStop` called on dragging stop.

`onDragStop` called on dragging stop. When `positionUnit="grid"`, the data object includes **`gridPlacement`**: `{ columnStart, rowStart, columnEnd, rowEnd }` (see [Grid system](#grid-system)).

``` javascript
type DraggableData = {
Expand All @@ -437,10 +543,9 @@ type DraggableEventHandler = (
## Instance API


#### `updateSize(size: { width: string | number, height: string | number })`
#### `updateSize(size: { width: string | number, height: string | number } | GridSize)`

Update component size.
For example, you can set `300`, `'300px'`, `50%`.
Update component size. For example, you can set `300`, `'300px'`, `50%`. When `sizeUnit="grid"`, pass **`GridSize`**: `{ columnSpan, rowSpan }`.

- for example

Expand All @@ -464,10 +569,9 @@ class YourComponent extends Component {
}
```

#### `updatePosition({ x: number, y: number }): void`
#### `updatePosition({ x: number, y: number } | GridPosition): void`

Update component position.
`grid` `bounds` props is ignored, when this method called.
Update component position. When `positionUnit="grid"`, pass **`GridPosition`**: `{ columnStart, rowStart }`. When using px or %, pass `{ x, y }`. `grid` and `bounds` props are ignored when this method is called.

- for example

Expand Down Expand Up @@ -510,6 +614,10 @@ If you have a bug to report, please reproduce the bug in [CodeSandbox](https://c

## Changelog

#### v10.5.3

- Add grid system: `positionUnit="grid"`, `sizeUnit="grid"`, `gridConfig`, and `layoutMode="grid"`. Callbacks report `gridPlacement`; `updatePosition`/`updateSize` accept grid types.
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog entry in the README describes the feature as "Add grid system" but doesn't mention the percentage positioning feature at all. Since issue #651 specifically requested percentage positioning and that's mentioned in the PR title, the changelog should explicitly mention both features: percentage positioning (positionUnit="%") and the grid system (positionUnit="grid", etc.).

Suggested change
- Add grid system: `positionUnit="grid"`, `sizeUnit="grid"`, `gridConfig`, and `layoutMode="grid"`. Callbacks report `gridPlacement`; `updatePosition`/`updateSize` accept grid types.
- Add percentage positioning and grid system: `positionUnit="%"` and `positionUnit="grid"`, `sizeUnit="grid"`, `gridConfig`, and `layoutMode="grid"`. Callbacks report `gridPlacement`; `updatePosition`/`updateSize` accept grid types.

Copilot uses AI. Check for mistakes.

#### v10.5.1

- Upgrade `re-resizable` to `6.11.0`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-rnd",
"version": "10.5.2",
"version": "10.5.3",
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version bump from 10.5.2 to 10.5.3 is only a patch version increment, but this PR adds significant new features (percentage positioning with positionUnit="%" and an entire grid system with positionUnit="grid", sizeUnit="grid", gridConfig, and layoutMode). According to semantic versioning, new features should result in a minor version bump (10.6.0), while patch versions are typically reserved for bug fixes. Consider updating the version to 10.6.0.

Suggested change
"version": "10.5.3",
"version": "10.6.0",

Copilot uses AI. Check for mistakes.
"description": "A draggable and resizable React Component",
"title": "react-rnd",
"main": "./lib/index.es5.js",
Expand Down
3 changes: 3 additions & 0 deletions src/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export type HandleComponent = {
topLeft?: React.ReactElement<any>;
}

export type PositionUnit = 'px' | '%';
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Flow type definition for PositionUnit is incomplete. It only includes 'px' | '%' but the TypeScript implementation also supports 'grid'. This inconsistency will cause issues for Flow users who want to use the grid feature.

Suggested change
export type PositionUnit = 'px' | '%';
export type PositionUnit = 'px' | '%' | 'grid';

Copilot uses AI. Check for mistakes.

export type Props = {
dragGrid?: Grid,
default?: {
Expand All @@ -114,6 +116,7 @@ export type Props = {
x: number,
y: number,
},
positionUnit?: PositionUnit,
size?: Size,
Comment on lines 109 to 120
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Flow type definitions are missing several critical types and signatures required for the grid feature. The Props type is missing sizeUnit, gridConfig, and layoutMode properties. Additionally, position and size don't support the grid types (GridPosition and GridSize). The default property also doesn't support RndDefaultGrid. These omissions will prevent Flow users from using the grid system.

Copilot uses AI. Check for mistakes.
resizeGrid?: Grid,
bounds?: string,
Expand Down
Loading