react-resizable-panels 0.0.59 → 0.0.61
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 +10 -0
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +226 -166
- package/dist/react-resizable-panels.browser.development.cjs.js +229 -169
- package/dist/react-resizable-panels.browser.development.esm.js +229 -169
- package/dist/react-resizable-panels.browser.esm.js +226 -166
- package/dist/react-resizable-panels.cjs.js +226 -166
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +229 -169
- package/dist/react-resizable-panels.development.esm.js +229 -169
- package/dist/react-resizable-panels.development.node.cjs.js +273 -87
- package/dist/react-resizable-panels.development.node.esm.js +273 -87
- package/dist/react-resizable-panels.esm.js +226 -166
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +270 -84
- package/dist/react-resizable-panels.node.esm.js +270 -84
- package/package.json +1 -1
- package/src/Panel.ts +2 -0
- package/src/PanelGroup.ts +242 -208
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +12 -2
- 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)
|
|
@@ -722,6 +724,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
722
724
|
|
|
723
725
|
function useWindowSplitterPanelGroupBehavior({
|
|
724
726
|
committedValuesRef,
|
|
727
|
+
eagerValuesRef,
|
|
725
728
|
groupId,
|
|
726
729
|
layout,
|
|
727
730
|
panelDataArray,
|
|
@@ -774,7 +777,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
774
777
|
useEffect(() => {
|
|
775
778
|
const {
|
|
776
779
|
panelDataArray
|
|
777
|
-
} =
|
|
780
|
+
} = eagerValuesRef.current;
|
|
778
781
|
const groupElement = getPanelGroupElement(groupId);
|
|
779
782
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
780
783
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -832,7 +835,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
832
835
|
return () => {
|
|
833
836
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
834
837
|
};
|
|
835
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
838
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
836
839
|
}
|
|
837
840
|
|
|
838
841
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1117,6 +1120,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1117
1120
|
return callable;
|
|
1118
1121
|
}
|
|
1119
1122
|
|
|
1123
|
+
function getPanelElementsForGroup(groupId) {
|
|
1124
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1120
1127
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1121
1128
|
// or on a browser with cookies/storage disabled.
|
|
1122
1129
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1343,7 +1350,7 @@ const defaultStorage = {
|
|
|
1343
1350
|
};
|
|
1344
1351
|
const debounceMap = {};
|
|
1345
1352
|
function PanelGroupWithForwardedRef({
|
|
1346
|
-
autoSaveId,
|
|
1353
|
+
autoSaveId = null,
|
|
1347
1354
|
children,
|
|
1348
1355
|
className: classNameFromProps = "",
|
|
1349
1356
|
dataAttributes,
|
|
@@ -1360,20 +1367,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1360
1367
|
const groupId = useUniqueId(idFromProps);
|
|
1361
1368
|
const [dragState, setDragState] = useState(null);
|
|
1362
1369
|
const [layout, setLayout] = useState([]);
|
|
1363
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1364
1370
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1365
1371
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1366
1372
|
const prevDeltaRef = useRef(0);
|
|
1367
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1368
1373
|
const committedValuesRef = useRef({
|
|
1374
|
+
autoSaveId,
|
|
1369
1375
|
direction,
|
|
1370
1376
|
dragState,
|
|
1371
1377
|
id: groupId,
|
|
1372
1378
|
keyboardResizeByPercentage,
|
|
1373
1379
|
keyboardResizeByPixels,
|
|
1374
|
-
layout,
|
|
1375
1380
|
onLayout,
|
|
1376
|
-
|
|
1381
|
+
storage
|
|
1382
|
+
});
|
|
1383
|
+
const eagerValuesRef = useRef({
|
|
1384
|
+
layout,
|
|
1385
|
+
panelDataArray: []
|
|
1377
1386
|
});
|
|
1378
1387
|
const devWarningsRef = useRef({
|
|
1379
1388
|
didLogIdAndOrderWarning: false,
|
|
@@ -1384,9 +1393,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1384
1393
|
getId: () => committedValuesRef.current.id,
|
|
1385
1394
|
getLayout: () => {
|
|
1386
1395
|
const {
|
|
1387
|
-
id: groupId
|
|
1388
|
-
layout
|
|
1396
|
+
id: groupId
|
|
1389
1397
|
} = committedValuesRef.current;
|
|
1398
|
+
const {
|
|
1399
|
+
layout
|
|
1400
|
+
} = eagerValuesRef.current;
|
|
1390
1401
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1391
1402
|
return layout.map(sizePercentage => {
|
|
1392
1403
|
return {
|
|
@@ -1398,10 +1409,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1398
1409
|
setLayout: mixedSizes => {
|
|
1399
1410
|
const {
|
|
1400
1411
|
id: groupId,
|
|
1412
|
+
onLayout
|
|
1413
|
+
} = committedValuesRef.current;
|
|
1414
|
+
const {
|
|
1401
1415
|
layout: prevLayout,
|
|
1402
|
-
onLayout,
|
|
1403
1416
|
panelDataArray
|
|
1404
|
-
} =
|
|
1417
|
+
} = eagerValuesRef.current;
|
|
1405
1418
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1406
1419
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1407
1420
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1411,6 +1424,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1411
1424
|
});
|
|
1412
1425
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1413
1426
|
setLayout(safeLayout);
|
|
1427
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1414
1428
|
if (onLayout) {
|
|
1415
1429
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1416
1430
|
sizePercentage,
|
|
@@ -1422,21 +1436,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1422
1436
|
}
|
|
1423
1437
|
}), []);
|
|
1424
1438
|
useIsomorphicLayoutEffect(() => {
|
|
1439
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1425
1440
|
committedValuesRef.current.direction = direction;
|
|
1426
1441
|
committedValuesRef.current.dragState = dragState;
|
|
1427
1442
|
committedValuesRef.current.id = groupId;
|
|
1428
|
-
committedValuesRef.current.layout = layout;
|
|
1429
1443
|
committedValuesRef.current.onLayout = onLayout;
|
|
1430
|
-
committedValuesRef.current.
|
|
1444
|
+
committedValuesRef.current.storage = storage;
|
|
1445
|
+
|
|
1446
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1447
|
+
// TODO [217] Move these values into a separate ref
|
|
1431
1448
|
});
|
|
1449
|
+
|
|
1432
1450
|
useWindowSplitterPanelGroupBehavior({
|
|
1433
1451
|
committedValuesRef,
|
|
1452
|
+
eagerValuesRef,
|
|
1434
1453
|
groupId,
|
|
1435
1454
|
layout,
|
|
1436
|
-
panelDataArray,
|
|
1455
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1437
1456
|
setLayout
|
|
1438
1457
|
});
|
|
1439
1458
|
useEffect(() => {
|
|
1459
|
+
const {
|
|
1460
|
+
panelDataArray
|
|
1461
|
+
} = eagerValuesRef.current;
|
|
1462
|
+
|
|
1440
1463
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1441
1464
|
if (autoSaveId) {
|
|
1442
1465
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1449,63 +1472,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1449
1472
|
}
|
|
1450
1473
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1451
1474
|
}
|
|
1452
|
-
}, [autoSaveId, layout,
|
|
1453
|
-
|
|
1454
|
-
// Once all panels have registered themselves,
|
|
1455
|
-
// Compute the initial sizes based on default weights.
|
|
1456
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1475
|
+
}, [autoSaveId, layout, storage]);
|
|
1457
1476
|
useIsomorphicLayoutEffect(() => {
|
|
1458
1477
|
const {
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
} = committedValuesRef.current;
|
|
1463
|
-
if (layout.length === panelDataArray.length) {
|
|
1464
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1465
|
-
return;
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
// If this panel has been configured to persist sizing information,
|
|
1469
|
-
// default size should be restored from local storage if possible.
|
|
1470
|
-
let unsafeLayout = null;
|
|
1471
|
-
if (autoSaveId) {
|
|
1472
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1473
|
-
}
|
|
1474
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1475
|
-
if (groupSizePixels <= 0) {
|
|
1476
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1477
|
-
constraints
|
|
1478
|
-
}) => constraints))) {
|
|
1479
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1480
|
-
return;
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
if (unsafeLayout == null) {
|
|
1484
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1485
|
-
groupSizePixels,
|
|
1486
|
-
panelDataArray
|
|
1487
|
-
});
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1491
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1492
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1493
|
-
groupSizePixels,
|
|
1494
|
-
layout: unsafeLayout,
|
|
1495
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1496
|
-
});
|
|
1497
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1498
|
-
setLayout(validatedLayout);
|
|
1499
|
-
}
|
|
1500
|
-
if (onLayout) {
|
|
1501
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1502
|
-
sizePercentage,
|
|
1503
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1504
|
-
})));
|
|
1505
|
-
}
|
|
1506
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1507
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1508
|
-
useIsomorphicLayoutEffect(() => {
|
|
1478
|
+
layout: prevLayout,
|
|
1479
|
+
panelDataArray
|
|
1480
|
+
} = eagerValuesRef.current;
|
|
1509
1481
|
const constraints = panelDataArray.map(({
|
|
1510
1482
|
constraints
|
|
1511
1483
|
}) => constraints);
|
|
@@ -1519,7 +1491,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1519
1491
|
const resizeObserver = new ResizeObserver(() => {
|
|
1520
1492
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1521
1493
|
const {
|
|
1522
|
-
layout: prevLayout,
|
|
1523
1494
|
onLayout
|
|
1524
1495
|
} = committedValuesRef.current;
|
|
1525
1496
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1529,6 +1500,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1529
1500
|
});
|
|
1530
1501
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1531
1502
|
setLayout(nextLayout);
|
|
1503
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1532
1504
|
if (onLayout) {
|
|
1533
1505
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1534
1506
|
sizePercentage,
|
|
@@ -1543,20 +1515,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1543
1515
|
resizeObserver.disconnect();
|
|
1544
1516
|
};
|
|
1545
1517
|
}
|
|
1546
|
-
}, [groupId
|
|
1518
|
+
}, [groupId]);
|
|
1547
1519
|
|
|
1548
1520
|
// DEV warnings
|
|
1549
1521
|
useEffect(() => {
|
|
1550
1522
|
{
|
|
1523
|
+
const {
|
|
1524
|
+
panelDataArray
|
|
1525
|
+
} = eagerValuesRef.current;
|
|
1551
1526
|
const {
|
|
1552
1527
|
didLogIdAndOrderWarning,
|
|
1553
1528
|
didLogPanelConstraintsWarning,
|
|
1554
1529
|
prevPanelIds
|
|
1555
1530
|
} = devWarningsRef.current;
|
|
1556
1531
|
if (!didLogIdAndOrderWarning) {
|
|
1557
|
-
const {
|
|
1558
|
-
panelDataArray
|
|
1559
|
-
} = committedValuesRef.current;
|
|
1560
1532
|
const panelIds = panelDataArray.map(({
|
|
1561
1533
|
id
|
|
1562
1534
|
}) => id);
|
|
@@ -1593,22 +1565,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1593
1565
|
|
|
1594
1566
|
// External APIs are safe to memoize via committed values ref
|
|
1595
1567
|
const collapsePanel = useCallback(panelData => {
|
|
1568
|
+
const {
|
|
1569
|
+
onLayout
|
|
1570
|
+
} = committedValuesRef.current;
|
|
1596
1571
|
const {
|
|
1597
1572
|
layout: prevLayout,
|
|
1598
|
-
onLayout,
|
|
1599
1573
|
panelDataArray
|
|
1600
|
-
} =
|
|
1601
|
-
|
|
1602
|
-
// See issues/211
|
|
1603
|
-
if (panelDataArray.find(({
|
|
1604
|
-
id
|
|
1605
|
-
}) => id === panelData.id) == null) {
|
|
1606
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1607
|
-
panelData,
|
|
1608
|
-
type: "collapse"
|
|
1609
|
-
}]);
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1574
|
+
} = eagerValuesRef.current;
|
|
1612
1575
|
if (panelData.constraints.collapsible) {
|
|
1613
1576
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1614
1577
|
const {
|
|
@@ -1633,6 +1596,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1633
1596
|
});
|
|
1634
1597
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1635
1598
|
setLayout(nextLayout);
|
|
1599
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1636
1600
|
if (onLayout) {
|
|
1637
1601
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1638
1602
|
sizePercentage,
|
|
@@ -1647,22 +1611,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1647
1611
|
|
|
1648
1612
|
// External APIs are safe to memoize via committed values ref
|
|
1649
1613
|
const expandPanel = useCallback(panelData => {
|
|
1614
|
+
const {
|
|
1615
|
+
onLayout
|
|
1616
|
+
} = committedValuesRef.current;
|
|
1650
1617
|
const {
|
|
1651
1618
|
layout: prevLayout,
|
|
1652
|
-
onLayout,
|
|
1653
1619
|
panelDataArray
|
|
1654
|
-
} =
|
|
1655
|
-
|
|
1656
|
-
// See issues/211
|
|
1657
|
-
if (panelDataArray.find(({
|
|
1658
|
-
id
|
|
1659
|
-
}) => id === panelData.id) == null) {
|
|
1660
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1661
|
-
panelData,
|
|
1662
|
-
type: "expand"
|
|
1663
|
-
}]);
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1620
|
+
} = eagerValuesRef.current;
|
|
1666
1621
|
if (panelData.constraints.collapsible) {
|
|
1667
1622
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1668
1623
|
const {
|
|
@@ -1688,6 +1643,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1688
1643
|
});
|
|
1689
1644
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1690
1645
|
setLayout(nextLayout);
|
|
1646
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1691
1647
|
if (onLayout) {
|
|
1692
1648
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1693
1649
|
sizePercentage,
|
|
@@ -1705,7 +1661,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1705
1661
|
const {
|
|
1706
1662
|
layout,
|
|
1707
1663
|
panelDataArray
|
|
1708
|
-
} =
|
|
1664
|
+
} = eagerValuesRef.current;
|
|
1709
1665
|
const {
|
|
1710
1666
|
panelSizePercentage,
|
|
1711
1667
|
panelSizePixels
|
|
@@ -1718,6 +1674,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1718
1674
|
|
|
1719
1675
|
// This API should never read from committedValuesRef
|
|
1720
1676
|
const getPanelStyle = useCallback(panelData => {
|
|
1677
|
+
const {
|
|
1678
|
+
panelDataArray
|
|
1679
|
+
} = eagerValuesRef.current;
|
|
1721
1680
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1722
1681
|
return computePanelFlexBoxStyle({
|
|
1723
1682
|
dragState,
|
|
@@ -1725,14 +1684,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1725
1684
|
panelData: panelDataArray,
|
|
1726
1685
|
panelIndex
|
|
1727
1686
|
});
|
|
1728
|
-
}, [dragState, layout
|
|
1687
|
+
}, [dragState, layout]);
|
|
1729
1688
|
|
|
1730
1689
|
// External APIs are safe to memoize via committed values ref
|
|
1731
1690
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1732
1691
|
const {
|
|
1733
1692
|
layout,
|
|
1734
1693
|
panelDataArray
|
|
1735
|
-
} =
|
|
1694
|
+
} = eagerValuesRef.current;
|
|
1736
1695
|
const {
|
|
1737
1696
|
collapsedSizePercentage,
|
|
1738
1697
|
collapsible,
|
|
@@ -1746,7 +1705,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1746
1705
|
const {
|
|
1747
1706
|
layout,
|
|
1748
1707
|
panelDataArray
|
|
1749
|
-
} =
|
|
1708
|
+
} = eagerValuesRef.current;
|
|
1750
1709
|
const {
|
|
1751
1710
|
collapsedSizePercentage,
|
|
1752
1711
|
collapsible,
|
|
@@ -1755,22 +1714,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1755
1714
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1756
1715
|
}, [groupId]);
|
|
1757
1716
|
const registerPanel = useCallback(panelData => {
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1717
|
+
const {
|
|
1718
|
+
autoSaveId,
|
|
1719
|
+
id: groupId,
|
|
1720
|
+
onLayout,
|
|
1721
|
+
storage
|
|
1722
|
+
} = committedValuesRef.current;
|
|
1723
|
+
const {
|
|
1724
|
+
layout: prevLayout,
|
|
1725
|
+
panelDataArray
|
|
1726
|
+
} = eagerValuesRef.current;
|
|
1727
|
+
panelDataArray.push(panelData);
|
|
1728
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1729
|
+
const orderA = panelA.order;
|
|
1730
|
+
const orderB = panelB.order;
|
|
1731
|
+
if (orderA == null && orderB == null) {
|
|
1732
|
+
return 0;
|
|
1733
|
+
} else if (orderA == null) {
|
|
1734
|
+
return -1;
|
|
1735
|
+
} else if (orderB == null) {
|
|
1736
|
+
return 1;
|
|
1737
|
+
} else {
|
|
1738
|
+
return orderA - orderB;
|
|
1739
|
+
}
|
|
1740
|
+
});
|
|
1741
|
+
|
|
1742
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1743
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1744
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1745
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// If this panel has been configured to persist sizing information,
|
|
1750
|
+
// default size should be restored from local storage if possible.
|
|
1751
|
+
let unsafeLayout = null;
|
|
1752
|
+
if (autoSaveId) {
|
|
1753
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1754
|
+
}
|
|
1755
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1756
|
+
if (groupSizePixels <= 0) {
|
|
1757
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1758
|
+
constraints
|
|
1759
|
+
}) => constraints))) {
|
|
1760
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
if (unsafeLayout == null) {
|
|
1765
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1766
|
+
groupSizePixels,
|
|
1767
|
+
panelDataArray
|
|
1772
1768
|
});
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1772
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1773
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1774
|
+
groupSizePixels,
|
|
1775
|
+
layout: unsafeLayout,
|
|
1776
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1773
1777
|
});
|
|
1778
|
+
|
|
1779
|
+
// Offscreen mode makes this a bit weird;
|
|
1780
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1781
|
+
// but the overall layout doesn't change between these two cases.
|
|
1782
|
+
setLayout(nextLayout);
|
|
1783
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1784
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1785
|
+
if (onLayout) {
|
|
1786
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1787
|
+
sizePercentage,
|
|
1788
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1789
|
+
})));
|
|
1790
|
+
}
|
|
1791
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1792
|
+
}
|
|
1774
1793
|
}, []);
|
|
1775
1794
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1776
1795
|
return function resizeHandler(event) {
|
|
@@ -1781,10 +1800,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1781
1800
|
id: groupId,
|
|
1782
1801
|
keyboardResizeByPercentage,
|
|
1783
1802
|
keyboardResizeByPixels,
|
|
1784
|
-
onLayout
|
|
1785
|
-
panelDataArray,
|
|
1786
|
-
layout: prevLayout
|
|
1803
|
+
onLayout
|
|
1787
1804
|
} = committedValuesRef.current;
|
|
1805
|
+
const {
|
|
1806
|
+
layout: prevLayout,
|
|
1807
|
+
panelDataArray
|
|
1808
|
+
} = eagerValuesRef.current;
|
|
1788
1809
|
const {
|
|
1789
1810
|
initialLayout
|
|
1790
1811
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1840,6 +1861,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1840
1861
|
}
|
|
1841
1862
|
if (layoutChanged) {
|
|
1842
1863
|
setLayout(nextLayout);
|
|
1864
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1843
1865
|
if (onLayout) {
|
|
1844
1866
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1845
1867
|
sizePercentage,
|
|
@@ -1853,23 +1875,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1853
1875
|
|
|
1854
1876
|
// External APIs are safe to memoize via committed values ref
|
|
1855
1877
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1878
|
+
const {
|
|
1879
|
+
onLayout
|
|
1880
|
+
} = committedValuesRef.current;
|
|
1856
1881
|
const {
|
|
1857
1882
|
layout: prevLayout,
|
|
1858
|
-
onLayout,
|
|
1859
1883
|
panelDataArray
|
|
1860
|
-
} =
|
|
1861
|
-
|
|
1862
|
-
// See issues/211
|
|
1863
|
-
if (panelDataArray.find(({
|
|
1864
|
-
id
|
|
1865
|
-
}) => id === panelData.id) == null) {
|
|
1866
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1867
|
-
panelData,
|
|
1868
|
-
mixedSizes,
|
|
1869
|
-
type: "resize"
|
|
1870
|
-
}]);
|
|
1871
|
-
return;
|
|
1872
|
-
}
|
|
1884
|
+
} = eagerValuesRef.current;
|
|
1873
1885
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1874
1886
|
const {
|
|
1875
1887
|
groupSizePixels,
|
|
@@ -1889,6 +1901,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1889
1901
|
});
|
|
1890
1902
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1891
1903
|
setLayout(nextLayout);
|
|
1904
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1892
1905
|
if (onLayout) {
|
|
1893
1906
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1894
1907
|
sizePercentage,
|
|
@@ -1900,9 +1913,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1900
1913
|
}, [groupId]);
|
|
1901
1914
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1902
1915
|
const {
|
|
1903
|
-
direction
|
|
1904
|
-
layout
|
|
1916
|
+
direction
|
|
1905
1917
|
} = committedValuesRef.current;
|
|
1918
|
+
const {
|
|
1919
|
+
layout
|
|
1920
|
+
} = eagerValuesRef.current;
|
|
1906
1921
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1907
1922
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1908
1923
|
setDragState({
|
|
@@ -1916,42 +1931,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1916
1931
|
resetGlobalCursorStyle();
|
|
1917
1932
|
setDragState(null);
|
|
1918
1933
|
}, []);
|
|
1934
|
+
const unregisterPanelRef = useRef({
|
|
1935
|
+
pendingPanelIds: new Set(),
|
|
1936
|
+
timeout: null
|
|
1937
|
+
});
|
|
1919
1938
|
const unregisterPanel = useCallback(panelData => {
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1939
|
+
const {
|
|
1940
|
+
id: groupId,
|
|
1941
|
+
onLayout
|
|
1942
|
+
} = committedValuesRef.current;
|
|
1943
|
+
const {
|
|
1944
|
+
layout: prevLayout,
|
|
1945
|
+
panelDataArray
|
|
1946
|
+
} = eagerValuesRef.current;
|
|
1947
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1948
|
+
if (index >= 0) {
|
|
1949
|
+
panelDataArray.splice(index, 1);
|
|
1950
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1951
|
+
}
|
|
1952
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1953
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1957
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1958
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1959
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1960
|
+
const {
|
|
1961
|
+
pendingPanelIds
|
|
1962
|
+
} = unregisterPanelRef.current;
|
|
1963
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1964
|
+
|
|
1965
|
+
// TRICKY
|
|
1966
|
+
// Strict effects mode
|
|
1967
|
+
let unmountDueToStrictMode = false;
|
|
1968
|
+
pendingPanelIds.forEach(panelId => {
|
|
1969
|
+
pendingPanelIds.delete(panelId);
|
|
1970
|
+
if (panelDataArray.find(({
|
|
1971
|
+
id
|
|
1972
|
+
}) => id === panelId) == null) {
|
|
1973
|
+
unmountDueToStrictMode = true;
|
|
1974
|
+
|
|
1975
|
+
// TRICKY
|
|
1976
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1977
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1978
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1979
|
+
delete map[panelData.id];
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
if (!unmountDueToStrictMode) {
|
|
1983
|
+
return;
|
|
1926
1984
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1985
|
+
if (panelDataArray.length === 0) {
|
|
1986
|
+
// The group is unmounting; skip layout calculation.
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1990
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1991
|
+
groupSizePixels,
|
|
1992
|
+
panelDataArray
|
|
1993
|
+
});
|
|
1930
1994
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
{
|
|
1949
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1950
|
-
break;
|
|
1951
|
-
}
|
|
1995
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1996
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1997
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1998
|
+
groupSizePixels,
|
|
1999
|
+
layout: unsafeLayout,
|
|
2000
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
2001
|
+
});
|
|
2002
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
2003
|
+
setLayout(nextLayout);
|
|
2004
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
2005
|
+
if (onLayout) {
|
|
2006
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
2007
|
+
sizePercentage,
|
|
2008
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
2009
|
+
})));
|
|
2010
|
+
}
|
|
2011
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1952
2012
|
}
|
|
1953
|
-
}
|
|
1954
|
-
}, [
|
|
2013
|
+
}, 0);
|
|
2014
|
+
}, []);
|
|
1955
2015
|
const context = useMemo(() => ({
|
|
1956
2016
|
collapsePanel,
|
|
1957
2017
|
direction,
|