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,
|
|
@@ -168,6 +169,7 @@ function PanelWithForwardedRef({
|
|
|
168
169
|
// CSS selectors
|
|
169
170
|
"data-panel": "",
|
|
170
171
|
"data-panel-id": panelId,
|
|
172
|
+
"data-panel-group-id": groupId,
|
|
171
173
|
// e2e test attributes
|
|
172
174
|
"data-panel-collapsible": collapsible || undefined ,
|
|
173
175
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -180,8 +182,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
180
182
|
PanelWithForwardedRef.displayName = "Panel";
|
|
181
183
|
Panel.displayName = "forwardRef(Panel)";
|
|
182
184
|
|
|
183
|
-
const PRECISION = 10;
|
|
184
|
-
|
|
185
185
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
186
186
|
return pixels / groupSizePixels * 100;
|
|
187
187
|
}
|
|
@@ -259,6 +259,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
const PRECISION = 10;
|
|
263
|
+
|
|
262
264
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
263
265
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
264
266
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -742,15 +744,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
742
744
|
}, [groupId, layout, panelDataArray]);
|
|
743
745
|
useEffect(() => {
|
|
744
746
|
const {
|
|
745
|
-
direction,
|
|
746
747
|
panelDataArray
|
|
747
748
|
} = committedValuesRef.current;
|
|
748
749
|
const groupElement = getPanelGroupElement(groupId);
|
|
749
750
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
750
|
-
const {
|
|
751
|
-
height,
|
|
752
|
-
width
|
|
753
|
-
} = groupElement.getBoundingClientRect();
|
|
754
751
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
755
752
|
const cleanupFunctions = handles.map(handle => {
|
|
756
753
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -770,21 +767,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
770
767
|
if (index >= 0) {
|
|
771
768
|
const panelData = panelDataArray[index];
|
|
772
769
|
const size = layout[index];
|
|
773
|
-
if (size != null) {
|
|
774
|
-
var _getPercentageSizeFro;
|
|
770
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
771
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
775
772
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
776
|
-
const
|
|
773
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
774
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
775
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
776
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
777
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
777
778
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
778
779
|
sizePixels: panelData.constraints.minSizePixels
|
|
779
|
-
}, groupSizePixels)) !== null &&
|
|
780
|
-
let delta = 0;
|
|
781
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
782
|
-
delta = direction === "horizontal" ? width : height;
|
|
783
|
-
} else {
|
|
784
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
785
|
-
}
|
|
780
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
786
781
|
const nextLayout = adjustLayoutByDelta({
|
|
787
|
-
delta,
|
|
782
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
788
783
|
groupSizePixels,
|
|
789
784
|
layout,
|
|
790
785
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1093,6 +1088,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1093
1088
|
return callable;
|
|
1094
1089
|
}
|
|
1095
1090
|
|
|
1091
|
+
function getPanelElementsForGroup(groupId) {
|
|
1092
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1096
1095
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1097
1096
|
// or on a browser with cookies/storage disabled.
|
|
1098
1097
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1319,7 +1318,7 @@ const defaultStorage = {
|
|
|
1319
1318
|
};
|
|
1320
1319
|
const debounceMap = {};
|
|
1321
1320
|
function PanelGroupWithForwardedRef({
|
|
1322
|
-
autoSaveId,
|
|
1321
|
+
autoSaveId = null,
|
|
1323
1322
|
children,
|
|
1324
1323
|
className: classNameFromProps = "",
|
|
1325
1324
|
dataAttributes,
|
|
@@ -1336,11 +1335,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1336
1335
|
const groupId = useUniqueId(idFromProps);
|
|
1337
1336
|
const [dragState, setDragState] = useState(null);
|
|
1338
1337
|
const [layout, setLayout] = useState([]);
|
|
1339
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1340
1338
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1341
1339
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1342
1340
|
const prevDeltaRef = useRef(0);
|
|
1343
1341
|
const committedValuesRef = useRef({
|
|
1342
|
+
autoSaveId,
|
|
1344
1343
|
direction,
|
|
1345
1344
|
dragState,
|
|
1346
1345
|
id: groupId,
|
|
@@ -1348,7 +1347,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1348
1347
|
keyboardResizeByPixels,
|
|
1349
1348
|
layout,
|
|
1350
1349
|
onLayout,
|
|
1351
|
-
panelDataArray
|
|
1350
|
+
panelDataArray: [],
|
|
1351
|
+
storage
|
|
1352
1352
|
});
|
|
1353
1353
|
const devWarningsRef = useRef({
|
|
1354
1354
|
didLogIdAndOrderWarning: false,
|
|
@@ -1386,6 +1386,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1386
1386
|
});
|
|
1387
1387
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1388
1388
|
setLayout(safeLayout);
|
|
1389
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1389
1390
|
if (onLayout) {
|
|
1390
1391
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1391
1392
|
sizePercentage,
|
|
@@ -1397,21 +1398,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1397
1398
|
}
|
|
1398
1399
|
}), []);
|
|
1399
1400
|
useIsomorphicLayoutEffect(() => {
|
|
1401
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1400
1402
|
committedValuesRef.current.direction = direction;
|
|
1401
1403
|
committedValuesRef.current.dragState = dragState;
|
|
1402
1404
|
committedValuesRef.current.id = groupId;
|
|
1403
|
-
committedValuesRef.current.layout = layout;
|
|
1404
1405
|
committedValuesRef.current.onLayout = onLayout;
|
|
1405
|
-
committedValuesRef.current.
|
|
1406
|
+
committedValuesRef.current.storage = storage;
|
|
1407
|
+
|
|
1408
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1409
|
+
// TODO [217] Move these values into a separate ref
|
|
1406
1410
|
});
|
|
1411
|
+
|
|
1407
1412
|
useWindowSplitterPanelGroupBehavior({
|
|
1408
1413
|
committedValuesRef,
|
|
1409
1414
|
groupId,
|
|
1410
1415
|
layout,
|
|
1411
|
-
panelDataArray,
|
|
1416
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1412
1417
|
setLayout
|
|
1413
1418
|
});
|
|
1414
1419
|
useEffect(() => {
|
|
1420
|
+
const {
|
|
1421
|
+
panelDataArray
|
|
1422
|
+
} = committedValuesRef.current;
|
|
1423
|
+
|
|
1415
1424
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1416
1425
|
if (autoSaveId) {
|
|
1417
1426
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1424,59 +1433,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1424
1433
|
}
|
|
1425
1434
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1426
1435
|
}
|
|
1427
|
-
}, [autoSaveId, layout,
|
|
1428
|
-
|
|
1429
|
-
// Once all panels have registered themselves,
|
|
1430
|
-
// Compute the initial sizes based on default weights.
|
|
1431
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1436
|
+
}, [autoSaveId, layout, storage]);
|
|
1432
1437
|
useIsomorphicLayoutEffect(() => {
|
|
1433
1438
|
const {
|
|
1434
|
-
|
|
1435
|
-
layout,
|
|
1436
|
-
onLayout
|
|
1439
|
+
panelDataArray
|
|
1437
1440
|
} = committedValuesRef.current;
|
|
1438
|
-
if (layout.length === panelDataArray.length) {
|
|
1439
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1440
|
-
return;
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
// If this panel has been configured to persist sizing information,
|
|
1444
|
-
// default size should be restored from local storage if possible.
|
|
1445
|
-
let unsafeLayout = null;
|
|
1446
|
-
if (autoSaveId) {
|
|
1447
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1448
|
-
}
|
|
1449
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1450
|
-
if (groupSizePixels <= 0) {
|
|
1451
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
if (unsafeLayout == null) {
|
|
1455
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1456
|
-
groupSizePixels,
|
|
1457
|
-
panelDataArray
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1462
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1463
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1464
|
-
groupSizePixels,
|
|
1465
|
-
layout: unsafeLayout,
|
|
1466
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1467
|
-
});
|
|
1468
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1469
|
-
setLayout(validatedLayout);
|
|
1470
|
-
}
|
|
1471
|
-
if (onLayout) {
|
|
1472
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1473
|
-
sizePercentage,
|
|
1474
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1475
|
-
})));
|
|
1476
|
-
}
|
|
1477
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1478
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1479
|
-
useIsomorphicLayoutEffect(() => {
|
|
1480
1441
|
const constraints = panelDataArray.map(({
|
|
1481
1442
|
constraints
|
|
1482
1443
|
}) => constraints);
|
|
@@ -1500,6 +1461,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1500
1461
|
});
|
|
1501
1462
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1502
1463
|
setLayout(nextLayout);
|
|
1464
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1503
1465
|
if (onLayout) {
|
|
1504
1466
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1505
1467
|
sizePercentage,
|
|
@@ -1514,20 +1476,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1514
1476
|
resizeObserver.disconnect();
|
|
1515
1477
|
};
|
|
1516
1478
|
}
|
|
1517
|
-
}, [groupId
|
|
1479
|
+
}, [groupId]);
|
|
1518
1480
|
|
|
1519
1481
|
// DEV warnings
|
|
1520
1482
|
useEffect(() => {
|
|
1521
1483
|
{
|
|
1484
|
+
const {
|
|
1485
|
+
panelDataArray
|
|
1486
|
+
} = committedValuesRef.current;
|
|
1522
1487
|
const {
|
|
1523
1488
|
didLogIdAndOrderWarning,
|
|
1524
1489
|
didLogPanelConstraintsWarning,
|
|
1525
1490
|
prevPanelIds
|
|
1526
1491
|
} = devWarningsRef.current;
|
|
1527
1492
|
if (!didLogIdAndOrderWarning) {
|
|
1528
|
-
const {
|
|
1529
|
-
panelDataArray
|
|
1530
|
-
} = committedValuesRef.current;
|
|
1531
1493
|
const panelIds = panelDataArray.map(({
|
|
1532
1494
|
id
|
|
1533
1495
|
}) => id);
|
|
@@ -1593,6 +1555,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1593
1555
|
});
|
|
1594
1556
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1595
1557
|
setLayout(nextLayout);
|
|
1558
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1596
1559
|
if (onLayout) {
|
|
1597
1560
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1598
1561
|
sizePercentage,
|
|
@@ -1637,6 +1600,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1637
1600
|
});
|
|
1638
1601
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1639
1602
|
setLayout(nextLayout);
|
|
1603
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1640
1604
|
if (onLayout) {
|
|
1641
1605
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1642
1606
|
sizePercentage,
|
|
@@ -1667,6 +1631,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1667
1631
|
|
|
1668
1632
|
// This API should never read from committedValuesRef
|
|
1669
1633
|
const getPanelStyle = useCallback(panelData => {
|
|
1634
|
+
const {
|
|
1635
|
+
panelDataArray
|
|
1636
|
+
} = committedValuesRef.current;
|
|
1670
1637
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1671
1638
|
return computePanelFlexBoxStyle({
|
|
1672
1639
|
dragState,
|
|
@@ -1674,7 +1641,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1674
1641
|
panelData: panelDataArray,
|
|
1675
1642
|
panelIndex
|
|
1676
1643
|
});
|
|
1677
|
-
}, [dragState, layout
|
|
1644
|
+
}, [dragState, layout]);
|
|
1678
1645
|
|
|
1679
1646
|
// External APIs are safe to memoize via committed values ref
|
|
1680
1647
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1704,22 +1671,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1704
1671
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1705
1672
|
}, [groupId]);
|
|
1706
1673
|
const registerPanel = useCallback(panelData => {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1674
|
+
const {
|
|
1675
|
+
autoSaveId,
|
|
1676
|
+
id: groupId,
|
|
1677
|
+
layout: prevLayout,
|
|
1678
|
+
onLayout,
|
|
1679
|
+
panelDataArray,
|
|
1680
|
+
storage
|
|
1681
|
+
} = committedValuesRef.current;
|
|
1682
|
+
panelDataArray.push(panelData);
|
|
1683
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1684
|
+
const orderA = panelA.order;
|
|
1685
|
+
const orderB = panelB.order;
|
|
1686
|
+
if (orderA == null && orderB == null) {
|
|
1687
|
+
return 0;
|
|
1688
|
+
} else if (orderA == null) {
|
|
1689
|
+
return -1;
|
|
1690
|
+
} else if (orderB == null) {
|
|
1691
|
+
return 1;
|
|
1692
|
+
} else {
|
|
1693
|
+
return orderA - orderB;
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
|
|
1697
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1698
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1699
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1700
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1701
|
+
return;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
// If this panel has been configured to persist sizing information,
|
|
1705
|
+
// default size should be restored from local storage if possible.
|
|
1706
|
+
let unsafeLayout = null;
|
|
1707
|
+
if (autoSaveId) {
|
|
1708
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1709
|
+
}
|
|
1710
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1711
|
+
if (groupSizePixels <= 0) {
|
|
1712
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1713
|
+
constraints
|
|
1714
|
+
}) => constraints))) {
|
|
1715
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
if (unsafeLayout == null) {
|
|
1720
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1721
|
+
groupSizePixels,
|
|
1722
|
+
panelDataArray
|
|
1721
1723
|
});
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1727
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1728
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1729
|
+
groupSizePixels,
|
|
1730
|
+
layout: unsafeLayout,
|
|
1731
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1722
1732
|
});
|
|
1733
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1734
|
+
setLayout(nextLayout);
|
|
1735
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1736
|
+
if (onLayout) {
|
|
1737
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1738
|
+
sizePercentage,
|
|
1739
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1740
|
+
})));
|
|
1741
|
+
}
|
|
1742
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1743
|
+
}
|
|
1723
1744
|
}, []);
|
|
1724
1745
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1725
1746
|
return function resizeHandler(event) {
|
|
@@ -1789,6 +1810,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1789
1810
|
}
|
|
1790
1811
|
if (layoutChanged) {
|
|
1791
1812
|
setLayout(nextLayout);
|
|
1813
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1792
1814
|
if (onLayout) {
|
|
1793
1815
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1794
1816
|
sizePercentage,
|
|
@@ -1826,6 +1848,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1826
1848
|
});
|
|
1827
1849
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1828
1850
|
setLayout(nextLayout);
|
|
1851
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1829
1852
|
if (onLayout) {
|
|
1830
1853
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1831
1854
|
sizePercentage,
|
|
@@ -1853,16 +1876,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1853
1876
|
resetGlobalCursorStyle();
|
|
1854
1877
|
setDragState(null);
|
|
1855
1878
|
}, []);
|
|
1879
|
+
const unregisterPanelRef = useRef({
|
|
1880
|
+
pendingPanelIds: new Set(),
|
|
1881
|
+
timeout: null
|
|
1882
|
+
});
|
|
1856
1883
|
const unregisterPanel = useCallback(panelData => {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1884
|
+
const {
|
|
1885
|
+
id: groupId,
|
|
1886
|
+
layout: prevLayout,
|
|
1887
|
+
onLayout,
|
|
1888
|
+
panelDataArray
|
|
1889
|
+
} = committedValuesRef.current;
|
|
1890
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1891
|
+
if (index >= 0) {
|
|
1892
|
+
panelDataArray.splice(index, 1);
|
|
1893
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1894
|
+
}
|
|
1895
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1896
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1900
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1901
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1902
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1903
|
+
const {
|
|
1904
|
+
pendingPanelIds
|
|
1905
|
+
} = unregisterPanelRef.current;
|
|
1906
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1907
|
+
|
|
1908
|
+
// TRICKY
|
|
1909
|
+
// Strict effects mode
|
|
1910
|
+
let unmountDueToStrictMode = false;
|
|
1911
|
+
pendingPanelIds.forEach(panelId => {
|
|
1912
|
+
pendingPanelIds.delete(panelId);
|
|
1913
|
+
if (panelDataArray.find(({
|
|
1914
|
+
id
|
|
1915
|
+
}) => id === panelId) == null) {
|
|
1916
|
+
unmountDueToStrictMode = true;
|
|
1917
|
+
|
|
1918
|
+
// TRICKY
|
|
1919
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1920
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1921
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1922
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
if (!unmountDueToStrictMode) {
|
|
1926
|
+
return;
|
|
1863
1927
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1928
|
+
if (panelDataArray.length === 0) {
|
|
1929
|
+
// The group is unmounting; skip layout calculation.
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1933
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1934
|
+
groupSizePixels,
|
|
1935
|
+
panelDataArray
|
|
1936
|
+
});
|
|
1937
|
+
|
|
1938
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1939
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1940
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1941
|
+
groupSizePixels,
|
|
1942
|
+
layout: unsafeLayout,
|
|
1943
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1944
|
+
});
|
|
1945
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1946
|
+
setLayout(nextLayout);
|
|
1947
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1948
|
+
if (onLayout) {
|
|
1949
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1950
|
+
sizePercentage,
|
|
1951
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1952
|
+
})));
|
|
1953
|
+
}
|
|
1954
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1955
|
+
}
|
|
1956
|
+
}, 0);
|
|
1866
1957
|
}, []);
|
|
1867
1958
|
const context = useMemo(() => ({
|
|
1868
1959
|
collapsePanel,
|