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
|
@@ -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)
|
|
@@ -715,6 +717,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
715
717
|
|
|
716
718
|
function useWindowSplitterPanelGroupBehavior({
|
|
717
719
|
committedValuesRef,
|
|
720
|
+
eagerValuesRef,
|
|
718
721
|
groupId,
|
|
719
722
|
layout,
|
|
720
723
|
panelDataArray,
|
|
@@ -767,7 +770,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
767
770
|
useEffect(() => {
|
|
768
771
|
const {
|
|
769
772
|
panelDataArray
|
|
770
|
-
} =
|
|
773
|
+
} = eagerValuesRef.current;
|
|
771
774
|
const groupElement = getPanelGroupElement(groupId);
|
|
772
775
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
773
776
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -825,7 +828,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
825
828
|
return () => {
|
|
826
829
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
827
830
|
};
|
|
828
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
831
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
829
832
|
}
|
|
830
833
|
|
|
831
834
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1110,6 +1113,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1110
1113
|
return callable;
|
|
1111
1114
|
}
|
|
1112
1115
|
|
|
1116
|
+
function getPanelElementsForGroup(groupId) {
|
|
1117
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1113
1120
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1114
1121
|
// or on a browser with cookies/storage disabled.
|
|
1115
1122
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1336,7 +1343,7 @@ const defaultStorage = {
|
|
|
1336
1343
|
};
|
|
1337
1344
|
const debounceMap = {};
|
|
1338
1345
|
function PanelGroupWithForwardedRef({
|
|
1339
|
-
autoSaveId,
|
|
1346
|
+
autoSaveId = null,
|
|
1340
1347
|
children,
|
|
1341
1348
|
className: classNameFromProps = "",
|
|
1342
1349
|
dataAttributes,
|
|
@@ -1353,20 +1360,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1353
1360
|
const groupId = useUniqueId(idFromProps);
|
|
1354
1361
|
const [dragState, setDragState] = useState(null);
|
|
1355
1362
|
const [layout, setLayout] = useState([]);
|
|
1356
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1357
1363
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1358
1364
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1359
1365
|
const prevDeltaRef = useRef(0);
|
|
1360
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1361
1366
|
const committedValuesRef = useRef({
|
|
1367
|
+
autoSaveId,
|
|
1362
1368
|
direction,
|
|
1363
1369
|
dragState,
|
|
1364
1370
|
id: groupId,
|
|
1365
1371
|
keyboardResizeByPercentage,
|
|
1366
1372
|
keyboardResizeByPixels,
|
|
1367
|
-
layout,
|
|
1368
1373
|
onLayout,
|
|
1369
|
-
|
|
1374
|
+
storage
|
|
1375
|
+
});
|
|
1376
|
+
const eagerValuesRef = useRef({
|
|
1377
|
+
layout,
|
|
1378
|
+
panelDataArray: []
|
|
1370
1379
|
});
|
|
1371
1380
|
const devWarningsRef = useRef({
|
|
1372
1381
|
didLogIdAndOrderWarning: false,
|
|
@@ -1377,9 +1386,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1377
1386
|
getId: () => committedValuesRef.current.id,
|
|
1378
1387
|
getLayout: () => {
|
|
1379
1388
|
const {
|
|
1380
|
-
id: groupId
|
|
1381
|
-
layout
|
|
1389
|
+
id: groupId
|
|
1382
1390
|
} = committedValuesRef.current;
|
|
1391
|
+
const {
|
|
1392
|
+
layout
|
|
1393
|
+
} = eagerValuesRef.current;
|
|
1383
1394
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1384
1395
|
return layout.map(sizePercentage => {
|
|
1385
1396
|
return {
|
|
@@ -1391,10 +1402,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1391
1402
|
setLayout: mixedSizes => {
|
|
1392
1403
|
const {
|
|
1393
1404
|
id: groupId,
|
|
1405
|
+
onLayout
|
|
1406
|
+
} = committedValuesRef.current;
|
|
1407
|
+
const {
|
|
1394
1408
|
layout: prevLayout,
|
|
1395
|
-
onLayout,
|
|
1396
1409
|
panelDataArray
|
|
1397
|
-
} =
|
|
1410
|
+
} = eagerValuesRef.current;
|
|
1398
1411
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1399
1412
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1400
1413
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1404,6 +1417,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1404
1417
|
});
|
|
1405
1418
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1406
1419
|
setLayout(safeLayout);
|
|
1420
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1407
1421
|
if (onLayout) {
|
|
1408
1422
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1409
1423
|
sizePercentage,
|
|
@@ -1415,21 +1429,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1415
1429
|
}
|
|
1416
1430
|
}), []);
|
|
1417
1431
|
useIsomorphicLayoutEffect(() => {
|
|
1432
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1418
1433
|
committedValuesRef.current.direction = direction;
|
|
1419
1434
|
committedValuesRef.current.dragState = dragState;
|
|
1420
1435
|
committedValuesRef.current.id = groupId;
|
|
1421
|
-
committedValuesRef.current.layout = layout;
|
|
1422
1436
|
committedValuesRef.current.onLayout = onLayout;
|
|
1423
|
-
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
|
|
1424
1441
|
});
|
|
1442
|
+
|
|
1425
1443
|
useWindowSplitterPanelGroupBehavior({
|
|
1426
1444
|
committedValuesRef,
|
|
1445
|
+
eagerValuesRef,
|
|
1427
1446
|
groupId,
|
|
1428
1447
|
layout,
|
|
1429
|
-
panelDataArray,
|
|
1448
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1430
1449
|
setLayout
|
|
1431
1450
|
});
|
|
1432
1451
|
useEffect(() => {
|
|
1452
|
+
const {
|
|
1453
|
+
panelDataArray
|
|
1454
|
+
} = eagerValuesRef.current;
|
|
1455
|
+
|
|
1433
1456
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1434
1457
|
if (autoSaveId) {
|
|
1435
1458
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1442,63 +1465,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1442
1465
|
}
|
|
1443
1466
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1444
1467
|
}
|
|
1445
|
-
}, [autoSaveId, layout,
|
|
1446
|
-
|
|
1447
|
-
// Once all panels have registered themselves,
|
|
1448
|
-
// Compute the initial sizes based on default weights.
|
|
1449
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1468
|
+
}, [autoSaveId, layout, storage]);
|
|
1450
1469
|
useIsomorphicLayoutEffect(() => {
|
|
1451
1470
|
const {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
} = committedValuesRef.current;
|
|
1456
|
-
if (layout.length === panelDataArray.length) {
|
|
1457
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1458
|
-
return;
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
// If this panel has been configured to persist sizing information,
|
|
1462
|
-
// default size should be restored from local storage if possible.
|
|
1463
|
-
let unsafeLayout = null;
|
|
1464
|
-
if (autoSaveId) {
|
|
1465
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1466
|
-
}
|
|
1467
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1468
|
-
if (groupSizePixels <= 0) {
|
|
1469
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1470
|
-
constraints
|
|
1471
|
-
}) => constraints))) {
|
|
1472
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1473
|
-
return;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
if (unsafeLayout == null) {
|
|
1477
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1478
|
-
groupSizePixels,
|
|
1479
|
-
panelDataArray
|
|
1480
|
-
});
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1484
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1485
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1486
|
-
groupSizePixels,
|
|
1487
|
-
layout: unsafeLayout,
|
|
1488
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1489
|
-
});
|
|
1490
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1491
|
-
setLayout(validatedLayout);
|
|
1492
|
-
}
|
|
1493
|
-
if (onLayout) {
|
|
1494
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1495
|
-
sizePercentage,
|
|
1496
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1497
|
-
})));
|
|
1498
|
-
}
|
|
1499
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1500
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1501
|
-
useIsomorphicLayoutEffect(() => {
|
|
1471
|
+
layout: prevLayout,
|
|
1472
|
+
panelDataArray
|
|
1473
|
+
} = eagerValuesRef.current;
|
|
1502
1474
|
const constraints = panelDataArray.map(({
|
|
1503
1475
|
constraints
|
|
1504
1476
|
}) => constraints);
|
|
@@ -1512,7 +1484,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1512
1484
|
const resizeObserver = new ResizeObserver(() => {
|
|
1513
1485
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1514
1486
|
const {
|
|
1515
|
-
layout: prevLayout,
|
|
1516
1487
|
onLayout
|
|
1517
1488
|
} = committedValuesRef.current;
|
|
1518
1489
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1522,6 +1493,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1522
1493
|
});
|
|
1523
1494
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1524
1495
|
setLayout(nextLayout);
|
|
1496
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1525
1497
|
if (onLayout) {
|
|
1526
1498
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1527
1499
|
sizePercentage,
|
|
@@ -1536,20 +1508,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1536
1508
|
resizeObserver.disconnect();
|
|
1537
1509
|
};
|
|
1538
1510
|
}
|
|
1539
|
-
}, [groupId
|
|
1511
|
+
}, [groupId]);
|
|
1540
1512
|
|
|
1541
1513
|
// DEV warnings
|
|
1542
1514
|
useEffect(() => {
|
|
1543
1515
|
{
|
|
1516
|
+
const {
|
|
1517
|
+
panelDataArray
|
|
1518
|
+
} = eagerValuesRef.current;
|
|
1544
1519
|
const {
|
|
1545
1520
|
didLogIdAndOrderWarning,
|
|
1546
1521
|
didLogPanelConstraintsWarning,
|
|
1547
1522
|
prevPanelIds
|
|
1548
1523
|
} = devWarningsRef.current;
|
|
1549
1524
|
if (!didLogIdAndOrderWarning) {
|
|
1550
|
-
const {
|
|
1551
|
-
panelDataArray
|
|
1552
|
-
} = committedValuesRef.current;
|
|
1553
1525
|
const panelIds = panelDataArray.map(({
|
|
1554
1526
|
id
|
|
1555
1527
|
}) => id);
|
|
@@ -1586,22 +1558,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1586
1558
|
|
|
1587
1559
|
// External APIs are safe to memoize via committed values ref
|
|
1588
1560
|
const collapsePanel = useCallback(panelData => {
|
|
1561
|
+
const {
|
|
1562
|
+
onLayout
|
|
1563
|
+
} = committedValuesRef.current;
|
|
1589
1564
|
const {
|
|
1590
1565
|
layout: prevLayout,
|
|
1591
|
-
onLayout,
|
|
1592
1566
|
panelDataArray
|
|
1593
|
-
} =
|
|
1594
|
-
|
|
1595
|
-
// See issues/211
|
|
1596
|
-
if (panelDataArray.find(({
|
|
1597
|
-
id
|
|
1598
|
-
}) => id === panelData.id) == null) {
|
|
1599
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1600
|
-
panelData,
|
|
1601
|
-
type: "collapse"
|
|
1602
|
-
}]);
|
|
1603
|
-
return;
|
|
1604
|
-
}
|
|
1567
|
+
} = eagerValuesRef.current;
|
|
1605
1568
|
if (panelData.constraints.collapsible) {
|
|
1606
1569
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1607
1570
|
const {
|
|
@@ -1626,6 +1589,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1626
1589
|
});
|
|
1627
1590
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1628
1591
|
setLayout(nextLayout);
|
|
1592
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1629
1593
|
if (onLayout) {
|
|
1630
1594
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1631
1595
|
sizePercentage,
|
|
@@ -1640,22 +1604,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1640
1604
|
|
|
1641
1605
|
// External APIs are safe to memoize via committed values ref
|
|
1642
1606
|
const expandPanel = useCallback(panelData => {
|
|
1607
|
+
const {
|
|
1608
|
+
onLayout
|
|
1609
|
+
} = committedValuesRef.current;
|
|
1643
1610
|
const {
|
|
1644
1611
|
layout: prevLayout,
|
|
1645
|
-
onLayout,
|
|
1646
1612
|
panelDataArray
|
|
1647
|
-
} =
|
|
1648
|
-
|
|
1649
|
-
// See issues/211
|
|
1650
|
-
if (panelDataArray.find(({
|
|
1651
|
-
id
|
|
1652
|
-
}) => id === panelData.id) == null) {
|
|
1653
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1654
|
-
panelData,
|
|
1655
|
-
type: "expand"
|
|
1656
|
-
}]);
|
|
1657
|
-
return;
|
|
1658
|
-
}
|
|
1613
|
+
} = eagerValuesRef.current;
|
|
1659
1614
|
if (panelData.constraints.collapsible) {
|
|
1660
1615
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1661
1616
|
const {
|
|
@@ -1681,6 +1636,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1681
1636
|
});
|
|
1682
1637
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1683
1638
|
setLayout(nextLayout);
|
|
1639
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1684
1640
|
if (onLayout) {
|
|
1685
1641
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1686
1642
|
sizePercentage,
|
|
@@ -1698,7 +1654,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1698
1654
|
const {
|
|
1699
1655
|
layout,
|
|
1700
1656
|
panelDataArray
|
|
1701
|
-
} =
|
|
1657
|
+
} = eagerValuesRef.current;
|
|
1702
1658
|
const {
|
|
1703
1659
|
panelSizePercentage,
|
|
1704
1660
|
panelSizePixels
|
|
@@ -1711,6 +1667,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1711
1667
|
|
|
1712
1668
|
// This API should never read from committedValuesRef
|
|
1713
1669
|
const getPanelStyle = useCallback(panelData => {
|
|
1670
|
+
const {
|
|
1671
|
+
panelDataArray
|
|
1672
|
+
} = eagerValuesRef.current;
|
|
1714
1673
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1715
1674
|
return computePanelFlexBoxStyle({
|
|
1716
1675
|
dragState,
|
|
@@ -1718,14 +1677,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1718
1677
|
panelData: panelDataArray,
|
|
1719
1678
|
panelIndex
|
|
1720
1679
|
});
|
|
1721
|
-
}, [dragState, layout
|
|
1680
|
+
}, [dragState, layout]);
|
|
1722
1681
|
|
|
1723
1682
|
// External APIs are safe to memoize via committed values ref
|
|
1724
1683
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1725
1684
|
const {
|
|
1726
1685
|
layout,
|
|
1727
1686
|
panelDataArray
|
|
1728
|
-
} =
|
|
1687
|
+
} = eagerValuesRef.current;
|
|
1729
1688
|
const {
|
|
1730
1689
|
collapsedSizePercentage,
|
|
1731
1690
|
collapsible,
|
|
@@ -1739,7 +1698,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1739
1698
|
const {
|
|
1740
1699
|
layout,
|
|
1741
1700
|
panelDataArray
|
|
1742
|
-
} =
|
|
1701
|
+
} = eagerValuesRef.current;
|
|
1743
1702
|
const {
|
|
1744
1703
|
collapsedSizePercentage,
|
|
1745
1704
|
collapsible,
|
|
@@ -1748,22 +1707,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1748
1707
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1749
1708
|
}, [groupId]);
|
|
1750
1709
|
const registerPanel = useCallback(panelData => {
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1710
|
+
const {
|
|
1711
|
+
autoSaveId,
|
|
1712
|
+
id: groupId,
|
|
1713
|
+
onLayout,
|
|
1714
|
+
storage
|
|
1715
|
+
} = committedValuesRef.current;
|
|
1716
|
+
const {
|
|
1717
|
+
layout: prevLayout,
|
|
1718
|
+
panelDataArray
|
|
1719
|
+
} = eagerValuesRef.current;
|
|
1720
|
+
panelDataArray.push(panelData);
|
|
1721
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1722
|
+
const orderA = panelA.order;
|
|
1723
|
+
const orderB = panelB.order;
|
|
1724
|
+
if (orderA == null && orderB == null) {
|
|
1725
|
+
return 0;
|
|
1726
|
+
} else if (orderA == null) {
|
|
1727
|
+
return -1;
|
|
1728
|
+
} else if (orderB == null) {
|
|
1729
|
+
return 1;
|
|
1730
|
+
} else {
|
|
1731
|
+
return orderA - orderB;
|
|
1732
|
+
}
|
|
1733
|
+
});
|
|
1734
|
+
|
|
1735
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1736
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1737
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1738
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// If this panel has been configured to persist sizing information,
|
|
1743
|
+
// default size should be restored from local storage if possible.
|
|
1744
|
+
let unsafeLayout = null;
|
|
1745
|
+
if (autoSaveId) {
|
|
1746
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1747
|
+
}
|
|
1748
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1749
|
+
if (groupSizePixels <= 0) {
|
|
1750
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1751
|
+
constraints
|
|
1752
|
+
}) => constraints))) {
|
|
1753
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
if (unsafeLayout == null) {
|
|
1758
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1759
|
+
groupSizePixels,
|
|
1760
|
+
panelDataArray
|
|
1765
1761
|
});
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1765
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1766
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1767
|
+
groupSizePixels,
|
|
1768
|
+
layout: unsafeLayout,
|
|
1769
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1766
1770
|
});
|
|
1771
|
+
|
|
1772
|
+
// Offscreen mode makes this a bit weird;
|
|
1773
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1774
|
+
// but the overall layout doesn't change between these two cases.
|
|
1775
|
+
setLayout(nextLayout);
|
|
1776
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1777
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1778
|
+
if (onLayout) {
|
|
1779
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1780
|
+
sizePercentage,
|
|
1781
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1782
|
+
})));
|
|
1783
|
+
}
|
|
1784
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1785
|
+
}
|
|
1767
1786
|
}, []);
|
|
1768
1787
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1769
1788
|
return function resizeHandler(event) {
|
|
@@ -1774,10 +1793,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1774
1793
|
id: groupId,
|
|
1775
1794
|
keyboardResizeByPercentage,
|
|
1776
1795
|
keyboardResizeByPixels,
|
|
1777
|
-
onLayout
|
|
1778
|
-
panelDataArray,
|
|
1779
|
-
layout: prevLayout
|
|
1796
|
+
onLayout
|
|
1780
1797
|
} = committedValuesRef.current;
|
|
1798
|
+
const {
|
|
1799
|
+
layout: prevLayout,
|
|
1800
|
+
panelDataArray
|
|
1801
|
+
} = eagerValuesRef.current;
|
|
1781
1802
|
const {
|
|
1782
1803
|
initialLayout
|
|
1783
1804
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1833,6 +1854,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1833
1854
|
}
|
|
1834
1855
|
if (layoutChanged) {
|
|
1835
1856
|
setLayout(nextLayout);
|
|
1857
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1836
1858
|
if (onLayout) {
|
|
1837
1859
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1838
1860
|
sizePercentage,
|
|
@@ -1846,23 +1868,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1846
1868
|
|
|
1847
1869
|
// External APIs are safe to memoize via committed values ref
|
|
1848
1870
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1871
|
+
const {
|
|
1872
|
+
onLayout
|
|
1873
|
+
} = committedValuesRef.current;
|
|
1849
1874
|
const {
|
|
1850
1875
|
layout: prevLayout,
|
|
1851
|
-
onLayout,
|
|
1852
1876
|
panelDataArray
|
|
1853
|
-
} =
|
|
1854
|
-
|
|
1855
|
-
// See issues/211
|
|
1856
|
-
if (panelDataArray.find(({
|
|
1857
|
-
id
|
|
1858
|
-
}) => id === panelData.id) == null) {
|
|
1859
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1860
|
-
panelData,
|
|
1861
|
-
mixedSizes,
|
|
1862
|
-
type: "resize"
|
|
1863
|
-
}]);
|
|
1864
|
-
return;
|
|
1865
|
-
}
|
|
1877
|
+
} = eagerValuesRef.current;
|
|
1866
1878
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1867
1879
|
const {
|
|
1868
1880
|
groupSizePixels,
|
|
@@ -1882,6 +1894,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1882
1894
|
});
|
|
1883
1895
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1884
1896
|
setLayout(nextLayout);
|
|
1897
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1885
1898
|
if (onLayout) {
|
|
1886
1899
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1887
1900
|
sizePercentage,
|
|
@@ -1893,9 +1906,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1893
1906
|
}, [groupId]);
|
|
1894
1907
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1895
1908
|
const {
|
|
1896
|
-
direction
|
|
1897
|
-
layout
|
|
1909
|
+
direction
|
|
1898
1910
|
} = committedValuesRef.current;
|
|
1911
|
+
const {
|
|
1912
|
+
layout
|
|
1913
|
+
} = eagerValuesRef.current;
|
|
1899
1914
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1900
1915
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1901
1916
|
setDragState({
|
|
@@ -1909,42 +1924,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1909
1924
|
resetGlobalCursorStyle();
|
|
1910
1925
|
setDragState(null);
|
|
1911
1926
|
}, []);
|
|
1927
|
+
const unregisterPanelRef = useRef({
|
|
1928
|
+
pendingPanelIds: new Set(),
|
|
1929
|
+
timeout: null
|
|
1930
|
+
});
|
|
1912
1931
|
const unregisterPanel = useCallback(panelData => {
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1932
|
+
const {
|
|
1933
|
+
id: groupId,
|
|
1934
|
+
onLayout
|
|
1935
|
+
} = committedValuesRef.current;
|
|
1936
|
+
const {
|
|
1937
|
+
layout: prevLayout,
|
|
1938
|
+
panelDataArray
|
|
1939
|
+
} = eagerValuesRef.current;
|
|
1940
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1941
|
+
if (index >= 0) {
|
|
1942
|
+
panelDataArray.splice(index, 1);
|
|
1943
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1944
|
+
}
|
|
1945
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1946
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1950
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1951
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1952
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1953
|
+
const {
|
|
1954
|
+
pendingPanelIds
|
|
1955
|
+
} = unregisterPanelRef.current;
|
|
1956
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1957
|
+
|
|
1958
|
+
// TRICKY
|
|
1959
|
+
// Strict effects mode
|
|
1960
|
+
let unmountDueToStrictMode = false;
|
|
1961
|
+
pendingPanelIds.forEach(panelId => {
|
|
1962
|
+
pendingPanelIds.delete(panelId);
|
|
1963
|
+
if (panelDataArray.find(({
|
|
1964
|
+
id
|
|
1965
|
+
}) => id === panelId) == null) {
|
|
1966
|
+
unmountDueToStrictMode = true;
|
|
1967
|
+
|
|
1968
|
+
// TRICKY
|
|
1969
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1970
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1971
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1972
|
+
delete map[panelData.id];
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
if (!unmountDueToStrictMode) {
|
|
1976
|
+
return;
|
|
1919
1977
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1978
|
+
if (panelDataArray.length === 0) {
|
|
1979
|
+
// The group is unmounting; skip layout calculation.
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1983
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1984
|
+
groupSizePixels,
|
|
1985
|
+
panelDataArray
|
|
1986
|
+
});
|
|
1923
1987
|
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
{
|
|
1942
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1943
|
-
break;
|
|
1944
|
-
}
|
|
1988
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1989
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1990
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1991
|
+
groupSizePixels,
|
|
1992
|
+
layout: unsafeLayout,
|
|
1993
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1994
|
+
});
|
|
1995
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1996
|
+
setLayout(nextLayout);
|
|
1997
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1998
|
+
if (onLayout) {
|
|
1999
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
2000
|
+
sizePercentage,
|
|
2001
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
2002
|
+
})));
|
|
2003
|
+
}
|
|
2004
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1945
2005
|
}
|
|
1946
|
-
}
|
|
1947
|
-
}, [
|
|
2006
|
+
}, 0);
|
|
2007
|
+
}, []);
|
|
1948
2008
|
const context = useMemo(() => ({
|
|
1949
2009
|
collapsePanel,
|
|
1950
2010
|
direction,
|