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
|
@@ -93,6 +93,7 @@ function PanelWithForwardedRef({
|
|
|
93
93
|
expandPanel,
|
|
94
94
|
getPanelSize,
|
|
95
95
|
getPanelStyle,
|
|
96
|
+
groupId,
|
|
96
97
|
isPanelCollapsed,
|
|
97
98
|
registerPanel,
|
|
98
99
|
resizePanel,
|
|
@@ -192,6 +193,7 @@ function PanelWithForwardedRef({
|
|
|
192
193
|
// CSS selectors
|
|
193
194
|
"data-panel": "",
|
|
194
195
|
"data-panel-id": panelId,
|
|
196
|
+
"data-panel-group-id": groupId,
|
|
195
197
|
// e2e test attributes
|
|
196
198
|
"data-panel-collapsible": collapsible || undefined ,
|
|
197
199
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -204,8 +206,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
204
206
|
PanelWithForwardedRef.displayName = "Panel";
|
|
205
207
|
Panel.displayName = "forwardRef(Panel)";
|
|
206
208
|
|
|
207
|
-
const PRECISION = 10;
|
|
208
|
-
|
|
209
209
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
210
210
|
return pixels / groupSizePixels * 100;
|
|
211
211
|
}
|
|
@@ -283,6 +283,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
283
283
|
};
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
const PRECISION = 10;
|
|
287
|
+
|
|
286
288
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
287
289
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
288
290
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -766,15 +768,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
766
768
|
}, [groupId, layout, panelDataArray]);
|
|
767
769
|
useEffect(() => {
|
|
768
770
|
const {
|
|
769
|
-
direction,
|
|
770
771
|
panelDataArray
|
|
771
772
|
} = committedValuesRef.current;
|
|
772
773
|
const groupElement = getPanelGroupElement(groupId);
|
|
773
774
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
774
|
-
const {
|
|
775
|
-
height,
|
|
776
|
-
width
|
|
777
|
-
} = groupElement.getBoundingClientRect();
|
|
778
775
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
779
776
|
const cleanupFunctions = handles.map(handle => {
|
|
780
777
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -794,21 +791,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
794
791
|
if (index >= 0) {
|
|
795
792
|
const panelData = panelDataArray[index];
|
|
796
793
|
const size = layout[index];
|
|
797
|
-
if (size != null) {
|
|
798
|
-
var _getPercentageSizeFro;
|
|
794
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
795
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
799
796
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
800
|
-
const
|
|
797
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
798
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
799
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
800
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
801
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
801
802
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
802
803
|
sizePixels: panelData.constraints.minSizePixels
|
|
803
|
-
}, groupSizePixels)) !== null &&
|
|
804
|
-
let delta = 0;
|
|
805
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
806
|
-
delta = direction === "horizontal" ? width : height;
|
|
807
|
-
} else {
|
|
808
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
809
|
-
}
|
|
804
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
810
805
|
const nextLayout = adjustLayoutByDelta({
|
|
811
|
-
delta,
|
|
806
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
812
807
|
groupSizePixels,
|
|
813
808
|
layout,
|
|
814
809
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1117,6 +1112,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1117
1112
|
return callable;
|
|
1118
1113
|
}
|
|
1119
1114
|
|
|
1115
|
+
function getPanelElementsForGroup(groupId) {
|
|
1116
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1120
1119
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1121
1120
|
// or on a browser with cookies/storage disabled.
|
|
1122
1121
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1343,7 +1342,7 @@ const defaultStorage = {
|
|
|
1343
1342
|
};
|
|
1344
1343
|
const debounceMap = {};
|
|
1345
1344
|
function PanelGroupWithForwardedRef({
|
|
1346
|
-
autoSaveId,
|
|
1345
|
+
autoSaveId = null,
|
|
1347
1346
|
children,
|
|
1348
1347
|
className: classNameFromProps = "",
|
|
1349
1348
|
dataAttributes,
|
|
@@ -1360,11 +1359,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1360
1359
|
const groupId = useUniqueId(idFromProps);
|
|
1361
1360
|
const [dragState, setDragState] = useState(null);
|
|
1362
1361
|
const [layout, setLayout] = useState([]);
|
|
1363
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1364
1362
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1365
1363
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1366
1364
|
const prevDeltaRef = useRef(0);
|
|
1367
1365
|
const committedValuesRef = useRef({
|
|
1366
|
+
autoSaveId,
|
|
1368
1367
|
direction,
|
|
1369
1368
|
dragState,
|
|
1370
1369
|
id: groupId,
|
|
@@ -1372,7 +1371,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1372
1371
|
keyboardResizeByPixels,
|
|
1373
1372
|
layout,
|
|
1374
1373
|
onLayout,
|
|
1375
|
-
panelDataArray
|
|
1374
|
+
panelDataArray: [],
|
|
1375
|
+
storage
|
|
1376
1376
|
});
|
|
1377
1377
|
const devWarningsRef = useRef({
|
|
1378
1378
|
didLogIdAndOrderWarning: false,
|
|
@@ -1410,6 +1410,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1410
1410
|
});
|
|
1411
1411
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1412
1412
|
setLayout(safeLayout);
|
|
1413
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1413
1414
|
if (onLayout) {
|
|
1414
1415
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1415
1416
|
sizePercentage,
|
|
@@ -1421,21 +1422,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1421
1422
|
}
|
|
1422
1423
|
}), []);
|
|
1423
1424
|
useIsomorphicLayoutEffect(() => {
|
|
1425
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1424
1426
|
committedValuesRef.current.direction = direction;
|
|
1425
1427
|
committedValuesRef.current.dragState = dragState;
|
|
1426
1428
|
committedValuesRef.current.id = groupId;
|
|
1427
|
-
committedValuesRef.current.layout = layout;
|
|
1428
1429
|
committedValuesRef.current.onLayout = onLayout;
|
|
1429
|
-
committedValuesRef.current.
|
|
1430
|
+
committedValuesRef.current.storage = storage;
|
|
1431
|
+
|
|
1432
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1433
|
+
// TODO [217] Move these values into a separate ref
|
|
1430
1434
|
});
|
|
1435
|
+
|
|
1431
1436
|
useWindowSplitterPanelGroupBehavior({
|
|
1432
1437
|
committedValuesRef,
|
|
1433
1438
|
groupId,
|
|
1434
1439
|
layout,
|
|
1435
|
-
panelDataArray,
|
|
1440
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1436
1441
|
setLayout
|
|
1437
1442
|
});
|
|
1438
1443
|
useEffect(() => {
|
|
1444
|
+
const {
|
|
1445
|
+
panelDataArray
|
|
1446
|
+
} = committedValuesRef.current;
|
|
1447
|
+
|
|
1439
1448
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1440
1449
|
if (autoSaveId) {
|
|
1441
1450
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1448,59 +1457,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1448
1457
|
}
|
|
1449
1458
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1450
1459
|
}
|
|
1451
|
-
}, [autoSaveId, layout,
|
|
1452
|
-
|
|
1453
|
-
// Once all panels have registered themselves,
|
|
1454
|
-
// Compute the initial sizes based on default weights.
|
|
1455
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1460
|
+
}, [autoSaveId, layout, storage]);
|
|
1456
1461
|
useIsomorphicLayoutEffect(() => {
|
|
1457
1462
|
const {
|
|
1458
|
-
|
|
1459
|
-
layout,
|
|
1460
|
-
onLayout
|
|
1463
|
+
panelDataArray
|
|
1461
1464
|
} = committedValuesRef.current;
|
|
1462
|
-
if (layout.length === panelDataArray.length) {
|
|
1463
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1464
|
-
return;
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
// If this panel has been configured to persist sizing information,
|
|
1468
|
-
// default size should be restored from local storage if possible.
|
|
1469
|
-
let unsafeLayout = null;
|
|
1470
|
-
if (autoSaveId) {
|
|
1471
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1472
|
-
}
|
|
1473
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1474
|
-
if (groupSizePixels <= 0) {
|
|
1475
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1478
|
-
if (unsafeLayout == null) {
|
|
1479
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1480
|
-
groupSizePixels,
|
|
1481
|
-
panelDataArray
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1486
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1487
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1488
|
-
groupSizePixels,
|
|
1489
|
-
layout: unsafeLayout,
|
|
1490
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1491
|
-
});
|
|
1492
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1493
|
-
setLayout(validatedLayout);
|
|
1494
|
-
}
|
|
1495
|
-
if (onLayout) {
|
|
1496
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1497
|
-
sizePercentage,
|
|
1498
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1499
|
-
})));
|
|
1500
|
-
}
|
|
1501
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1502
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1503
|
-
useIsomorphicLayoutEffect(() => {
|
|
1504
1465
|
const constraints = panelDataArray.map(({
|
|
1505
1466
|
constraints
|
|
1506
1467
|
}) => constraints);
|
|
@@ -1524,6 +1485,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1524
1485
|
});
|
|
1525
1486
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1526
1487
|
setLayout(nextLayout);
|
|
1488
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1527
1489
|
if (onLayout) {
|
|
1528
1490
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1529
1491
|
sizePercentage,
|
|
@@ -1538,20 +1500,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1538
1500
|
resizeObserver.disconnect();
|
|
1539
1501
|
};
|
|
1540
1502
|
}
|
|
1541
|
-
}, [groupId
|
|
1503
|
+
}, [groupId]);
|
|
1542
1504
|
|
|
1543
1505
|
// DEV warnings
|
|
1544
1506
|
useEffect(() => {
|
|
1545
1507
|
{
|
|
1508
|
+
const {
|
|
1509
|
+
panelDataArray
|
|
1510
|
+
} = committedValuesRef.current;
|
|
1546
1511
|
const {
|
|
1547
1512
|
didLogIdAndOrderWarning,
|
|
1548
1513
|
didLogPanelConstraintsWarning,
|
|
1549
1514
|
prevPanelIds
|
|
1550
1515
|
} = devWarningsRef.current;
|
|
1551
1516
|
if (!didLogIdAndOrderWarning) {
|
|
1552
|
-
const {
|
|
1553
|
-
panelDataArray
|
|
1554
|
-
} = committedValuesRef.current;
|
|
1555
1517
|
const panelIds = panelDataArray.map(({
|
|
1556
1518
|
id
|
|
1557
1519
|
}) => id);
|
|
@@ -1617,6 +1579,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1617
1579
|
});
|
|
1618
1580
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1619
1581
|
setLayout(nextLayout);
|
|
1582
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1620
1583
|
if (onLayout) {
|
|
1621
1584
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1622
1585
|
sizePercentage,
|
|
@@ -1661,6 +1624,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1661
1624
|
});
|
|
1662
1625
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1663
1626
|
setLayout(nextLayout);
|
|
1627
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1664
1628
|
if (onLayout) {
|
|
1665
1629
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1666
1630
|
sizePercentage,
|
|
@@ -1691,6 +1655,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1691
1655
|
|
|
1692
1656
|
// This API should never read from committedValuesRef
|
|
1693
1657
|
const getPanelStyle = useCallback(panelData => {
|
|
1658
|
+
const {
|
|
1659
|
+
panelDataArray
|
|
1660
|
+
} = committedValuesRef.current;
|
|
1694
1661
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1695
1662
|
return computePanelFlexBoxStyle({
|
|
1696
1663
|
dragState,
|
|
@@ -1698,7 +1665,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1698
1665
|
panelData: panelDataArray,
|
|
1699
1666
|
panelIndex
|
|
1700
1667
|
});
|
|
1701
|
-
}, [dragState, layout
|
|
1668
|
+
}, [dragState, layout]);
|
|
1702
1669
|
|
|
1703
1670
|
// External APIs are safe to memoize via committed values ref
|
|
1704
1671
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1728,22 +1695,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1728
1695
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1729
1696
|
}, [groupId]);
|
|
1730
1697
|
const registerPanel = useCallback(panelData => {
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1698
|
+
const {
|
|
1699
|
+
autoSaveId,
|
|
1700
|
+
id: groupId,
|
|
1701
|
+
layout: prevLayout,
|
|
1702
|
+
onLayout,
|
|
1703
|
+
panelDataArray,
|
|
1704
|
+
storage
|
|
1705
|
+
} = committedValuesRef.current;
|
|
1706
|
+
panelDataArray.push(panelData);
|
|
1707
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1708
|
+
const orderA = panelA.order;
|
|
1709
|
+
const orderB = panelB.order;
|
|
1710
|
+
if (orderA == null && orderB == null) {
|
|
1711
|
+
return 0;
|
|
1712
|
+
} else if (orderA == null) {
|
|
1713
|
+
return -1;
|
|
1714
|
+
} else if (orderB == null) {
|
|
1715
|
+
return 1;
|
|
1716
|
+
} else {
|
|
1717
|
+
return orderA - orderB;
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
|
|
1721
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1722
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1723
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1724
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// If this panel has been configured to persist sizing information,
|
|
1729
|
+
// default size should be restored from local storage if possible.
|
|
1730
|
+
let unsafeLayout = null;
|
|
1731
|
+
if (autoSaveId) {
|
|
1732
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1733
|
+
}
|
|
1734
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1735
|
+
if (groupSizePixels <= 0) {
|
|
1736
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1737
|
+
constraints
|
|
1738
|
+
}) => constraints))) {
|
|
1739
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
if (unsafeLayout == null) {
|
|
1744
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1745
|
+
groupSizePixels,
|
|
1746
|
+
panelDataArray
|
|
1745
1747
|
});
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1751
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1752
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1753
|
+
groupSizePixels,
|
|
1754
|
+
layout: unsafeLayout,
|
|
1755
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1746
1756
|
});
|
|
1757
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1758
|
+
setLayout(nextLayout);
|
|
1759
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1760
|
+
if (onLayout) {
|
|
1761
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1762
|
+
sizePercentage,
|
|
1763
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1764
|
+
})));
|
|
1765
|
+
}
|
|
1766
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1767
|
+
}
|
|
1747
1768
|
}, []);
|
|
1748
1769
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1749
1770
|
return function resizeHandler(event) {
|
|
@@ -1813,6 +1834,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1813
1834
|
}
|
|
1814
1835
|
if (layoutChanged) {
|
|
1815
1836
|
setLayout(nextLayout);
|
|
1837
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1816
1838
|
if (onLayout) {
|
|
1817
1839
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1818
1840
|
sizePercentage,
|
|
@@ -1850,6 +1872,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1850
1872
|
});
|
|
1851
1873
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1852
1874
|
setLayout(nextLayout);
|
|
1875
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1853
1876
|
if (onLayout) {
|
|
1854
1877
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1855
1878
|
sizePercentage,
|
|
@@ -1877,16 +1900,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1877
1900
|
resetGlobalCursorStyle();
|
|
1878
1901
|
setDragState(null);
|
|
1879
1902
|
}, []);
|
|
1903
|
+
const unregisterPanelRef = useRef({
|
|
1904
|
+
pendingPanelIds: new Set(),
|
|
1905
|
+
timeout: null
|
|
1906
|
+
});
|
|
1880
1907
|
const unregisterPanel = useCallback(panelData => {
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1908
|
+
const {
|
|
1909
|
+
id: groupId,
|
|
1910
|
+
layout: prevLayout,
|
|
1911
|
+
onLayout,
|
|
1912
|
+
panelDataArray
|
|
1913
|
+
} = committedValuesRef.current;
|
|
1914
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1915
|
+
if (index >= 0) {
|
|
1916
|
+
panelDataArray.splice(index, 1);
|
|
1917
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1918
|
+
}
|
|
1919
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1920
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1924
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1925
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1926
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1927
|
+
const {
|
|
1928
|
+
pendingPanelIds
|
|
1929
|
+
} = unregisterPanelRef.current;
|
|
1930
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1931
|
+
|
|
1932
|
+
// TRICKY
|
|
1933
|
+
// Strict effects mode
|
|
1934
|
+
let unmountDueToStrictMode = false;
|
|
1935
|
+
pendingPanelIds.forEach(panelId => {
|
|
1936
|
+
pendingPanelIds.delete(panelId);
|
|
1937
|
+
if (panelDataArray.find(({
|
|
1938
|
+
id
|
|
1939
|
+
}) => id === panelId) == null) {
|
|
1940
|
+
unmountDueToStrictMode = true;
|
|
1941
|
+
|
|
1942
|
+
// TRICKY
|
|
1943
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1944
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1945
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1946
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1947
|
+
}
|
|
1948
|
+
});
|
|
1949
|
+
if (!unmountDueToStrictMode) {
|
|
1950
|
+
return;
|
|
1887
1951
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1952
|
+
if (panelDataArray.length === 0) {
|
|
1953
|
+
// The group is unmounting; skip layout calculation.
|
|
1954
|
+
return;
|
|
1955
|
+
}
|
|
1956
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1957
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1958
|
+
groupSizePixels,
|
|
1959
|
+
panelDataArray
|
|
1960
|
+
});
|
|
1961
|
+
|
|
1962
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1963
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1964
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1965
|
+
groupSizePixels,
|
|
1966
|
+
layout: unsafeLayout,
|
|
1967
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1968
|
+
});
|
|
1969
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1970
|
+
setLayout(nextLayout);
|
|
1971
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1972
|
+
if (onLayout) {
|
|
1973
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1974
|
+
sizePercentage,
|
|
1975
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1976
|
+
})));
|
|
1977
|
+
}
|
|
1978
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1979
|
+
}
|
|
1980
|
+
}, 0);
|
|
1890
1981
|
}, []);
|
|
1891
1982
|
const context = useMemo(() => ({
|
|
1892
1983
|
collapsePanel,
|