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
|
@@ -71,6 +71,7 @@ function PanelWithForwardedRef({
|
|
|
71
71
|
expandPanel,
|
|
72
72
|
getPanelSize,
|
|
73
73
|
getPanelStyle,
|
|
74
|
+
groupId,
|
|
74
75
|
isPanelCollapsed,
|
|
75
76
|
registerPanel,
|
|
76
77
|
resizePanel,
|
|
@@ -175,6 +176,7 @@ function PanelWithForwardedRef({
|
|
|
175
176
|
// CSS selectors
|
|
176
177
|
"data-panel": "",
|
|
177
178
|
"data-panel-id": panelId,
|
|
179
|
+
"data-panel-group-id": groupId,
|
|
178
180
|
// e2e test attributes
|
|
179
181
|
"data-panel-collapsible": collapsible || undefined ,
|
|
180
182
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -187,8 +189,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
187
189
|
PanelWithForwardedRef.displayName = "Panel";
|
|
188
190
|
Panel.displayName = "forwardRef(Panel)";
|
|
189
191
|
|
|
190
|
-
const PRECISION = 10;
|
|
191
|
-
|
|
192
192
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
193
193
|
return pixels / groupSizePixels * 100;
|
|
194
194
|
}
|
|
@@ -266,6 +266,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
266
266
|
};
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
const PRECISION = 10;
|
|
270
|
+
|
|
269
271
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
270
272
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
271
273
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -749,15 +751,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
749
751
|
}, [groupId, layout, panelDataArray]);
|
|
750
752
|
useEffect(() => {
|
|
751
753
|
const {
|
|
752
|
-
direction,
|
|
753
754
|
panelDataArray
|
|
754
755
|
} = committedValuesRef.current;
|
|
755
756
|
const groupElement = getPanelGroupElement(groupId);
|
|
756
757
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
757
|
-
const {
|
|
758
|
-
height,
|
|
759
|
-
width
|
|
760
|
-
} = groupElement.getBoundingClientRect();
|
|
761
758
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
762
759
|
const cleanupFunctions = handles.map(handle => {
|
|
763
760
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -777,21 +774,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
777
774
|
if (index >= 0) {
|
|
778
775
|
const panelData = panelDataArray[index];
|
|
779
776
|
const size = layout[index];
|
|
780
|
-
if (size != null) {
|
|
781
|
-
var _getPercentageSizeFro;
|
|
777
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
778
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
782
779
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
783
|
-
const
|
|
780
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
781
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
782
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
783
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
784
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
784
785
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
785
786
|
sizePixels: panelData.constraints.minSizePixels
|
|
786
|
-
}, groupSizePixels)) !== null &&
|
|
787
|
-
let delta = 0;
|
|
788
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
789
|
-
delta = direction === "horizontal" ? width : height;
|
|
790
|
-
} else {
|
|
791
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
792
|
-
}
|
|
787
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
793
788
|
const nextLayout = adjustLayoutByDelta({
|
|
794
|
-
delta,
|
|
789
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
795
790
|
groupSizePixels,
|
|
796
791
|
layout,
|
|
797
792
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1100,6 +1095,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1100
1095
|
return callable;
|
|
1101
1096
|
}
|
|
1102
1097
|
|
|
1098
|
+
function getPanelElementsForGroup(groupId) {
|
|
1099
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1103
1102
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1104
1103
|
// or on a browser with cookies/storage disabled.
|
|
1105
1104
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1326,7 +1325,7 @@ const defaultStorage = {
|
|
|
1326
1325
|
};
|
|
1327
1326
|
const debounceMap = {};
|
|
1328
1327
|
function PanelGroupWithForwardedRef({
|
|
1329
|
-
autoSaveId,
|
|
1328
|
+
autoSaveId = null,
|
|
1330
1329
|
children,
|
|
1331
1330
|
className: classNameFromProps = "",
|
|
1332
1331
|
dataAttributes,
|
|
@@ -1343,11 +1342,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1343
1342
|
const groupId = useUniqueId(idFromProps);
|
|
1344
1343
|
const [dragState, setDragState] = useState(null);
|
|
1345
1344
|
const [layout, setLayout] = useState([]);
|
|
1346
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1347
1345
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1348
1346
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1349
1347
|
const prevDeltaRef = useRef(0);
|
|
1350
1348
|
const committedValuesRef = useRef({
|
|
1349
|
+
autoSaveId,
|
|
1351
1350
|
direction,
|
|
1352
1351
|
dragState,
|
|
1353
1352
|
id: groupId,
|
|
@@ -1355,7 +1354,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1355
1354
|
keyboardResizeByPixels,
|
|
1356
1355
|
layout,
|
|
1357
1356
|
onLayout,
|
|
1358
|
-
panelDataArray
|
|
1357
|
+
panelDataArray: [],
|
|
1358
|
+
storage
|
|
1359
1359
|
});
|
|
1360
1360
|
const devWarningsRef = useRef({
|
|
1361
1361
|
didLogIdAndOrderWarning: false,
|
|
@@ -1393,6 +1393,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1393
1393
|
});
|
|
1394
1394
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1395
1395
|
setLayout(safeLayout);
|
|
1396
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1396
1397
|
if (onLayout) {
|
|
1397
1398
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1398
1399
|
sizePercentage,
|
|
@@ -1404,21 +1405,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1404
1405
|
}
|
|
1405
1406
|
}), []);
|
|
1406
1407
|
useIsomorphicLayoutEffect(() => {
|
|
1408
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1407
1409
|
committedValuesRef.current.direction = direction;
|
|
1408
1410
|
committedValuesRef.current.dragState = dragState;
|
|
1409
1411
|
committedValuesRef.current.id = groupId;
|
|
1410
|
-
committedValuesRef.current.layout = layout;
|
|
1411
1412
|
committedValuesRef.current.onLayout = onLayout;
|
|
1412
|
-
committedValuesRef.current.
|
|
1413
|
+
committedValuesRef.current.storage = storage;
|
|
1414
|
+
|
|
1415
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1416
|
+
// TODO [217] Move these values into a separate ref
|
|
1413
1417
|
});
|
|
1418
|
+
|
|
1414
1419
|
useWindowSplitterPanelGroupBehavior({
|
|
1415
1420
|
committedValuesRef,
|
|
1416
1421
|
groupId,
|
|
1417
1422
|
layout,
|
|
1418
|
-
panelDataArray,
|
|
1423
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1419
1424
|
setLayout
|
|
1420
1425
|
});
|
|
1421
1426
|
useEffect(() => {
|
|
1427
|
+
const {
|
|
1428
|
+
panelDataArray
|
|
1429
|
+
} = committedValuesRef.current;
|
|
1430
|
+
|
|
1422
1431
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1423
1432
|
if (autoSaveId) {
|
|
1424
1433
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1431,59 +1440,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1431
1440
|
}
|
|
1432
1441
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1433
1442
|
}
|
|
1434
|
-
}, [autoSaveId, layout,
|
|
1435
|
-
|
|
1436
|
-
// Once all panels have registered themselves,
|
|
1437
|
-
// Compute the initial sizes based on default weights.
|
|
1438
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1443
|
+
}, [autoSaveId, layout, storage]);
|
|
1439
1444
|
useIsomorphicLayoutEffect(() => {
|
|
1440
1445
|
const {
|
|
1441
|
-
|
|
1442
|
-
layout,
|
|
1443
|
-
onLayout
|
|
1446
|
+
panelDataArray
|
|
1444
1447
|
} = committedValuesRef.current;
|
|
1445
|
-
if (layout.length === panelDataArray.length) {
|
|
1446
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
// If this panel has been configured to persist sizing information,
|
|
1451
|
-
// default size should be restored from local storage if possible.
|
|
1452
|
-
let unsafeLayout = null;
|
|
1453
|
-
if (autoSaveId) {
|
|
1454
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1455
|
-
}
|
|
1456
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1457
|
-
if (groupSizePixels <= 0) {
|
|
1458
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1459
|
-
return;
|
|
1460
|
-
}
|
|
1461
|
-
if (unsafeLayout == null) {
|
|
1462
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1463
|
-
groupSizePixels,
|
|
1464
|
-
panelDataArray
|
|
1465
|
-
});
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1469
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1470
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1471
|
-
groupSizePixels,
|
|
1472
|
-
layout: unsafeLayout,
|
|
1473
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1474
|
-
});
|
|
1475
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1476
|
-
setLayout(validatedLayout);
|
|
1477
|
-
}
|
|
1478
|
-
if (onLayout) {
|
|
1479
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1480
|
-
sizePercentage,
|
|
1481
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1482
|
-
})));
|
|
1483
|
-
}
|
|
1484
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1485
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1486
|
-
useIsomorphicLayoutEffect(() => {
|
|
1487
1448
|
const constraints = panelDataArray.map(({
|
|
1488
1449
|
constraints
|
|
1489
1450
|
}) => constraints);
|
|
@@ -1507,6 +1468,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1507
1468
|
});
|
|
1508
1469
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1509
1470
|
setLayout(nextLayout);
|
|
1471
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1510
1472
|
if (onLayout) {
|
|
1511
1473
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1512
1474
|
sizePercentage,
|
|
@@ -1521,20 +1483,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1521
1483
|
resizeObserver.disconnect();
|
|
1522
1484
|
};
|
|
1523
1485
|
}
|
|
1524
|
-
}, [groupId
|
|
1486
|
+
}, [groupId]);
|
|
1525
1487
|
|
|
1526
1488
|
// DEV warnings
|
|
1527
1489
|
useEffect(() => {
|
|
1528
1490
|
{
|
|
1491
|
+
const {
|
|
1492
|
+
panelDataArray
|
|
1493
|
+
} = committedValuesRef.current;
|
|
1529
1494
|
const {
|
|
1530
1495
|
didLogIdAndOrderWarning,
|
|
1531
1496
|
didLogPanelConstraintsWarning,
|
|
1532
1497
|
prevPanelIds
|
|
1533
1498
|
} = devWarningsRef.current;
|
|
1534
1499
|
if (!didLogIdAndOrderWarning) {
|
|
1535
|
-
const {
|
|
1536
|
-
panelDataArray
|
|
1537
|
-
} = committedValuesRef.current;
|
|
1538
1500
|
const panelIds = panelDataArray.map(({
|
|
1539
1501
|
id
|
|
1540
1502
|
}) => id);
|
|
@@ -1600,6 +1562,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1600
1562
|
});
|
|
1601
1563
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1602
1564
|
setLayout(nextLayout);
|
|
1565
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1603
1566
|
if (onLayout) {
|
|
1604
1567
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1605
1568
|
sizePercentage,
|
|
@@ -1644,6 +1607,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1644
1607
|
});
|
|
1645
1608
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1646
1609
|
setLayout(nextLayout);
|
|
1610
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1647
1611
|
if (onLayout) {
|
|
1648
1612
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1649
1613
|
sizePercentage,
|
|
@@ -1674,6 +1638,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1674
1638
|
|
|
1675
1639
|
// This API should never read from committedValuesRef
|
|
1676
1640
|
const getPanelStyle = useCallback(panelData => {
|
|
1641
|
+
const {
|
|
1642
|
+
panelDataArray
|
|
1643
|
+
} = committedValuesRef.current;
|
|
1677
1644
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1678
1645
|
return computePanelFlexBoxStyle({
|
|
1679
1646
|
dragState,
|
|
@@ -1681,7 +1648,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1681
1648
|
panelData: panelDataArray,
|
|
1682
1649
|
panelIndex
|
|
1683
1650
|
});
|
|
1684
|
-
}, [dragState, layout
|
|
1651
|
+
}, [dragState, layout]);
|
|
1685
1652
|
|
|
1686
1653
|
// External APIs are safe to memoize via committed values ref
|
|
1687
1654
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1711,22 +1678,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1711
1678
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1712
1679
|
}, [groupId]);
|
|
1713
1680
|
const registerPanel = useCallback(panelData => {
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1681
|
+
const {
|
|
1682
|
+
autoSaveId,
|
|
1683
|
+
id: groupId,
|
|
1684
|
+
layout: prevLayout,
|
|
1685
|
+
onLayout,
|
|
1686
|
+
panelDataArray,
|
|
1687
|
+
storage
|
|
1688
|
+
} = committedValuesRef.current;
|
|
1689
|
+
panelDataArray.push(panelData);
|
|
1690
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1691
|
+
const orderA = panelA.order;
|
|
1692
|
+
const orderB = panelB.order;
|
|
1693
|
+
if (orderA == null && orderB == null) {
|
|
1694
|
+
return 0;
|
|
1695
|
+
} else if (orderA == null) {
|
|
1696
|
+
return -1;
|
|
1697
|
+
} else if (orderB == null) {
|
|
1698
|
+
return 1;
|
|
1699
|
+
} else {
|
|
1700
|
+
return orderA - orderB;
|
|
1701
|
+
}
|
|
1702
|
+
});
|
|
1703
|
+
|
|
1704
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1705
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1706
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1707
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
// If this panel has been configured to persist sizing information,
|
|
1712
|
+
// default size should be restored from local storage if possible.
|
|
1713
|
+
let unsafeLayout = null;
|
|
1714
|
+
if (autoSaveId) {
|
|
1715
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1716
|
+
}
|
|
1717
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1718
|
+
if (groupSizePixels <= 0) {
|
|
1719
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1720
|
+
constraints
|
|
1721
|
+
}) => constraints))) {
|
|
1722
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
if (unsafeLayout == null) {
|
|
1727
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1728
|
+
groupSizePixels,
|
|
1729
|
+
panelDataArray
|
|
1728
1730
|
});
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1734
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1735
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1736
|
+
groupSizePixels,
|
|
1737
|
+
layout: unsafeLayout,
|
|
1738
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1729
1739
|
});
|
|
1740
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1741
|
+
setLayout(nextLayout);
|
|
1742
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1743
|
+
if (onLayout) {
|
|
1744
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1745
|
+
sizePercentage,
|
|
1746
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1747
|
+
})));
|
|
1748
|
+
}
|
|
1749
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1750
|
+
}
|
|
1730
1751
|
}, []);
|
|
1731
1752
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1732
1753
|
return function resizeHandler(event) {
|
|
@@ -1796,6 +1817,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1796
1817
|
}
|
|
1797
1818
|
if (layoutChanged) {
|
|
1798
1819
|
setLayout(nextLayout);
|
|
1820
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1799
1821
|
if (onLayout) {
|
|
1800
1822
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1801
1823
|
sizePercentage,
|
|
@@ -1833,6 +1855,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1833
1855
|
});
|
|
1834
1856
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1835
1857
|
setLayout(nextLayout);
|
|
1858
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1836
1859
|
if (onLayout) {
|
|
1837
1860
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1838
1861
|
sizePercentage,
|
|
@@ -1860,16 +1883,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1860
1883
|
resetGlobalCursorStyle();
|
|
1861
1884
|
setDragState(null);
|
|
1862
1885
|
}, []);
|
|
1886
|
+
const unregisterPanelRef = useRef({
|
|
1887
|
+
pendingPanelIds: new Set(),
|
|
1888
|
+
timeout: null
|
|
1889
|
+
});
|
|
1863
1890
|
const unregisterPanel = useCallback(panelData => {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1891
|
+
const {
|
|
1892
|
+
id: groupId,
|
|
1893
|
+
layout: prevLayout,
|
|
1894
|
+
onLayout,
|
|
1895
|
+
panelDataArray
|
|
1896
|
+
} = committedValuesRef.current;
|
|
1897
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1898
|
+
if (index >= 0) {
|
|
1899
|
+
panelDataArray.splice(index, 1);
|
|
1900
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1901
|
+
}
|
|
1902
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1903
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1907
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1908
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1909
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1910
|
+
const {
|
|
1911
|
+
pendingPanelIds
|
|
1912
|
+
} = unregisterPanelRef.current;
|
|
1913
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1914
|
+
|
|
1915
|
+
// TRICKY
|
|
1916
|
+
// Strict effects mode
|
|
1917
|
+
let unmountDueToStrictMode = false;
|
|
1918
|
+
pendingPanelIds.forEach(panelId => {
|
|
1919
|
+
pendingPanelIds.delete(panelId);
|
|
1920
|
+
if (panelDataArray.find(({
|
|
1921
|
+
id
|
|
1922
|
+
}) => id === panelId) == null) {
|
|
1923
|
+
unmountDueToStrictMode = true;
|
|
1924
|
+
|
|
1925
|
+
// TRICKY
|
|
1926
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1927
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1928
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1929
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1930
|
+
}
|
|
1931
|
+
});
|
|
1932
|
+
if (!unmountDueToStrictMode) {
|
|
1933
|
+
return;
|
|
1870
1934
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1935
|
+
if (panelDataArray.length === 0) {
|
|
1936
|
+
// The group is unmounting; skip layout calculation.
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1939
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1940
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1941
|
+
groupSizePixels,
|
|
1942
|
+
panelDataArray
|
|
1943
|
+
});
|
|
1944
|
+
|
|
1945
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1946
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1947
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1948
|
+
groupSizePixels,
|
|
1949
|
+
layout: unsafeLayout,
|
|
1950
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1951
|
+
});
|
|
1952
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1953
|
+
setLayout(nextLayout);
|
|
1954
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1955
|
+
if (onLayout) {
|
|
1956
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1957
|
+
sizePercentage,
|
|
1958
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1959
|
+
})));
|
|
1960
|
+
}
|
|
1961
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1962
|
+
}
|
|
1963
|
+
}, 0);
|
|
1873
1964
|
}, []);
|
|
1874
1965
|
const context = useMemo(() => ({
|
|
1875
1966
|
collapsePanel,
|