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
|
@@ -67,6 +67,7 @@ function PanelWithForwardedRef({
|
|
|
67
67
|
expandPanel,
|
|
68
68
|
getPanelSize,
|
|
69
69
|
getPanelStyle,
|
|
70
|
+
groupId,
|
|
70
71
|
isPanelCollapsed,
|
|
71
72
|
registerPanel,
|
|
72
73
|
resizePanel,
|
|
@@ -143,6 +144,7 @@ function PanelWithForwardedRef({
|
|
|
143
144
|
// CSS selectors
|
|
144
145
|
"data-panel": "",
|
|
145
146
|
"data-panel-id": panelId,
|
|
147
|
+
"data-panel-group-id": groupId,
|
|
146
148
|
// e2e test attributes
|
|
147
149
|
"data-panel-collapsible": collapsible || undefined ,
|
|
148
150
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -155,8 +157,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
155
157
|
PanelWithForwardedRef.displayName = "Panel";
|
|
156
158
|
Panel.displayName = "forwardRef(Panel)";
|
|
157
159
|
|
|
158
|
-
const PRECISION = 10;
|
|
159
|
-
|
|
160
160
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
161
161
|
return pixels / groupSizePixels * 100;
|
|
162
162
|
}
|
|
@@ -234,6 +234,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
const PRECISION = 10;
|
|
238
|
+
|
|
237
239
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
238
240
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
239
241
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -627,15 +629,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
627
629
|
});
|
|
628
630
|
useEffect(() => {
|
|
629
631
|
const {
|
|
630
|
-
direction,
|
|
631
632
|
panelDataArray
|
|
632
633
|
} = committedValuesRef.current;
|
|
633
634
|
const groupElement = getPanelGroupElement(groupId);
|
|
634
635
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
635
|
-
const {
|
|
636
|
-
height,
|
|
637
|
-
width
|
|
638
|
-
} = groupElement.getBoundingClientRect();
|
|
639
636
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
640
637
|
const cleanupFunctions = handles.map(handle => {
|
|
641
638
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -655,21 +652,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
655
652
|
if (index >= 0) {
|
|
656
653
|
const panelData = panelDataArray[index];
|
|
657
654
|
const size = layout[index];
|
|
658
|
-
if (size != null) {
|
|
659
|
-
var _getPercentageSizeFro;
|
|
655
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
656
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
660
657
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
661
|
-
const
|
|
658
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
659
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
660
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
661
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
662
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
662
663
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
663
664
|
sizePixels: panelData.constraints.minSizePixels
|
|
664
|
-
}, groupSizePixels)) !== null &&
|
|
665
|
-
let delta = 0;
|
|
666
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
667
|
-
delta = direction === "horizontal" ? width : height;
|
|
668
|
-
} else {
|
|
669
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
670
|
-
}
|
|
665
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
671
666
|
const nextLayout = adjustLayoutByDelta({
|
|
672
|
-
delta,
|
|
667
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
673
668
|
groupSizePixels,
|
|
674
669
|
layout,
|
|
675
670
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -790,6 +785,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
790
785
|
}
|
|
791
786
|
}
|
|
792
787
|
|
|
788
|
+
function calculateUnsafeDefaultLayout({
|
|
789
|
+
groupSizePixels,
|
|
790
|
+
panelDataArray
|
|
791
|
+
}) {
|
|
792
|
+
const layout = Array(panelDataArray.length);
|
|
793
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
794
|
+
let numPanelsWithSizes = 0;
|
|
795
|
+
let remainingSize = 100;
|
|
796
|
+
|
|
797
|
+
// Distribute default sizes first
|
|
798
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
799
|
+
const {
|
|
800
|
+
defaultSizePercentage
|
|
801
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
802
|
+
if (defaultSizePercentage != null) {
|
|
803
|
+
numPanelsWithSizes++;
|
|
804
|
+
layout[index] = defaultSizePercentage;
|
|
805
|
+
remainingSize -= defaultSizePercentage;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
810
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
811
|
+
const {
|
|
812
|
+
defaultSizePercentage
|
|
813
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
814
|
+
if (defaultSizePercentage != null) {
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
818
|
+
const size = remainingSize / numRemainingPanels;
|
|
819
|
+
numPanelsWithSizes++;
|
|
820
|
+
layout[index] = size;
|
|
821
|
+
remainingSize -= size;
|
|
822
|
+
}
|
|
823
|
+
return layout;
|
|
824
|
+
}
|
|
825
|
+
|
|
793
826
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
794
827
|
return percentage / 100 * groupSizePixels;
|
|
795
828
|
}
|
|
@@ -940,6 +973,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
940
973
|
return callable;
|
|
941
974
|
}
|
|
942
975
|
|
|
976
|
+
function getPanelElementsForGroup(groupId) {
|
|
977
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
978
|
+
}
|
|
979
|
+
|
|
943
980
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
944
981
|
// or on a browser with cookies/storage disabled.
|
|
945
982
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -995,6 +1032,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
995
1032
|
} catch (error) {}
|
|
996
1033
|
return null;
|
|
997
1034
|
}
|
|
1035
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1036
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1037
|
+
if (state) {
|
|
1038
|
+
var _state$key;
|
|
1039
|
+
const key = getSerializationKey(panels);
|
|
1040
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1041
|
+
}
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
998
1044
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
999
1045
|
const key = getSerializationKey(panels);
|
|
1000
1046
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -1006,6 +1052,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1006
1052
|
}
|
|
1007
1053
|
}
|
|
1008
1054
|
|
|
1055
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1056
|
+
return constraints.some(constraints => {
|
|
1057
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1009
1061
|
function validatePanelConstraints({
|
|
1010
1062
|
groupSizePixels,
|
|
1011
1063
|
panelConstraints,
|
|
@@ -1151,7 +1203,7 @@ const defaultStorage = {
|
|
|
1151
1203
|
};
|
|
1152
1204
|
const debounceMap = {};
|
|
1153
1205
|
function PanelGroupWithForwardedRef({
|
|
1154
|
-
autoSaveId,
|
|
1206
|
+
autoSaveId = null,
|
|
1155
1207
|
children,
|
|
1156
1208
|
className: classNameFromProps = "",
|
|
1157
1209
|
dataAttributes,
|
|
@@ -1168,11 +1220,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1168
1220
|
const groupId = useUniqueId(idFromProps);
|
|
1169
1221
|
const [dragState, setDragState] = useState(null);
|
|
1170
1222
|
const [layout, setLayout] = useState([]);
|
|
1171
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1172
1223
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1173
1224
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1174
1225
|
const prevDeltaRef = useRef(0);
|
|
1175
1226
|
const committedValuesRef = useRef({
|
|
1227
|
+
autoSaveId,
|
|
1176
1228
|
direction,
|
|
1177
1229
|
dragState,
|
|
1178
1230
|
id: groupId,
|
|
@@ -1180,7 +1232,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1180
1232
|
keyboardResizeByPixels,
|
|
1181
1233
|
layout,
|
|
1182
1234
|
onLayout,
|
|
1183
|
-
panelDataArray
|
|
1235
|
+
panelDataArray: [],
|
|
1236
|
+
storage
|
|
1184
1237
|
});
|
|
1185
1238
|
const devWarningsRef = useRef({
|
|
1186
1239
|
didLogIdAndOrderWarning: false,
|
|
@@ -1218,6 +1271,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1218
1271
|
});
|
|
1219
1272
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1220
1273
|
setLayout(safeLayout);
|
|
1274
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1221
1275
|
if (onLayout) {
|
|
1222
1276
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1223
1277
|
sizePercentage,
|
|
@@ -1228,14 +1282,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1228
1282
|
}
|
|
1229
1283
|
}
|
|
1230
1284
|
}), []);
|
|
1285
|
+
|
|
1231
1286
|
useWindowSplitterPanelGroupBehavior({
|
|
1232
1287
|
committedValuesRef,
|
|
1233
1288
|
groupId,
|
|
1234
1289
|
layout,
|
|
1235
|
-
panelDataArray,
|
|
1290
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1236
1291
|
setLayout
|
|
1237
1292
|
});
|
|
1238
1293
|
useEffect(() => {
|
|
1294
|
+
const {
|
|
1295
|
+
panelDataArray
|
|
1296
|
+
} = committedValuesRef.current;
|
|
1297
|
+
|
|
1239
1298
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1240
1299
|
if (autoSaveId) {
|
|
1241
1300
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1248,20 +1307,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1248
1307
|
}
|
|
1249
1308
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1250
1309
|
}
|
|
1251
|
-
}, [autoSaveId, layout,
|
|
1310
|
+
}, [autoSaveId, layout, storage]);
|
|
1252
1311
|
|
|
1253
1312
|
// DEV warnings
|
|
1254
1313
|
useEffect(() => {
|
|
1255
1314
|
{
|
|
1315
|
+
const {
|
|
1316
|
+
panelDataArray
|
|
1317
|
+
} = committedValuesRef.current;
|
|
1256
1318
|
const {
|
|
1257
1319
|
didLogIdAndOrderWarning,
|
|
1258
1320
|
didLogPanelConstraintsWarning,
|
|
1259
1321
|
prevPanelIds
|
|
1260
1322
|
} = devWarningsRef.current;
|
|
1261
1323
|
if (!didLogIdAndOrderWarning) {
|
|
1262
|
-
const {
|
|
1263
|
-
panelDataArray
|
|
1264
|
-
} = committedValuesRef.current;
|
|
1265
1324
|
const panelIds = panelDataArray.map(({
|
|
1266
1325
|
id
|
|
1267
1326
|
}) => id);
|
|
@@ -1327,6 +1386,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1327
1386
|
});
|
|
1328
1387
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1329
1388
|
setLayout(nextLayout);
|
|
1389
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1330
1390
|
if (onLayout) {
|
|
1331
1391
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1332
1392
|
sizePercentage,
|
|
@@ -1371,6 +1431,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1371
1431
|
});
|
|
1372
1432
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1373
1433
|
setLayout(nextLayout);
|
|
1434
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1374
1435
|
if (onLayout) {
|
|
1375
1436
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1376
1437
|
sizePercentage,
|
|
@@ -1401,6 +1462,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1401
1462
|
|
|
1402
1463
|
// This API should never read from committedValuesRef
|
|
1403
1464
|
const getPanelStyle = useCallback(panelData => {
|
|
1465
|
+
const {
|
|
1466
|
+
panelDataArray
|
|
1467
|
+
} = committedValuesRef.current;
|
|
1404
1468
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1405
1469
|
return computePanelFlexBoxStyle({
|
|
1406
1470
|
dragState,
|
|
@@ -1408,7 +1472,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1408
1472
|
panelData: panelDataArray,
|
|
1409
1473
|
panelIndex
|
|
1410
1474
|
});
|
|
1411
|
-
}, [dragState, layout
|
|
1475
|
+
}, [dragState, layout]);
|
|
1412
1476
|
|
|
1413
1477
|
// External APIs are safe to memoize via committed values ref
|
|
1414
1478
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1438,22 +1502,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1438
1502
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1439
1503
|
}, [groupId]);
|
|
1440
1504
|
const registerPanel = useCallback(panelData => {
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1505
|
+
const {
|
|
1506
|
+
autoSaveId,
|
|
1507
|
+
id: groupId,
|
|
1508
|
+
layout: prevLayout,
|
|
1509
|
+
onLayout,
|
|
1510
|
+
panelDataArray,
|
|
1511
|
+
storage
|
|
1512
|
+
} = committedValuesRef.current;
|
|
1513
|
+
panelDataArray.push(panelData);
|
|
1514
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1515
|
+
const orderA = panelA.order;
|
|
1516
|
+
const orderB = panelB.order;
|
|
1517
|
+
if (orderA == null && orderB == null) {
|
|
1518
|
+
return 0;
|
|
1519
|
+
} else if (orderA == null) {
|
|
1520
|
+
return -1;
|
|
1521
|
+
} else if (orderB == null) {
|
|
1522
|
+
return 1;
|
|
1523
|
+
} else {
|
|
1524
|
+
return orderA - orderB;
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
|
|
1528
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1529
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1530
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1531
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// If this panel has been configured to persist sizing information,
|
|
1536
|
+
// default size should be restored from local storage if possible.
|
|
1537
|
+
let unsafeLayout = null;
|
|
1538
|
+
if (autoSaveId) {
|
|
1539
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1540
|
+
}
|
|
1541
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1542
|
+
if (groupSizePixels <= 0) {
|
|
1543
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1544
|
+
constraints
|
|
1545
|
+
}) => constraints))) {
|
|
1546
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1547
|
+
return;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
if (unsafeLayout == null) {
|
|
1551
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1552
|
+
groupSizePixels,
|
|
1553
|
+
panelDataArray
|
|
1455
1554
|
});
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1558
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1559
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1560
|
+
groupSizePixels,
|
|
1561
|
+
layout: unsafeLayout,
|
|
1562
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1456
1563
|
});
|
|
1564
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1565
|
+
setLayout(nextLayout);
|
|
1566
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1567
|
+
if (onLayout) {
|
|
1568
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1569
|
+
sizePercentage,
|
|
1570
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1571
|
+
})));
|
|
1572
|
+
}
|
|
1573
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1574
|
+
}
|
|
1457
1575
|
}, []);
|
|
1458
1576
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1459
1577
|
return function resizeHandler(event) {
|
|
@@ -1523,6 +1641,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1523
1641
|
}
|
|
1524
1642
|
if (layoutChanged) {
|
|
1525
1643
|
setLayout(nextLayout);
|
|
1644
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1526
1645
|
if (onLayout) {
|
|
1527
1646
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1528
1647
|
sizePercentage,
|
|
@@ -1560,6 +1679,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1560
1679
|
});
|
|
1561
1680
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1562
1681
|
setLayout(nextLayout);
|
|
1682
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1563
1683
|
if (onLayout) {
|
|
1564
1684
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1565
1685
|
sizePercentage,
|
|
@@ -1587,16 +1707,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1587
1707
|
resetGlobalCursorStyle();
|
|
1588
1708
|
setDragState(null);
|
|
1589
1709
|
}, []);
|
|
1710
|
+
const unregisterPanelRef = useRef({
|
|
1711
|
+
pendingPanelIds: new Set(),
|
|
1712
|
+
timeout: null
|
|
1713
|
+
});
|
|
1590
1714
|
const unregisterPanel = useCallback(panelData => {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1715
|
+
const {
|
|
1716
|
+
id: groupId,
|
|
1717
|
+
layout: prevLayout,
|
|
1718
|
+
onLayout,
|
|
1719
|
+
panelDataArray
|
|
1720
|
+
} = committedValuesRef.current;
|
|
1721
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1722
|
+
if (index >= 0) {
|
|
1723
|
+
panelDataArray.splice(index, 1);
|
|
1724
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1725
|
+
}
|
|
1726
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1727
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1731
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1732
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1733
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1734
|
+
const {
|
|
1735
|
+
pendingPanelIds
|
|
1736
|
+
} = unregisterPanelRef.current;
|
|
1737
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1738
|
+
|
|
1739
|
+
// TRICKY
|
|
1740
|
+
// Strict effects mode
|
|
1741
|
+
let unmountDueToStrictMode = false;
|
|
1742
|
+
pendingPanelIds.forEach(panelId => {
|
|
1743
|
+
pendingPanelIds.delete(panelId);
|
|
1744
|
+
if (panelDataArray.find(({
|
|
1745
|
+
id
|
|
1746
|
+
}) => id === panelId) == null) {
|
|
1747
|
+
unmountDueToStrictMode = true;
|
|
1748
|
+
|
|
1749
|
+
// TRICKY
|
|
1750
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1751
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1752
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1753
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
if (!unmountDueToStrictMode) {
|
|
1757
|
+
return;
|
|
1597
1758
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1759
|
+
if (panelDataArray.length === 0) {
|
|
1760
|
+
// The group is unmounting; skip layout calculation.
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1764
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1765
|
+
groupSizePixels,
|
|
1766
|
+
panelDataArray
|
|
1767
|
+
});
|
|
1768
|
+
|
|
1769
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1770
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1771
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1772
|
+
groupSizePixels,
|
|
1773
|
+
layout: unsafeLayout,
|
|
1774
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1775
|
+
});
|
|
1776
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1777
|
+
setLayout(nextLayout);
|
|
1778
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1779
|
+
if (onLayout) {
|
|
1780
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1781
|
+
sizePercentage,
|
|
1782
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1783
|
+
})));
|
|
1784
|
+
}
|
|
1785
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1786
|
+
}
|
|
1787
|
+
}, 0);
|
|
1600
1788
|
}, []);
|
|
1601
1789
|
const context = useMemo(() => ({
|
|
1602
1790
|
collapsePanel,
|