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
|
@@ -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)
|
|
@@ -698,6 +700,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
698
700
|
|
|
699
701
|
function useWindowSplitterPanelGroupBehavior({
|
|
700
702
|
committedValuesRef,
|
|
703
|
+
eagerValuesRef,
|
|
701
704
|
groupId,
|
|
702
705
|
layout,
|
|
703
706
|
panelDataArray,
|
|
@@ -750,7 +753,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
750
753
|
useEffect(() => {
|
|
751
754
|
const {
|
|
752
755
|
panelDataArray
|
|
753
|
-
} =
|
|
756
|
+
} = eagerValuesRef.current;
|
|
754
757
|
const groupElement = getPanelGroupElement(groupId);
|
|
755
758
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
756
759
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -808,7 +811,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
808
811
|
return () => {
|
|
809
812
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
810
813
|
};
|
|
811
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
814
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
812
815
|
}
|
|
813
816
|
|
|
814
817
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1093,6 +1096,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1093
1096
|
return callable;
|
|
1094
1097
|
}
|
|
1095
1098
|
|
|
1099
|
+
function getPanelElementsForGroup(groupId) {
|
|
1100
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1096
1103
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1097
1104
|
// or on a browser with cookies/storage disabled.
|
|
1098
1105
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1319,7 +1326,7 @@ const defaultStorage = {
|
|
|
1319
1326
|
};
|
|
1320
1327
|
const debounceMap = {};
|
|
1321
1328
|
function PanelGroupWithForwardedRef({
|
|
1322
|
-
autoSaveId,
|
|
1329
|
+
autoSaveId = null,
|
|
1323
1330
|
children,
|
|
1324
1331
|
className: classNameFromProps = "",
|
|
1325
1332
|
dataAttributes,
|
|
@@ -1336,20 +1343,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1336
1343
|
const groupId = useUniqueId(idFromProps);
|
|
1337
1344
|
const [dragState, setDragState] = useState(null);
|
|
1338
1345
|
const [layout, setLayout] = useState([]);
|
|
1339
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1340
1346
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1341
1347
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1342
1348
|
const prevDeltaRef = useRef(0);
|
|
1343
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1344
1349
|
const committedValuesRef = useRef({
|
|
1350
|
+
autoSaveId,
|
|
1345
1351
|
direction,
|
|
1346
1352
|
dragState,
|
|
1347
1353
|
id: groupId,
|
|
1348
1354
|
keyboardResizeByPercentage,
|
|
1349
1355
|
keyboardResizeByPixels,
|
|
1350
|
-
layout,
|
|
1351
1356
|
onLayout,
|
|
1352
|
-
|
|
1357
|
+
storage
|
|
1358
|
+
});
|
|
1359
|
+
const eagerValuesRef = useRef({
|
|
1360
|
+
layout,
|
|
1361
|
+
panelDataArray: []
|
|
1353
1362
|
});
|
|
1354
1363
|
const devWarningsRef = useRef({
|
|
1355
1364
|
didLogIdAndOrderWarning: false,
|
|
@@ -1360,9 +1369,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1360
1369
|
getId: () => committedValuesRef.current.id,
|
|
1361
1370
|
getLayout: () => {
|
|
1362
1371
|
const {
|
|
1363
|
-
id: groupId
|
|
1364
|
-
layout
|
|
1372
|
+
id: groupId
|
|
1365
1373
|
} = committedValuesRef.current;
|
|
1374
|
+
const {
|
|
1375
|
+
layout
|
|
1376
|
+
} = eagerValuesRef.current;
|
|
1366
1377
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1367
1378
|
return layout.map(sizePercentage => {
|
|
1368
1379
|
return {
|
|
@@ -1374,10 +1385,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1374
1385
|
setLayout: mixedSizes => {
|
|
1375
1386
|
const {
|
|
1376
1387
|
id: groupId,
|
|
1388
|
+
onLayout
|
|
1389
|
+
} = committedValuesRef.current;
|
|
1390
|
+
const {
|
|
1377
1391
|
layout: prevLayout,
|
|
1378
|
-
onLayout,
|
|
1379
1392
|
panelDataArray
|
|
1380
|
-
} =
|
|
1393
|
+
} = eagerValuesRef.current;
|
|
1381
1394
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1382
1395
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1383
1396
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1387,6 +1400,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1387
1400
|
});
|
|
1388
1401
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1389
1402
|
setLayout(safeLayout);
|
|
1403
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1390
1404
|
if (onLayout) {
|
|
1391
1405
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1392
1406
|
sizePercentage,
|
|
@@ -1398,21 +1412,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1398
1412
|
}
|
|
1399
1413
|
}), []);
|
|
1400
1414
|
useIsomorphicLayoutEffect(() => {
|
|
1415
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1401
1416
|
committedValuesRef.current.direction = direction;
|
|
1402
1417
|
committedValuesRef.current.dragState = dragState;
|
|
1403
1418
|
committedValuesRef.current.id = groupId;
|
|
1404
|
-
committedValuesRef.current.layout = layout;
|
|
1405
1419
|
committedValuesRef.current.onLayout = onLayout;
|
|
1406
|
-
committedValuesRef.current.
|
|
1420
|
+
committedValuesRef.current.storage = storage;
|
|
1421
|
+
|
|
1422
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1423
|
+
// TODO [217] Move these values into a separate ref
|
|
1407
1424
|
});
|
|
1425
|
+
|
|
1408
1426
|
useWindowSplitterPanelGroupBehavior({
|
|
1409
1427
|
committedValuesRef,
|
|
1428
|
+
eagerValuesRef,
|
|
1410
1429
|
groupId,
|
|
1411
1430
|
layout,
|
|
1412
|
-
panelDataArray,
|
|
1431
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1413
1432
|
setLayout
|
|
1414
1433
|
});
|
|
1415
1434
|
useEffect(() => {
|
|
1435
|
+
const {
|
|
1436
|
+
panelDataArray
|
|
1437
|
+
} = eagerValuesRef.current;
|
|
1438
|
+
|
|
1416
1439
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1417
1440
|
if (autoSaveId) {
|
|
1418
1441
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1425,63 +1448,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1425
1448
|
}
|
|
1426
1449
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1427
1450
|
}
|
|
1428
|
-
}, [autoSaveId, layout,
|
|
1429
|
-
|
|
1430
|
-
// Once all panels have registered themselves,
|
|
1431
|
-
// Compute the initial sizes based on default weights.
|
|
1432
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1451
|
+
}, [autoSaveId, layout, storage]);
|
|
1433
1452
|
useIsomorphicLayoutEffect(() => {
|
|
1434
1453
|
const {
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
} = committedValuesRef.current;
|
|
1439
|
-
if (layout.length === panelDataArray.length) {
|
|
1440
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
// If this panel has been configured to persist sizing information,
|
|
1445
|
-
// default size should be restored from local storage if possible.
|
|
1446
|
-
let unsafeLayout = null;
|
|
1447
|
-
if (autoSaveId) {
|
|
1448
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1449
|
-
}
|
|
1450
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1451
|
-
if (groupSizePixels <= 0) {
|
|
1452
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1453
|
-
constraints
|
|
1454
|
-
}) => constraints))) {
|
|
1455
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1456
|
-
return;
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
if (unsafeLayout == null) {
|
|
1460
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1461
|
-
groupSizePixels,
|
|
1462
|
-
panelDataArray
|
|
1463
|
-
});
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1467
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1468
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1469
|
-
groupSizePixels,
|
|
1470
|
-
layout: unsafeLayout,
|
|
1471
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1472
|
-
});
|
|
1473
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1474
|
-
setLayout(validatedLayout);
|
|
1475
|
-
}
|
|
1476
|
-
if (onLayout) {
|
|
1477
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1478
|
-
sizePercentage,
|
|
1479
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1480
|
-
})));
|
|
1481
|
-
}
|
|
1482
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1483
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1484
|
-
useIsomorphicLayoutEffect(() => {
|
|
1454
|
+
layout: prevLayout,
|
|
1455
|
+
panelDataArray
|
|
1456
|
+
} = eagerValuesRef.current;
|
|
1485
1457
|
const constraints = panelDataArray.map(({
|
|
1486
1458
|
constraints
|
|
1487
1459
|
}) => constraints);
|
|
@@ -1495,7 +1467,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1495
1467
|
const resizeObserver = new ResizeObserver(() => {
|
|
1496
1468
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1497
1469
|
const {
|
|
1498
|
-
layout: prevLayout,
|
|
1499
1470
|
onLayout
|
|
1500
1471
|
} = committedValuesRef.current;
|
|
1501
1472
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1505,6 +1476,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1505
1476
|
});
|
|
1506
1477
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1507
1478
|
setLayout(nextLayout);
|
|
1479
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1508
1480
|
if (onLayout) {
|
|
1509
1481
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1510
1482
|
sizePercentage,
|
|
@@ -1519,20 +1491,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1519
1491
|
resizeObserver.disconnect();
|
|
1520
1492
|
};
|
|
1521
1493
|
}
|
|
1522
|
-
}, [groupId
|
|
1494
|
+
}, [groupId]);
|
|
1523
1495
|
|
|
1524
1496
|
// DEV warnings
|
|
1525
1497
|
useEffect(() => {
|
|
1526
1498
|
{
|
|
1499
|
+
const {
|
|
1500
|
+
panelDataArray
|
|
1501
|
+
} = eagerValuesRef.current;
|
|
1527
1502
|
const {
|
|
1528
1503
|
didLogIdAndOrderWarning,
|
|
1529
1504
|
didLogPanelConstraintsWarning,
|
|
1530
1505
|
prevPanelIds
|
|
1531
1506
|
} = devWarningsRef.current;
|
|
1532
1507
|
if (!didLogIdAndOrderWarning) {
|
|
1533
|
-
const {
|
|
1534
|
-
panelDataArray
|
|
1535
|
-
} = committedValuesRef.current;
|
|
1536
1508
|
const panelIds = panelDataArray.map(({
|
|
1537
1509
|
id
|
|
1538
1510
|
}) => id);
|
|
@@ -1569,22 +1541,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1569
1541
|
|
|
1570
1542
|
// External APIs are safe to memoize via committed values ref
|
|
1571
1543
|
const collapsePanel = useCallback(panelData => {
|
|
1544
|
+
const {
|
|
1545
|
+
onLayout
|
|
1546
|
+
} = committedValuesRef.current;
|
|
1572
1547
|
const {
|
|
1573
1548
|
layout: prevLayout,
|
|
1574
|
-
onLayout,
|
|
1575
1549
|
panelDataArray
|
|
1576
|
-
} =
|
|
1577
|
-
|
|
1578
|
-
// See issues/211
|
|
1579
|
-
if (panelDataArray.find(({
|
|
1580
|
-
id
|
|
1581
|
-
}) => id === panelData.id) == null) {
|
|
1582
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1583
|
-
panelData,
|
|
1584
|
-
type: "collapse"
|
|
1585
|
-
}]);
|
|
1586
|
-
return;
|
|
1587
|
-
}
|
|
1550
|
+
} = eagerValuesRef.current;
|
|
1588
1551
|
if (panelData.constraints.collapsible) {
|
|
1589
1552
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1590
1553
|
const {
|
|
@@ -1609,6 +1572,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1609
1572
|
});
|
|
1610
1573
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1611
1574
|
setLayout(nextLayout);
|
|
1575
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1612
1576
|
if (onLayout) {
|
|
1613
1577
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1614
1578
|
sizePercentage,
|
|
@@ -1623,22 +1587,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1623
1587
|
|
|
1624
1588
|
// External APIs are safe to memoize via committed values ref
|
|
1625
1589
|
const expandPanel = useCallback(panelData => {
|
|
1590
|
+
const {
|
|
1591
|
+
onLayout
|
|
1592
|
+
} = committedValuesRef.current;
|
|
1626
1593
|
const {
|
|
1627
1594
|
layout: prevLayout,
|
|
1628
|
-
onLayout,
|
|
1629
1595
|
panelDataArray
|
|
1630
|
-
} =
|
|
1631
|
-
|
|
1632
|
-
// See issues/211
|
|
1633
|
-
if (panelDataArray.find(({
|
|
1634
|
-
id
|
|
1635
|
-
}) => id === panelData.id) == null) {
|
|
1636
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1637
|
-
panelData,
|
|
1638
|
-
type: "expand"
|
|
1639
|
-
}]);
|
|
1640
|
-
return;
|
|
1641
|
-
}
|
|
1596
|
+
} = eagerValuesRef.current;
|
|
1642
1597
|
if (panelData.constraints.collapsible) {
|
|
1643
1598
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1644
1599
|
const {
|
|
@@ -1664,6 +1619,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1664
1619
|
});
|
|
1665
1620
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1666
1621
|
setLayout(nextLayout);
|
|
1622
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1667
1623
|
if (onLayout) {
|
|
1668
1624
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1669
1625
|
sizePercentage,
|
|
@@ -1681,7 +1637,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1681
1637
|
const {
|
|
1682
1638
|
layout,
|
|
1683
1639
|
panelDataArray
|
|
1684
|
-
} =
|
|
1640
|
+
} = eagerValuesRef.current;
|
|
1685
1641
|
const {
|
|
1686
1642
|
panelSizePercentage,
|
|
1687
1643
|
panelSizePixels
|
|
@@ -1694,6 +1650,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1694
1650
|
|
|
1695
1651
|
// This API should never read from committedValuesRef
|
|
1696
1652
|
const getPanelStyle = useCallback(panelData => {
|
|
1653
|
+
const {
|
|
1654
|
+
panelDataArray
|
|
1655
|
+
} = eagerValuesRef.current;
|
|
1697
1656
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1698
1657
|
return computePanelFlexBoxStyle({
|
|
1699
1658
|
dragState,
|
|
@@ -1701,14 +1660,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1701
1660
|
panelData: panelDataArray,
|
|
1702
1661
|
panelIndex
|
|
1703
1662
|
});
|
|
1704
|
-
}, [dragState, layout
|
|
1663
|
+
}, [dragState, layout]);
|
|
1705
1664
|
|
|
1706
1665
|
// External APIs are safe to memoize via committed values ref
|
|
1707
1666
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1708
1667
|
const {
|
|
1709
1668
|
layout,
|
|
1710
1669
|
panelDataArray
|
|
1711
|
-
} =
|
|
1670
|
+
} = eagerValuesRef.current;
|
|
1712
1671
|
const {
|
|
1713
1672
|
collapsedSizePercentage,
|
|
1714
1673
|
collapsible,
|
|
@@ -1722,7 +1681,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1722
1681
|
const {
|
|
1723
1682
|
layout,
|
|
1724
1683
|
panelDataArray
|
|
1725
|
-
} =
|
|
1684
|
+
} = eagerValuesRef.current;
|
|
1726
1685
|
const {
|
|
1727
1686
|
collapsedSizePercentage,
|
|
1728
1687
|
collapsible,
|
|
@@ -1731,22 +1690,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1731
1690
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1732
1691
|
}, [groupId]);
|
|
1733
1692
|
const registerPanel = useCallback(panelData => {
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1693
|
+
const {
|
|
1694
|
+
autoSaveId,
|
|
1695
|
+
id: groupId,
|
|
1696
|
+
onLayout,
|
|
1697
|
+
storage
|
|
1698
|
+
} = committedValuesRef.current;
|
|
1699
|
+
const {
|
|
1700
|
+
layout: prevLayout,
|
|
1701
|
+
panelDataArray
|
|
1702
|
+
} = eagerValuesRef.current;
|
|
1703
|
+
panelDataArray.push(panelData);
|
|
1704
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1705
|
+
const orderA = panelA.order;
|
|
1706
|
+
const orderB = panelB.order;
|
|
1707
|
+
if (orderA == null && orderB == null) {
|
|
1708
|
+
return 0;
|
|
1709
|
+
} else if (orderA == null) {
|
|
1710
|
+
return -1;
|
|
1711
|
+
} else if (orderB == null) {
|
|
1712
|
+
return 1;
|
|
1713
|
+
} else {
|
|
1714
|
+
return orderA - orderB;
|
|
1715
|
+
}
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1718
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1719
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1720
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1721
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
// If this panel has been configured to persist sizing information,
|
|
1726
|
+
// default size should be restored from local storage if possible.
|
|
1727
|
+
let unsafeLayout = null;
|
|
1728
|
+
if (autoSaveId) {
|
|
1729
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1730
|
+
}
|
|
1731
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1732
|
+
if (groupSizePixels <= 0) {
|
|
1733
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1734
|
+
constraints
|
|
1735
|
+
}) => constraints))) {
|
|
1736
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
if (unsafeLayout == null) {
|
|
1741
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1742
|
+
groupSizePixels,
|
|
1743
|
+
panelDataArray
|
|
1748
1744
|
});
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1748
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1749
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1750
|
+
groupSizePixels,
|
|
1751
|
+
layout: unsafeLayout,
|
|
1752
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1749
1753
|
});
|
|
1754
|
+
|
|
1755
|
+
// Offscreen mode makes this a bit weird;
|
|
1756
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1757
|
+
// but the overall layout doesn't change between these two cases.
|
|
1758
|
+
setLayout(nextLayout);
|
|
1759
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1760
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1761
|
+
if (onLayout) {
|
|
1762
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1763
|
+
sizePercentage,
|
|
1764
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1765
|
+
})));
|
|
1766
|
+
}
|
|
1767
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1768
|
+
}
|
|
1750
1769
|
}, []);
|
|
1751
1770
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1752
1771
|
return function resizeHandler(event) {
|
|
@@ -1757,10 +1776,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1757
1776
|
id: groupId,
|
|
1758
1777
|
keyboardResizeByPercentage,
|
|
1759
1778
|
keyboardResizeByPixels,
|
|
1760
|
-
onLayout
|
|
1761
|
-
panelDataArray,
|
|
1762
|
-
layout: prevLayout
|
|
1779
|
+
onLayout
|
|
1763
1780
|
} = committedValuesRef.current;
|
|
1781
|
+
const {
|
|
1782
|
+
layout: prevLayout,
|
|
1783
|
+
panelDataArray
|
|
1784
|
+
} = eagerValuesRef.current;
|
|
1764
1785
|
const {
|
|
1765
1786
|
initialLayout
|
|
1766
1787
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1816,6 +1837,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1816
1837
|
}
|
|
1817
1838
|
if (layoutChanged) {
|
|
1818
1839
|
setLayout(nextLayout);
|
|
1840
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1819
1841
|
if (onLayout) {
|
|
1820
1842
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1821
1843
|
sizePercentage,
|
|
@@ -1829,23 +1851,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1829
1851
|
|
|
1830
1852
|
// External APIs are safe to memoize via committed values ref
|
|
1831
1853
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1854
|
+
const {
|
|
1855
|
+
onLayout
|
|
1856
|
+
} = committedValuesRef.current;
|
|
1832
1857
|
const {
|
|
1833
1858
|
layout: prevLayout,
|
|
1834
|
-
onLayout,
|
|
1835
1859
|
panelDataArray
|
|
1836
|
-
} =
|
|
1837
|
-
|
|
1838
|
-
// See issues/211
|
|
1839
|
-
if (panelDataArray.find(({
|
|
1840
|
-
id
|
|
1841
|
-
}) => id === panelData.id) == null) {
|
|
1842
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1843
|
-
panelData,
|
|
1844
|
-
mixedSizes,
|
|
1845
|
-
type: "resize"
|
|
1846
|
-
}]);
|
|
1847
|
-
return;
|
|
1848
|
-
}
|
|
1860
|
+
} = eagerValuesRef.current;
|
|
1849
1861
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1850
1862
|
const {
|
|
1851
1863
|
groupSizePixels,
|
|
@@ -1865,6 +1877,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1865
1877
|
});
|
|
1866
1878
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1867
1879
|
setLayout(nextLayout);
|
|
1880
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1868
1881
|
if (onLayout) {
|
|
1869
1882
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1870
1883
|
sizePercentage,
|
|
@@ -1876,9 +1889,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1876
1889
|
}, [groupId]);
|
|
1877
1890
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1878
1891
|
const {
|
|
1879
|
-
direction
|
|
1880
|
-
layout
|
|
1892
|
+
direction
|
|
1881
1893
|
} = committedValuesRef.current;
|
|
1894
|
+
const {
|
|
1895
|
+
layout
|
|
1896
|
+
} = eagerValuesRef.current;
|
|
1882
1897
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1883
1898
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1884
1899
|
setDragState({
|
|
@@ -1892,42 +1907,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1892
1907
|
resetGlobalCursorStyle();
|
|
1893
1908
|
setDragState(null);
|
|
1894
1909
|
}, []);
|
|
1910
|
+
const unregisterPanelRef = useRef({
|
|
1911
|
+
pendingPanelIds: new Set(),
|
|
1912
|
+
timeout: null
|
|
1913
|
+
});
|
|
1895
1914
|
const unregisterPanel = useCallback(panelData => {
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1915
|
+
const {
|
|
1916
|
+
id: groupId,
|
|
1917
|
+
onLayout
|
|
1918
|
+
} = committedValuesRef.current;
|
|
1919
|
+
const {
|
|
1920
|
+
layout: prevLayout,
|
|
1921
|
+
panelDataArray
|
|
1922
|
+
} = eagerValuesRef.current;
|
|
1923
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1924
|
+
if (index >= 0) {
|
|
1925
|
+
panelDataArray.splice(index, 1);
|
|
1926
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1927
|
+
}
|
|
1928
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1929
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1933
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1934
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1935
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1936
|
+
const {
|
|
1937
|
+
pendingPanelIds
|
|
1938
|
+
} = unregisterPanelRef.current;
|
|
1939
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1940
|
+
|
|
1941
|
+
// TRICKY
|
|
1942
|
+
// Strict effects mode
|
|
1943
|
+
let unmountDueToStrictMode = false;
|
|
1944
|
+
pendingPanelIds.forEach(panelId => {
|
|
1945
|
+
pendingPanelIds.delete(panelId);
|
|
1946
|
+
if (panelDataArray.find(({
|
|
1947
|
+
id
|
|
1948
|
+
}) => id === panelId) == null) {
|
|
1949
|
+
unmountDueToStrictMode = true;
|
|
1950
|
+
|
|
1951
|
+
// TRICKY
|
|
1952
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1953
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1954
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1955
|
+
delete map[panelData.id];
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
if (!unmountDueToStrictMode) {
|
|
1959
|
+
return;
|
|
1902
1960
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1961
|
+
if (panelDataArray.length === 0) {
|
|
1962
|
+
// The group is unmounting; skip layout calculation.
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1966
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1967
|
+
groupSizePixels,
|
|
1968
|
+
panelDataArray
|
|
1969
|
+
});
|
|
1906
1970
|
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
{
|
|
1925
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1926
|
-
break;
|
|
1927
|
-
}
|
|
1971
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1972
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1973
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1974
|
+
groupSizePixels,
|
|
1975
|
+
layout: unsafeLayout,
|
|
1976
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1977
|
+
});
|
|
1978
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1979
|
+
setLayout(nextLayout);
|
|
1980
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1981
|
+
if (onLayout) {
|
|
1982
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1983
|
+
sizePercentage,
|
|
1984
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1985
|
+
})));
|
|
1986
|
+
}
|
|
1987
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1928
1988
|
}
|
|
1929
|
-
}
|
|
1930
|
-
}, [
|
|
1989
|
+
}, 0);
|
|
1990
|
+
}, []);
|
|
1931
1991
|
const context = useMemo(() => ({
|
|
1932
1992
|
collapsePanel,
|
|
1933
1993
|
direction,
|