react-resizable-panels 0.0.50 → 0.0.52
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 +8 -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 +95 -57
- package/dist/react-resizable-panels.cjs.js.map +1 -0
- package/dist/react-resizable-panels.development.cjs.js +95 -57
- package/dist/react-resizable-panels.development.esm.js +95 -57
- package/dist/react-resizable-panels.esm.js +95 -57
- package/dist/react-resizable-panels.esm.js.map +1 -0
- package/package.json +1 -1
- package/src/Panel.ts +5 -0
- package/src/PanelGroup.ts +68 -37
- package/src/types.ts +2 -1
- package/src/utils/group.ts +28 -21
|
@@ -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;
|
|
@@ -281,27 +284,28 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
281
284
|
nextSizes[index] = baseSizes[index] + deltaApplied;
|
|
282
285
|
return nextSizes;
|
|
283
286
|
}
|
|
284
|
-
function callPanelCallbacks(panelsArray,
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
287
|
+
function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
288
|
+
sizes.forEach((size, index) => {
|
|
289
|
+
const {
|
|
290
|
+
callbacksRef,
|
|
291
|
+
collapsedSize,
|
|
292
|
+
collapsible,
|
|
293
|
+
id
|
|
294
|
+
} = panelsArray[index].current;
|
|
295
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[id];
|
|
296
|
+
if (lastNotifiedSize !== size) {
|
|
297
|
+
panelIdToLastNotifiedSizeMap[id] = size;
|
|
292
298
|
const {
|
|
293
299
|
onCollapse,
|
|
294
300
|
onResize
|
|
295
301
|
} = callbacksRef.current;
|
|
296
302
|
if (onResize) {
|
|
297
|
-
onResize(
|
|
303
|
+
onResize(size, lastNotifiedSize);
|
|
298
304
|
}
|
|
299
305
|
if (collapsible && onCollapse) {
|
|
300
|
-
|
|
301
|
-
// and initial size of undefined (when mounting)
|
|
302
|
-
if (!prevSize && nextSize !== 0) {
|
|
306
|
+
if ((lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
303
307
|
onCollapse(false);
|
|
304
|
-
} else if (
|
|
308
|
+
} else if (lastNotifiedSize !== collapsedSize && size === collapsedSize) {
|
|
305
309
|
onCollapse(true);
|
|
306
310
|
}
|
|
307
311
|
}
|
|
@@ -393,11 +397,17 @@ function panelsMapToSortedArray(panels) {
|
|
|
393
397
|
}
|
|
394
398
|
function safeResizePanel(panel, delta, prevSize, event) {
|
|
395
399
|
const nextSizeUnsafe = prevSize + delta;
|
|
396
|
-
|
|
397
|
-
|
|
400
|
+
const {
|
|
401
|
+
collapsedSize,
|
|
402
|
+
collapsible,
|
|
403
|
+
maxSize,
|
|
404
|
+
minSize
|
|
405
|
+
} = panel.current;
|
|
406
|
+
if (collapsible) {
|
|
407
|
+
if (prevSize > collapsedSize) {
|
|
398
408
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
399
|
-
if (nextSizeUnsafe <=
|
|
400
|
-
return
|
|
409
|
+
if (nextSizeUnsafe <= minSize / 2 + collapsedSize) {
|
|
410
|
+
return collapsedSize;
|
|
401
411
|
}
|
|
402
412
|
} else {
|
|
403
413
|
const isKeyboardEvent = event?.type?.startsWith("key");
|
|
@@ -405,13 +415,13 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
405
415
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
406
416
|
// but mouse events should wait until the panel has reached its min size
|
|
407
417
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
408
|
-
if (nextSizeUnsafe <
|
|
409
|
-
return
|
|
418
|
+
if (nextSizeUnsafe < minSize) {
|
|
419
|
+
return collapsedSize;
|
|
410
420
|
}
|
|
411
421
|
}
|
|
412
422
|
}
|
|
413
423
|
}
|
|
414
|
-
const nextSize = Math.min(
|
|
424
|
+
const nextSize = Math.min(maxSize, Math.max(minSize, nextSizeUnsafe));
|
|
415
425
|
return nextSize;
|
|
416
426
|
}
|
|
417
427
|
|
|
@@ -844,6 +854,7 @@ function PanelGroupWithForwardedRef({
|
|
|
844
854
|
useEffect(() => {
|
|
845
855
|
callbacksRef.current.onLayout = onLayout;
|
|
846
856
|
});
|
|
857
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
847
858
|
|
|
848
859
|
// 0-1 values representing the relative size of each panel.
|
|
849
860
|
const [sizes, setSizes] = useState([]);
|
|
@@ -868,7 +879,13 @@ function PanelGroupWithForwardedRef({
|
|
|
868
879
|
setLayout: sizes => {
|
|
869
880
|
const total = sizes.reduce((accumulated, current) => accumulated + current, 0);
|
|
870
881
|
assert(total === 100, "Panel sizes must add up to 100%");
|
|
882
|
+
const {
|
|
883
|
+
panels
|
|
884
|
+
} = committedValuesRef.current;
|
|
885
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
886
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
871
887
|
setSizes(sizes);
|
|
888
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
872
889
|
}
|
|
873
890
|
}), []);
|
|
874
891
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -890,33 +907,25 @@ function PanelGroupWithForwardedRef({
|
|
|
890
907
|
const {
|
|
891
908
|
onLayout
|
|
892
909
|
} = callbacksRef.current;
|
|
893
|
-
if (onLayout) {
|
|
894
|
-
const {
|
|
895
|
-
sizes
|
|
896
|
-
} = committedValuesRef.current;
|
|
897
|
-
|
|
898
|
-
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
899
|
-
if (sizes.length > 0) {
|
|
900
|
-
onLayout(sizes);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
}, [sizes]);
|
|
904
|
-
|
|
905
|
-
// Notify Panel listeners about their initial sizes and collapsed state after mount.
|
|
906
|
-
// Subsequent changes will be called by the resizeHandler.
|
|
907
|
-
const didNotifyCallbacksAfterMountRef = useRef(false);
|
|
908
|
-
useIsomorphicLayoutEffect(() => {
|
|
909
|
-
if (didNotifyCallbacksAfterMountRef.current) {
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
910
|
const {
|
|
913
911
|
panels,
|
|
914
912
|
sizes
|
|
915
913
|
} = committedValuesRef.current;
|
|
914
|
+
|
|
915
|
+
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
916
916
|
if (sizes.length > 0) {
|
|
917
|
-
|
|
917
|
+
if (onLayout) {
|
|
918
|
+
onLayout(sizes);
|
|
919
|
+
}
|
|
920
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
921
|
+
|
|
922
|
+
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
923
|
+
// Some cases are difficult to detect though,
|
|
924
|
+
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
925
|
+
// In this case, the best we can do is notify on commit.
|
|
926
|
+
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
918
927
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
919
|
-
callPanelCallbacks(panelsArray,
|
|
928
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
920
929
|
}
|
|
921
930
|
}, [sizes]);
|
|
922
931
|
|
|
@@ -1085,9 +1094,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1085
1094
|
}
|
|
1086
1095
|
}
|
|
1087
1096
|
if (sizesChanged) {
|
|
1088
|
-
|
|
1089
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1097
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1090
1098
|
setSizes(nextSizes);
|
|
1099
|
+
|
|
1100
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1101
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1102
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1091
1103
|
}
|
|
1092
1104
|
prevDeltaRef.current = delta;
|
|
1093
1105
|
};
|
|
@@ -1109,7 +1121,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1109
1121
|
sizes: prevSizes
|
|
1110
1122
|
} = committedValuesRef.current;
|
|
1111
1123
|
const panel = panels.get(id);
|
|
1112
|
-
if (panel == null
|
|
1124
|
+
if (panel == null) {
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
const {
|
|
1128
|
+
collapsedSize,
|
|
1129
|
+
collapsible
|
|
1130
|
+
} = panel.current;
|
|
1131
|
+
if (!collapsible) {
|
|
1113
1132
|
return;
|
|
1114
1133
|
}
|
|
1115
1134
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
@@ -1118,7 +1137,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1118
1137
|
return;
|
|
1119
1138
|
}
|
|
1120
1139
|
const currentSize = prevSizes[index];
|
|
1121
|
-
if (currentSize ===
|
|
1140
|
+
if (currentSize === collapsedSize) {
|
|
1122
1141
|
// Panel is already collapsed.
|
|
1123
1142
|
return;
|
|
1124
1143
|
}
|
|
@@ -1128,12 +1147,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1128
1147
|
return;
|
|
1129
1148
|
}
|
|
1130
1149
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1131
|
-
const delta = isLastPanel ? currentSize :
|
|
1150
|
+
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1132
1151
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1133
1152
|
if (prevSizes !== nextSizes) {
|
|
1134
|
-
|
|
1135
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1153
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1136
1154
|
setSizes(nextSizes);
|
|
1155
|
+
|
|
1156
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1157
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1158
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1137
1159
|
}
|
|
1138
1160
|
}, []);
|
|
1139
1161
|
const expandPanel = useCallback(id => {
|
|
@@ -1145,7 +1167,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1145
1167
|
if (panel == null) {
|
|
1146
1168
|
return;
|
|
1147
1169
|
}
|
|
1148
|
-
const
|
|
1170
|
+
const {
|
|
1171
|
+
collapsedSize,
|
|
1172
|
+
minSize
|
|
1173
|
+
} = panel.current;
|
|
1174
|
+
const sizeBeforeCollapse = panelSizeBeforeCollapse.current.get(id) || minSize;
|
|
1149
1175
|
if (!sizeBeforeCollapse) {
|
|
1150
1176
|
return;
|
|
1151
1177
|
}
|
|
@@ -1155,7 +1181,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1155
1181
|
return;
|
|
1156
1182
|
}
|
|
1157
1183
|
const currentSize = prevSizes[index];
|
|
1158
|
-
if (currentSize !==
|
|
1184
|
+
if (currentSize !== collapsedSize) {
|
|
1159
1185
|
// Panel is already expanded.
|
|
1160
1186
|
return;
|
|
1161
1187
|
}
|
|
@@ -1164,12 +1190,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1164
1190
|
return;
|
|
1165
1191
|
}
|
|
1166
1192
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1167
|
-
const delta = isLastPanel ?
|
|
1193
|
+
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1168
1194
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1169
1195
|
if (prevSizes !== nextSizes) {
|
|
1170
|
-
|
|
1171
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1196
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1172
1197
|
setSizes(nextSizes);
|
|
1198
|
+
|
|
1199
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1200
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1201
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1173
1202
|
}
|
|
1174
1203
|
}, []);
|
|
1175
1204
|
const resizePanel = useCallback((id, nextSize) => {
|
|
@@ -1181,6 +1210,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1181
1210
|
if (panel == null) {
|
|
1182
1211
|
return;
|
|
1183
1212
|
}
|
|
1213
|
+
const {
|
|
1214
|
+
collapsedSize,
|
|
1215
|
+
collapsible,
|
|
1216
|
+
maxSize,
|
|
1217
|
+
minSize
|
|
1218
|
+
} = panel.current;
|
|
1184
1219
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1185
1220
|
const index = panelsArray.indexOf(panel);
|
|
1186
1221
|
if (index < 0) {
|
|
@@ -1190,8 +1225,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1190
1225
|
if (currentSize === nextSize) {
|
|
1191
1226
|
return;
|
|
1192
1227
|
}
|
|
1193
|
-
if (
|
|
1194
|
-
nextSize = Math.min(
|
|
1228
|
+
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1229
|
+
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1195
1230
|
}
|
|
1196
1231
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1197
1232
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1201,9 +1236,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1201
1236
|
const delta = isLastPanel ? currentSize - nextSize : nextSize - currentSize;
|
|
1202
1237
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1203
1238
|
if (prevSizes !== nextSizes) {
|
|
1204
|
-
|
|
1205
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1239
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1206
1240
|
setSizes(nextSizes);
|
|
1241
|
+
|
|
1242
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1243
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1244
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1207
1245
|
}
|
|
1208
1246
|
}, []);
|
|
1209
1247
|
const context = useMemo(() => ({
|
|
@@ -45,6 +45,7 @@ PanelGroupContext.displayName = "PanelGroupContext";
|
|
|
45
45
|
function PanelWithForwardedRef({
|
|
46
46
|
children = null,
|
|
47
47
|
className: classNameFromProps = "",
|
|
48
|
+
collapsedSize = 0,
|
|
48
49
|
collapsible = false,
|
|
49
50
|
defaultSize = null,
|
|
50
51
|
forwardedRef,
|
|
@@ -102,6 +103,7 @@ function PanelWithForwardedRef({
|
|
|
102
103
|
});
|
|
103
104
|
const panelDataRef = useRef({
|
|
104
105
|
callbacksRef,
|
|
106
|
+
collapsedSize,
|
|
105
107
|
collapsible,
|
|
106
108
|
defaultSize,
|
|
107
109
|
id: panelId,
|
|
@@ -112,6 +114,7 @@ function PanelWithForwardedRef({
|
|
|
112
114
|
useIsomorphicLayoutEffect(() => {
|
|
113
115
|
committedValuesRef.current.size = parseSizeFromStyle(style);
|
|
114
116
|
panelDataRef.current.callbacksRef = callbacksRef;
|
|
117
|
+
panelDataRef.current.collapsedSize = collapsedSize;
|
|
115
118
|
panelDataRef.current.collapsible = collapsible;
|
|
116
119
|
panelDataRef.current.defaultSize = defaultSize;
|
|
117
120
|
panelDataRef.current.id = panelId;
|
|
@@ -257,27 +260,28 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
257
260
|
nextSizes[index] = baseSizes[index] + deltaApplied;
|
|
258
261
|
return nextSizes;
|
|
259
262
|
}
|
|
260
|
-
function callPanelCallbacks(panelsArray,
|
|
261
|
-
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
263
|
+
function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
264
|
+
sizes.forEach((size, index) => {
|
|
265
|
+
const {
|
|
266
|
+
callbacksRef,
|
|
267
|
+
collapsedSize,
|
|
268
|
+
collapsible,
|
|
269
|
+
id
|
|
270
|
+
} = panelsArray[index].current;
|
|
271
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[id];
|
|
272
|
+
if (lastNotifiedSize !== size) {
|
|
273
|
+
panelIdToLastNotifiedSizeMap[id] = size;
|
|
268
274
|
const {
|
|
269
275
|
onCollapse,
|
|
270
276
|
onResize
|
|
271
277
|
} = callbacksRef.current;
|
|
272
278
|
if (onResize) {
|
|
273
|
-
onResize(
|
|
279
|
+
onResize(size, lastNotifiedSize);
|
|
274
280
|
}
|
|
275
281
|
if (collapsible && onCollapse) {
|
|
276
|
-
|
|
277
|
-
// and initial size of undefined (when mounting)
|
|
278
|
-
if (!prevSize && nextSize !== 0) {
|
|
282
|
+
if ((lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
279
283
|
onCollapse(false);
|
|
280
|
-
} else if (
|
|
284
|
+
} else if (lastNotifiedSize !== collapsedSize && size === collapsedSize) {
|
|
281
285
|
onCollapse(true);
|
|
282
286
|
}
|
|
283
287
|
}
|
|
@@ -369,11 +373,17 @@ function panelsMapToSortedArray(panels) {
|
|
|
369
373
|
}
|
|
370
374
|
function safeResizePanel(panel, delta, prevSize, event) {
|
|
371
375
|
const nextSizeUnsafe = prevSize + delta;
|
|
372
|
-
|
|
373
|
-
|
|
376
|
+
const {
|
|
377
|
+
collapsedSize,
|
|
378
|
+
collapsible,
|
|
379
|
+
maxSize,
|
|
380
|
+
minSize
|
|
381
|
+
} = panel.current;
|
|
382
|
+
if (collapsible) {
|
|
383
|
+
if (prevSize > collapsedSize) {
|
|
374
384
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
375
|
-
if (nextSizeUnsafe <=
|
|
376
|
-
return
|
|
385
|
+
if (nextSizeUnsafe <= minSize / 2 + collapsedSize) {
|
|
386
|
+
return collapsedSize;
|
|
377
387
|
}
|
|
378
388
|
} else {
|
|
379
389
|
const isKeyboardEvent = event?.type?.startsWith("key");
|
|
@@ -381,13 +391,13 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
381
391
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
382
392
|
// but mouse events should wait until the panel has reached its min size
|
|
383
393
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
384
|
-
if (nextSizeUnsafe <
|
|
385
|
-
return
|
|
394
|
+
if (nextSizeUnsafe < minSize) {
|
|
395
|
+
return collapsedSize;
|
|
386
396
|
}
|
|
387
397
|
}
|
|
388
398
|
}
|
|
389
399
|
}
|
|
390
|
-
const nextSize = Math.min(
|
|
400
|
+
const nextSize = Math.min(maxSize, Math.max(minSize, nextSizeUnsafe));
|
|
391
401
|
return nextSize;
|
|
392
402
|
}
|
|
393
403
|
|
|
@@ -820,6 +830,7 @@ function PanelGroupWithForwardedRef({
|
|
|
820
830
|
useEffect(() => {
|
|
821
831
|
callbacksRef.current.onLayout = onLayout;
|
|
822
832
|
});
|
|
833
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
823
834
|
|
|
824
835
|
// 0-1 values representing the relative size of each panel.
|
|
825
836
|
const [sizes, setSizes] = useState([]);
|
|
@@ -844,7 +855,13 @@ function PanelGroupWithForwardedRef({
|
|
|
844
855
|
setLayout: sizes => {
|
|
845
856
|
const total = sizes.reduce((accumulated, current) => accumulated + current, 0);
|
|
846
857
|
assert(total === 100, "Panel sizes must add up to 100%");
|
|
858
|
+
const {
|
|
859
|
+
panels
|
|
860
|
+
} = committedValuesRef.current;
|
|
861
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
862
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
847
863
|
setSizes(sizes);
|
|
864
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
848
865
|
}
|
|
849
866
|
}), []);
|
|
850
867
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -866,33 +883,25 @@ function PanelGroupWithForwardedRef({
|
|
|
866
883
|
const {
|
|
867
884
|
onLayout
|
|
868
885
|
} = callbacksRef.current;
|
|
869
|
-
if (onLayout) {
|
|
870
|
-
const {
|
|
871
|
-
sizes
|
|
872
|
-
} = committedValuesRef.current;
|
|
873
|
-
|
|
874
|
-
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
875
|
-
if (sizes.length > 0) {
|
|
876
|
-
onLayout(sizes);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
}, [sizes]);
|
|
880
|
-
|
|
881
|
-
// Notify Panel listeners about their initial sizes and collapsed state after mount.
|
|
882
|
-
// Subsequent changes will be called by the resizeHandler.
|
|
883
|
-
const didNotifyCallbacksAfterMountRef = useRef(false);
|
|
884
|
-
useIsomorphicLayoutEffect(() => {
|
|
885
|
-
if (didNotifyCallbacksAfterMountRef.current) {
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
886
|
const {
|
|
889
887
|
panels,
|
|
890
888
|
sizes
|
|
891
889
|
} = committedValuesRef.current;
|
|
890
|
+
|
|
891
|
+
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
892
892
|
if (sizes.length > 0) {
|
|
893
|
-
|
|
893
|
+
if (onLayout) {
|
|
894
|
+
onLayout(sizes);
|
|
895
|
+
}
|
|
896
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
897
|
+
|
|
898
|
+
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
899
|
+
// Some cases are difficult to detect though,
|
|
900
|
+
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
901
|
+
// In this case, the best we can do is notify on commit.
|
|
902
|
+
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
894
903
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
895
|
-
callPanelCallbacks(panelsArray,
|
|
904
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
896
905
|
}
|
|
897
906
|
}, [sizes]);
|
|
898
907
|
|
|
@@ -1061,9 +1070,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1061
1070
|
}
|
|
1062
1071
|
}
|
|
1063
1072
|
if (sizesChanged) {
|
|
1064
|
-
|
|
1065
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1073
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1066
1074
|
setSizes(nextSizes);
|
|
1075
|
+
|
|
1076
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1077
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1078
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1067
1079
|
}
|
|
1068
1080
|
prevDeltaRef.current = delta;
|
|
1069
1081
|
};
|
|
@@ -1085,7 +1097,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1085
1097
|
sizes: prevSizes
|
|
1086
1098
|
} = committedValuesRef.current;
|
|
1087
1099
|
const panel = panels.get(id);
|
|
1088
|
-
if (panel == null
|
|
1100
|
+
if (panel == null) {
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
const {
|
|
1104
|
+
collapsedSize,
|
|
1105
|
+
collapsible
|
|
1106
|
+
} = panel.current;
|
|
1107
|
+
if (!collapsible) {
|
|
1089
1108
|
return;
|
|
1090
1109
|
}
|
|
1091
1110
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
@@ -1094,7 +1113,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1094
1113
|
return;
|
|
1095
1114
|
}
|
|
1096
1115
|
const currentSize = prevSizes[index];
|
|
1097
|
-
if (currentSize ===
|
|
1116
|
+
if (currentSize === collapsedSize) {
|
|
1098
1117
|
// Panel is already collapsed.
|
|
1099
1118
|
return;
|
|
1100
1119
|
}
|
|
@@ -1104,12 +1123,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1104
1123
|
return;
|
|
1105
1124
|
}
|
|
1106
1125
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1107
|
-
const delta = isLastPanel ? currentSize :
|
|
1126
|
+
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1108
1127
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1109
1128
|
if (prevSizes !== nextSizes) {
|
|
1110
|
-
|
|
1111
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1129
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1112
1130
|
setSizes(nextSizes);
|
|
1131
|
+
|
|
1132
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1133
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1134
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1113
1135
|
}
|
|
1114
1136
|
}, []);
|
|
1115
1137
|
const expandPanel = useCallback(id => {
|
|
@@ -1121,7 +1143,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1121
1143
|
if (panel == null) {
|
|
1122
1144
|
return;
|
|
1123
1145
|
}
|
|
1124
|
-
const
|
|
1146
|
+
const {
|
|
1147
|
+
collapsedSize,
|
|
1148
|
+
minSize
|
|
1149
|
+
} = panel.current;
|
|
1150
|
+
const sizeBeforeCollapse = panelSizeBeforeCollapse.current.get(id) || minSize;
|
|
1125
1151
|
if (!sizeBeforeCollapse) {
|
|
1126
1152
|
return;
|
|
1127
1153
|
}
|
|
@@ -1131,7 +1157,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1131
1157
|
return;
|
|
1132
1158
|
}
|
|
1133
1159
|
const currentSize = prevSizes[index];
|
|
1134
|
-
if (currentSize !==
|
|
1160
|
+
if (currentSize !== collapsedSize) {
|
|
1135
1161
|
// Panel is already expanded.
|
|
1136
1162
|
return;
|
|
1137
1163
|
}
|
|
@@ -1140,12 +1166,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1140
1166
|
return;
|
|
1141
1167
|
}
|
|
1142
1168
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1143
|
-
const delta = isLastPanel ?
|
|
1169
|
+
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1144
1170
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1145
1171
|
if (prevSizes !== nextSizes) {
|
|
1146
|
-
|
|
1147
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1172
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1148
1173
|
setSizes(nextSizes);
|
|
1174
|
+
|
|
1175
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1176
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1177
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1149
1178
|
}
|
|
1150
1179
|
}, []);
|
|
1151
1180
|
const resizePanel = useCallback((id, nextSize) => {
|
|
@@ -1157,6 +1186,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1157
1186
|
if (panel == null) {
|
|
1158
1187
|
return;
|
|
1159
1188
|
}
|
|
1189
|
+
const {
|
|
1190
|
+
collapsedSize,
|
|
1191
|
+
collapsible,
|
|
1192
|
+
maxSize,
|
|
1193
|
+
minSize
|
|
1194
|
+
} = panel.current;
|
|
1160
1195
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1161
1196
|
const index = panelsArray.indexOf(panel);
|
|
1162
1197
|
if (index < 0) {
|
|
@@ -1166,8 +1201,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1166
1201
|
if (currentSize === nextSize) {
|
|
1167
1202
|
return;
|
|
1168
1203
|
}
|
|
1169
|
-
if (
|
|
1170
|
-
nextSize = Math.min(
|
|
1204
|
+
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1205
|
+
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1171
1206
|
}
|
|
1172
1207
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1173
1208
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1177,9 +1212,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1177
1212
|
const delta = isLastPanel ? currentSize - nextSize : nextSize - currentSize;
|
|
1178
1213
|
const nextSizes = adjustByDelta(null, panels, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1179
1214
|
if (prevSizes !== nextSizes) {
|
|
1180
|
-
|
|
1181
|
-
callPanelCallbacks(panelsArray, prevSizes, nextSizes);
|
|
1215
|
+
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1182
1216
|
setSizes(nextSizes);
|
|
1217
|
+
|
|
1218
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
1219
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
1220
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1183
1221
|
}
|
|
1184
1222
|
}, []);
|
|
1185
1223
|
const context = useMemo(() => ({
|