react-resizable-panels 0.0.26 → 0.0.28
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 +5 -0
- package/README.md +14 -12
- package/dist/react-resizable-panels.d.ts +9 -2
- package/dist/react-resizable-panels.d.ts.map +1 -1
- package/dist/react-resizable-panels.js +79 -22
- package/dist/react-resizable-panels.js.map +1 -1
- package/dist/react-resizable-panels.module.js +80 -23
- package/dist/react-resizable-panels.module.js.map +1 -1
- package/package.json +1 -1
- package/src/Panel.ts +24 -6
- package/src/PanelGroup.ts +30 -5
- package/src/hooks/useIsomorphicEffect.ts +6 -0
- package/src/types.ts +6 -1
- package/src/utils/coordinates.ts +58 -14
- package/src/utils/group.ts +8 -0
package/src/PanelGroup.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
ReactNode,
|
|
6
6
|
useCallback,
|
|
7
7
|
useEffect,
|
|
8
|
-
useLayoutEffect,
|
|
9
8
|
useMemo,
|
|
10
9
|
useRef,
|
|
11
10
|
useState,
|
|
@@ -22,8 +21,9 @@ import {
|
|
|
22
21
|
getResizeHandlePanelIds,
|
|
23
22
|
panelsMapToSortedArray,
|
|
24
23
|
} from "./utils/group";
|
|
25
|
-
import
|
|
24
|
+
import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
|
|
26
25
|
import useUniqueId from "./hooks/useUniqueId";
|
|
26
|
+
import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterBehavior";
|
|
27
27
|
import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
|
|
28
28
|
|
|
29
29
|
export type CommittedValues = {
|
|
@@ -74,7 +74,7 @@ export default function PanelGroup({
|
|
|
74
74
|
sizes,
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
useIsomorphicLayoutEffect(() => {
|
|
78
78
|
committedValuesRef.current.direction = direction;
|
|
79
79
|
committedValuesRef.current.panels = panels;
|
|
80
80
|
committedValuesRef.current.sizes = sizes;
|
|
@@ -91,7 +91,7 @@ export default function PanelGroup({
|
|
|
91
91
|
// Once all panels have registered themselves,
|
|
92
92
|
// Compute the initial sizes based on default weights.
|
|
93
93
|
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
94
|
-
|
|
94
|
+
useIsomorphicLayoutEffect(() => {
|
|
95
95
|
const sizes = committedValuesRef.current.sizes;
|
|
96
96
|
if (sizes.length === panels.size) {
|
|
97
97
|
// Only compute (or restore) default sizes once per panel configuration.
|
|
@@ -168,6 +168,20 @@ export default function PanelGroup({
|
|
|
168
168
|
(id: string): CSSProperties => {
|
|
169
169
|
const { panels } = committedValuesRef.current;
|
|
170
170
|
|
|
171
|
+
// Before mounting, Panels will not yet have registered themselves.
|
|
172
|
+
// This includes server rendering.
|
|
173
|
+
// At this point the best we can do is render everything with the same size.
|
|
174
|
+
if (panels.size === 0) {
|
|
175
|
+
return {
|
|
176
|
+
flexBasis: "auto",
|
|
177
|
+
flexGrow: 1,
|
|
178
|
+
flexShrink: 1,
|
|
179
|
+
|
|
180
|
+
// Without this, Panel sizes may be unintentionally overridden by their content.
|
|
181
|
+
overflow: "hidden",
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
171
185
|
const flexGrow = getFlexGrow(panels, id, sizes);
|
|
172
186
|
|
|
173
187
|
return {
|
|
@@ -221,7 +235,9 @@ export default function PanelGroup({
|
|
|
221
235
|
event,
|
|
222
236
|
groupId,
|
|
223
237
|
handleId,
|
|
238
|
+
panelsArray,
|
|
224
239
|
direction,
|
|
240
|
+
prevSizes,
|
|
225
241
|
dragOffsetRef.current
|
|
226
242
|
);
|
|
227
243
|
if (movement === 0) {
|
|
@@ -262,10 +278,19 @@ export default function PanelGroup({
|
|
|
262
278
|
nextSizes.forEach((nextSize, index) => {
|
|
263
279
|
const prevSize = prevSizes[index];
|
|
264
280
|
if (prevSize !== nextSize) {
|
|
265
|
-
const onResize =
|
|
281
|
+
const { onCollapse, onResize } =
|
|
282
|
+
panelsArray[index].callbacksRef.current;
|
|
266
283
|
if (onResize) {
|
|
267
284
|
onResize(nextSize);
|
|
268
285
|
}
|
|
286
|
+
|
|
287
|
+
if (onCollapse) {
|
|
288
|
+
if (prevSize === 0 && nextSize !== 0) {
|
|
289
|
+
onCollapse(false);
|
|
290
|
+
} else if (prevSize !== 0 && nextSize === 0) {
|
|
291
|
+
onCollapse(true);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
269
294
|
}
|
|
270
295
|
});
|
|
271
296
|
|
package/src/types.ts
CHANGED
|
@@ -2,14 +2,19 @@ import { RefObject } from "react";
|
|
|
2
2
|
|
|
3
3
|
export type Direction = "horizontal" | "vertical";
|
|
4
4
|
|
|
5
|
+
export type PanelOnCollapse = (collapsed: boolean) => void;
|
|
5
6
|
export type PanelOnResize = (size: number) => void;
|
|
6
7
|
|
|
7
8
|
export type PanelData = {
|
|
9
|
+
callbacksRef: RefObject<{
|
|
10
|
+
onCollapse: PanelOnCollapse | null;
|
|
11
|
+
onResize: PanelOnResize | null;
|
|
12
|
+
}>;
|
|
13
|
+
collapsible: boolean;
|
|
8
14
|
defaultSize: number;
|
|
9
15
|
id: string;
|
|
10
16
|
maxSize: number;
|
|
11
17
|
minSize: number;
|
|
12
|
-
onResizeRef: RefObject<PanelOnResize | null>;
|
|
13
18
|
order: number | null;
|
|
14
19
|
};
|
|
15
20
|
|
package/src/utils/coordinates.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PRECISION } from "../constants";
|
|
2
|
+
import { Direction, PanelData, ResizeEvent } from "../types";
|
|
3
|
+
import {
|
|
4
|
+
getPanelGroup,
|
|
5
|
+
getResizeHandle,
|
|
6
|
+
getResizeHandlePanelIds,
|
|
7
|
+
} from "./group";
|
|
3
8
|
|
|
4
9
|
export type Coordinates = {
|
|
5
10
|
movement: number;
|
|
@@ -41,33 +46,72 @@ export function getMovement(
|
|
|
41
46
|
event: ResizeEvent,
|
|
42
47
|
groupId: string,
|
|
43
48
|
handleId: string,
|
|
49
|
+
panelsArray: PanelData[],
|
|
44
50
|
direction: Direction,
|
|
51
|
+
sizes: number[],
|
|
45
52
|
initialOffset: number
|
|
46
53
|
): number {
|
|
47
|
-
|
|
54
|
+
if (isKeyDown(event)) {
|
|
55
|
+
const isHorizontal = direction === "horizontal";
|
|
48
56
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
const groupElement = getPanelGroup(groupId);
|
|
58
|
+
const rect = groupElement.getBoundingClientRect();
|
|
59
|
+
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
52
60
|
|
|
53
|
-
if (isKeyDown(event)) {
|
|
54
61
|
const denominator = event.shiftKey ? 10 : 100;
|
|
55
|
-
const delta =
|
|
62
|
+
const delta = groupSizeInPixels / denominator;
|
|
56
63
|
|
|
64
|
+
let movement = 0;
|
|
57
65
|
switch (event.key) {
|
|
58
66
|
case "ArrowDown":
|
|
59
|
-
|
|
67
|
+
movement = isHorizontal ? 0 : delta;
|
|
68
|
+
break;
|
|
60
69
|
case "ArrowLeft":
|
|
61
|
-
|
|
70
|
+
movement = isHorizontal ? -delta : 0;
|
|
71
|
+
break;
|
|
62
72
|
case "ArrowRight":
|
|
63
|
-
|
|
73
|
+
movement = isHorizontal ? delta : 0;
|
|
74
|
+
break;
|
|
64
75
|
case "ArrowUp":
|
|
65
|
-
|
|
76
|
+
movement = isHorizontal ? 0 : -delta;
|
|
77
|
+
break;
|
|
66
78
|
case "End":
|
|
67
|
-
|
|
79
|
+
movement = groupSizeInPixels;
|
|
80
|
+
break;
|
|
68
81
|
case "Home":
|
|
69
|
-
|
|
82
|
+
movement = -groupSizeInPixels;
|
|
83
|
+
break;
|
|
70
84
|
}
|
|
85
|
+
|
|
86
|
+
// If the Panel being resized is collapsible,
|
|
87
|
+
// we need to special case resizing around the minSize boundary.
|
|
88
|
+
// If contracting, Panels should shrink to their minSize and then snap to fully collapsed.
|
|
89
|
+
// If expanding from collapsed, they should snap back to their minSize.
|
|
90
|
+
const [idBefore, idAfter] = getResizeHandlePanelIds(
|
|
91
|
+
groupId,
|
|
92
|
+
handleId,
|
|
93
|
+
panelsArray
|
|
94
|
+
);
|
|
95
|
+
const targetPanelId = movement < 0 ? idBefore : idAfter;
|
|
96
|
+
const targetPanelIndex = panelsArray.findIndex(
|
|
97
|
+
(panel) => panel.id === targetPanelId
|
|
98
|
+
);
|
|
99
|
+
const targetPanel = panelsArray[targetPanelIndex];
|
|
100
|
+
if (targetPanel.collapsible) {
|
|
101
|
+
const prevSize = sizes[targetPanelIndex];
|
|
102
|
+
if (
|
|
103
|
+
prevSize === 0 ||
|
|
104
|
+
prevSize.toPrecision(PRECISION) ===
|
|
105
|
+
targetPanel.minSize.toPrecision(PRECISION)
|
|
106
|
+
) {
|
|
107
|
+
movement =
|
|
108
|
+
movement < 0
|
|
109
|
+
? -targetPanel.minSize * groupSizeInPixels
|
|
110
|
+
: targetPanel.minSize * groupSizeInPixels;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return movement;
|
|
71
115
|
} else {
|
|
72
116
|
return getDragOffset(event, handleId, direction, initialOffset);
|
|
73
117
|
}
|
package/src/utils/group.ts
CHANGED
|
@@ -178,9 +178,17 @@ function safeResizePanel(
|
|
|
178
178
|
prevSize: number
|
|
179
179
|
): number {
|
|
180
180
|
const nextSizeUnsafe = prevSize + delta;
|
|
181
|
+
|
|
182
|
+
if (panel.collapsible) {
|
|
183
|
+
if (nextSizeUnsafe <= 0) {
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
181
188
|
const nextSize = Math.min(
|
|
182
189
|
panel.maxSize,
|
|
183
190
|
Math.max(panel.minSize, nextSizeUnsafe)
|
|
184
191
|
);
|
|
192
|
+
|
|
185
193
|
return nextSize;
|
|
186
194
|
}
|