react-resizable-panels 1.0.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +29 -104
- package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
- package/dist/declarations/src/PanelResizeHandleRegistry.d.ts +20 -0
- package/dist/react-resizable-panels.browser.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.esm.js +367 -140
- package/dist/react-resizable-panels.browser.esm.js +367 -140
- package/dist/react-resizable-panels.cjs.js +367 -140
- package/dist/react-resizable-panels.development.cjs.js +367 -140
- package/dist/react-resizable-panels.development.esm.js +367 -140
- package/dist/react-resizable-panels.development.node.cjs.js +367 -140
- package/dist/react-resizable-panels.development.node.esm.js +367 -140
- package/dist/react-resizable-panels.esm.js +367 -140
- package/dist/react-resizable-panels.node.cjs.js +367 -140
- package/dist/react-resizable-panels.node.esm.js +367 -140
- package/package.json +1 -1
- package/src/Panel.test.tsx +52 -0
- package/src/PanelGroup.ts +23 -16
- package/src/PanelResizeHandle.ts +64 -82
- package/src/PanelResizeHandleRegistry.ts +263 -0
- package/src/utils/calculateDragOffsetPercentage.ts +1 -1
- package/src/utils/cursor.ts +63 -33
- package/src/utils/events/getResizeEventCoordinates.ts +24 -0
- package/src/utils/events/getResizeEventCursorPosition.ts +14 -0
- package/src/utils/{events.ts → events/index.ts} +1 -1
- package/src/utils/getInputType.ts +5 -0
- package/src/utils/getResizeEventCursorPosition.ts +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
- Support resizing multiple (intersecting) panels at once (#274)
|
|
6
|
+
This behavior can be customized using a new `hitAreaMargins` prop; defaults to a 15 pixel margin for _coarse_ inputs and a 5 pixel margin for _fine_ inputs.
|
|
7
|
+
|
|
8
|
+
## 1.0.10
|
|
9
|
+
|
|
10
|
+
- Fixed edge case constraints check bug that could cause a collapsed panel to re-expand unnecessarily (#273)
|
|
11
|
+
|
|
3
12
|
## 1.0.9
|
|
4
13
|
|
|
5
14
|
- DOM util methods scope param defaults to `document` (#262)
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
|
20
20
|
</PanelGroup>;
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
## If you like this project, 🎉 [become a sponsor](https://github.com/sponsors/bvaughn/) or ☕ [buy me a coffee](http://givebrian.coffee/)
|
|
24
24
|
|
|
25
25
|
## Props
|
|
26
26
|
|
|
@@ -44,11 +44,11 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
|
44
44
|
- `setItem: (name: string, value: string) => void`
|
|
45
45
|
|
|
46
46
|
`PanelGroup` components also expose an imperative API for manual resizing:
|
|
47
|
-
| method
|
|
48
|
-
|
|
|
49
|
-
| `getId(): string`
|
|
50
|
-
| `getLayout(): number[]`
|
|
51
|
-
| `setLayout(layout: number[])` | Resize panel group to the specified _layout_ (`[1 - 100, ...]`).
|
|
47
|
+
| method | description |
|
|
48
|
+
| :---------------------------- | :--------------------------------------------------------------- |
|
|
49
|
+
| `getId(): string` | Gets the panel group's ID. |
|
|
50
|
+
| `getLayout(): number[]` | Gets the panel group's current _layout_ (`[1 - 100, ...]`). |
|
|
51
|
+
| `setLayout(layout: number[])` | Resize panel group to the specified _layout_ (`[1 - 100, ...]`). |
|
|
52
52
|
|
|
53
53
|
### `Panel`
|
|
54
54
|
|
|
@@ -63,7 +63,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
|
63
63
|
| `maxSize` | `?number = 100` | Maximum allowable size of panel (numeric value between 1-100); defaults to `100` |
|
|
64
64
|
| `minSize` | `?number = 10` | Minimum allowable size of panel (numeric value between 1-100); defaults to `10` |
|
|
65
65
|
| `onCollapse` | `?() => void` | Called when panel is collapsed |
|
|
66
|
-
| `
|
|
66
|
+
| `onExpand` | `?() => void` | Called when panel is expanded |
|
|
67
67
|
| `onResize` | `?(size: number) => void` | Called when panel is resized; `size` parameter is a numeric value between 1-100. <sup>1</sup> |
|
|
68
68
|
| `order` | `?number` | Order of panel within group; required for groups with conditionally rendered panels |
|
|
69
69
|
| `style` | `?CSSProperties` | CSS style to attach to root element |
|
|
@@ -72,28 +72,29 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
|
72
72
|
<sup>1</sup>: If any `Panel` has an `onResize` callback, the `order` prop should be provided for all `Panel`s.
|
|
73
73
|
|
|
74
74
|
`Panel` components also expose an imperative API for manual resizing:
|
|
75
|
-
| method
|
|
76
|
-
|
|
|
77
|
-
| `collapse()`
|
|
78
|
-
| `expand()`
|
|
79
|
-
| `getId(): string`
|
|
80
|
-
| `getSize(): number`
|
|
81
|
-
| `isCollapsed(): boolean` | Returns `true` if the panel is currently _collapsed_ (`size === 0`).
|
|
82
|
-
| `isExpanded(): boolean`
|
|
83
|
-
| `getSize(): number`
|
|
84
|
-
| `resize(size: number)`
|
|
75
|
+
| method | description |
|
|
76
|
+
| :----------------------- | :--------------------------------------------------------------------------------- |
|
|
77
|
+
| `collapse()`v | If panel is `collapsible`, collapse it fully. |
|
|
78
|
+
| `expand()` | If panel is currently _collapsed_, expand it to its most recent size. |
|
|
79
|
+
| `getId(): string` | Gets the ID of the panel. |
|
|
80
|
+
| `getSize(): number` | Gets the current size of the panel as a percentage (`1 - 100`). |
|
|
81
|
+
| `isCollapsed(): boolean` | Returns `true` if the panel is currently _collapsed_ (`size === 0`). |
|
|
82
|
+
| `isExpanded(): boolean` | Returns `true` if the panel is currently _not collapsed_ (`!isCollapsed()`). |
|
|
83
|
+
| `getSize(): number` | Returns the most recently committed size of the panel as a percentage (`1 - 100`). |
|
|
84
|
+
| `resize(size: number)` | Resize panel to the specified _percentage_ (`1 - 100`). |
|
|
85
85
|
|
|
86
86
|
### `PanelResizeHandle`
|
|
87
87
|
|
|
88
|
-
| prop
|
|
89
|
-
|
|
|
90
|
-
| `children`
|
|
91
|
-
| `className`
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
88
|
+
| prop | type | description |
|
|
89
|
+
| :--------------- | :-------------------------------------------- | :------------------------------------------------------------------------------ |
|
|
90
|
+
| `children` | `?ReactNode` | Custom drag UI; can be any arbitrary React element(s) |
|
|
91
|
+
| `className` | `?string` | Class name to attach to root element |
|
|
92
|
+
| `hitAreaMargins` | `?{ coarse: number = 15; fine: number = 5; }` | Allow this much margin when determining resizable handle hit detection |
|
|
93
|
+
| `disabled` | `?boolean` | Disable drag handle |
|
|
94
|
+
| `id` | `?string` | Resize handle id (unique within group); falls back to `useId` when not provided |
|
|
95
|
+
| `onDragging` | `?(isDragging: boolean) => void` | Called when group layout changes |
|
|
96
|
+
| `style` | `?CSSProperties` | CSS style to attach to root element |
|
|
97
|
+
| `tagName` | `?string = "div"` | HTML element tag name for root element |
|
|
97
98
|
|
|
98
99
|
---
|
|
99
100
|
|
|
@@ -123,62 +124,6 @@ The `Panel` API doesn't _require_ `id` and `order` props because they aren't nec
|
|
|
123
124
|
</PanelGroup>
|
|
124
125
|
```
|
|
125
126
|
|
|
126
|
-
### How can I use persistent layouts with SSR?
|
|
127
|
-
|
|
128
|
-
By default, this library uses `localStorage` to persist layouts. With server rendering, this can cause a flicker when the default layout (rendered on the server) is replaced with the persisted layout (in `localStorage`). The way to avoid this flicker is to also persist the layout with a cookie like so:
|
|
129
|
-
|
|
130
|
-
##### Server component
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
import ResizablePanels from "@/app/ResizablePanels";
|
|
134
|
-
import { cookies } from "next/headers";
|
|
135
|
-
|
|
136
|
-
export function ServerComponent() {
|
|
137
|
-
const layout = cookies().get("react-resizable-panels:layout");
|
|
138
|
-
|
|
139
|
-
let defaultLayout;
|
|
140
|
-
if (layout) {
|
|
141
|
-
defaultLayout = JSON.parse(layout.value);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return <ClientComponent defaultLayout={defaultLayout} />;
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
##### Client component
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
"use client";
|
|
152
|
-
|
|
153
|
-
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
154
|
-
|
|
155
|
-
export function ClientComponent({
|
|
156
|
-
defaultLayout = [33, 67],
|
|
157
|
-
}: {
|
|
158
|
-
defaultLayout: number[] | undefined;
|
|
159
|
-
}) {
|
|
160
|
-
const onLayout = (sizes: number[]) => {
|
|
161
|
-
document.cookie = `react-resizable-panels:layout=${JSON.stringify(sizes)}`;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
return (
|
|
165
|
-
<PanelGroup direction="horizontal" onLayout={onLayout}>
|
|
166
|
-
<Panel defaultSize={defaultLayout[0]}>{/* ... */}</Panel>
|
|
167
|
-
<PanelResizeHandle className="w-2 bg-blue-800" />
|
|
168
|
-
<Panel defaultSize={defaultLayout[1]}>{/* ... */}</Panel>
|
|
169
|
-
</PanelGroup>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## FAQ
|
|
177
|
-
|
|
178
|
-
### Can panel sizes be specified in pixels?
|
|
179
|
-
|
|
180
|
-
No. Pixel-based constraints [added significant complexity](https://github.com/bvaughn/react-resizable-panels/pull/176) to the initialization and validation logic and so I've decided not to support them. You may be able to implement a version of this yourself following [a pattern like this](https://github.com/bvaughn/react-resizable-panels/issues/46#issuecomment-1368108416) but it is not officially supported by this library.
|
|
181
|
-
|
|
182
127
|
### Can a attach a ref to the DOM elements?
|
|
183
128
|
|
|
184
129
|
No. I think exposing two refs (one for the component's imperative API and one for a DOM element) would be awkward. This library does export several utility methods for accessing the underlying DOM elements though. For example:
|
|
@@ -230,31 +175,11 @@ This likely means that you haven't applied any CSS to style the resize handles.
|
|
|
230
175
|
<PanelResizeHandle className="w-2 bg-blue-800" />
|
|
231
176
|
```
|
|
232
177
|
|
|
233
|
-
### How can I fix layout/sizing problems with conditionally rendered panels?
|
|
234
|
-
|
|
235
|
-
The `Panel` API doesn't _require_ `id` and `order` props because they aren't necessary for static layouts. When panels are conditionally rendered though, it's best to supply these values.
|
|
236
|
-
|
|
237
|
-
```tsx
|
|
238
|
-
<PanelGroup direction="horizontal">
|
|
239
|
-
{renderSideBar && (
|
|
240
|
-
<>
|
|
241
|
-
<Panel id="sidebar" minSize={25} order={1}>
|
|
242
|
-
<Sidebar />
|
|
243
|
-
</Panel>
|
|
244
|
-
<PanelResizeHandle />
|
|
245
|
-
</>
|
|
246
|
-
)}
|
|
247
|
-
<Panel minSize={25} order={2}>
|
|
248
|
-
<Main />
|
|
249
|
-
</Panel>
|
|
250
|
-
</PanelGroup>
|
|
251
|
-
```
|
|
252
|
-
|
|
253
178
|
### How can I use persistent layouts with SSR?
|
|
254
179
|
|
|
255
180
|
By default, this library uses `localStorage` to persist layouts. With server rendering, this can cause a flicker when the default layout (rendered on the server) is replaced with the persisted layout (in `localStorage`). The way to avoid this flicker is to also persist the layout with a cookie like so:
|
|
256
181
|
|
|
257
|
-
|
|
182
|
+
#### Server component
|
|
258
183
|
|
|
259
184
|
```tsx
|
|
260
185
|
import ResizablePanels from "@/app/ResizablePanels";
|
|
@@ -272,7 +197,7 @@ export function ServerComponent() {
|
|
|
272
197
|
}
|
|
273
198
|
```
|
|
274
199
|
|
|
275
|
-
|
|
200
|
+
#### Client component
|
|
276
201
|
|
|
277
202
|
```tsx
|
|
278
203
|
"use client";
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { CSSProperties, HTMLAttributes, PropsWithChildren, ReactElement } from "./vendor/react.js";
|
|
2
|
+
import { PointerHitAreaMargins } from "./PanelResizeHandleRegistry.js";
|
|
2
3
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
3
4
|
export type PanelResizeHandleProps = Omit<HTMLAttributes<keyof HTMLElementTagNameMap>, "id"> & PropsWithChildren<{
|
|
4
5
|
className?: string;
|
|
5
6
|
disabled?: boolean;
|
|
7
|
+
hitAreaMargins?: PointerHitAreaMargins;
|
|
6
8
|
id?: string | null;
|
|
7
9
|
onDragging?: PanelResizeHandleOnDragging;
|
|
8
10
|
style?: CSSProperties;
|
|
9
11
|
tabIndex?: number;
|
|
10
12
|
tagName?: keyof HTMLElementTagNameMap;
|
|
11
13
|
}>;
|
|
12
|
-
export declare function PanelResizeHandle({ children, className: classNameFromProps, disabled, id: idFromProps, onDragging, style: styleFromProps, tabIndex, tagName: Type, ...rest }: PanelResizeHandleProps): ReactElement;
|
|
14
|
+
export declare function PanelResizeHandle({ children, className: classNameFromProps, disabled, hitAreaMargins, id: idFromProps, onDragging, style: styleFromProps, tabIndex, tagName: Type, ...rest }: PanelResizeHandleProps): ReactElement;
|
|
13
15
|
export declare namespace PanelResizeHandle {
|
|
14
16
|
var displayName: string;
|
|
15
17
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Direction, ResizeEvent } from "./types.js";
|
|
2
|
+
export type ResizeHandlerAction = "down" | "move" | "up";
|
|
3
|
+
export type ResizeHandlerState = "drag" | "hover" | "inactive";
|
|
4
|
+
export type SetResizeHandlerState = (action: ResizeHandlerAction, state: ResizeHandlerState, event: ResizeEvent) => void;
|
|
5
|
+
export type PointerHitAreaMargins = {
|
|
6
|
+
coarse: number;
|
|
7
|
+
fine: number;
|
|
8
|
+
};
|
|
9
|
+
export type ResizeHandlerData = {
|
|
10
|
+
direction: Direction;
|
|
11
|
+
element: HTMLElement;
|
|
12
|
+
hitAreaMargins: PointerHitAreaMargins;
|
|
13
|
+
setResizeHandlerState: SetResizeHandlerState;
|
|
14
|
+
};
|
|
15
|
+
export declare const EXCEEDED_HORIZONTAL_MIN = 1;
|
|
16
|
+
export declare const EXCEEDED_HORIZONTAL_MAX = 2;
|
|
17
|
+
export declare const EXCEEDED_VERTICAL_MIN = 4;
|
|
18
|
+
export declare const EXCEEDED_VERTICAL_MAX = 8;
|
|
19
|
+
export declare function registerResizeHandle(resizeHandleId: string, element: HTMLElement, direction: Direction, hitAreaMargins: PointerHitAreaMargins, setResizeHandlerState: SetResizeHandlerState): () => void;
|
|
20
|
+
export declare function reportConstraintsViolation(resizeHandleId: string, flag: number): void;
|