react-resizable-panels 0.0.58 → 0.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +189 -98
- package/dist/react-resizable-panels.browser.development.cjs.js +192 -101
- package/dist/react-resizable-panels.browser.development.esm.js +192 -101
- package/dist/react-resizable-panels.browser.esm.js +189 -98
- package/dist/react-resizable-panels.cjs.js +189 -98
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +192 -101
- package/dist/react-resizable-panels.development.esm.js +192 -101
- package/dist/react-resizable-panels.development.node.cjs.js +237 -49
- package/dist/react-resizable-panels.development.node.esm.js +237 -49
- package/dist/react-resizable-panels.esm.js +189 -98
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +234 -46
- package/dist/react-resizable-panels.node.esm.js +234 -46
- package/package.json +1 -1
- package/src/Panel.ts +2 -0
- package/src/PanelGroup.ts +221 -97
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +15 -15
- package/src/utils/dom/getPanelElementsForGroup.ts +5 -0
|
@@ -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,
|
|
@@ -188,6 +189,7 @@ function PanelWithForwardedRef({
|
|
|
188
189
|
// CSS selectors
|
|
189
190
|
"data-panel": "",
|
|
190
191
|
"data-panel-id": panelId,
|
|
192
|
+
"data-panel-group-id": groupId,
|
|
191
193
|
// e2e test attributes
|
|
192
194
|
"data-panel-collapsible": undefined,
|
|
193
195
|
"data-panel-size": undefined
|
|
@@ -200,8 +202,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
200
202
|
PanelWithForwardedRef.displayName = "Panel";
|
|
201
203
|
Panel.displayName = "forwardRef(Panel)";
|
|
202
204
|
|
|
203
|
-
const PRECISION = 10;
|
|
204
|
-
|
|
205
205
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
206
206
|
return pixels / groupSizePixels * 100;
|
|
207
207
|
}
|
|
@@ -279,6 +279,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
const PRECISION = 10;
|
|
283
|
+
|
|
282
284
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
283
285
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
284
286
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -752,15 +754,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
752
754
|
}, [groupId, layout, panelDataArray]);
|
|
753
755
|
useEffect(() => {
|
|
754
756
|
const {
|
|
755
|
-
direction,
|
|
756
757
|
panelDataArray
|
|
757
758
|
} = committedValuesRef.current;
|
|
758
759
|
const groupElement = getPanelGroupElement(groupId);
|
|
759
760
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
760
|
-
const {
|
|
761
|
-
height,
|
|
762
|
-
width
|
|
763
|
-
} = groupElement.getBoundingClientRect();
|
|
764
761
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
765
762
|
const cleanupFunctions = handles.map(handle => {
|
|
766
763
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -780,21 +777,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
780
777
|
if (index >= 0) {
|
|
781
778
|
const panelData = panelDataArray[index];
|
|
782
779
|
const size = layout[index];
|
|
783
|
-
if (size != null) {
|
|
784
|
-
var _getPercentageSizeFro;
|
|
780
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
781
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
785
782
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
786
|
-
const
|
|
783
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
784
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
785
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
786
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
787
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
787
788
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
788
789
|
sizePixels: panelData.constraints.minSizePixels
|
|
789
|
-
}, groupSizePixels)) !== null &&
|
|
790
|
-
let delta = 0;
|
|
791
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
792
|
-
delta = direction === "horizontal" ? width : height;
|
|
793
|
-
} else {
|
|
794
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
795
|
-
}
|
|
790
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
796
791
|
const nextLayout = adjustLayoutByDelta({
|
|
797
|
-
delta,
|
|
792
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
798
793
|
groupSizePixels,
|
|
799
794
|
layout,
|
|
800
795
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1103,6 +1098,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1103
1098
|
return callable;
|
|
1104
1099
|
}
|
|
1105
1100
|
|
|
1101
|
+
function getPanelElementsForGroup(groupId) {
|
|
1102
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1106
1105
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1107
1106
|
// or on a browser with cookies/storage disabled.
|
|
1108
1107
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1252,7 +1251,7 @@ const defaultStorage = {
|
|
|
1252
1251
|
};
|
|
1253
1252
|
const debounceMap = {};
|
|
1254
1253
|
function PanelGroupWithForwardedRef({
|
|
1255
|
-
autoSaveId,
|
|
1254
|
+
autoSaveId = null,
|
|
1256
1255
|
children,
|
|
1257
1256
|
className: classNameFromProps = "",
|
|
1258
1257
|
dataAttributes,
|
|
@@ -1269,11 +1268,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1269
1268
|
const groupId = useUniqueId(idFromProps);
|
|
1270
1269
|
const [dragState, setDragState] = useState(null);
|
|
1271
1270
|
const [layout, setLayout] = useState([]);
|
|
1272
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1273
1271
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1274
1272
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1275
1273
|
const prevDeltaRef = useRef(0);
|
|
1276
1274
|
const committedValuesRef = useRef({
|
|
1275
|
+
autoSaveId,
|
|
1277
1276
|
direction,
|
|
1278
1277
|
dragState,
|
|
1279
1278
|
id: groupId,
|
|
@@ -1281,7 +1280,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1281
1280
|
keyboardResizeByPixels,
|
|
1282
1281
|
layout,
|
|
1283
1282
|
onLayout,
|
|
1284
|
-
panelDataArray
|
|
1283
|
+
panelDataArray: [],
|
|
1284
|
+
storage
|
|
1285
1285
|
});
|
|
1286
1286
|
useRef({
|
|
1287
1287
|
didLogIdAndOrderWarning: false,
|
|
@@ -1319,6 +1319,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1319
1319
|
});
|
|
1320
1320
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1321
1321
|
setLayout(safeLayout);
|
|
1322
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1322
1323
|
if (onLayout) {
|
|
1323
1324
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1324
1325
|
sizePercentage,
|
|
@@ -1330,21 +1331,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1330
1331
|
}
|
|
1331
1332
|
}), []);
|
|
1332
1333
|
useIsomorphicLayoutEffect(() => {
|
|
1334
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1333
1335
|
committedValuesRef.current.direction = direction;
|
|
1334
1336
|
committedValuesRef.current.dragState = dragState;
|
|
1335
1337
|
committedValuesRef.current.id = groupId;
|
|
1336
|
-
committedValuesRef.current.layout = layout;
|
|
1337
1338
|
committedValuesRef.current.onLayout = onLayout;
|
|
1338
|
-
committedValuesRef.current.
|
|
1339
|
+
committedValuesRef.current.storage = storage;
|
|
1340
|
+
|
|
1341
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1342
|
+
// TODO [217] Move these values into a separate ref
|
|
1339
1343
|
});
|
|
1344
|
+
|
|
1340
1345
|
useWindowSplitterPanelGroupBehavior({
|
|
1341
1346
|
committedValuesRef,
|
|
1342
1347
|
groupId,
|
|
1343
1348
|
layout,
|
|
1344
|
-
panelDataArray,
|
|
1349
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1345
1350
|
setLayout
|
|
1346
1351
|
});
|
|
1347
1352
|
useEffect(() => {
|
|
1353
|
+
const {
|
|
1354
|
+
panelDataArray
|
|
1355
|
+
} = committedValuesRef.current;
|
|
1356
|
+
|
|
1348
1357
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1349
1358
|
if (autoSaveId) {
|
|
1350
1359
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1357,59 +1366,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1357
1366
|
}
|
|
1358
1367
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1359
1368
|
}
|
|
1360
|
-
}, [autoSaveId, layout,
|
|
1361
|
-
|
|
1362
|
-
// Once all panels have registered themselves,
|
|
1363
|
-
// Compute the initial sizes based on default weights.
|
|
1364
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1369
|
+
}, [autoSaveId, layout, storage]);
|
|
1365
1370
|
useIsomorphicLayoutEffect(() => {
|
|
1366
1371
|
const {
|
|
1367
|
-
|
|
1368
|
-
layout,
|
|
1369
|
-
onLayout
|
|
1372
|
+
panelDataArray
|
|
1370
1373
|
} = committedValuesRef.current;
|
|
1371
|
-
if (layout.length === panelDataArray.length) {
|
|
1372
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1373
|
-
return;
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
// If this panel has been configured to persist sizing information,
|
|
1377
|
-
// default size should be restored from local storage if possible.
|
|
1378
|
-
let unsafeLayout = null;
|
|
1379
|
-
if (autoSaveId) {
|
|
1380
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1381
|
-
}
|
|
1382
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1383
|
-
if (groupSizePixels <= 0) {
|
|
1384
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1387
|
-
if (unsafeLayout == null) {
|
|
1388
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1389
|
-
groupSizePixels,
|
|
1390
|
-
panelDataArray
|
|
1391
|
-
});
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1395
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1396
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1397
|
-
groupSizePixels,
|
|
1398
|
-
layout: unsafeLayout,
|
|
1399
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1400
|
-
});
|
|
1401
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1402
|
-
setLayout(validatedLayout);
|
|
1403
|
-
}
|
|
1404
|
-
if (onLayout) {
|
|
1405
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1406
|
-
sizePercentage,
|
|
1407
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1408
|
-
})));
|
|
1409
|
-
}
|
|
1410
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1411
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1412
|
-
useIsomorphicLayoutEffect(() => {
|
|
1413
1374
|
const constraints = panelDataArray.map(({
|
|
1414
1375
|
constraints
|
|
1415
1376
|
}) => constraints);
|
|
@@ -1433,6 +1394,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1433
1394
|
});
|
|
1434
1395
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1435
1396
|
setLayout(nextLayout);
|
|
1397
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1436
1398
|
if (onLayout) {
|
|
1437
1399
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1438
1400
|
sizePercentage,
|
|
@@ -1447,7 +1409,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1447
1409
|
resizeObserver.disconnect();
|
|
1448
1410
|
};
|
|
1449
1411
|
}
|
|
1450
|
-
}, [groupId
|
|
1412
|
+
}, [groupId]);
|
|
1451
1413
|
|
|
1452
1414
|
// DEV warnings
|
|
1453
1415
|
useEffect(() => {
|
|
@@ -1484,6 +1446,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1484
1446
|
});
|
|
1485
1447
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1486
1448
|
setLayout(nextLayout);
|
|
1449
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1487
1450
|
if (onLayout) {
|
|
1488
1451
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1489
1452
|
sizePercentage,
|
|
@@ -1528,6 +1491,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1528
1491
|
});
|
|
1529
1492
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1530
1493
|
setLayout(nextLayout);
|
|
1494
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1531
1495
|
if (onLayout) {
|
|
1532
1496
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1533
1497
|
sizePercentage,
|
|
@@ -1558,6 +1522,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1558
1522
|
|
|
1559
1523
|
// This API should never read from committedValuesRef
|
|
1560
1524
|
const getPanelStyle = useCallback(panelData => {
|
|
1525
|
+
const {
|
|
1526
|
+
panelDataArray
|
|
1527
|
+
} = committedValuesRef.current;
|
|
1561
1528
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1562
1529
|
return computePanelFlexBoxStyle({
|
|
1563
1530
|
dragState,
|
|
@@ -1565,7 +1532,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1565
1532
|
panelData: panelDataArray,
|
|
1566
1533
|
panelIndex
|
|
1567
1534
|
});
|
|
1568
|
-
}, [dragState, layout
|
|
1535
|
+
}, [dragState, layout]);
|
|
1569
1536
|
|
|
1570
1537
|
// External APIs are safe to memoize via committed values ref
|
|
1571
1538
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1595,22 +1562,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1595
1562
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1596
1563
|
}, [groupId]);
|
|
1597
1564
|
const registerPanel = useCallback(panelData => {
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1565
|
+
const {
|
|
1566
|
+
autoSaveId,
|
|
1567
|
+
id: groupId,
|
|
1568
|
+
layout: prevLayout,
|
|
1569
|
+
onLayout,
|
|
1570
|
+
panelDataArray,
|
|
1571
|
+
storage
|
|
1572
|
+
} = committedValuesRef.current;
|
|
1573
|
+
panelDataArray.push(panelData);
|
|
1574
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1575
|
+
const orderA = panelA.order;
|
|
1576
|
+
const orderB = panelB.order;
|
|
1577
|
+
if (orderA == null && orderB == null) {
|
|
1578
|
+
return 0;
|
|
1579
|
+
} else if (orderA == null) {
|
|
1580
|
+
return -1;
|
|
1581
|
+
} else if (orderB == null) {
|
|
1582
|
+
return 1;
|
|
1583
|
+
} else {
|
|
1584
|
+
return orderA - orderB;
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
|
|
1588
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1589
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1590
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1591
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// If this panel has been configured to persist sizing information,
|
|
1596
|
+
// default size should be restored from local storage if possible.
|
|
1597
|
+
let unsafeLayout = null;
|
|
1598
|
+
if (autoSaveId) {
|
|
1599
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1600
|
+
}
|
|
1601
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1602
|
+
if (groupSizePixels <= 0) {
|
|
1603
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1604
|
+
constraints
|
|
1605
|
+
}) => constraints))) {
|
|
1606
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
if (unsafeLayout == null) {
|
|
1611
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1612
|
+
groupSizePixels,
|
|
1613
|
+
panelDataArray
|
|
1612
1614
|
});
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1618
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1619
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1620
|
+
groupSizePixels,
|
|
1621
|
+
layout: unsafeLayout,
|
|
1622
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1613
1623
|
});
|
|
1624
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1625
|
+
setLayout(nextLayout);
|
|
1626
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1627
|
+
if (onLayout) {
|
|
1628
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1629
|
+
sizePercentage,
|
|
1630
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1631
|
+
})));
|
|
1632
|
+
}
|
|
1633
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1634
|
+
}
|
|
1614
1635
|
}, []);
|
|
1615
1636
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1616
1637
|
return function resizeHandler(event) {
|
|
@@ -1680,6 +1701,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1680
1701
|
}
|
|
1681
1702
|
if (layoutChanged) {
|
|
1682
1703
|
setLayout(nextLayout);
|
|
1704
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1683
1705
|
if (onLayout) {
|
|
1684
1706
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1685
1707
|
sizePercentage,
|
|
@@ -1717,6 +1739,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1717
1739
|
});
|
|
1718
1740
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1719
1741
|
setLayout(nextLayout);
|
|
1742
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1720
1743
|
if (onLayout) {
|
|
1721
1744
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1722
1745
|
sizePercentage,
|
|
@@ -1744,16 +1767,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1744
1767
|
resetGlobalCursorStyle();
|
|
1745
1768
|
setDragState(null);
|
|
1746
1769
|
}, []);
|
|
1770
|
+
const unregisterPanelRef = useRef({
|
|
1771
|
+
pendingPanelIds: new Set(),
|
|
1772
|
+
timeout: null
|
|
1773
|
+
});
|
|
1747
1774
|
const unregisterPanel = useCallback(panelData => {
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1775
|
+
const {
|
|
1776
|
+
id: groupId,
|
|
1777
|
+
layout: prevLayout,
|
|
1778
|
+
onLayout,
|
|
1779
|
+
panelDataArray
|
|
1780
|
+
} = committedValuesRef.current;
|
|
1781
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1782
|
+
if (index >= 0) {
|
|
1783
|
+
panelDataArray.splice(index, 1);
|
|
1784
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1785
|
+
}
|
|
1786
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1787
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1791
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1792
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1793
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1794
|
+
const {
|
|
1795
|
+
pendingPanelIds
|
|
1796
|
+
} = unregisterPanelRef.current;
|
|
1797
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1798
|
+
|
|
1799
|
+
// TRICKY
|
|
1800
|
+
// Strict effects mode
|
|
1801
|
+
let unmountDueToStrictMode = false;
|
|
1802
|
+
pendingPanelIds.forEach(panelId => {
|
|
1803
|
+
pendingPanelIds.delete(panelId);
|
|
1804
|
+
if (panelDataArray.find(({
|
|
1805
|
+
id
|
|
1806
|
+
}) => id === panelId) == null) {
|
|
1807
|
+
unmountDueToStrictMode = true;
|
|
1808
|
+
|
|
1809
|
+
// TRICKY
|
|
1810
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1811
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1812
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1813
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1814
|
+
}
|
|
1815
|
+
});
|
|
1816
|
+
if (!unmountDueToStrictMode) {
|
|
1817
|
+
return;
|
|
1754
1818
|
}
|
|
1755
|
-
|
|
1756
|
-
|
|
1819
|
+
if (panelDataArray.length === 0) {
|
|
1820
|
+
// The group is unmounting; skip layout calculation.
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1824
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1825
|
+
groupSizePixels,
|
|
1826
|
+
panelDataArray
|
|
1827
|
+
});
|
|
1828
|
+
|
|
1829
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1830
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1831
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1832
|
+
groupSizePixels,
|
|
1833
|
+
layout: unsafeLayout,
|
|
1834
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1835
|
+
});
|
|
1836
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1837
|
+
setLayout(nextLayout);
|
|
1838
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1839
|
+
if (onLayout) {
|
|
1840
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1841
|
+
sizePercentage,
|
|
1842
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1843
|
+
})));
|
|
1844
|
+
}
|
|
1845
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1846
|
+
}
|
|
1847
|
+
}, 0);
|
|
1757
1848
|
}, []);
|
|
1758
1849
|
const context = useMemo(() => ({
|
|
1759
1850
|
collapsePanel,
|