react-resizable-panels 0.0.58 → 0.0.60
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 +12 -0
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +189 -98
- package/dist/react-resizable-panels.browser.development.cjs.js +192 -101
- package/dist/react-resizable-panels.browser.development.esm.js +192 -101
- package/dist/react-resizable-panels.browser.esm.js +189 -98
- package/dist/react-resizable-panels.cjs.js +189 -98
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +192 -101
- package/dist/react-resizable-panels.development.esm.js +192 -101
- package/dist/react-resizable-panels.development.node.cjs.js +237 -49
- package/dist/react-resizable-panels.development.node.esm.js +237 -49
- package/dist/react-resizable-panels.esm.js +189 -98
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +234 -46
- package/dist/react-resizable-panels.node.esm.js +234 -46
- package/package.json +1 -1
- package/src/Panel.ts +2 -0
- package/src/PanelGroup.ts +221 -97
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +15 -15
- package/src/utils/dom/getPanelElementsForGroup.ts +5 -0
|
@@ -91,6 +91,7 @@ function PanelWithForwardedRef({
|
|
|
91
91
|
expandPanel,
|
|
92
92
|
getPanelSize,
|
|
93
93
|
getPanelStyle,
|
|
94
|
+
groupId,
|
|
94
95
|
isPanelCollapsed,
|
|
95
96
|
registerPanel,
|
|
96
97
|
resizePanel,
|
|
@@ -156,6 +157,7 @@ function PanelWithForwardedRef({
|
|
|
156
157
|
// CSS selectors
|
|
157
158
|
"data-panel": "",
|
|
158
159
|
"data-panel-id": panelId,
|
|
160
|
+
"data-panel-group-id": groupId,
|
|
159
161
|
// e2e test attributes
|
|
160
162
|
"data-panel-collapsible": undefined,
|
|
161
163
|
"data-panel-size": undefined
|
|
@@ -168,8 +170,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
168
170
|
PanelWithForwardedRef.displayName = "Panel";
|
|
169
171
|
Panel.displayName = "forwardRef(Panel)";
|
|
170
172
|
|
|
171
|
-
const PRECISION = 10;
|
|
172
|
-
|
|
173
173
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
174
174
|
return pixels / groupSizePixels * 100;
|
|
175
175
|
}
|
|
@@ -247,6 +247,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
247
247
|
};
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
const PRECISION = 10;
|
|
251
|
+
|
|
250
252
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
251
253
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
252
254
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -640,15 +642,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
640
642
|
});
|
|
641
643
|
useEffect(() => {
|
|
642
644
|
const {
|
|
643
|
-
direction,
|
|
644
645
|
panelDataArray
|
|
645
646
|
} = committedValuesRef.current;
|
|
646
647
|
const groupElement = getPanelGroupElement(groupId);
|
|
647
648
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
648
|
-
const {
|
|
649
|
-
height,
|
|
650
|
-
width
|
|
651
|
-
} = groupElement.getBoundingClientRect();
|
|
652
649
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
653
650
|
const cleanupFunctions = handles.map(handle => {
|
|
654
651
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -668,21 +665,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
668
665
|
if (index >= 0) {
|
|
669
666
|
const panelData = panelDataArray[index];
|
|
670
667
|
const size = layout[index];
|
|
671
|
-
if (size != null) {
|
|
672
|
-
var _getPercentageSizeFro;
|
|
668
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
669
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
673
670
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
674
|
-
const
|
|
671
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
672
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
673
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
674
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
675
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
675
676
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
676
677
|
sizePixels: panelData.constraints.minSizePixels
|
|
677
|
-
}, groupSizePixels)) !== null &&
|
|
678
|
-
let delta = 0;
|
|
679
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
680
|
-
delta = direction === "horizontal" ? width : height;
|
|
681
|
-
} else {
|
|
682
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
683
|
-
}
|
|
678
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
684
679
|
const nextLayout = adjustLayoutByDelta({
|
|
685
|
-
delta,
|
|
680
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
686
681
|
groupSizePixels,
|
|
687
682
|
layout,
|
|
688
683
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -803,6 +798,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
803
798
|
}
|
|
804
799
|
}
|
|
805
800
|
|
|
801
|
+
function calculateUnsafeDefaultLayout({
|
|
802
|
+
groupSizePixels,
|
|
803
|
+
panelDataArray
|
|
804
|
+
}) {
|
|
805
|
+
const layout = Array(panelDataArray.length);
|
|
806
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
807
|
+
let numPanelsWithSizes = 0;
|
|
808
|
+
let remainingSize = 100;
|
|
809
|
+
|
|
810
|
+
// Distribute default sizes first
|
|
811
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
812
|
+
const {
|
|
813
|
+
defaultSizePercentage
|
|
814
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
815
|
+
if (defaultSizePercentage != null) {
|
|
816
|
+
numPanelsWithSizes++;
|
|
817
|
+
layout[index] = defaultSizePercentage;
|
|
818
|
+
remainingSize -= defaultSizePercentage;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
823
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
824
|
+
const {
|
|
825
|
+
defaultSizePercentage
|
|
826
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
827
|
+
if (defaultSizePercentage != null) {
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
831
|
+
const size = remainingSize / numRemainingPanels;
|
|
832
|
+
numPanelsWithSizes++;
|
|
833
|
+
layout[index] = size;
|
|
834
|
+
remainingSize -= size;
|
|
835
|
+
}
|
|
836
|
+
return layout;
|
|
837
|
+
}
|
|
838
|
+
|
|
806
839
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
807
840
|
return percentage / 100 * groupSizePixels;
|
|
808
841
|
}
|
|
@@ -953,6 +986,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
953
986
|
return callable;
|
|
954
987
|
}
|
|
955
988
|
|
|
989
|
+
function getPanelElementsForGroup(groupId) {
|
|
990
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
991
|
+
}
|
|
992
|
+
|
|
956
993
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
957
994
|
// or on a browser with cookies/storage disabled.
|
|
958
995
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1008,6 +1045,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
1008
1045
|
} catch (error) {}
|
|
1009
1046
|
return null;
|
|
1010
1047
|
}
|
|
1048
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1049
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1050
|
+
if (state) {
|
|
1051
|
+
var _state$key;
|
|
1052
|
+
const key = getSerializationKey(panels);
|
|
1053
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1054
|
+
}
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1011
1057
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
1012
1058
|
const key = getSerializationKey(panels);
|
|
1013
1059
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -1019,6 +1065,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1019
1065
|
}
|
|
1020
1066
|
}
|
|
1021
1067
|
|
|
1068
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1069
|
+
return constraints.some(constraints => {
|
|
1070
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1022
1074
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1023
1075
|
function validatePanelGroupLayout({
|
|
1024
1076
|
groupSizePixels,
|
|
@@ -1087,7 +1139,7 @@ const defaultStorage = {
|
|
|
1087
1139
|
};
|
|
1088
1140
|
const debounceMap = {};
|
|
1089
1141
|
function PanelGroupWithForwardedRef({
|
|
1090
|
-
autoSaveId,
|
|
1142
|
+
autoSaveId = null,
|
|
1091
1143
|
children,
|
|
1092
1144
|
className: classNameFromProps = "",
|
|
1093
1145
|
dataAttributes,
|
|
@@ -1104,11 +1156,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1104
1156
|
const groupId = useUniqueId(idFromProps);
|
|
1105
1157
|
const [dragState, setDragState] = useState(null);
|
|
1106
1158
|
const [layout, setLayout] = useState([]);
|
|
1107
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1108
1159
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1109
1160
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1110
1161
|
const prevDeltaRef = useRef(0);
|
|
1111
1162
|
const committedValuesRef = useRef({
|
|
1163
|
+
autoSaveId,
|
|
1112
1164
|
direction,
|
|
1113
1165
|
dragState,
|
|
1114
1166
|
id: groupId,
|
|
@@ -1116,7 +1168,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1116
1168
|
keyboardResizeByPixels,
|
|
1117
1169
|
layout,
|
|
1118
1170
|
onLayout,
|
|
1119
|
-
panelDataArray
|
|
1171
|
+
panelDataArray: [],
|
|
1172
|
+
storage
|
|
1120
1173
|
});
|
|
1121
1174
|
useRef({
|
|
1122
1175
|
didLogIdAndOrderWarning: false,
|
|
@@ -1154,6 +1207,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1154
1207
|
});
|
|
1155
1208
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1156
1209
|
setLayout(safeLayout);
|
|
1210
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1157
1211
|
if (onLayout) {
|
|
1158
1212
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1159
1213
|
sizePercentage,
|
|
@@ -1164,14 +1218,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1164
1218
|
}
|
|
1165
1219
|
}
|
|
1166
1220
|
}), []);
|
|
1221
|
+
|
|
1167
1222
|
useWindowSplitterPanelGroupBehavior({
|
|
1168
1223
|
committedValuesRef,
|
|
1169
1224
|
groupId,
|
|
1170
1225
|
layout,
|
|
1171
|
-
panelDataArray,
|
|
1226
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1172
1227
|
setLayout
|
|
1173
1228
|
});
|
|
1174
1229
|
useEffect(() => {
|
|
1230
|
+
const {
|
|
1231
|
+
panelDataArray
|
|
1232
|
+
} = committedValuesRef.current;
|
|
1233
|
+
|
|
1175
1234
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1176
1235
|
if (autoSaveId) {
|
|
1177
1236
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1184,7 +1243,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1184
1243
|
}
|
|
1185
1244
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1186
1245
|
}
|
|
1187
|
-
}, [autoSaveId, layout,
|
|
1246
|
+
}, [autoSaveId, layout, storage]);
|
|
1188
1247
|
|
|
1189
1248
|
// DEV warnings
|
|
1190
1249
|
useEffect(() => {
|
|
@@ -1221,6 +1280,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1221
1280
|
});
|
|
1222
1281
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1223
1282
|
setLayout(nextLayout);
|
|
1283
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1224
1284
|
if (onLayout) {
|
|
1225
1285
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1226
1286
|
sizePercentage,
|
|
@@ -1265,6 +1325,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1265
1325
|
});
|
|
1266
1326
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1267
1327
|
setLayout(nextLayout);
|
|
1328
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1268
1329
|
if (onLayout) {
|
|
1269
1330
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1270
1331
|
sizePercentage,
|
|
@@ -1295,6 +1356,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1295
1356
|
|
|
1296
1357
|
// This API should never read from committedValuesRef
|
|
1297
1358
|
const getPanelStyle = useCallback(panelData => {
|
|
1359
|
+
const {
|
|
1360
|
+
panelDataArray
|
|
1361
|
+
} = committedValuesRef.current;
|
|
1298
1362
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1299
1363
|
return computePanelFlexBoxStyle({
|
|
1300
1364
|
dragState,
|
|
@@ -1302,7 +1366,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1302
1366
|
panelData: panelDataArray,
|
|
1303
1367
|
panelIndex
|
|
1304
1368
|
});
|
|
1305
|
-
}, [dragState, layout
|
|
1369
|
+
}, [dragState, layout]);
|
|
1306
1370
|
|
|
1307
1371
|
// External APIs are safe to memoize via committed values ref
|
|
1308
1372
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1332,22 +1396,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1332
1396
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1333
1397
|
}, [groupId]);
|
|
1334
1398
|
const registerPanel = useCallback(panelData => {
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1399
|
+
const {
|
|
1400
|
+
autoSaveId,
|
|
1401
|
+
id: groupId,
|
|
1402
|
+
layout: prevLayout,
|
|
1403
|
+
onLayout,
|
|
1404
|
+
panelDataArray,
|
|
1405
|
+
storage
|
|
1406
|
+
} = committedValuesRef.current;
|
|
1407
|
+
panelDataArray.push(panelData);
|
|
1408
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1409
|
+
const orderA = panelA.order;
|
|
1410
|
+
const orderB = panelB.order;
|
|
1411
|
+
if (orderA == null && orderB == null) {
|
|
1412
|
+
return 0;
|
|
1413
|
+
} else if (orderA == null) {
|
|
1414
|
+
return -1;
|
|
1415
|
+
} else if (orderB == null) {
|
|
1416
|
+
return 1;
|
|
1417
|
+
} else {
|
|
1418
|
+
return orderA - orderB;
|
|
1419
|
+
}
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1423
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1424
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1425
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
// If this panel has been configured to persist sizing information,
|
|
1430
|
+
// default size should be restored from local storage if possible.
|
|
1431
|
+
let unsafeLayout = null;
|
|
1432
|
+
if (autoSaveId) {
|
|
1433
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1434
|
+
}
|
|
1435
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1436
|
+
if (groupSizePixels <= 0) {
|
|
1437
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1438
|
+
constraints
|
|
1439
|
+
}) => constraints))) {
|
|
1440
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
if (unsafeLayout == null) {
|
|
1445
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1446
|
+
groupSizePixels,
|
|
1447
|
+
panelDataArray
|
|
1349
1448
|
});
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1452
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1453
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1454
|
+
groupSizePixels,
|
|
1455
|
+
layout: unsafeLayout,
|
|
1456
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1350
1457
|
});
|
|
1458
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1459
|
+
setLayout(nextLayout);
|
|
1460
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1461
|
+
if (onLayout) {
|
|
1462
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1463
|
+
sizePercentage,
|
|
1464
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1465
|
+
})));
|
|
1466
|
+
}
|
|
1467
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1468
|
+
}
|
|
1351
1469
|
}, []);
|
|
1352
1470
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1353
1471
|
return function resizeHandler(event) {
|
|
@@ -1417,6 +1535,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1417
1535
|
}
|
|
1418
1536
|
if (layoutChanged) {
|
|
1419
1537
|
setLayout(nextLayout);
|
|
1538
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1420
1539
|
if (onLayout) {
|
|
1421
1540
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1422
1541
|
sizePercentage,
|
|
@@ -1454,6 +1573,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1454
1573
|
});
|
|
1455
1574
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1456
1575
|
setLayout(nextLayout);
|
|
1576
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1457
1577
|
if (onLayout) {
|
|
1458
1578
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1459
1579
|
sizePercentage,
|
|
@@ -1481,16 +1601,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1481
1601
|
resetGlobalCursorStyle();
|
|
1482
1602
|
setDragState(null);
|
|
1483
1603
|
}, []);
|
|
1604
|
+
const unregisterPanelRef = useRef({
|
|
1605
|
+
pendingPanelIds: new Set(),
|
|
1606
|
+
timeout: null
|
|
1607
|
+
});
|
|
1484
1608
|
const unregisterPanel = useCallback(panelData => {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1609
|
+
const {
|
|
1610
|
+
id: groupId,
|
|
1611
|
+
layout: prevLayout,
|
|
1612
|
+
onLayout,
|
|
1613
|
+
panelDataArray
|
|
1614
|
+
} = committedValuesRef.current;
|
|
1615
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1616
|
+
if (index >= 0) {
|
|
1617
|
+
panelDataArray.splice(index, 1);
|
|
1618
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1619
|
+
}
|
|
1620
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1621
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1625
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1626
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1627
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1628
|
+
const {
|
|
1629
|
+
pendingPanelIds
|
|
1630
|
+
} = unregisterPanelRef.current;
|
|
1631
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1632
|
+
|
|
1633
|
+
// TRICKY
|
|
1634
|
+
// Strict effects mode
|
|
1635
|
+
let unmountDueToStrictMode = false;
|
|
1636
|
+
pendingPanelIds.forEach(panelId => {
|
|
1637
|
+
pendingPanelIds.delete(panelId);
|
|
1638
|
+
if (panelDataArray.find(({
|
|
1639
|
+
id
|
|
1640
|
+
}) => id === panelId) == null) {
|
|
1641
|
+
unmountDueToStrictMode = true;
|
|
1642
|
+
|
|
1643
|
+
// TRICKY
|
|
1644
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1645
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1646
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1647
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1648
|
+
}
|
|
1649
|
+
});
|
|
1650
|
+
if (!unmountDueToStrictMode) {
|
|
1651
|
+
return;
|
|
1491
1652
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1653
|
+
if (panelDataArray.length === 0) {
|
|
1654
|
+
// The group is unmounting; skip layout calculation.
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1658
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1659
|
+
groupSizePixels,
|
|
1660
|
+
panelDataArray
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1664
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1665
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1666
|
+
groupSizePixels,
|
|
1667
|
+
layout: unsafeLayout,
|
|
1668
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1669
|
+
});
|
|
1670
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1671
|
+
setLayout(nextLayout);
|
|
1672
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1673
|
+
if (onLayout) {
|
|
1674
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1675
|
+
sizePercentage,
|
|
1676
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1677
|
+
})));
|
|
1678
|
+
}
|
|
1679
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1680
|
+
}
|
|
1681
|
+
}, 0);
|
|
1494
1682
|
}, []);
|
|
1495
1683
|
const context = useMemo(() => ({
|
|
1496
1684
|
collapsePanel,
|