react-resizable-panels 1.0.10 → 2.0.1

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.1
4
+
5
+ - Fixed a regression introduced in 2.0.0 that caused React `onClick` and `onMouseUp` handlers not to fire.
6
+
7
+ ## 2.0.0
8
+
9
+ - Support resizing multiple (intersecting) panels at once (#274)
10
+ 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.
11
+
3
12
  ## 1.0.10
4
13
 
5
14
  - Fixed edge case constraints check bug that could cause a collapsed panel to re-expand unnecessarily (#273)
package/README.md CHANGED
@@ -20,7 +20,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
20
20
  </PanelGroup>;
21
21
  ```
22
22
 
23
- ### If you like this project, 🎉 [become a sponsor](https://github.com/sponsors/bvaughn/) or ☕ [buy me a coffee](http://givebrian.coffee/)
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 | 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, ...]`).
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
- | `onExpand` | `?() => void` | Called when panel is expanded |
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 | description
76
- | :--------------------------- | :---
77
- | `collapse()` | 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 commited size of the panel as a percentage (`1 - 100`).
84
- | `resize(size: number)` | Resize panel to the specified _percentage_ (`1 - 100`).
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 | 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
- | `disabled` | `?boolean` | Disable drag handle |
93
- | `id` | `?string` | Resize handle id (unique within group); falls back to `useId` when not provided |
94
- | `onDragging` | `?(isDragging: boolean) => void` | Called when group layout changes |
95
- | `style` | `?CSSProperties` | CSS style to attach to root element |
96
- | `tagName` | `?string = "div"` | HTML element tag name for root element |
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
- ##### Server component
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
- ##### Client component
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;