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
|
@@ -95,6 +95,7 @@ function PanelWithForwardedRef({
|
|
|
95
95
|
expandPanel,
|
|
96
96
|
getPanelSize,
|
|
97
97
|
getPanelStyle,
|
|
98
|
+
groupId,
|
|
98
99
|
isPanelCollapsed,
|
|
99
100
|
registerPanel,
|
|
100
101
|
resizePanel,
|
|
@@ -199,6 +200,7 @@ function PanelWithForwardedRef({
|
|
|
199
200
|
// CSS selectors
|
|
200
201
|
"data-panel": "",
|
|
201
202
|
"data-panel-id": panelId,
|
|
203
|
+
"data-panel-group-id": groupId,
|
|
202
204
|
// e2e test attributes
|
|
203
205
|
"data-panel-collapsible": collapsible || undefined ,
|
|
204
206
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -211,8 +213,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
211
213
|
PanelWithForwardedRef.displayName = "Panel";
|
|
212
214
|
Panel.displayName = "forwardRef(Panel)";
|
|
213
215
|
|
|
214
|
-
const PRECISION = 10;
|
|
215
|
-
|
|
216
216
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
217
217
|
return pixels / groupSizePixels * 100;
|
|
218
218
|
}
|
|
@@ -290,6 +290,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
290
290
|
};
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
+
const PRECISION = 10;
|
|
294
|
+
|
|
293
295
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
294
296
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
295
297
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -773,15 +775,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
773
775
|
}, [groupId, layout, panelDataArray]);
|
|
774
776
|
useEffect(() => {
|
|
775
777
|
const {
|
|
776
|
-
direction,
|
|
777
778
|
panelDataArray
|
|
778
779
|
} = committedValuesRef.current;
|
|
779
780
|
const groupElement = getPanelGroupElement(groupId);
|
|
780
781
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
781
|
-
const {
|
|
782
|
-
height,
|
|
783
|
-
width
|
|
784
|
-
} = groupElement.getBoundingClientRect();
|
|
785
782
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
786
783
|
const cleanupFunctions = handles.map(handle => {
|
|
787
784
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -801,21 +798,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
801
798
|
if (index >= 0) {
|
|
802
799
|
const panelData = panelDataArray[index];
|
|
803
800
|
const size = layout[index];
|
|
804
|
-
if (size != null) {
|
|
805
|
-
var _getPercentageSizeFro;
|
|
801
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
802
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
806
803
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
807
|
-
const
|
|
804
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
805
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
806
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
807
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
808
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
808
809
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
809
810
|
sizePixels: panelData.constraints.minSizePixels
|
|
810
|
-
}, groupSizePixels)) !== null &&
|
|
811
|
-
let delta = 0;
|
|
812
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
813
|
-
delta = direction === "horizontal" ? width : height;
|
|
814
|
-
} else {
|
|
815
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
816
|
-
}
|
|
811
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
817
812
|
const nextLayout = adjustLayoutByDelta({
|
|
818
|
-
delta,
|
|
813
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
819
814
|
groupSizePixels,
|
|
820
815
|
layout,
|
|
821
816
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1124,6 +1119,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1124
1119
|
return callable;
|
|
1125
1120
|
}
|
|
1126
1121
|
|
|
1122
|
+
function getPanelElementsForGroup(groupId) {
|
|
1123
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1127
1126
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1128
1127
|
// or on a browser with cookies/storage disabled.
|
|
1129
1128
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1350,7 +1349,7 @@ const defaultStorage = {
|
|
|
1350
1349
|
};
|
|
1351
1350
|
const debounceMap = {};
|
|
1352
1351
|
function PanelGroupWithForwardedRef({
|
|
1353
|
-
autoSaveId,
|
|
1352
|
+
autoSaveId = null,
|
|
1354
1353
|
children,
|
|
1355
1354
|
className: classNameFromProps = "",
|
|
1356
1355
|
dataAttributes,
|
|
@@ -1367,11 +1366,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1367
1366
|
const groupId = useUniqueId(idFromProps);
|
|
1368
1367
|
const [dragState, setDragState] = useState(null);
|
|
1369
1368
|
const [layout, setLayout] = useState([]);
|
|
1370
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1371
1369
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1372
1370
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1373
1371
|
const prevDeltaRef = useRef(0);
|
|
1374
1372
|
const committedValuesRef = useRef({
|
|
1373
|
+
autoSaveId,
|
|
1375
1374
|
direction,
|
|
1376
1375
|
dragState,
|
|
1377
1376
|
id: groupId,
|
|
@@ -1379,7 +1378,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1379
1378
|
keyboardResizeByPixels,
|
|
1380
1379
|
layout,
|
|
1381
1380
|
onLayout,
|
|
1382
|
-
panelDataArray
|
|
1381
|
+
panelDataArray: [],
|
|
1382
|
+
storage
|
|
1383
1383
|
});
|
|
1384
1384
|
const devWarningsRef = useRef({
|
|
1385
1385
|
didLogIdAndOrderWarning: false,
|
|
@@ -1417,6 +1417,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1417
1417
|
});
|
|
1418
1418
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1419
1419
|
setLayout(safeLayout);
|
|
1420
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1420
1421
|
if (onLayout) {
|
|
1421
1422
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1422
1423
|
sizePercentage,
|
|
@@ -1428,21 +1429,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1428
1429
|
}
|
|
1429
1430
|
}), []);
|
|
1430
1431
|
useIsomorphicLayoutEffect(() => {
|
|
1432
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1431
1433
|
committedValuesRef.current.direction = direction;
|
|
1432
1434
|
committedValuesRef.current.dragState = dragState;
|
|
1433
1435
|
committedValuesRef.current.id = groupId;
|
|
1434
|
-
committedValuesRef.current.layout = layout;
|
|
1435
1436
|
committedValuesRef.current.onLayout = onLayout;
|
|
1436
|
-
committedValuesRef.current.
|
|
1437
|
+
committedValuesRef.current.storage = storage;
|
|
1438
|
+
|
|
1439
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1440
|
+
// TODO [217] Move these values into a separate ref
|
|
1437
1441
|
});
|
|
1442
|
+
|
|
1438
1443
|
useWindowSplitterPanelGroupBehavior({
|
|
1439
1444
|
committedValuesRef,
|
|
1440
1445
|
groupId,
|
|
1441
1446
|
layout,
|
|
1442
|
-
panelDataArray,
|
|
1447
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1443
1448
|
setLayout
|
|
1444
1449
|
});
|
|
1445
1450
|
useEffect(() => {
|
|
1451
|
+
const {
|
|
1452
|
+
panelDataArray
|
|
1453
|
+
} = committedValuesRef.current;
|
|
1454
|
+
|
|
1446
1455
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1447
1456
|
if (autoSaveId) {
|
|
1448
1457
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1455,59 +1464,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1455
1464
|
}
|
|
1456
1465
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1457
1466
|
}
|
|
1458
|
-
}, [autoSaveId, layout,
|
|
1459
|
-
|
|
1460
|
-
// Once all panels have registered themselves,
|
|
1461
|
-
// Compute the initial sizes based on default weights.
|
|
1462
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1467
|
+
}, [autoSaveId, layout, storage]);
|
|
1463
1468
|
useIsomorphicLayoutEffect(() => {
|
|
1464
1469
|
const {
|
|
1465
|
-
|
|
1466
|
-
layout,
|
|
1467
|
-
onLayout
|
|
1470
|
+
panelDataArray
|
|
1468
1471
|
} = committedValuesRef.current;
|
|
1469
|
-
if (layout.length === panelDataArray.length) {
|
|
1470
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1471
|
-
return;
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
// If this panel has been configured to persist sizing information,
|
|
1475
|
-
// default size should be restored from local storage if possible.
|
|
1476
|
-
let unsafeLayout = null;
|
|
1477
|
-
if (autoSaveId) {
|
|
1478
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1479
|
-
}
|
|
1480
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1481
|
-
if (groupSizePixels <= 0) {
|
|
1482
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1483
|
-
return;
|
|
1484
|
-
}
|
|
1485
|
-
if (unsafeLayout == null) {
|
|
1486
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1487
|
-
groupSizePixels,
|
|
1488
|
-
panelDataArray
|
|
1489
|
-
});
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1493
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1494
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1495
|
-
groupSizePixels,
|
|
1496
|
-
layout: unsafeLayout,
|
|
1497
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1498
|
-
});
|
|
1499
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1500
|
-
setLayout(validatedLayout);
|
|
1501
|
-
}
|
|
1502
|
-
if (onLayout) {
|
|
1503
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1504
|
-
sizePercentage,
|
|
1505
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1506
|
-
})));
|
|
1507
|
-
}
|
|
1508
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1509
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1510
|
-
useIsomorphicLayoutEffect(() => {
|
|
1511
1472
|
const constraints = panelDataArray.map(({
|
|
1512
1473
|
constraints
|
|
1513
1474
|
}) => constraints);
|
|
@@ -1531,6 +1492,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1531
1492
|
});
|
|
1532
1493
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1533
1494
|
setLayout(nextLayout);
|
|
1495
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1534
1496
|
if (onLayout) {
|
|
1535
1497
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1536
1498
|
sizePercentage,
|
|
@@ -1545,20 +1507,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1545
1507
|
resizeObserver.disconnect();
|
|
1546
1508
|
};
|
|
1547
1509
|
}
|
|
1548
|
-
}, [groupId
|
|
1510
|
+
}, [groupId]);
|
|
1549
1511
|
|
|
1550
1512
|
// DEV warnings
|
|
1551
1513
|
useEffect(() => {
|
|
1552
1514
|
{
|
|
1515
|
+
const {
|
|
1516
|
+
panelDataArray
|
|
1517
|
+
} = committedValuesRef.current;
|
|
1553
1518
|
const {
|
|
1554
1519
|
didLogIdAndOrderWarning,
|
|
1555
1520
|
didLogPanelConstraintsWarning,
|
|
1556
1521
|
prevPanelIds
|
|
1557
1522
|
} = devWarningsRef.current;
|
|
1558
1523
|
if (!didLogIdAndOrderWarning) {
|
|
1559
|
-
const {
|
|
1560
|
-
panelDataArray
|
|
1561
|
-
} = committedValuesRef.current;
|
|
1562
1524
|
const panelIds = panelDataArray.map(({
|
|
1563
1525
|
id
|
|
1564
1526
|
}) => id);
|
|
@@ -1624,6 +1586,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1624
1586
|
});
|
|
1625
1587
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1626
1588
|
setLayout(nextLayout);
|
|
1589
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1627
1590
|
if (onLayout) {
|
|
1628
1591
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1629
1592
|
sizePercentage,
|
|
@@ -1668,6 +1631,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1668
1631
|
});
|
|
1669
1632
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1670
1633
|
setLayout(nextLayout);
|
|
1634
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1671
1635
|
if (onLayout) {
|
|
1672
1636
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1673
1637
|
sizePercentage,
|
|
@@ -1698,6 +1662,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1698
1662
|
|
|
1699
1663
|
// This API should never read from committedValuesRef
|
|
1700
1664
|
const getPanelStyle = useCallback(panelData => {
|
|
1665
|
+
const {
|
|
1666
|
+
panelDataArray
|
|
1667
|
+
} = committedValuesRef.current;
|
|
1701
1668
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1702
1669
|
return computePanelFlexBoxStyle({
|
|
1703
1670
|
dragState,
|
|
@@ -1705,7 +1672,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1705
1672
|
panelData: panelDataArray,
|
|
1706
1673
|
panelIndex
|
|
1707
1674
|
});
|
|
1708
|
-
}, [dragState, layout
|
|
1675
|
+
}, [dragState, layout]);
|
|
1709
1676
|
|
|
1710
1677
|
// External APIs are safe to memoize via committed values ref
|
|
1711
1678
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1735,22 +1702,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1735
1702
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1736
1703
|
}, [groupId]);
|
|
1737
1704
|
const registerPanel = useCallback(panelData => {
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1705
|
+
const {
|
|
1706
|
+
autoSaveId,
|
|
1707
|
+
id: groupId,
|
|
1708
|
+
layout: prevLayout,
|
|
1709
|
+
onLayout,
|
|
1710
|
+
panelDataArray,
|
|
1711
|
+
storage
|
|
1712
|
+
} = committedValuesRef.current;
|
|
1713
|
+
panelDataArray.push(panelData);
|
|
1714
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1715
|
+
const orderA = panelA.order;
|
|
1716
|
+
const orderB = panelB.order;
|
|
1717
|
+
if (orderA == null && orderB == null) {
|
|
1718
|
+
return 0;
|
|
1719
|
+
} else if (orderA == null) {
|
|
1720
|
+
return -1;
|
|
1721
|
+
} else if (orderB == null) {
|
|
1722
|
+
return 1;
|
|
1723
|
+
} else {
|
|
1724
|
+
return orderA - orderB;
|
|
1725
|
+
}
|
|
1726
|
+
});
|
|
1727
|
+
|
|
1728
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1729
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1730
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1731
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// If this panel has been configured to persist sizing information,
|
|
1736
|
+
// default size should be restored from local storage if possible.
|
|
1737
|
+
let unsafeLayout = null;
|
|
1738
|
+
if (autoSaveId) {
|
|
1739
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1740
|
+
}
|
|
1741
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1742
|
+
if (groupSizePixels <= 0) {
|
|
1743
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1744
|
+
constraints
|
|
1745
|
+
}) => constraints))) {
|
|
1746
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
if (unsafeLayout == null) {
|
|
1751
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1752
|
+
groupSizePixels,
|
|
1753
|
+
panelDataArray
|
|
1752
1754
|
});
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1758
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1759
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1760
|
+
groupSizePixels,
|
|
1761
|
+
layout: unsafeLayout,
|
|
1762
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1753
1763
|
});
|
|
1764
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1765
|
+
setLayout(nextLayout);
|
|
1766
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1767
|
+
if (onLayout) {
|
|
1768
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1769
|
+
sizePercentage,
|
|
1770
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1771
|
+
})));
|
|
1772
|
+
}
|
|
1773
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1774
|
+
}
|
|
1754
1775
|
}, []);
|
|
1755
1776
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1756
1777
|
return function resizeHandler(event) {
|
|
@@ -1820,6 +1841,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1820
1841
|
}
|
|
1821
1842
|
if (layoutChanged) {
|
|
1822
1843
|
setLayout(nextLayout);
|
|
1844
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1823
1845
|
if (onLayout) {
|
|
1824
1846
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1825
1847
|
sizePercentage,
|
|
@@ -1857,6 +1879,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1857
1879
|
});
|
|
1858
1880
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1859
1881
|
setLayout(nextLayout);
|
|
1882
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1860
1883
|
if (onLayout) {
|
|
1861
1884
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1862
1885
|
sizePercentage,
|
|
@@ -1884,16 +1907,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1884
1907
|
resetGlobalCursorStyle();
|
|
1885
1908
|
setDragState(null);
|
|
1886
1909
|
}, []);
|
|
1910
|
+
const unregisterPanelRef = useRef({
|
|
1911
|
+
pendingPanelIds: new Set(),
|
|
1912
|
+
timeout: null
|
|
1913
|
+
});
|
|
1887
1914
|
const unregisterPanel = useCallback(panelData => {
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1915
|
+
const {
|
|
1916
|
+
id: groupId,
|
|
1917
|
+
layout: prevLayout,
|
|
1918
|
+
onLayout,
|
|
1919
|
+
panelDataArray
|
|
1920
|
+
} = committedValuesRef.current;
|
|
1921
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1922
|
+
if (index >= 0) {
|
|
1923
|
+
panelDataArray.splice(index, 1);
|
|
1924
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1925
|
+
}
|
|
1926
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1927
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1931
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1932
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1933
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1934
|
+
const {
|
|
1935
|
+
pendingPanelIds
|
|
1936
|
+
} = unregisterPanelRef.current;
|
|
1937
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1938
|
+
|
|
1939
|
+
// TRICKY
|
|
1940
|
+
// Strict effects mode
|
|
1941
|
+
let unmountDueToStrictMode = false;
|
|
1942
|
+
pendingPanelIds.forEach(panelId => {
|
|
1943
|
+
pendingPanelIds.delete(panelId);
|
|
1944
|
+
if (panelDataArray.find(({
|
|
1945
|
+
id
|
|
1946
|
+
}) => id === panelId) == null) {
|
|
1947
|
+
unmountDueToStrictMode = true;
|
|
1948
|
+
|
|
1949
|
+
// TRICKY
|
|
1950
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1951
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1952
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1953
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1954
|
+
}
|
|
1955
|
+
});
|
|
1956
|
+
if (!unmountDueToStrictMode) {
|
|
1957
|
+
return;
|
|
1894
1958
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1959
|
+
if (panelDataArray.length === 0) {
|
|
1960
|
+
// The group is unmounting; skip layout calculation.
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1964
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1965
|
+
groupSizePixels,
|
|
1966
|
+
panelDataArray
|
|
1967
|
+
});
|
|
1968
|
+
|
|
1969
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1970
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1971
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1972
|
+
groupSizePixels,
|
|
1973
|
+
layout: unsafeLayout,
|
|
1974
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1975
|
+
});
|
|
1976
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1977
|
+
setLayout(nextLayout);
|
|
1978
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1979
|
+
if (onLayout) {
|
|
1980
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1981
|
+
sizePercentage,
|
|
1982
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1983
|
+
})));
|
|
1984
|
+
}
|
|
1985
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1986
|
+
}
|
|
1987
|
+
}, 0);
|
|
1897
1988
|
}, []);
|
|
1898
1989
|
const context = useMemo(() => ({
|
|
1899
1990
|
collapsePanel,
|