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
|
@@ -69,6 +69,7 @@ function PanelWithForwardedRef({
|
|
|
69
69
|
expandPanel,
|
|
70
70
|
getPanelSize,
|
|
71
71
|
getPanelStyle,
|
|
72
|
+
groupId,
|
|
72
73
|
isPanelCollapsed,
|
|
73
74
|
registerPanel,
|
|
74
75
|
resizePanel,
|
|
@@ -162,6 +163,7 @@ function PanelWithForwardedRef({
|
|
|
162
163
|
// CSS selectors
|
|
163
164
|
"data-panel": "",
|
|
164
165
|
"data-panel-id": panelId,
|
|
166
|
+
"data-panel-group-id": groupId,
|
|
165
167
|
// e2e test attributes
|
|
166
168
|
"data-panel-collapsible": undefined,
|
|
167
169
|
"data-panel-size": undefined
|
|
@@ -174,8 +176,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
174
176
|
PanelWithForwardedRef.displayName = "Panel";
|
|
175
177
|
Panel.displayName = "forwardRef(Panel)";
|
|
176
178
|
|
|
177
|
-
const PRECISION = 10;
|
|
178
|
-
|
|
179
179
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
180
180
|
return pixels / groupSizePixels * 100;
|
|
181
181
|
}
|
|
@@ -253,6 +253,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
253
253
|
};
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
const PRECISION = 10;
|
|
257
|
+
|
|
256
258
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
257
259
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
258
260
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -726,15 +728,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
726
728
|
}, [groupId, layout, panelDataArray]);
|
|
727
729
|
useEffect(() => {
|
|
728
730
|
const {
|
|
729
|
-
direction,
|
|
730
731
|
panelDataArray
|
|
731
732
|
} = committedValuesRef.current;
|
|
732
733
|
const groupElement = getPanelGroupElement(groupId);
|
|
733
734
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
734
|
-
const {
|
|
735
|
-
height,
|
|
736
|
-
width
|
|
737
|
-
} = groupElement.getBoundingClientRect();
|
|
738
735
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
739
736
|
const cleanupFunctions = handles.map(handle => {
|
|
740
737
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -754,21 +751,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
754
751
|
if (index >= 0) {
|
|
755
752
|
const panelData = panelDataArray[index];
|
|
756
753
|
const size = layout[index];
|
|
757
|
-
if (size != null) {
|
|
758
|
-
var _getPercentageSizeFro;
|
|
754
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
755
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
759
756
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
760
|
-
const
|
|
757
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
758
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
759
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
760
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
761
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
761
762
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
762
763
|
sizePixels: panelData.constraints.minSizePixels
|
|
763
|
-
}, groupSizePixels)) !== null &&
|
|
764
|
-
let delta = 0;
|
|
765
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
766
|
-
delta = direction === "horizontal" ? width : height;
|
|
767
|
-
} else {
|
|
768
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
769
|
-
}
|
|
764
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
770
765
|
const nextLayout = adjustLayoutByDelta({
|
|
771
|
-
delta,
|
|
766
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
772
767
|
groupSizePixels,
|
|
773
768
|
layout,
|
|
774
769
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1077,6 +1072,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1077
1072
|
return callable;
|
|
1078
1073
|
}
|
|
1079
1074
|
|
|
1075
|
+
function getPanelElementsForGroup(groupId) {
|
|
1076
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1080
1079
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1081
1080
|
// or on a browser with cookies/storage disabled.
|
|
1082
1081
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1226,7 +1225,7 @@ const defaultStorage = {
|
|
|
1226
1225
|
};
|
|
1227
1226
|
const debounceMap = {};
|
|
1228
1227
|
function PanelGroupWithForwardedRef({
|
|
1229
|
-
autoSaveId,
|
|
1228
|
+
autoSaveId = null,
|
|
1230
1229
|
children,
|
|
1231
1230
|
className: classNameFromProps = "",
|
|
1232
1231
|
dataAttributes,
|
|
@@ -1243,11 +1242,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1243
1242
|
const groupId = useUniqueId(idFromProps);
|
|
1244
1243
|
const [dragState, setDragState] = useState(null);
|
|
1245
1244
|
const [layout, setLayout] = useState([]);
|
|
1246
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1247
1245
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1248
1246
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1249
1247
|
const prevDeltaRef = useRef(0);
|
|
1250
1248
|
const committedValuesRef = useRef({
|
|
1249
|
+
autoSaveId,
|
|
1251
1250
|
direction,
|
|
1252
1251
|
dragState,
|
|
1253
1252
|
id: groupId,
|
|
@@ -1255,7 +1254,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1255
1254
|
keyboardResizeByPixels,
|
|
1256
1255
|
layout,
|
|
1257
1256
|
onLayout,
|
|
1258
|
-
panelDataArray
|
|
1257
|
+
panelDataArray: [],
|
|
1258
|
+
storage
|
|
1259
1259
|
});
|
|
1260
1260
|
useRef({
|
|
1261
1261
|
didLogIdAndOrderWarning: false,
|
|
@@ -1293,6 +1293,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1293
1293
|
});
|
|
1294
1294
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1295
1295
|
setLayout(safeLayout);
|
|
1296
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1296
1297
|
if (onLayout) {
|
|
1297
1298
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1298
1299
|
sizePercentage,
|
|
@@ -1304,21 +1305,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1304
1305
|
}
|
|
1305
1306
|
}), []);
|
|
1306
1307
|
useIsomorphicLayoutEffect(() => {
|
|
1308
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1307
1309
|
committedValuesRef.current.direction = direction;
|
|
1308
1310
|
committedValuesRef.current.dragState = dragState;
|
|
1309
1311
|
committedValuesRef.current.id = groupId;
|
|
1310
|
-
committedValuesRef.current.layout = layout;
|
|
1311
1312
|
committedValuesRef.current.onLayout = onLayout;
|
|
1312
|
-
committedValuesRef.current.
|
|
1313
|
+
committedValuesRef.current.storage = storage;
|
|
1314
|
+
|
|
1315
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1316
|
+
// TODO [217] Move these values into a separate ref
|
|
1313
1317
|
});
|
|
1318
|
+
|
|
1314
1319
|
useWindowSplitterPanelGroupBehavior({
|
|
1315
1320
|
committedValuesRef,
|
|
1316
1321
|
groupId,
|
|
1317
1322
|
layout,
|
|
1318
|
-
panelDataArray,
|
|
1323
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1319
1324
|
setLayout
|
|
1320
1325
|
});
|
|
1321
1326
|
useEffect(() => {
|
|
1327
|
+
const {
|
|
1328
|
+
panelDataArray
|
|
1329
|
+
} = committedValuesRef.current;
|
|
1330
|
+
|
|
1322
1331
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1323
1332
|
if (autoSaveId) {
|
|
1324
1333
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1331,59 +1340,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1331
1340
|
}
|
|
1332
1341
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1333
1342
|
}
|
|
1334
|
-
}, [autoSaveId, layout,
|
|
1335
|
-
|
|
1336
|
-
// Once all panels have registered themselves,
|
|
1337
|
-
// Compute the initial sizes based on default weights.
|
|
1338
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1343
|
+
}, [autoSaveId, layout, storage]);
|
|
1339
1344
|
useIsomorphicLayoutEffect(() => {
|
|
1340
1345
|
const {
|
|
1341
|
-
|
|
1342
|
-
layout,
|
|
1343
|
-
onLayout
|
|
1346
|
+
panelDataArray
|
|
1344
1347
|
} = committedValuesRef.current;
|
|
1345
|
-
if (layout.length === panelDataArray.length) {
|
|
1346
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
// If this panel has been configured to persist sizing information,
|
|
1351
|
-
// default size should be restored from local storage if possible.
|
|
1352
|
-
let unsafeLayout = null;
|
|
1353
|
-
if (autoSaveId) {
|
|
1354
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1355
|
-
}
|
|
1356
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1357
|
-
if (groupSizePixels <= 0) {
|
|
1358
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1359
|
-
return;
|
|
1360
|
-
}
|
|
1361
|
-
if (unsafeLayout == null) {
|
|
1362
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1363
|
-
groupSizePixels,
|
|
1364
|
-
panelDataArray
|
|
1365
|
-
});
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1369
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1370
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1371
|
-
groupSizePixels,
|
|
1372
|
-
layout: unsafeLayout,
|
|
1373
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1374
|
-
});
|
|
1375
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1376
|
-
setLayout(validatedLayout);
|
|
1377
|
-
}
|
|
1378
|
-
if (onLayout) {
|
|
1379
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1380
|
-
sizePercentage,
|
|
1381
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1382
|
-
})));
|
|
1383
|
-
}
|
|
1384
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1385
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1386
|
-
useIsomorphicLayoutEffect(() => {
|
|
1387
1348
|
const constraints = panelDataArray.map(({
|
|
1388
1349
|
constraints
|
|
1389
1350
|
}) => constraints);
|
|
@@ -1407,6 +1368,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1407
1368
|
});
|
|
1408
1369
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1409
1370
|
setLayout(nextLayout);
|
|
1371
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1410
1372
|
if (onLayout) {
|
|
1411
1373
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1412
1374
|
sizePercentage,
|
|
@@ -1421,7 +1383,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1421
1383
|
resizeObserver.disconnect();
|
|
1422
1384
|
};
|
|
1423
1385
|
}
|
|
1424
|
-
}, [groupId
|
|
1386
|
+
}, [groupId]);
|
|
1425
1387
|
|
|
1426
1388
|
// DEV warnings
|
|
1427
1389
|
useEffect(() => {
|
|
@@ -1458,6 +1420,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1458
1420
|
});
|
|
1459
1421
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1460
1422
|
setLayout(nextLayout);
|
|
1423
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1461
1424
|
if (onLayout) {
|
|
1462
1425
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1463
1426
|
sizePercentage,
|
|
@@ -1502,6 +1465,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1502
1465
|
});
|
|
1503
1466
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1504
1467
|
setLayout(nextLayout);
|
|
1468
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1505
1469
|
if (onLayout) {
|
|
1506
1470
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1507
1471
|
sizePercentage,
|
|
@@ -1532,6 +1496,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1532
1496
|
|
|
1533
1497
|
// This API should never read from committedValuesRef
|
|
1534
1498
|
const getPanelStyle = useCallback(panelData => {
|
|
1499
|
+
const {
|
|
1500
|
+
panelDataArray
|
|
1501
|
+
} = committedValuesRef.current;
|
|
1535
1502
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1536
1503
|
return computePanelFlexBoxStyle({
|
|
1537
1504
|
dragState,
|
|
@@ -1539,7 +1506,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1539
1506
|
panelData: panelDataArray,
|
|
1540
1507
|
panelIndex
|
|
1541
1508
|
});
|
|
1542
|
-
}, [dragState, layout
|
|
1509
|
+
}, [dragState, layout]);
|
|
1543
1510
|
|
|
1544
1511
|
// External APIs are safe to memoize via committed values ref
|
|
1545
1512
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1569,22 +1536,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1569
1536
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1570
1537
|
}, [groupId]);
|
|
1571
1538
|
const registerPanel = useCallback(panelData => {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1539
|
+
const {
|
|
1540
|
+
autoSaveId,
|
|
1541
|
+
id: groupId,
|
|
1542
|
+
layout: prevLayout,
|
|
1543
|
+
onLayout,
|
|
1544
|
+
panelDataArray,
|
|
1545
|
+
storage
|
|
1546
|
+
} = committedValuesRef.current;
|
|
1547
|
+
panelDataArray.push(panelData);
|
|
1548
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1549
|
+
const orderA = panelA.order;
|
|
1550
|
+
const orderB = panelB.order;
|
|
1551
|
+
if (orderA == null && orderB == null) {
|
|
1552
|
+
return 0;
|
|
1553
|
+
} else if (orderA == null) {
|
|
1554
|
+
return -1;
|
|
1555
|
+
} else if (orderB == null) {
|
|
1556
|
+
return 1;
|
|
1557
|
+
} else {
|
|
1558
|
+
return orderA - orderB;
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
|
|
1562
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1563
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1564
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1565
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
// If this panel has been configured to persist sizing information,
|
|
1570
|
+
// default size should be restored from local storage if possible.
|
|
1571
|
+
let unsafeLayout = null;
|
|
1572
|
+
if (autoSaveId) {
|
|
1573
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1574
|
+
}
|
|
1575
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1576
|
+
if (groupSizePixels <= 0) {
|
|
1577
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1578
|
+
constraints
|
|
1579
|
+
}) => constraints))) {
|
|
1580
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (unsafeLayout == null) {
|
|
1585
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1586
|
+
groupSizePixels,
|
|
1587
|
+
panelDataArray
|
|
1586
1588
|
});
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1592
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1593
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1594
|
+
groupSizePixels,
|
|
1595
|
+
layout: unsafeLayout,
|
|
1596
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1587
1597
|
});
|
|
1598
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1599
|
+
setLayout(nextLayout);
|
|
1600
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1601
|
+
if (onLayout) {
|
|
1602
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1603
|
+
sizePercentage,
|
|
1604
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1605
|
+
})));
|
|
1606
|
+
}
|
|
1607
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1608
|
+
}
|
|
1588
1609
|
}, []);
|
|
1589
1610
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1590
1611
|
return function resizeHandler(event) {
|
|
@@ -1654,6 +1675,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1654
1675
|
}
|
|
1655
1676
|
if (layoutChanged) {
|
|
1656
1677
|
setLayout(nextLayout);
|
|
1678
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1657
1679
|
if (onLayout) {
|
|
1658
1680
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1659
1681
|
sizePercentage,
|
|
@@ -1691,6 +1713,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1691
1713
|
});
|
|
1692
1714
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1693
1715
|
setLayout(nextLayout);
|
|
1716
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1694
1717
|
if (onLayout) {
|
|
1695
1718
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1696
1719
|
sizePercentage,
|
|
@@ -1718,16 +1741,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1718
1741
|
resetGlobalCursorStyle();
|
|
1719
1742
|
setDragState(null);
|
|
1720
1743
|
}, []);
|
|
1744
|
+
const unregisterPanelRef = useRef({
|
|
1745
|
+
pendingPanelIds: new Set(),
|
|
1746
|
+
timeout: null
|
|
1747
|
+
});
|
|
1721
1748
|
const unregisterPanel = useCallback(panelData => {
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1749
|
+
const {
|
|
1750
|
+
id: groupId,
|
|
1751
|
+
layout: prevLayout,
|
|
1752
|
+
onLayout,
|
|
1753
|
+
panelDataArray
|
|
1754
|
+
} = committedValuesRef.current;
|
|
1755
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1756
|
+
if (index >= 0) {
|
|
1757
|
+
panelDataArray.splice(index, 1);
|
|
1758
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1759
|
+
}
|
|
1760
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1761
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1765
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1766
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1767
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1768
|
+
const {
|
|
1769
|
+
pendingPanelIds
|
|
1770
|
+
} = unregisterPanelRef.current;
|
|
1771
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1772
|
+
|
|
1773
|
+
// TRICKY
|
|
1774
|
+
// Strict effects mode
|
|
1775
|
+
let unmountDueToStrictMode = false;
|
|
1776
|
+
pendingPanelIds.forEach(panelId => {
|
|
1777
|
+
pendingPanelIds.delete(panelId);
|
|
1778
|
+
if (panelDataArray.find(({
|
|
1779
|
+
id
|
|
1780
|
+
}) => id === panelId) == null) {
|
|
1781
|
+
unmountDueToStrictMode = true;
|
|
1782
|
+
|
|
1783
|
+
// TRICKY
|
|
1784
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1785
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1786
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1787
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
if (!unmountDueToStrictMode) {
|
|
1791
|
+
return;
|
|
1728
1792
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1793
|
+
if (panelDataArray.length === 0) {
|
|
1794
|
+
// The group is unmounting; skip layout calculation.
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1798
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1799
|
+
groupSizePixels,
|
|
1800
|
+
panelDataArray
|
|
1801
|
+
});
|
|
1802
|
+
|
|
1803
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1804
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1805
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1806
|
+
groupSizePixels,
|
|
1807
|
+
layout: unsafeLayout,
|
|
1808
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1809
|
+
});
|
|
1810
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1811
|
+
setLayout(nextLayout);
|
|
1812
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1813
|
+
if (onLayout) {
|
|
1814
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1815
|
+
sizePercentage,
|
|
1816
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1817
|
+
})));
|
|
1818
|
+
}
|
|
1819
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1820
|
+
}
|
|
1821
|
+
}, 0);
|
|
1731
1822
|
}, []);
|
|
1732
1823
|
const context = useMemo(() => ({
|
|
1733
1824
|
collapsePanel,
|