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
|
@@ -69,6 +69,7 @@ function PanelWithForwardedRef({
|
|
|
69
69
|
expandPanel,
|
|
70
70
|
getPanelSize,
|
|
71
71
|
getPanelStyle,
|
|
72
|
+
groupId,
|
|
72
73
|
isPanelCollapsed,
|
|
73
74
|
registerPanel,
|
|
74
75
|
resizePanel,
|
|
@@ -168,6 +169,7 @@ function PanelWithForwardedRef({
|
|
|
168
169
|
// CSS selectors
|
|
169
170
|
"data-panel": "",
|
|
170
171
|
"data-panel-id": panelId,
|
|
172
|
+
"data-panel-group-id": groupId,
|
|
171
173
|
// e2e test attributes
|
|
172
174
|
"data-panel-collapsible": collapsible || undefined ,
|
|
173
175
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -691,6 +693,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
691
693
|
|
|
692
694
|
function useWindowSplitterPanelGroupBehavior({
|
|
693
695
|
committedValuesRef,
|
|
696
|
+
eagerValuesRef,
|
|
694
697
|
groupId,
|
|
695
698
|
layout,
|
|
696
699
|
panelDataArray,
|
|
@@ -743,7 +746,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
743
746
|
useEffect(() => {
|
|
744
747
|
const {
|
|
745
748
|
panelDataArray
|
|
746
|
-
} =
|
|
749
|
+
} = eagerValuesRef.current;
|
|
747
750
|
const groupElement = getPanelGroupElement(groupId);
|
|
748
751
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
749
752
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -801,7 +804,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
801
804
|
return () => {
|
|
802
805
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
803
806
|
};
|
|
804
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
807
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
805
808
|
}
|
|
806
809
|
|
|
807
810
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1086,6 +1089,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1086
1089
|
return callable;
|
|
1087
1090
|
}
|
|
1088
1091
|
|
|
1092
|
+
function getPanelElementsForGroup(groupId) {
|
|
1093
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1089
1096
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1090
1097
|
// or on a browser with cookies/storage disabled.
|
|
1091
1098
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1312,7 +1319,7 @@ const defaultStorage = {
|
|
|
1312
1319
|
};
|
|
1313
1320
|
const debounceMap = {};
|
|
1314
1321
|
function PanelGroupWithForwardedRef({
|
|
1315
|
-
autoSaveId,
|
|
1322
|
+
autoSaveId = null,
|
|
1316
1323
|
children,
|
|
1317
1324
|
className: classNameFromProps = "",
|
|
1318
1325
|
dataAttributes,
|
|
@@ -1329,20 +1336,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1329
1336
|
const groupId = useUniqueId(idFromProps);
|
|
1330
1337
|
const [dragState, setDragState] = useState(null);
|
|
1331
1338
|
const [layout, setLayout] = useState([]);
|
|
1332
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1333
1339
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1334
1340
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1335
1341
|
const prevDeltaRef = useRef(0);
|
|
1336
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1337
1342
|
const committedValuesRef = useRef({
|
|
1343
|
+
autoSaveId,
|
|
1338
1344
|
direction,
|
|
1339
1345
|
dragState,
|
|
1340
1346
|
id: groupId,
|
|
1341
1347
|
keyboardResizeByPercentage,
|
|
1342
1348
|
keyboardResizeByPixels,
|
|
1343
|
-
layout,
|
|
1344
1349
|
onLayout,
|
|
1345
|
-
|
|
1350
|
+
storage
|
|
1351
|
+
});
|
|
1352
|
+
const eagerValuesRef = useRef({
|
|
1353
|
+
layout,
|
|
1354
|
+
panelDataArray: []
|
|
1346
1355
|
});
|
|
1347
1356
|
const devWarningsRef = useRef({
|
|
1348
1357
|
didLogIdAndOrderWarning: false,
|
|
@@ -1353,9 +1362,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1353
1362
|
getId: () => committedValuesRef.current.id,
|
|
1354
1363
|
getLayout: () => {
|
|
1355
1364
|
const {
|
|
1356
|
-
id: groupId
|
|
1357
|
-
layout
|
|
1365
|
+
id: groupId
|
|
1358
1366
|
} = committedValuesRef.current;
|
|
1367
|
+
const {
|
|
1368
|
+
layout
|
|
1369
|
+
} = eagerValuesRef.current;
|
|
1359
1370
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1360
1371
|
return layout.map(sizePercentage => {
|
|
1361
1372
|
return {
|
|
@@ -1367,10 +1378,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1367
1378
|
setLayout: mixedSizes => {
|
|
1368
1379
|
const {
|
|
1369
1380
|
id: groupId,
|
|
1381
|
+
onLayout
|
|
1382
|
+
} = committedValuesRef.current;
|
|
1383
|
+
const {
|
|
1370
1384
|
layout: prevLayout,
|
|
1371
|
-
onLayout,
|
|
1372
1385
|
panelDataArray
|
|
1373
|
-
} =
|
|
1386
|
+
} = eagerValuesRef.current;
|
|
1374
1387
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1375
1388
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1376
1389
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1380,6 +1393,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1380
1393
|
});
|
|
1381
1394
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1382
1395
|
setLayout(safeLayout);
|
|
1396
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1383
1397
|
if (onLayout) {
|
|
1384
1398
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1385
1399
|
sizePercentage,
|
|
@@ -1391,21 +1405,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1391
1405
|
}
|
|
1392
1406
|
}), []);
|
|
1393
1407
|
useIsomorphicLayoutEffect(() => {
|
|
1408
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1394
1409
|
committedValuesRef.current.direction = direction;
|
|
1395
1410
|
committedValuesRef.current.dragState = dragState;
|
|
1396
1411
|
committedValuesRef.current.id = groupId;
|
|
1397
|
-
committedValuesRef.current.layout = layout;
|
|
1398
1412
|
committedValuesRef.current.onLayout = onLayout;
|
|
1399
|
-
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
|
|
1400
1417
|
});
|
|
1418
|
+
|
|
1401
1419
|
useWindowSplitterPanelGroupBehavior({
|
|
1402
1420
|
committedValuesRef,
|
|
1421
|
+
eagerValuesRef,
|
|
1403
1422
|
groupId,
|
|
1404
1423
|
layout,
|
|
1405
|
-
panelDataArray,
|
|
1424
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1406
1425
|
setLayout
|
|
1407
1426
|
});
|
|
1408
1427
|
useEffect(() => {
|
|
1428
|
+
const {
|
|
1429
|
+
panelDataArray
|
|
1430
|
+
} = eagerValuesRef.current;
|
|
1431
|
+
|
|
1409
1432
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1410
1433
|
if (autoSaveId) {
|
|
1411
1434
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1418,63 +1441,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1418
1441
|
}
|
|
1419
1442
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1420
1443
|
}
|
|
1421
|
-
}, [autoSaveId, layout,
|
|
1422
|
-
|
|
1423
|
-
// Once all panels have registered themselves,
|
|
1424
|
-
// Compute the initial sizes based on default weights.
|
|
1425
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1444
|
+
}, [autoSaveId, layout, storage]);
|
|
1426
1445
|
useIsomorphicLayoutEffect(() => {
|
|
1427
1446
|
const {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
} = committedValuesRef.current;
|
|
1432
|
-
if (layout.length === panelDataArray.length) {
|
|
1433
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1434
|
-
return;
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
// If this panel has been configured to persist sizing information,
|
|
1438
|
-
// default size should be restored from local storage if possible.
|
|
1439
|
-
let unsafeLayout = null;
|
|
1440
|
-
if (autoSaveId) {
|
|
1441
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1442
|
-
}
|
|
1443
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1444
|
-
if (groupSizePixels <= 0) {
|
|
1445
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1446
|
-
constraints
|
|
1447
|
-
}) => constraints))) {
|
|
1448
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1449
|
-
return;
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
if (unsafeLayout == null) {
|
|
1453
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1454
|
-
groupSizePixels,
|
|
1455
|
-
panelDataArray
|
|
1456
|
-
});
|
|
1457
|
-
}
|
|
1458
|
-
|
|
1459
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1460
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1461
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1462
|
-
groupSizePixels,
|
|
1463
|
-
layout: unsafeLayout,
|
|
1464
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1465
|
-
});
|
|
1466
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1467
|
-
setLayout(validatedLayout);
|
|
1468
|
-
}
|
|
1469
|
-
if (onLayout) {
|
|
1470
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1471
|
-
sizePercentage,
|
|
1472
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1473
|
-
})));
|
|
1474
|
-
}
|
|
1475
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1476
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1477
|
-
useIsomorphicLayoutEffect(() => {
|
|
1447
|
+
layout: prevLayout,
|
|
1448
|
+
panelDataArray
|
|
1449
|
+
} = eagerValuesRef.current;
|
|
1478
1450
|
const constraints = panelDataArray.map(({
|
|
1479
1451
|
constraints
|
|
1480
1452
|
}) => constraints);
|
|
@@ -1488,7 +1460,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1488
1460
|
const resizeObserver = new ResizeObserver(() => {
|
|
1489
1461
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1490
1462
|
const {
|
|
1491
|
-
layout: prevLayout,
|
|
1492
1463
|
onLayout
|
|
1493
1464
|
} = committedValuesRef.current;
|
|
1494
1465
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1498,6 +1469,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1498
1469
|
});
|
|
1499
1470
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1500
1471
|
setLayout(nextLayout);
|
|
1472
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1501
1473
|
if (onLayout) {
|
|
1502
1474
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1503
1475
|
sizePercentage,
|
|
@@ -1512,20 +1484,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1512
1484
|
resizeObserver.disconnect();
|
|
1513
1485
|
};
|
|
1514
1486
|
}
|
|
1515
|
-
}, [groupId
|
|
1487
|
+
}, [groupId]);
|
|
1516
1488
|
|
|
1517
1489
|
// DEV warnings
|
|
1518
1490
|
useEffect(() => {
|
|
1519
1491
|
{
|
|
1492
|
+
const {
|
|
1493
|
+
panelDataArray
|
|
1494
|
+
} = eagerValuesRef.current;
|
|
1520
1495
|
const {
|
|
1521
1496
|
didLogIdAndOrderWarning,
|
|
1522
1497
|
didLogPanelConstraintsWarning,
|
|
1523
1498
|
prevPanelIds
|
|
1524
1499
|
} = devWarningsRef.current;
|
|
1525
1500
|
if (!didLogIdAndOrderWarning) {
|
|
1526
|
-
const {
|
|
1527
|
-
panelDataArray
|
|
1528
|
-
} = committedValuesRef.current;
|
|
1529
1501
|
const panelIds = panelDataArray.map(({
|
|
1530
1502
|
id
|
|
1531
1503
|
}) => id);
|
|
@@ -1562,22 +1534,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1562
1534
|
|
|
1563
1535
|
// External APIs are safe to memoize via committed values ref
|
|
1564
1536
|
const collapsePanel = useCallback(panelData => {
|
|
1537
|
+
const {
|
|
1538
|
+
onLayout
|
|
1539
|
+
} = committedValuesRef.current;
|
|
1565
1540
|
const {
|
|
1566
1541
|
layout: prevLayout,
|
|
1567
|
-
onLayout,
|
|
1568
1542
|
panelDataArray
|
|
1569
|
-
} =
|
|
1570
|
-
|
|
1571
|
-
// See issues/211
|
|
1572
|
-
if (panelDataArray.find(({
|
|
1573
|
-
id
|
|
1574
|
-
}) => id === panelData.id) == null) {
|
|
1575
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1576
|
-
panelData,
|
|
1577
|
-
type: "collapse"
|
|
1578
|
-
}]);
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1543
|
+
} = eagerValuesRef.current;
|
|
1581
1544
|
if (panelData.constraints.collapsible) {
|
|
1582
1545
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1583
1546
|
const {
|
|
@@ -1602,6 +1565,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1602
1565
|
});
|
|
1603
1566
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1604
1567
|
setLayout(nextLayout);
|
|
1568
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1605
1569
|
if (onLayout) {
|
|
1606
1570
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1607
1571
|
sizePercentage,
|
|
@@ -1616,22 +1580,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1616
1580
|
|
|
1617
1581
|
// External APIs are safe to memoize via committed values ref
|
|
1618
1582
|
const expandPanel = useCallback(panelData => {
|
|
1583
|
+
const {
|
|
1584
|
+
onLayout
|
|
1585
|
+
} = committedValuesRef.current;
|
|
1619
1586
|
const {
|
|
1620
1587
|
layout: prevLayout,
|
|
1621
|
-
onLayout,
|
|
1622
1588
|
panelDataArray
|
|
1623
|
-
} =
|
|
1624
|
-
|
|
1625
|
-
// See issues/211
|
|
1626
|
-
if (panelDataArray.find(({
|
|
1627
|
-
id
|
|
1628
|
-
}) => id === panelData.id) == null) {
|
|
1629
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1630
|
-
panelData,
|
|
1631
|
-
type: "expand"
|
|
1632
|
-
}]);
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1589
|
+
} = eagerValuesRef.current;
|
|
1635
1590
|
if (panelData.constraints.collapsible) {
|
|
1636
1591
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1637
1592
|
const {
|
|
@@ -1657,6 +1612,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1657
1612
|
});
|
|
1658
1613
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1659
1614
|
setLayout(nextLayout);
|
|
1615
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1660
1616
|
if (onLayout) {
|
|
1661
1617
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1662
1618
|
sizePercentage,
|
|
@@ -1674,7 +1630,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1674
1630
|
const {
|
|
1675
1631
|
layout,
|
|
1676
1632
|
panelDataArray
|
|
1677
|
-
} =
|
|
1633
|
+
} = eagerValuesRef.current;
|
|
1678
1634
|
const {
|
|
1679
1635
|
panelSizePercentage,
|
|
1680
1636
|
panelSizePixels
|
|
@@ -1687,6 +1643,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1687
1643
|
|
|
1688
1644
|
// This API should never read from committedValuesRef
|
|
1689
1645
|
const getPanelStyle = useCallback(panelData => {
|
|
1646
|
+
const {
|
|
1647
|
+
panelDataArray
|
|
1648
|
+
} = eagerValuesRef.current;
|
|
1690
1649
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1691
1650
|
return computePanelFlexBoxStyle({
|
|
1692
1651
|
dragState,
|
|
@@ -1694,14 +1653,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1694
1653
|
panelData: panelDataArray,
|
|
1695
1654
|
panelIndex
|
|
1696
1655
|
});
|
|
1697
|
-
}, [dragState, layout
|
|
1656
|
+
}, [dragState, layout]);
|
|
1698
1657
|
|
|
1699
1658
|
// External APIs are safe to memoize via committed values ref
|
|
1700
1659
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1701
1660
|
const {
|
|
1702
1661
|
layout,
|
|
1703
1662
|
panelDataArray
|
|
1704
|
-
} =
|
|
1663
|
+
} = eagerValuesRef.current;
|
|
1705
1664
|
const {
|
|
1706
1665
|
collapsedSizePercentage,
|
|
1707
1666
|
collapsible,
|
|
@@ -1715,7 +1674,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1715
1674
|
const {
|
|
1716
1675
|
layout,
|
|
1717
1676
|
panelDataArray
|
|
1718
|
-
} =
|
|
1677
|
+
} = eagerValuesRef.current;
|
|
1719
1678
|
const {
|
|
1720
1679
|
collapsedSizePercentage,
|
|
1721
1680
|
collapsible,
|
|
@@ -1724,22 +1683,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1724
1683
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1725
1684
|
}, [groupId]);
|
|
1726
1685
|
const registerPanel = useCallback(panelData => {
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1686
|
+
const {
|
|
1687
|
+
autoSaveId,
|
|
1688
|
+
id: groupId,
|
|
1689
|
+
onLayout,
|
|
1690
|
+
storage
|
|
1691
|
+
} = committedValuesRef.current;
|
|
1692
|
+
const {
|
|
1693
|
+
layout: prevLayout,
|
|
1694
|
+
panelDataArray
|
|
1695
|
+
} = eagerValuesRef.current;
|
|
1696
|
+
panelDataArray.push(panelData);
|
|
1697
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1698
|
+
const orderA = panelA.order;
|
|
1699
|
+
const orderB = panelB.order;
|
|
1700
|
+
if (orderA == null && orderB == null) {
|
|
1701
|
+
return 0;
|
|
1702
|
+
} else if (orderA == null) {
|
|
1703
|
+
return -1;
|
|
1704
|
+
} else if (orderB == null) {
|
|
1705
|
+
return 1;
|
|
1706
|
+
} else {
|
|
1707
|
+
return orderA - orderB;
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
|
|
1711
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1712
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1713
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1714
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
// If this panel has been configured to persist sizing information,
|
|
1719
|
+
// default size should be restored from local storage if possible.
|
|
1720
|
+
let unsafeLayout = null;
|
|
1721
|
+
if (autoSaveId) {
|
|
1722
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1723
|
+
}
|
|
1724
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1725
|
+
if (groupSizePixels <= 0) {
|
|
1726
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1727
|
+
constraints
|
|
1728
|
+
}) => constraints))) {
|
|
1729
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
if (unsafeLayout == null) {
|
|
1734
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1735
|
+
groupSizePixels,
|
|
1736
|
+
panelDataArray
|
|
1741
1737
|
});
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1741
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1742
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1743
|
+
groupSizePixels,
|
|
1744
|
+
layout: unsafeLayout,
|
|
1745
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1742
1746
|
});
|
|
1747
|
+
|
|
1748
|
+
// Offscreen mode makes this a bit weird;
|
|
1749
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1750
|
+
// but the overall layout doesn't change between these two cases.
|
|
1751
|
+
setLayout(nextLayout);
|
|
1752
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1753
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1754
|
+
if (onLayout) {
|
|
1755
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1756
|
+
sizePercentage,
|
|
1757
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1758
|
+
})));
|
|
1759
|
+
}
|
|
1760
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1761
|
+
}
|
|
1743
1762
|
}, []);
|
|
1744
1763
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1745
1764
|
return function resizeHandler(event) {
|
|
@@ -1750,10 +1769,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1750
1769
|
id: groupId,
|
|
1751
1770
|
keyboardResizeByPercentage,
|
|
1752
1771
|
keyboardResizeByPixels,
|
|
1753
|
-
onLayout
|
|
1754
|
-
panelDataArray,
|
|
1755
|
-
layout: prevLayout
|
|
1772
|
+
onLayout
|
|
1756
1773
|
} = committedValuesRef.current;
|
|
1774
|
+
const {
|
|
1775
|
+
layout: prevLayout,
|
|
1776
|
+
panelDataArray
|
|
1777
|
+
} = eagerValuesRef.current;
|
|
1757
1778
|
const {
|
|
1758
1779
|
initialLayout
|
|
1759
1780
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1809,6 +1830,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1809
1830
|
}
|
|
1810
1831
|
if (layoutChanged) {
|
|
1811
1832
|
setLayout(nextLayout);
|
|
1833
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1812
1834
|
if (onLayout) {
|
|
1813
1835
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1814
1836
|
sizePercentage,
|
|
@@ -1822,23 +1844,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1822
1844
|
|
|
1823
1845
|
// External APIs are safe to memoize via committed values ref
|
|
1824
1846
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1847
|
+
const {
|
|
1848
|
+
onLayout
|
|
1849
|
+
} = committedValuesRef.current;
|
|
1825
1850
|
const {
|
|
1826
1851
|
layout: prevLayout,
|
|
1827
|
-
onLayout,
|
|
1828
1852
|
panelDataArray
|
|
1829
|
-
} =
|
|
1830
|
-
|
|
1831
|
-
// See issues/211
|
|
1832
|
-
if (panelDataArray.find(({
|
|
1833
|
-
id
|
|
1834
|
-
}) => id === panelData.id) == null) {
|
|
1835
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1836
|
-
panelData,
|
|
1837
|
-
mixedSizes,
|
|
1838
|
-
type: "resize"
|
|
1839
|
-
}]);
|
|
1840
|
-
return;
|
|
1841
|
-
}
|
|
1853
|
+
} = eagerValuesRef.current;
|
|
1842
1854
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1843
1855
|
const {
|
|
1844
1856
|
groupSizePixels,
|
|
@@ -1858,6 +1870,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1858
1870
|
});
|
|
1859
1871
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1860
1872
|
setLayout(nextLayout);
|
|
1873
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1861
1874
|
if (onLayout) {
|
|
1862
1875
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1863
1876
|
sizePercentage,
|
|
@@ -1869,9 +1882,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1869
1882
|
}, [groupId]);
|
|
1870
1883
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1871
1884
|
const {
|
|
1872
|
-
direction
|
|
1873
|
-
layout
|
|
1885
|
+
direction
|
|
1874
1886
|
} = committedValuesRef.current;
|
|
1887
|
+
const {
|
|
1888
|
+
layout
|
|
1889
|
+
} = eagerValuesRef.current;
|
|
1875
1890
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1876
1891
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1877
1892
|
setDragState({
|
|
@@ -1885,42 +1900,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1885
1900
|
resetGlobalCursorStyle();
|
|
1886
1901
|
setDragState(null);
|
|
1887
1902
|
}, []);
|
|
1903
|
+
const unregisterPanelRef = useRef({
|
|
1904
|
+
pendingPanelIds: new Set(),
|
|
1905
|
+
timeout: null
|
|
1906
|
+
});
|
|
1888
1907
|
const unregisterPanel = useCallback(panelData => {
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1908
|
+
const {
|
|
1909
|
+
id: groupId,
|
|
1910
|
+
onLayout
|
|
1911
|
+
} = committedValuesRef.current;
|
|
1912
|
+
const {
|
|
1913
|
+
layout: prevLayout,
|
|
1914
|
+
panelDataArray
|
|
1915
|
+
} = eagerValuesRef.current;
|
|
1916
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1917
|
+
if (index >= 0) {
|
|
1918
|
+
panelDataArray.splice(index, 1);
|
|
1919
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1920
|
+
}
|
|
1921
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1922
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1926
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1927
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1928
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1929
|
+
const {
|
|
1930
|
+
pendingPanelIds
|
|
1931
|
+
} = unregisterPanelRef.current;
|
|
1932
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1933
|
+
|
|
1934
|
+
// TRICKY
|
|
1935
|
+
// Strict effects mode
|
|
1936
|
+
let unmountDueToStrictMode = false;
|
|
1937
|
+
pendingPanelIds.forEach(panelId => {
|
|
1938
|
+
pendingPanelIds.delete(panelId);
|
|
1939
|
+
if (panelDataArray.find(({
|
|
1940
|
+
id
|
|
1941
|
+
}) => id === panelId) == null) {
|
|
1942
|
+
unmountDueToStrictMode = true;
|
|
1943
|
+
|
|
1944
|
+
// TRICKY
|
|
1945
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1946
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1947
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1948
|
+
delete map[panelData.id];
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
if (!unmountDueToStrictMode) {
|
|
1952
|
+
return;
|
|
1895
1953
|
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1954
|
+
if (panelDataArray.length === 0) {
|
|
1955
|
+
// The group is unmounting; skip layout calculation.
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1959
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1960
|
+
groupSizePixels,
|
|
1961
|
+
panelDataArray
|
|
1962
|
+
});
|
|
1899
1963
|
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
{
|
|
1918
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1919
|
-
break;
|
|
1920
|
-
}
|
|
1964
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1965
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1966
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1967
|
+
groupSizePixels,
|
|
1968
|
+
layout: unsafeLayout,
|
|
1969
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1970
|
+
});
|
|
1971
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1972
|
+
setLayout(nextLayout);
|
|
1973
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1974
|
+
if (onLayout) {
|
|
1975
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1976
|
+
sizePercentage,
|
|
1977
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1978
|
+
})));
|
|
1979
|
+
}
|
|
1980
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1921
1981
|
}
|
|
1922
|
-
}
|
|
1923
|
-
}, [
|
|
1982
|
+
}, 0);
|
|
1983
|
+
}, []);
|
|
1924
1984
|
const context = useMemo(() => ({
|
|
1925
1985
|
collapsePanel,
|
|
1926
1986
|
direction,
|