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,
|
|
@@ -167,6 +168,7 @@ function PanelWithForwardedRef({
|
|
|
167
168
|
// CSS selectors
|
|
168
169
|
"data-panel": "",
|
|
169
170
|
"data-panel-id": panelId,
|
|
171
|
+
"data-panel-group-id": groupId,
|
|
170
172
|
// e2e test attributes
|
|
171
173
|
"data-panel-collapsible": collapsible || undefined ,
|
|
172
174
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -179,8 +181,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
179
181
|
PanelWithForwardedRef.displayName = "Panel";
|
|
180
182
|
Panel.displayName = "forwardRef(Panel)";
|
|
181
183
|
|
|
182
|
-
const PRECISION = 10;
|
|
183
|
-
|
|
184
184
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
185
185
|
return pixels / groupSizePixels * 100;
|
|
186
186
|
}
|
|
@@ -258,6 +258,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
const PRECISION = 10;
|
|
262
|
+
|
|
261
263
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
262
264
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
263
265
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -651,15 +653,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
651
653
|
});
|
|
652
654
|
useEffect(() => {
|
|
653
655
|
const {
|
|
654
|
-
direction,
|
|
655
656
|
panelDataArray
|
|
656
657
|
} = committedValuesRef.current;
|
|
657
658
|
const groupElement = getPanelGroupElement(groupId);
|
|
658
659
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
659
|
-
const {
|
|
660
|
-
height,
|
|
661
|
-
width
|
|
662
|
-
} = groupElement.getBoundingClientRect();
|
|
663
660
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
664
661
|
const cleanupFunctions = handles.map(handle => {
|
|
665
662
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -679,21 +676,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
679
676
|
if (index >= 0) {
|
|
680
677
|
const panelData = panelDataArray[index];
|
|
681
678
|
const size = layout[index];
|
|
682
|
-
if (size != null) {
|
|
683
|
-
var _getPercentageSizeFro;
|
|
679
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
680
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
684
681
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
685
|
-
const
|
|
682
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
683
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
684
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
685
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
686
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
686
687
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
687
688
|
sizePixels: panelData.constraints.minSizePixels
|
|
688
|
-
}, groupSizePixels)) !== null &&
|
|
689
|
-
let delta = 0;
|
|
690
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
691
|
-
delta = direction === "horizontal" ? width : height;
|
|
692
|
-
} else {
|
|
693
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
694
|
-
}
|
|
689
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
695
690
|
const nextLayout = adjustLayoutByDelta({
|
|
696
|
-
delta,
|
|
691
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
697
692
|
groupSizePixels,
|
|
698
693
|
layout,
|
|
699
694
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -814,6 +809,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
814
809
|
}
|
|
815
810
|
}
|
|
816
811
|
|
|
812
|
+
function calculateUnsafeDefaultLayout({
|
|
813
|
+
groupSizePixels,
|
|
814
|
+
panelDataArray
|
|
815
|
+
}) {
|
|
816
|
+
const layout = Array(panelDataArray.length);
|
|
817
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
818
|
+
let numPanelsWithSizes = 0;
|
|
819
|
+
let remainingSize = 100;
|
|
820
|
+
|
|
821
|
+
// Distribute default sizes first
|
|
822
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
823
|
+
const {
|
|
824
|
+
defaultSizePercentage
|
|
825
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
826
|
+
if (defaultSizePercentage != null) {
|
|
827
|
+
numPanelsWithSizes++;
|
|
828
|
+
layout[index] = defaultSizePercentage;
|
|
829
|
+
remainingSize -= defaultSizePercentage;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
834
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
835
|
+
const {
|
|
836
|
+
defaultSizePercentage
|
|
837
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
838
|
+
if (defaultSizePercentage != null) {
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
842
|
+
const size = remainingSize / numRemainingPanels;
|
|
843
|
+
numPanelsWithSizes++;
|
|
844
|
+
layout[index] = size;
|
|
845
|
+
remainingSize -= size;
|
|
846
|
+
}
|
|
847
|
+
return layout;
|
|
848
|
+
}
|
|
849
|
+
|
|
817
850
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
818
851
|
return percentage / 100 * groupSizePixels;
|
|
819
852
|
}
|
|
@@ -964,6 +997,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
964
997
|
return callable;
|
|
965
998
|
}
|
|
966
999
|
|
|
1000
|
+
function getPanelElementsForGroup(groupId) {
|
|
1001
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1002
|
+
}
|
|
1003
|
+
|
|
967
1004
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
968
1005
|
// or on a browser with cookies/storage disabled.
|
|
969
1006
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1019,6 +1056,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
1019
1056
|
} catch (error) {}
|
|
1020
1057
|
return null;
|
|
1021
1058
|
}
|
|
1059
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1060
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1061
|
+
if (state) {
|
|
1062
|
+
var _state$key;
|
|
1063
|
+
const key = getSerializationKey(panels);
|
|
1064
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1065
|
+
}
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1022
1068
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
1023
1069
|
const key = getSerializationKey(panels);
|
|
1024
1070
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -1030,6 +1076,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1030
1076
|
}
|
|
1031
1077
|
}
|
|
1032
1078
|
|
|
1079
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1080
|
+
return constraints.some(constraints => {
|
|
1081
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1033
1085
|
function validatePanelConstraints({
|
|
1034
1086
|
groupSizePixels,
|
|
1035
1087
|
panelConstraints,
|
|
@@ -1175,7 +1227,7 @@ const defaultStorage = {
|
|
|
1175
1227
|
};
|
|
1176
1228
|
const debounceMap = {};
|
|
1177
1229
|
function PanelGroupWithForwardedRef({
|
|
1178
|
-
autoSaveId,
|
|
1230
|
+
autoSaveId = null,
|
|
1179
1231
|
children,
|
|
1180
1232
|
className: classNameFromProps = "",
|
|
1181
1233
|
dataAttributes,
|
|
@@ -1192,11 +1244,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1192
1244
|
const groupId = useUniqueId(idFromProps);
|
|
1193
1245
|
const [dragState, setDragState] = useState(null);
|
|
1194
1246
|
const [layout, setLayout] = useState([]);
|
|
1195
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1196
1247
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1197
1248
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1198
1249
|
const prevDeltaRef = useRef(0);
|
|
1199
1250
|
const committedValuesRef = useRef({
|
|
1251
|
+
autoSaveId,
|
|
1200
1252
|
direction,
|
|
1201
1253
|
dragState,
|
|
1202
1254
|
id: groupId,
|
|
@@ -1204,7 +1256,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1204
1256
|
keyboardResizeByPixels,
|
|
1205
1257
|
layout,
|
|
1206
1258
|
onLayout,
|
|
1207
|
-
panelDataArray
|
|
1259
|
+
panelDataArray: [],
|
|
1260
|
+
storage
|
|
1208
1261
|
});
|
|
1209
1262
|
const devWarningsRef = useRef({
|
|
1210
1263
|
didLogIdAndOrderWarning: false,
|
|
@@ -1242,6 +1295,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1242
1295
|
});
|
|
1243
1296
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1244
1297
|
setLayout(safeLayout);
|
|
1298
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1245
1299
|
if (onLayout) {
|
|
1246
1300
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1247
1301
|
sizePercentage,
|
|
@@ -1252,14 +1306,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1252
1306
|
}
|
|
1253
1307
|
}
|
|
1254
1308
|
}), []);
|
|
1309
|
+
|
|
1255
1310
|
useWindowSplitterPanelGroupBehavior({
|
|
1256
1311
|
committedValuesRef,
|
|
1257
1312
|
groupId,
|
|
1258
1313
|
layout,
|
|
1259
|
-
panelDataArray,
|
|
1314
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1260
1315
|
setLayout
|
|
1261
1316
|
});
|
|
1262
1317
|
useEffect(() => {
|
|
1318
|
+
const {
|
|
1319
|
+
panelDataArray
|
|
1320
|
+
} = committedValuesRef.current;
|
|
1321
|
+
|
|
1263
1322
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1264
1323
|
if (autoSaveId) {
|
|
1265
1324
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1272,20 +1331,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1272
1331
|
}
|
|
1273
1332
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1274
1333
|
}
|
|
1275
|
-
}, [autoSaveId, layout,
|
|
1334
|
+
}, [autoSaveId, layout, storage]);
|
|
1276
1335
|
|
|
1277
1336
|
// DEV warnings
|
|
1278
1337
|
useEffect(() => {
|
|
1279
1338
|
{
|
|
1339
|
+
const {
|
|
1340
|
+
panelDataArray
|
|
1341
|
+
} = committedValuesRef.current;
|
|
1280
1342
|
const {
|
|
1281
1343
|
didLogIdAndOrderWarning,
|
|
1282
1344
|
didLogPanelConstraintsWarning,
|
|
1283
1345
|
prevPanelIds
|
|
1284
1346
|
} = devWarningsRef.current;
|
|
1285
1347
|
if (!didLogIdAndOrderWarning) {
|
|
1286
|
-
const {
|
|
1287
|
-
panelDataArray
|
|
1288
|
-
} = committedValuesRef.current;
|
|
1289
1348
|
const panelIds = panelDataArray.map(({
|
|
1290
1349
|
id
|
|
1291
1350
|
}) => id);
|
|
@@ -1351,6 +1410,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1351
1410
|
});
|
|
1352
1411
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1353
1412
|
setLayout(nextLayout);
|
|
1413
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1354
1414
|
if (onLayout) {
|
|
1355
1415
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1356
1416
|
sizePercentage,
|
|
@@ -1395,6 +1455,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1395
1455
|
});
|
|
1396
1456
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1397
1457
|
setLayout(nextLayout);
|
|
1458
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1398
1459
|
if (onLayout) {
|
|
1399
1460
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1400
1461
|
sizePercentage,
|
|
@@ -1425,6 +1486,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1425
1486
|
|
|
1426
1487
|
// This API should never read from committedValuesRef
|
|
1427
1488
|
const getPanelStyle = useCallback(panelData => {
|
|
1489
|
+
const {
|
|
1490
|
+
panelDataArray
|
|
1491
|
+
} = committedValuesRef.current;
|
|
1428
1492
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1429
1493
|
return computePanelFlexBoxStyle({
|
|
1430
1494
|
dragState,
|
|
@@ -1432,7 +1496,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1432
1496
|
panelData: panelDataArray,
|
|
1433
1497
|
panelIndex
|
|
1434
1498
|
});
|
|
1435
|
-
}, [dragState, layout
|
|
1499
|
+
}, [dragState, layout]);
|
|
1436
1500
|
|
|
1437
1501
|
// External APIs are safe to memoize via committed values ref
|
|
1438
1502
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1462,22 +1526,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1462
1526
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1463
1527
|
}, [groupId]);
|
|
1464
1528
|
const registerPanel = useCallback(panelData => {
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1529
|
+
const {
|
|
1530
|
+
autoSaveId,
|
|
1531
|
+
id: groupId,
|
|
1532
|
+
layout: prevLayout,
|
|
1533
|
+
onLayout,
|
|
1534
|
+
panelDataArray,
|
|
1535
|
+
storage
|
|
1536
|
+
} = committedValuesRef.current;
|
|
1537
|
+
panelDataArray.push(panelData);
|
|
1538
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1539
|
+
const orderA = panelA.order;
|
|
1540
|
+
const orderB = panelB.order;
|
|
1541
|
+
if (orderA == null && orderB == null) {
|
|
1542
|
+
return 0;
|
|
1543
|
+
} else if (orderA == null) {
|
|
1544
|
+
return -1;
|
|
1545
|
+
} else if (orderB == null) {
|
|
1546
|
+
return 1;
|
|
1547
|
+
} else {
|
|
1548
|
+
return orderA - orderB;
|
|
1549
|
+
}
|
|
1550
|
+
});
|
|
1551
|
+
|
|
1552
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1553
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1554
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1555
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
// If this panel has been configured to persist sizing information,
|
|
1560
|
+
// default size should be restored from local storage if possible.
|
|
1561
|
+
let unsafeLayout = null;
|
|
1562
|
+
if (autoSaveId) {
|
|
1563
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1564
|
+
}
|
|
1565
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1566
|
+
if (groupSizePixels <= 0) {
|
|
1567
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1568
|
+
constraints
|
|
1569
|
+
}) => constraints))) {
|
|
1570
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (unsafeLayout == null) {
|
|
1575
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1576
|
+
groupSizePixels,
|
|
1577
|
+
panelDataArray
|
|
1479
1578
|
});
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1582
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1583
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1584
|
+
groupSizePixels,
|
|
1585
|
+
layout: unsafeLayout,
|
|
1586
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1480
1587
|
});
|
|
1588
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1589
|
+
setLayout(nextLayout);
|
|
1590
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1591
|
+
if (onLayout) {
|
|
1592
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1593
|
+
sizePercentage,
|
|
1594
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1595
|
+
})));
|
|
1596
|
+
}
|
|
1597
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1598
|
+
}
|
|
1481
1599
|
}, []);
|
|
1482
1600
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1483
1601
|
return function resizeHandler(event) {
|
|
@@ -1547,6 +1665,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1547
1665
|
}
|
|
1548
1666
|
if (layoutChanged) {
|
|
1549
1667
|
setLayout(nextLayout);
|
|
1668
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1550
1669
|
if (onLayout) {
|
|
1551
1670
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1552
1671
|
sizePercentage,
|
|
@@ -1584,6 +1703,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1584
1703
|
});
|
|
1585
1704
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1586
1705
|
setLayout(nextLayout);
|
|
1706
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1587
1707
|
if (onLayout) {
|
|
1588
1708
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1589
1709
|
sizePercentage,
|
|
@@ -1611,16 +1731,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1611
1731
|
resetGlobalCursorStyle();
|
|
1612
1732
|
setDragState(null);
|
|
1613
1733
|
}, []);
|
|
1734
|
+
const unregisterPanelRef = useRef({
|
|
1735
|
+
pendingPanelIds: new Set(),
|
|
1736
|
+
timeout: null
|
|
1737
|
+
});
|
|
1614
1738
|
const unregisterPanel = useCallback(panelData => {
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1739
|
+
const {
|
|
1740
|
+
id: groupId,
|
|
1741
|
+
layout: prevLayout,
|
|
1742
|
+
onLayout,
|
|
1743
|
+
panelDataArray
|
|
1744
|
+
} = committedValuesRef.current;
|
|
1745
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1746
|
+
if (index >= 0) {
|
|
1747
|
+
panelDataArray.splice(index, 1);
|
|
1748
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1749
|
+
}
|
|
1750
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1751
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1755
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1756
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1757
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1758
|
+
const {
|
|
1759
|
+
pendingPanelIds
|
|
1760
|
+
} = unregisterPanelRef.current;
|
|
1761
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1762
|
+
|
|
1763
|
+
// TRICKY
|
|
1764
|
+
// Strict effects mode
|
|
1765
|
+
let unmountDueToStrictMode = false;
|
|
1766
|
+
pendingPanelIds.forEach(panelId => {
|
|
1767
|
+
pendingPanelIds.delete(panelId);
|
|
1768
|
+
if (panelDataArray.find(({
|
|
1769
|
+
id
|
|
1770
|
+
}) => id === panelId) == null) {
|
|
1771
|
+
unmountDueToStrictMode = true;
|
|
1772
|
+
|
|
1773
|
+
// TRICKY
|
|
1774
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1775
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1776
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1777
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
if (!unmountDueToStrictMode) {
|
|
1781
|
+
return;
|
|
1621
1782
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1783
|
+
if (panelDataArray.length === 0) {
|
|
1784
|
+
// The group is unmounting; skip layout calculation.
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1788
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1789
|
+
groupSizePixels,
|
|
1790
|
+
panelDataArray
|
|
1791
|
+
});
|
|
1792
|
+
|
|
1793
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1794
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1795
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1796
|
+
groupSizePixels,
|
|
1797
|
+
layout: unsafeLayout,
|
|
1798
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1799
|
+
});
|
|
1800
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1801
|
+
setLayout(nextLayout);
|
|
1802
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1803
|
+
if (onLayout) {
|
|
1804
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1805
|
+
sizePercentage,
|
|
1806
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1807
|
+
})));
|
|
1808
|
+
}
|
|
1809
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1810
|
+
}
|
|
1811
|
+
}, 0);
|
|
1624
1812
|
}, []);
|
|
1625
1813
|
const context = useMemo(() => ({
|
|
1626
1814
|
collapsePanel,
|