react-resizable-panels 0.0.51 → 0.0.53
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 +7 -0
- package/README.md +15 -14
- package/dist/declarations/src/Panel.d.ts +1 -0
- package/dist/declarations/src/types.d.ts +2 -1
- package/dist/react-resizable-panels.cjs.js +77 -42
- package/dist/react-resizable-panels.development.cjs.js +77 -42
- package/dist/react-resizable-panels.development.esm.js +77 -42
- package/dist/react-resizable-panels.esm.js +77 -42
- package/package.json +1 -1
- package/src/Panel.ts +5 -0
- package/src/PanelGroup.ts +47 -35
- package/src/types.ts +2 -1
- package/src/utils/group.ts +26 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.0.53
|
|
4
|
+
* Fix edge case race condition for `onResize` callbacks during initial mount
|
|
5
|
+
|
|
6
|
+
## 0.0.52
|
|
7
|
+
* [162](https://github.com/bvaughn/react-resizable-panels/issues/162): Add `Panel.collapsedSize` property to allow panels to be collapsed to custom, non-0 sizes
|
|
8
|
+
* [161](https://github.com/bvaughn/react-resizable-panels/pull/161): Bug fix: `onResize` should be called for the initial `Panel` size regardless of the `onLayout` prop
|
|
9
|
+
|
|
3
10
|
## 0.0.51
|
|
4
11
|
* [154](https://github.com/bvaughn/react-resizable-panels/issues/154): `onResize` and `onCollapse` props are called in response to `PanelGroup.setLayout`
|
|
5
12
|
* [123](https://github.com/bvaughn/react-resizable-panels/issues/123): `onResize` called when number of panels in a group change due to conditional rendering
|
package/README.md
CHANGED
|
@@ -49,20 +49,21 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
|
49
49
|
| `setLayout(panelSizes: number[])` | Resize panel group to the specified _panelSizes_ (`[1 - 100, ...]`).
|
|
50
50
|
|
|
51
51
|
### `Panel`
|
|
52
|
-
| prop
|
|
53
|
-
|
|
|
54
|
-
| `children`
|
|
55
|
-
| `className`
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
52
|
+
| prop | type | description
|
|
53
|
+
| :-------------- | :------------------------------ | :---
|
|
54
|
+
| `children` | `ReactNode` | Arbitrary React element(s)
|
|
55
|
+
| `className` | `?string` | Class name to attach to root element
|
|
56
|
+
| `collapsedSize` | `?number=0` | Panel should collapse to this size
|
|
57
|
+
| `collapsible` | `?boolean=false` | Panel should collapse when resized beyond its `minSize`
|
|
58
|
+
| `defaultSize` | `?number` | Initial size of panel (numeric value between 1-100)
|
|
59
|
+
| `id` | `?string` | Panel id (unique within group); falls back to `useId` when not provided
|
|
60
|
+
| `maxSize` | `?number = 100` | Maximum allowable size of panel (numeric value between 1-100); defaults to `100`
|
|
61
|
+
| `minSize` | `?number = 10` | Minimum allowable size of panel (numeric value between 1-100); defaults to `10`
|
|
62
|
+
| `onCollapse` | `?(collapsed: boolean) => void` | Called when panel is collapsed; `collapsed` boolean parameter reflecting the new state
|
|
63
|
+
| `onResize` | `?(size: number) => void` | Called when panel is resized; `size` parameter is a numeric value between 1-100. <sup>1</sup>
|
|
64
|
+
| `order` | `?number` | Order of panel within group; required for groups with conditionally rendered panels
|
|
65
|
+
| `style` | `?CSSProperties` | CSS style to attach to root element
|
|
66
|
+
| `tagName` | `?string = "div"` | HTML element tag name for root element
|
|
66
67
|
|
|
67
68
|
<sup>1</sup>: If any `Panel` has an `onResize` callback, the `order` prop should be provided for all `Panel`s.
|
|
68
69
|
|
|
@@ -6,7 +6,7 @@ export type PanelGroupStorage = {
|
|
|
6
6
|
};
|
|
7
7
|
export type PanelGroupOnLayout = (sizes: number[]) => void;
|
|
8
8
|
export type PanelOnCollapse = (collapsed: boolean) => void;
|
|
9
|
-
export type PanelOnResize = (size: number) => void;
|
|
9
|
+
export type PanelOnResize = (size: number, prevSize: number) => void;
|
|
10
10
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
11
11
|
export type PanelCallbackRef = RefObject<{
|
|
12
12
|
onCollapse: PanelOnCollapse | null;
|
|
@@ -15,6 +15,7 @@ export type PanelCallbackRef = RefObject<{
|
|
|
15
15
|
export type PanelData = {
|
|
16
16
|
current: {
|
|
17
17
|
callbacksRef: PanelCallbackRef;
|
|
18
|
+
collapsedSize: number;
|
|
18
19
|
collapsible: boolean;
|
|
19
20
|
defaultSize: number | null;
|
|
20
21
|
id: string;
|
|
@@ -69,6 +69,7 @@ PanelGroupContext.displayName = "PanelGroupContext";
|
|
|
69
69
|
function PanelWithForwardedRef({
|
|
70
70
|
children = null,
|
|
71
71
|
className: classNameFromProps = "",
|
|
72
|
+
collapsedSize = 0,
|
|
72
73
|
collapsible = false,
|
|
73
74
|
defaultSize = null,
|
|
74
75
|
forwardedRef,
|
|
@@ -126,6 +127,7 @@ function PanelWithForwardedRef({
|
|
|
126
127
|
});
|
|
127
128
|
const panelDataRef = useRef({
|
|
128
129
|
callbacksRef,
|
|
130
|
+
collapsedSize,
|
|
129
131
|
collapsible,
|
|
130
132
|
defaultSize,
|
|
131
133
|
id: panelId,
|
|
@@ -136,6 +138,7 @@ function PanelWithForwardedRef({
|
|
|
136
138
|
useIsomorphicLayoutEffect(() => {
|
|
137
139
|
committedValuesRef.current.size = parseSizeFromStyle(style);
|
|
138
140
|
panelDataRef.current.callbacksRef = callbacksRef;
|
|
141
|
+
panelDataRef.current.collapsedSize = collapsedSize;
|
|
139
142
|
panelDataRef.current.collapsible = collapsible;
|
|
140
143
|
panelDataRef.current.defaultSize = defaultSize;
|
|
141
144
|
panelDataRef.current.id = panelId;
|
|
@@ -283,11 +286,18 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
283
286
|
}
|
|
284
287
|
function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
285
288
|
sizes.forEach((size, index) => {
|
|
289
|
+
const panelRef = panelsArray[index];
|
|
290
|
+
if (!panelRef) {
|
|
291
|
+
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
292
|
+
// The subsequent render+effects will handle the resize notification
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
286
295
|
const {
|
|
287
296
|
callbacksRef,
|
|
297
|
+
collapsedSize,
|
|
288
298
|
collapsible,
|
|
289
299
|
id
|
|
290
|
-
} =
|
|
300
|
+
} = panelRef.current;
|
|
291
301
|
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[id];
|
|
292
302
|
if (lastNotifiedSize !== size) {
|
|
293
303
|
panelIdToLastNotifiedSizeMap[id] = size;
|
|
@@ -296,14 +306,12 @@ function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
|
296
306
|
onResize
|
|
297
307
|
} = callbacksRef.current;
|
|
298
308
|
if (onResize) {
|
|
299
|
-
onResize(size);
|
|
309
|
+
onResize(size, lastNotifiedSize);
|
|
300
310
|
}
|
|
301
311
|
if (collapsible && onCollapse) {
|
|
302
|
-
|
|
303
|
-
// and initial size of undefined (when mounting)
|
|
304
|
-
if (!lastNotifiedSize && size !== 0) {
|
|
312
|
+
if ((lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
305
313
|
onCollapse(false);
|
|
306
|
-
} else if (lastNotifiedSize !==
|
|
314
|
+
} else if (lastNotifiedSize !== collapsedSize && size === collapsedSize) {
|
|
307
315
|
onCollapse(true);
|
|
308
316
|
}
|
|
309
317
|
}
|
|
@@ -395,11 +403,17 @@ function panelsMapToSortedArray(panels) {
|
|
|
395
403
|
}
|
|
396
404
|
function safeResizePanel(panel, delta, prevSize, event) {
|
|
397
405
|
const nextSizeUnsafe = prevSize + delta;
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
const {
|
|
407
|
+
collapsedSize,
|
|
408
|
+
collapsible,
|
|
409
|
+
maxSize,
|
|
410
|
+
minSize
|
|
411
|
+
} = panel.current;
|
|
412
|
+
if (collapsible) {
|
|
413
|
+
if (prevSize > collapsedSize) {
|
|
400
414
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
401
|
-
if (nextSizeUnsafe <=
|
|
402
|
-
return
|
|
415
|
+
if (nextSizeUnsafe <= minSize / 2 + collapsedSize) {
|
|
416
|
+
return collapsedSize;
|
|
403
417
|
}
|
|
404
418
|
} else {
|
|
405
419
|
const isKeyboardEvent = event?.type?.startsWith("key");
|
|
@@ -407,13 +421,13 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
407
421
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
408
422
|
// but mouse events should wait until the panel has reached its min size
|
|
409
423
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
410
|
-
if (nextSizeUnsafe <
|
|
411
|
-
return
|
|
424
|
+
if (nextSizeUnsafe < minSize) {
|
|
425
|
+
return collapsedSize;
|
|
412
426
|
}
|
|
413
427
|
}
|
|
414
428
|
}
|
|
415
429
|
}
|
|
416
|
-
const nextSize = Math.min(
|
|
430
|
+
const nextSize = Math.min(maxSize, Math.max(minSize, nextSizeUnsafe));
|
|
417
431
|
return nextSize;
|
|
418
432
|
}
|
|
419
433
|
|
|
@@ -869,8 +883,8 @@ function PanelGroupWithForwardedRef({
|
|
|
869
883
|
} = committedValuesRef.current;
|
|
870
884
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
871
885
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
872
|
-
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
873
886
|
setSizes(sizes);
|
|
887
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
874
888
|
}
|
|
875
889
|
}), []);
|
|
876
890
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -892,25 +906,25 @@ function PanelGroupWithForwardedRef({
|
|
|
892
906
|
const {
|
|
893
907
|
onLayout
|
|
894
908
|
} = callbacksRef.current;
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
} = committedValuesRef.current;
|
|
909
|
+
const {
|
|
910
|
+
panels,
|
|
911
|
+
sizes
|
|
912
|
+
} = committedValuesRef.current;
|
|
900
913
|
|
|
901
|
-
|
|
902
|
-
|
|
914
|
+
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
915
|
+
if (sizes.length > 0) {
|
|
916
|
+
if (onLayout) {
|
|
903
917
|
onLayout(sizes);
|
|
904
|
-
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
905
|
-
|
|
906
|
-
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
907
|
-
// Some cases are difficult to detect though,
|
|
908
|
-
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
909
|
-
// In this case, the best we can do is notify on commit.
|
|
910
|
-
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
911
|
-
const panelsArray = panelsMapToSortedArray(panels);
|
|
912
|
-
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
913
918
|
}
|
|
919
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
920
|
+
|
|
921
|
+
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
922
|
+
// Some cases are difficult to detect though,
|
|
923
|
+
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
924
|
+
// In this case, the best we can do is notify on commit.
|
|
925
|
+
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
926
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
927
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
914
928
|
}
|
|
915
929
|
}, [sizes]);
|
|
916
930
|
|
|
@@ -1075,10 +1089,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1075
1089
|
}
|
|
1076
1090
|
if (sizesChanged) {
|
|
1077
1091
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1092
|
+
setSizes(nextSizes);
|
|
1078
1093
|
|
|
1079
1094
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1095
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1080
1096
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1081
|
-
setSizes(nextSizes);
|
|
1082
1097
|
}
|
|
1083
1098
|
prevDeltaRef.current = delta;
|
|
1084
1099
|
};
|
|
@@ -1100,7 +1115,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1100
1115
|
sizes: prevSizes
|
|
1101
1116
|
} = committedValuesRef.current;
|
|
1102
1117
|
const panel = panels.get(id);
|
|
1103
|
-
if (panel == null
|
|
1118
|
+
if (panel == null) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
const {
|
|
1122
|
+
collapsedSize,
|
|
1123
|
+
collapsible
|
|
1124
|
+
} = panel.current;
|
|
1125
|
+
if (!collapsible) {
|
|
1104
1126
|
return;
|
|
1105
1127
|
}
|
|
1106
1128
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
@@ -1109,7 +1131,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1109
1131
|
return;
|
|
1110
1132
|
}
|
|
1111
1133
|
const currentSize = prevSizes[index];
|
|
1112
|
-
if (currentSize ===
|
|
1134
|
+
if (currentSize === collapsedSize) {
|
|
1113
1135
|
// Panel is already collapsed.
|
|
1114
1136
|
return;
|
|
1115
1137
|
}
|
|
@@ -1119,14 +1141,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1119
1141
|
return;
|
|
1120
1142
|
}
|
|
1121
1143
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1122
|
-
const delta = isLastPanel ? currentSize :
|
|
1144
|
+
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1123
1145
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1124
1146
|
if (prevSizes !== nextSizes) {
|
|
1125
1147
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1148
|
+
setSizes(nextSizes);
|
|
1126
1149
|
|
|
1127
1150
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1151
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1128
1152
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1129
|
-
setSizes(nextSizes);
|
|
1130
1153
|
}
|
|
1131
1154
|
}, []);
|
|
1132
1155
|
const expandPanel = useCallback(id => {
|
|
@@ -1138,7 +1161,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1138
1161
|
if (panel == null) {
|
|
1139
1162
|
return;
|
|
1140
1163
|
}
|
|
1141
|
-
const
|
|
1164
|
+
const {
|
|
1165
|
+
collapsedSize,
|
|
1166
|
+
minSize
|
|
1167
|
+
} = panel.current;
|
|
1168
|
+
const sizeBeforeCollapse = panelSizeBeforeCollapse.current.get(id) || minSize;
|
|
1142
1169
|
if (!sizeBeforeCollapse) {
|
|
1143
1170
|
return;
|
|
1144
1171
|
}
|
|
@@ -1148,7 +1175,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1148
1175
|
return;
|
|
1149
1176
|
}
|
|
1150
1177
|
const currentSize = prevSizes[index];
|
|
1151
|
-
if (currentSize !==
|
|
1178
|
+
if (currentSize !== collapsedSize) {
|
|
1152
1179
|
// Panel is already expanded.
|
|
1153
1180
|
return;
|
|
1154
1181
|
}
|
|
@@ -1157,14 +1184,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1157
1184
|
return;
|
|
1158
1185
|
}
|
|
1159
1186
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1160
|
-
const delta = isLastPanel ?
|
|
1187
|
+
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1161
1188
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1162
1189
|
if (prevSizes !== nextSizes) {
|
|
1163
1190
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1191
|
+
setSizes(nextSizes);
|
|
1164
1192
|
|
|
1165
1193
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1194
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1166
1195
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1167
|
-
setSizes(nextSizes);
|
|
1168
1196
|
}
|
|
1169
1197
|
}, []);
|
|
1170
1198
|
const resizePanel = useCallback((id, nextSize) => {
|
|
@@ -1176,6 +1204,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1176
1204
|
if (panel == null) {
|
|
1177
1205
|
return;
|
|
1178
1206
|
}
|
|
1207
|
+
const {
|
|
1208
|
+
collapsedSize,
|
|
1209
|
+
collapsible,
|
|
1210
|
+
maxSize,
|
|
1211
|
+
minSize
|
|
1212
|
+
} = panel.current;
|
|
1179
1213
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1180
1214
|
const index = panelsArray.indexOf(panel);
|
|
1181
1215
|
if (index < 0) {
|
|
@@ -1185,8 +1219,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1185
1219
|
if (currentSize === nextSize) {
|
|
1186
1220
|
return;
|
|
1187
1221
|
}
|
|
1188
|
-
if (
|
|
1189
|
-
nextSize = Math.min(
|
|
1222
|
+
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1223
|
+
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1190
1224
|
}
|
|
1191
1225
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1192
1226
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1197,10 +1231,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1197
1231
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1198
1232
|
if (prevSizes !== nextSizes) {
|
|
1199
1233
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1234
|
+
setSizes(nextSizes);
|
|
1200
1235
|
|
|
1201
1236
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1237
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1202
1238
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1203
|
-
setSizes(nextSizes);
|
|
1204
1239
|
}
|
|
1205
1240
|
}, []);
|
|
1206
1241
|
const context = useMemo(() => ({
|
|
@@ -69,6 +69,7 @@ PanelGroupContext.displayName = "PanelGroupContext";
|
|
|
69
69
|
function PanelWithForwardedRef({
|
|
70
70
|
children = null,
|
|
71
71
|
className: classNameFromProps = "",
|
|
72
|
+
collapsedSize = 0,
|
|
72
73
|
collapsible = false,
|
|
73
74
|
defaultSize = null,
|
|
74
75
|
forwardedRef,
|
|
@@ -126,6 +127,7 @@ function PanelWithForwardedRef({
|
|
|
126
127
|
});
|
|
127
128
|
const panelDataRef = useRef({
|
|
128
129
|
callbacksRef,
|
|
130
|
+
collapsedSize,
|
|
129
131
|
collapsible,
|
|
130
132
|
defaultSize,
|
|
131
133
|
id: panelId,
|
|
@@ -136,6 +138,7 @@ function PanelWithForwardedRef({
|
|
|
136
138
|
useIsomorphicLayoutEffect(() => {
|
|
137
139
|
committedValuesRef.current.size = parseSizeFromStyle(style);
|
|
138
140
|
panelDataRef.current.callbacksRef = callbacksRef;
|
|
141
|
+
panelDataRef.current.collapsedSize = collapsedSize;
|
|
139
142
|
panelDataRef.current.collapsible = collapsible;
|
|
140
143
|
panelDataRef.current.defaultSize = defaultSize;
|
|
141
144
|
panelDataRef.current.id = panelId;
|
|
@@ -283,11 +286,18 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
283
286
|
}
|
|
284
287
|
function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
285
288
|
sizes.forEach((size, index) => {
|
|
289
|
+
const panelRef = panelsArray[index];
|
|
290
|
+
if (!panelRef) {
|
|
291
|
+
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
292
|
+
// The subsequent render+effects will handle the resize notification
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
286
295
|
const {
|
|
287
296
|
callbacksRef,
|
|
297
|
+
collapsedSize,
|
|
288
298
|
collapsible,
|
|
289
299
|
id
|
|
290
|
-
} =
|
|
300
|
+
} = panelRef.current;
|
|
291
301
|
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[id];
|
|
292
302
|
if (lastNotifiedSize !== size) {
|
|
293
303
|
panelIdToLastNotifiedSizeMap[id] = size;
|
|
@@ -296,14 +306,12 @@ function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
|
296
306
|
onResize
|
|
297
307
|
} = callbacksRef.current;
|
|
298
308
|
if (onResize) {
|
|
299
|
-
onResize(size);
|
|
309
|
+
onResize(size, lastNotifiedSize);
|
|
300
310
|
}
|
|
301
311
|
if (collapsible && onCollapse) {
|
|
302
|
-
|
|
303
|
-
// and initial size of undefined (when mounting)
|
|
304
|
-
if (!lastNotifiedSize && size !== 0) {
|
|
312
|
+
if ((lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
305
313
|
onCollapse(false);
|
|
306
|
-
} else if (lastNotifiedSize !==
|
|
314
|
+
} else if (lastNotifiedSize !== collapsedSize && size === collapsedSize) {
|
|
307
315
|
onCollapse(true);
|
|
308
316
|
}
|
|
309
317
|
}
|
|
@@ -395,11 +403,17 @@ function panelsMapToSortedArray(panels) {
|
|
|
395
403
|
}
|
|
396
404
|
function safeResizePanel(panel, delta, prevSize, event) {
|
|
397
405
|
const nextSizeUnsafe = prevSize + delta;
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
const {
|
|
407
|
+
collapsedSize,
|
|
408
|
+
collapsible,
|
|
409
|
+
maxSize,
|
|
410
|
+
minSize
|
|
411
|
+
} = panel.current;
|
|
412
|
+
if (collapsible) {
|
|
413
|
+
if (prevSize > collapsedSize) {
|
|
400
414
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
401
|
-
if (nextSizeUnsafe <=
|
|
402
|
-
return
|
|
415
|
+
if (nextSizeUnsafe <= minSize / 2 + collapsedSize) {
|
|
416
|
+
return collapsedSize;
|
|
403
417
|
}
|
|
404
418
|
} else {
|
|
405
419
|
const isKeyboardEvent = event?.type?.startsWith("key");
|
|
@@ -407,13 +421,13 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
407
421
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
408
422
|
// but mouse events should wait until the panel has reached its min size
|
|
409
423
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
410
|
-
if (nextSizeUnsafe <
|
|
411
|
-
return
|
|
424
|
+
if (nextSizeUnsafe < minSize) {
|
|
425
|
+
return collapsedSize;
|
|
412
426
|
}
|
|
413
427
|
}
|
|
414
428
|
}
|
|
415
429
|
}
|
|
416
|
-
const nextSize = Math.min(
|
|
430
|
+
const nextSize = Math.min(maxSize, Math.max(minSize, nextSizeUnsafe));
|
|
417
431
|
return nextSize;
|
|
418
432
|
}
|
|
419
433
|
|
|
@@ -876,8 +890,8 @@ function PanelGroupWithForwardedRef({
|
|
|
876
890
|
} = committedValuesRef.current;
|
|
877
891
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
878
892
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
879
|
-
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
880
893
|
setSizes(sizes);
|
|
894
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
881
895
|
}
|
|
882
896
|
}), []);
|
|
883
897
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -899,25 +913,25 @@ function PanelGroupWithForwardedRef({
|
|
|
899
913
|
const {
|
|
900
914
|
onLayout
|
|
901
915
|
} = callbacksRef.current;
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
} = committedValuesRef.current;
|
|
916
|
+
const {
|
|
917
|
+
panels,
|
|
918
|
+
sizes
|
|
919
|
+
} = committedValuesRef.current;
|
|
907
920
|
|
|
908
|
-
|
|
909
|
-
|
|
921
|
+
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
922
|
+
if (sizes.length > 0) {
|
|
923
|
+
if (onLayout) {
|
|
910
924
|
onLayout(sizes);
|
|
911
|
-
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
912
|
-
|
|
913
|
-
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
914
|
-
// Some cases are difficult to detect though,
|
|
915
|
-
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
916
|
-
// In this case, the best we can do is notify on commit.
|
|
917
|
-
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
918
|
-
const panelsArray = panelsMapToSortedArray(panels);
|
|
919
|
-
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
920
925
|
}
|
|
926
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
927
|
+
|
|
928
|
+
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
929
|
+
// Some cases are difficult to detect though,
|
|
930
|
+
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
931
|
+
// In this case, the best we can do is notify on commit.
|
|
932
|
+
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
933
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
934
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
921
935
|
}
|
|
922
936
|
}, [sizes]);
|
|
923
937
|
|
|
@@ -1087,10 +1101,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1087
1101
|
}
|
|
1088
1102
|
if (sizesChanged) {
|
|
1089
1103
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1104
|
+
setSizes(nextSizes);
|
|
1090
1105
|
|
|
1091
1106
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1107
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1092
1108
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1093
|
-
setSizes(nextSizes);
|
|
1094
1109
|
}
|
|
1095
1110
|
prevDeltaRef.current = delta;
|
|
1096
1111
|
};
|
|
@@ -1112,7 +1127,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1112
1127
|
sizes: prevSizes
|
|
1113
1128
|
} = committedValuesRef.current;
|
|
1114
1129
|
const panel = panels.get(id);
|
|
1115
|
-
if (panel == null
|
|
1130
|
+
if (panel == null) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
const {
|
|
1134
|
+
collapsedSize,
|
|
1135
|
+
collapsible
|
|
1136
|
+
} = panel.current;
|
|
1137
|
+
if (!collapsible) {
|
|
1116
1138
|
return;
|
|
1117
1139
|
}
|
|
1118
1140
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
@@ -1121,7 +1143,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1121
1143
|
return;
|
|
1122
1144
|
}
|
|
1123
1145
|
const currentSize = prevSizes[index];
|
|
1124
|
-
if (currentSize ===
|
|
1146
|
+
if (currentSize === collapsedSize) {
|
|
1125
1147
|
// Panel is already collapsed.
|
|
1126
1148
|
return;
|
|
1127
1149
|
}
|
|
@@ -1131,14 +1153,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1131
1153
|
return;
|
|
1132
1154
|
}
|
|
1133
1155
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1134
|
-
const delta = isLastPanel ? currentSize :
|
|
1156
|
+
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1135
1157
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1136
1158
|
if (prevSizes !== nextSizes) {
|
|
1137
1159
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1160
|
+
setSizes(nextSizes);
|
|
1138
1161
|
|
|
1139
1162
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1163
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1140
1164
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1141
|
-
setSizes(nextSizes);
|
|
1142
1165
|
}
|
|
1143
1166
|
}, []);
|
|
1144
1167
|
const expandPanel = useCallback(id => {
|
|
@@ -1150,7 +1173,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1150
1173
|
if (panel == null) {
|
|
1151
1174
|
return;
|
|
1152
1175
|
}
|
|
1153
|
-
const
|
|
1176
|
+
const {
|
|
1177
|
+
collapsedSize,
|
|
1178
|
+
minSize
|
|
1179
|
+
} = panel.current;
|
|
1180
|
+
const sizeBeforeCollapse = panelSizeBeforeCollapse.current.get(id) || minSize;
|
|
1154
1181
|
if (!sizeBeforeCollapse) {
|
|
1155
1182
|
return;
|
|
1156
1183
|
}
|
|
@@ -1160,7 +1187,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1160
1187
|
return;
|
|
1161
1188
|
}
|
|
1162
1189
|
const currentSize = prevSizes[index];
|
|
1163
|
-
if (currentSize !==
|
|
1190
|
+
if (currentSize !== collapsedSize) {
|
|
1164
1191
|
// Panel is already expanded.
|
|
1165
1192
|
return;
|
|
1166
1193
|
}
|
|
@@ -1169,14 +1196,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1169
1196
|
return;
|
|
1170
1197
|
}
|
|
1171
1198
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1172
|
-
const delta = isLastPanel ?
|
|
1199
|
+
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1173
1200
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1174
1201
|
if (prevSizes !== nextSizes) {
|
|
1175
1202
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1203
|
+
setSizes(nextSizes);
|
|
1176
1204
|
|
|
1177
1205
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1206
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1178
1207
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1179
|
-
setSizes(nextSizes);
|
|
1180
1208
|
}
|
|
1181
1209
|
}, []);
|
|
1182
1210
|
const resizePanel = useCallback((id, nextSize) => {
|
|
@@ -1188,6 +1216,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1188
1216
|
if (panel == null) {
|
|
1189
1217
|
return;
|
|
1190
1218
|
}
|
|
1219
|
+
const {
|
|
1220
|
+
collapsedSize,
|
|
1221
|
+
collapsible,
|
|
1222
|
+
maxSize,
|
|
1223
|
+
minSize
|
|
1224
|
+
} = panel.current;
|
|
1191
1225
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1192
1226
|
const index = panelsArray.indexOf(panel);
|
|
1193
1227
|
if (index < 0) {
|
|
@@ -1197,8 +1231,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1197
1231
|
if (currentSize === nextSize) {
|
|
1198
1232
|
return;
|
|
1199
1233
|
}
|
|
1200
|
-
if (
|
|
1201
|
-
nextSize = Math.min(
|
|
1234
|
+
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1235
|
+
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1202
1236
|
}
|
|
1203
1237
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1204
1238
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1209,10 +1243,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1209
1243
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1210
1244
|
if (prevSizes !== nextSizes) {
|
|
1211
1245
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1246
|
+
setSizes(nextSizes);
|
|
1212
1247
|
|
|
1213
1248
|
// If resize change handlers have been declared, this is the time to call them.
|
|
1249
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1214
1250
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1215
|
-
setSizes(nextSizes);
|
|
1216
1251
|
}
|
|
1217
1252
|
}, []);
|
|
1218
1253
|
const context = useMemo(() => ({
|