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
|
@@ -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,
|
|
@@ -164,6 +165,7 @@ function PanelWithForwardedRef({
|
|
|
164
165
|
// CSS selectors
|
|
165
166
|
"data-panel": "",
|
|
166
167
|
"data-panel-id": panelId,
|
|
168
|
+
"data-panel-group-id": groupId,
|
|
167
169
|
// e2e test attributes
|
|
168
170
|
"data-panel-collapsible": undefined,
|
|
169
171
|
"data-panel-size": undefined
|
|
@@ -176,8 +178,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
176
178
|
PanelWithForwardedRef.displayName = "Panel";
|
|
177
179
|
Panel.displayName = "forwardRef(Panel)";
|
|
178
180
|
|
|
179
|
-
const PRECISION = 10;
|
|
180
|
-
|
|
181
181
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
182
182
|
return pixels / groupSizePixels * 100;
|
|
183
183
|
}
|
|
@@ -255,6 +255,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
const PRECISION = 10;
|
|
259
|
+
|
|
258
260
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
259
261
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
260
262
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -728,15 +730,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
728
730
|
}, [groupId, layout, panelDataArray]);
|
|
729
731
|
useEffect(() => {
|
|
730
732
|
const {
|
|
731
|
-
direction,
|
|
732
733
|
panelDataArray
|
|
733
734
|
} = committedValuesRef.current;
|
|
734
735
|
const groupElement = getPanelGroupElement(groupId);
|
|
735
736
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
736
|
-
const {
|
|
737
|
-
height,
|
|
738
|
-
width
|
|
739
|
-
} = groupElement.getBoundingClientRect();
|
|
740
737
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
741
738
|
const cleanupFunctions = handles.map(handle => {
|
|
742
739
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -756,21 +753,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
756
753
|
if (index >= 0) {
|
|
757
754
|
const panelData = panelDataArray[index];
|
|
758
755
|
const size = layout[index];
|
|
759
|
-
if (size != null) {
|
|
760
|
-
var _getPercentageSizeFro;
|
|
756
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
757
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
761
758
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
762
|
-
const
|
|
759
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
760
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
761
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
762
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
763
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
763
764
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
764
765
|
sizePixels: panelData.constraints.minSizePixels
|
|
765
|
-
}, groupSizePixels)) !== null &&
|
|
766
|
-
let delta = 0;
|
|
767
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
768
|
-
delta = direction === "horizontal" ? width : height;
|
|
769
|
-
} else {
|
|
770
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
771
|
-
}
|
|
766
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
772
767
|
const nextLayout = adjustLayoutByDelta({
|
|
773
|
-
delta,
|
|
768
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
774
769
|
groupSizePixels,
|
|
775
770
|
layout,
|
|
776
771
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -1079,6 +1074,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1079
1074
|
return callable;
|
|
1080
1075
|
}
|
|
1081
1076
|
|
|
1077
|
+
function getPanelElementsForGroup(groupId) {
|
|
1078
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1082
1081
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1083
1082
|
// or on a browser with cookies/storage disabled.
|
|
1084
1083
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1228,7 +1227,7 @@ const defaultStorage = {
|
|
|
1228
1227
|
};
|
|
1229
1228
|
const debounceMap = {};
|
|
1230
1229
|
function PanelGroupWithForwardedRef({
|
|
1231
|
-
autoSaveId,
|
|
1230
|
+
autoSaveId = null,
|
|
1232
1231
|
children,
|
|
1233
1232
|
className: classNameFromProps = "",
|
|
1234
1233
|
dataAttributes,
|
|
@@ -1245,11 +1244,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1245
1244
|
const groupId = useUniqueId(idFromProps);
|
|
1246
1245
|
const [dragState, setDragState] = useState(null);
|
|
1247
1246
|
const [layout, setLayout] = useState([]);
|
|
1248
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1249
1247
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1250
1248
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1251
1249
|
const prevDeltaRef = useRef(0);
|
|
1252
1250
|
const committedValuesRef = useRef({
|
|
1251
|
+
autoSaveId,
|
|
1253
1252
|
direction,
|
|
1254
1253
|
dragState,
|
|
1255
1254
|
id: groupId,
|
|
@@ -1257,7 +1256,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1257
1256
|
keyboardResizeByPixels,
|
|
1258
1257
|
layout,
|
|
1259
1258
|
onLayout,
|
|
1260
|
-
panelDataArray
|
|
1259
|
+
panelDataArray: [],
|
|
1260
|
+
storage
|
|
1261
1261
|
});
|
|
1262
1262
|
useRef({
|
|
1263
1263
|
didLogIdAndOrderWarning: false,
|
|
@@ -1295,6 +1295,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1295
1295
|
});
|
|
1296
1296
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1297
1297
|
setLayout(safeLayout);
|
|
1298
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1298
1299
|
if (onLayout) {
|
|
1299
1300
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1300
1301
|
sizePercentage,
|
|
@@ -1306,21 +1307,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1306
1307
|
}
|
|
1307
1308
|
}), []);
|
|
1308
1309
|
useIsomorphicLayoutEffect(() => {
|
|
1310
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1309
1311
|
committedValuesRef.current.direction = direction;
|
|
1310
1312
|
committedValuesRef.current.dragState = dragState;
|
|
1311
1313
|
committedValuesRef.current.id = groupId;
|
|
1312
|
-
committedValuesRef.current.layout = layout;
|
|
1313
1314
|
committedValuesRef.current.onLayout = onLayout;
|
|
1314
|
-
committedValuesRef.current.
|
|
1315
|
+
committedValuesRef.current.storage = storage;
|
|
1316
|
+
|
|
1317
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1318
|
+
// TODO [217] Move these values into a separate ref
|
|
1315
1319
|
});
|
|
1320
|
+
|
|
1316
1321
|
useWindowSplitterPanelGroupBehavior({
|
|
1317
1322
|
committedValuesRef,
|
|
1318
1323
|
groupId,
|
|
1319
1324
|
layout,
|
|
1320
|
-
panelDataArray,
|
|
1325
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1321
1326
|
setLayout
|
|
1322
1327
|
});
|
|
1323
1328
|
useEffect(() => {
|
|
1329
|
+
const {
|
|
1330
|
+
panelDataArray
|
|
1331
|
+
} = committedValuesRef.current;
|
|
1332
|
+
|
|
1324
1333
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1325
1334
|
if (autoSaveId) {
|
|
1326
1335
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1333,59 +1342,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1333
1342
|
}
|
|
1334
1343
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1335
1344
|
}
|
|
1336
|
-
}, [autoSaveId, layout,
|
|
1337
|
-
|
|
1338
|
-
// Once all panels have registered themselves,
|
|
1339
|
-
// Compute the initial sizes based on default weights.
|
|
1340
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1345
|
+
}, [autoSaveId, layout, storage]);
|
|
1341
1346
|
useIsomorphicLayoutEffect(() => {
|
|
1342
1347
|
const {
|
|
1343
|
-
|
|
1344
|
-
layout,
|
|
1345
|
-
onLayout
|
|
1348
|
+
panelDataArray
|
|
1346
1349
|
} = committedValuesRef.current;
|
|
1347
|
-
if (layout.length === panelDataArray.length) {
|
|
1348
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1349
|
-
return;
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
// If this panel has been configured to persist sizing information,
|
|
1353
|
-
// default size should be restored from local storage if possible.
|
|
1354
|
-
let unsafeLayout = null;
|
|
1355
|
-
if (autoSaveId) {
|
|
1356
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1357
|
-
}
|
|
1358
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1359
|
-
if (groupSizePixels <= 0) {
|
|
1360
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1361
|
-
return;
|
|
1362
|
-
}
|
|
1363
|
-
if (unsafeLayout == null) {
|
|
1364
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1365
|
-
groupSizePixels,
|
|
1366
|
-
panelDataArray
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1371
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1372
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1373
|
-
groupSizePixels,
|
|
1374
|
-
layout: unsafeLayout,
|
|
1375
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1376
|
-
});
|
|
1377
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1378
|
-
setLayout(validatedLayout);
|
|
1379
|
-
}
|
|
1380
|
-
if (onLayout) {
|
|
1381
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1382
|
-
sizePercentage,
|
|
1383
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1384
|
-
})));
|
|
1385
|
-
}
|
|
1386
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1387
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1388
|
-
useIsomorphicLayoutEffect(() => {
|
|
1389
1350
|
const constraints = panelDataArray.map(({
|
|
1390
1351
|
constraints
|
|
1391
1352
|
}) => constraints);
|
|
@@ -1409,6 +1370,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1409
1370
|
});
|
|
1410
1371
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1411
1372
|
setLayout(nextLayout);
|
|
1373
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1412
1374
|
if (onLayout) {
|
|
1413
1375
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1414
1376
|
sizePercentage,
|
|
@@ -1423,7 +1385,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1423
1385
|
resizeObserver.disconnect();
|
|
1424
1386
|
};
|
|
1425
1387
|
}
|
|
1426
|
-
}, [groupId
|
|
1388
|
+
}, [groupId]);
|
|
1427
1389
|
|
|
1428
1390
|
// DEV warnings
|
|
1429
1391
|
useEffect(() => {
|
|
@@ -1460,6 +1422,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1460
1422
|
});
|
|
1461
1423
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1462
1424
|
setLayout(nextLayout);
|
|
1425
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1463
1426
|
if (onLayout) {
|
|
1464
1427
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1465
1428
|
sizePercentage,
|
|
@@ -1504,6 +1467,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1504
1467
|
});
|
|
1505
1468
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1506
1469
|
setLayout(nextLayout);
|
|
1470
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1507
1471
|
if (onLayout) {
|
|
1508
1472
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1509
1473
|
sizePercentage,
|
|
@@ -1534,6 +1498,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1534
1498
|
|
|
1535
1499
|
// This API should never read from committedValuesRef
|
|
1536
1500
|
const getPanelStyle = useCallback(panelData => {
|
|
1501
|
+
const {
|
|
1502
|
+
panelDataArray
|
|
1503
|
+
} = committedValuesRef.current;
|
|
1537
1504
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1538
1505
|
return computePanelFlexBoxStyle({
|
|
1539
1506
|
dragState,
|
|
@@ -1541,7 +1508,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1541
1508
|
panelData: panelDataArray,
|
|
1542
1509
|
panelIndex
|
|
1543
1510
|
});
|
|
1544
|
-
}, [dragState, layout
|
|
1511
|
+
}, [dragState, layout]);
|
|
1545
1512
|
|
|
1546
1513
|
// External APIs are safe to memoize via committed values ref
|
|
1547
1514
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1571,22 +1538,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1571
1538
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1572
1539
|
}, [groupId]);
|
|
1573
1540
|
const registerPanel = useCallback(panelData => {
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1541
|
+
const {
|
|
1542
|
+
autoSaveId,
|
|
1543
|
+
id: groupId,
|
|
1544
|
+
layout: prevLayout,
|
|
1545
|
+
onLayout,
|
|
1546
|
+
panelDataArray,
|
|
1547
|
+
storage
|
|
1548
|
+
} = committedValuesRef.current;
|
|
1549
|
+
panelDataArray.push(panelData);
|
|
1550
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1551
|
+
const orderA = panelA.order;
|
|
1552
|
+
const orderB = panelB.order;
|
|
1553
|
+
if (orderA == null && orderB == null) {
|
|
1554
|
+
return 0;
|
|
1555
|
+
} else if (orderA == null) {
|
|
1556
|
+
return -1;
|
|
1557
|
+
} else if (orderB == null) {
|
|
1558
|
+
return 1;
|
|
1559
|
+
} else {
|
|
1560
|
+
return orderA - orderB;
|
|
1561
|
+
}
|
|
1562
|
+
});
|
|
1563
|
+
|
|
1564
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1565
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1566
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1567
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// If this panel has been configured to persist sizing information,
|
|
1572
|
+
// default size should be restored from local storage if possible.
|
|
1573
|
+
let unsafeLayout = null;
|
|
1574
|
+
if (autoSaveId) {
|
|
1575
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1576
|
+
}
|
|
1577
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1578
|
+
if (groupSizePixels <= 0) {
|
|
1579
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1580
|
+
constraints
|
|
1581
|
+
}) => constraints))) {
|
|
1582
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
if (unsafeLayout == null) {
|
|
1587
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1588
|
+
groupSizePixels,
|
|
1589
|
+
panelDataArray
|
|
1588
1590
|
});
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1594
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1595
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1596
|
+
groupSizePixels,
|
|
1597
|
+
layout: unsafeLayout,
|
|
1598
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1589
1599
|
});
|
|
1600
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1601
|
+
setLayout(nextLayout);
|
|
1602
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1603
|
+
if (onLayout) {
|
|
1604
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1605
|
+
sizePercentage,
|
|
1606
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1607
|
+
})));
|
|
1608
|
+
}
|
|
1609
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1610
|
+
}
|
|
1590
1611
|
}, []);
|
|
1591
1612
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1592
1613
|
return function resizeHandler(event) {
|
|
@@ -1656,6 +1677,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1656
1677
|
}
|
|
1657
1678
|
if (layoutChanged) {
|
|
1658
1679
|
setLayout(nextLayout);
|
|
1680
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1659
1681
|
if (onLayout) {
|
|
1660
1682
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1661
1683
|
sizePercentage,
|
|
@@ -1693,6 +1715,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1693
1715
|
});
|
|
1694
1716
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1695
1717
|
setLayout(nextLayout);
|
|
1718
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1696
1719
|
if (onLayout) {
|
|
1697
1720
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1698
1721
|
sizePercentage,
|
|
@@ -1720,16 +1743,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1720
1743
|
resetGlobalCursorStyle();
|
|
1721
1744
|
setDragState(null);
|
|
1722
1745
|
}, []);
|
|
1746
|
+
const unregisterPanelRef = useRef({
|
|
1747
|
+
pendingPanelIds: new Set(),
|
|
1748
|
+
timeout: null
|
|
1749
|
+
});
|
|
1723
1750
|
const unregisterPanel = useCallback(panelData => {
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1751
|
+
const {
|
|
1752
|
+
id: groupId,
|
|
1753
|
+
layout: prevLayout,
|
|
1754
|
+
onLayout,
|
|
1755
|
+
panelDataArray
|
|
1756
|
+
} = committedValuesRef.current;
|
|
1757
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1758
|
+
if (index >= 0) {
|
|
1759
|
+
panelDataArray.splice(index, 1);
|
|
1760
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1761
|
+
}
|
|
1762
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1763
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1767
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1768
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1769
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1770
|
+
const {
|
|
1771
|
+
pendingPanelIds
|
|
1772
|
+
} = unregisterPanelRef.current;
|
|
1773
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1774
|
+
|
|
1775
|
+
// TRICKY
|
|
1776
|
+
// Strict effects mode
|
|
1777
|
+
let unmountDueToStrictMode = false;
|
|
1778
|
+
pendingPanelIds.forEach(panelId => {
|
|
1779
|
+
pendingPanelIds.delete(panelId);
|
|
1780
|
+
if (panelDataArray.find(({
|
|
1781
|
+
id
|
|
1782
|
+
}) => id === panelId) == null) {
|
|
1783
|
+
unmountDueToStrictMode = true;
|
|
1784
|
+
|
|
1785
|
+
// TRICKY
|
|
1786
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1787
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1788
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1789
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1790
|
+
}
|
|
1791
|
+
});
|
|
1792
|
+
if (!unmountDueToStrictMode) {
|
|
1793
|
+
return;
|
|
1730
1794
|
}
|
|
1731
|
-
|
|
1732
|
-
|
|
1795
|
+
if (panelDataArray.length === 0) {
|
|
1796
|
+
// The group is unmounting; skip layout calculation.
|
|
1797
|
+
return;
|
|
1798
|
+
}
|
|
1799
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1800
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1801
|
+
groupSizePixels,
|
|
1802
|
+
panelDataArray
|
|
1803
|
+
});
|
|
1804
|
+
|
|
1805
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1806
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1807
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1808
|
+
groupSizePixels,
|
|
1809
|
+
layout: unsafeLayout,
|
|
1810
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1811
|
+
});
|
|
1812
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1813
|
+
setLayout(nextLayout);
|
|
1814
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1815
|
+
if (onLayout) {
|
|
1816
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1817
|
+
sizePercentage,
|
|
1818
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1819
|
+
})));
|
|
1820
|
+
}
|
|
1821
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1822
|
+
}
|
|
1823
|
+
}, 0);
|
|
1733
1824
|
}, []);
|
|
1734
1825
|
const context = useMemo(() => ({
|
|
1735
1826
|
collapsePanel,
|