react-resizable-panels 0.0.59 → 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 +6 -0
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +177 -143
- package/dist/react-resizable-panels.browser.development.cjs.js +180 -146
- package/dist/react-resizable-panels.browser.development.esm.js +180 -146
- package/dist/react-resizable-panels.browser.esm.js +177 -143
- package/dist/react-resizable-panels.cjs.js +177 -143
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +180 -146
- package/dist/react-resizable-panels.development.esm.js +180 -146
- package/dist/react-resizable-panels.development.node.cjs.js +226 -66
- package/dist/react-resizable-panels.development.node.esm.js +226 -66
- package/dist/react-resizable-panels.esm.js +177 -143
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +223 -63
- package/dist/react-resizable-panels.node.esm.js +223 -63
- package/package.json +1 -1
- package/src/Panel.ts +2 -0
- package/src/PanelGroup.ts +219 -177
- package/src/utils/dom/getPanelElementsForGroup.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.0.60
|
|
4
|
+
|
|
5
|
+
- Better support imperative API usage from mount effects.
|
|
6
|
+
- Better support strict effects mode.
|
|
7
|
+
- Better checks not to call `onResize` or `onLayout` more than once.
|
|
8
|
+
|
|
3
9
|
## 0.0.59
|
|
4
10
|
|
|
5
11
|
- Support imperative panel API usage on-mount.
|
|
@@ -11,7 +11,7 @@ export type PanelGroupStorage = {
|
|
|
11
11
|
};
|
|
12
12
|
export type PanelGroupOnLayout = (layout: MixedSizes[]) => void;
|
|
13
13
|
export type PanelGroupProps = PropsWithChildren<{
|
|
14
|
-
autoSaveId?: string;
|
|
14
|
+
autoSaveId?: string | null;
|
|
15
15
|
className?: string;
|
|
16
16
|
dataAttributes?: DataAttributes;
|
|
17
17
|
direction: Direction;
|
|
@@ -24,7 +24,7 @@ export type PanelGroupProps = PropsWithChildren<{
|
|
|
24
24
|
tagName?: ElementType;
|
|
25
25
|
}>;
|
|
26
26
|
export declare const PanelGroup: import("react").ForwardRefExoticComponent<{
|
|
27
|
-
autoSaveId?: string | undefined;
|
|
27
|
+
autoSaveId?: string | null | undefined;
|
|
28
28
|
className?: string | undefined;
|
|
29
29
|
dataAttributes?: DataAttributes | undefined;
|
|
30
30
|
direction: Direction;
|
|
@@ -93,6 +93,7 @@ function PanelWithForwardedRef({
|
|
|
93
93
|
expandPanel,
|
|
94
94
|
getPanelSize,
|
|
95
95
|
getPanelStyle,
|
|
96
|
+
groupId,
|
|
96
97
|
isPanelCollapsed,
|
|
97
98
|
registerPanel,
|
|
98
99
|
resizePanel,
|
|
@@ -186,6 +187,7 @@ function PanelWithForwardedRef({
|
|
|
186
187
|
// CSS selectors
|
|
187
188
|
"data-panel": "",
|
|
188
189
|
"data-panel-id": panelId,
|
|
190
|
+
"data-panel-group-id": groupId,
|
|
189
191
|
// e2e test attributes
|
|
190
192
|
"data-panel-collapsible": undefined,
|
|
191
193
|
"data-panel-size": undefined
|
|
@@ -1094,6 +1096,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1094
1096
|
return callable;
|
|
1095
1097
|
}
|
|
1096
1098
|
|
|
1099
|
+
function getPanelElementsForGroup(groupId) {
|
|
1100
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1097
1103
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1098
1104
|
// or on a browser with cookies/storage disabled.
|
|
1099
1105
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1243,7 +1249,7 @@ const defaultStorage = {
|
|
|
1243
1249
|
};
|
|
1244
1250
|
const debounceMap = {};
|
|
1245
1251
|
function PanelGroupWithForwardedRef({
|
|
1246
|
-
autoSaveId,
|
|
1252
|
+
autoSaveId = null,
|
|
1247
1253
|
children,
|
|
1248
1254
|
className: classNameFromProps = "",
|
|
1249
1255
|
dataAttributes,
|
|
@@ -1260,12 +1266,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1260
1266
|
const groupId = useUniqueId(idFromProps);
|
|
1261
1267
|
const [dragState, setDragState] = useState(null);
|
|
1262
1268
|
const [layout, setLayout] = useState([]);
|
|
1263
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1264
1269
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1265
1270
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1266
1271
|
const prevDeltaRef = useRef(0);
|
|
1267
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1268
1272
|
const committedValuesRef = useRef({
|
|
1273
|
+
autoSaveId,
|
|
1269
1274
|
direction,
|
|
1270
1275
|
dragState,
|
|
1271
1276
|
id: groupId,
|
|
@@ -1273,7 +1278,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1273
1278
|
keyboardResizeByPixels,
|
|
1274
1279
|
layout,
|
|
1275
1280
|
onLayout,
|
|
1276
|
-
panelDataArray
|
|
1281
|
+
panelDataArray: [],
|
|
1282
|
+
storage
|
|
1277
1283
|
});
|
|
1278
1284
|
useRef({
|
|
1279
1285
|
didLogIdAndOrderWarning: false,
|
|
@@ -1311,6 +1317,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1311
1317
|
});
|
|
1312
1318
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1313
1319
|
setLayout(safeLayout);
|
|
1320
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1314
1321
|
if (onLayout) {
|
|
1315
1322
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1316
1323
|
sizePercentage,
|
|
@@ -1322,21 +1329,29 @@ function PanelGroupWithForwardedRef({
|
|
|
1322
1329
|
}
|
|
1323
1330
|
}), []);
|
|
1324
1331
|
useIsomorphicLayoutEffect(() => {
|
|
1332
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1325
1333
|
committedValuesRef.current.direction = direction;
|
|
1326
1334
|
committedValuesRef.current.dragState = dragState;
|
|
1327
1335
|
committedValuesRef.current.id = groupId;
|
|
1328
|
-
committedValuesRef.current.layout = layout;
|
|
1329
1336
|
committedValuesRef.current.onLayout = onLayout;
|
|
1330
|
-
committedValuesRef.current.
|
|
1337
|
+
committedValuesRef.current.storage = storage;
|
|
1338
|
+
|
|
1339
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1340
|
+
// TODO [217] Move these values into a separate ref
|
|
1331
1341
|
});
|
|
1342
|
+
|
|
1332
1343
|
useWindowSplitterPanelGroupBehavior({
|
|
1333
1344
|
committedValuesRef,
|
|
1334
1345
|
groupId,
|
|
1335
1346
|
layout,
|
|
1336
|
-
panelDataArray,
|
|
1347
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1337
1348
|
setLayout
|
|
1338
1349
|
});
|
|
1339
1350
|
useEffect(() => {
|
|
1351
|
+
const {
|
|
1352
|
+
panelDataArray
|
|
1353
|
+
} = committedValuesRef.current;
|
|
1354
|
+
|
|
1340
1355
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1341
1356
|
if (autoSaveId) {
|
|
1342
1357
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1349,63 +1364,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1349
1364
|
}
|
|
1350
1365
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1351
1366
|
}
|
|
1352
|
-
}, [autoSaveId, layout,
|
|
1353
|
-
|
|
1354
|
-
// Once all panels have registered themselves,
|
|
1355
|
-
// Compute the initial sizes based on default weights.
|
|
1356
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1367
|
+
}, [autoSaveId, layout, storage]);
|
|
1357
1368
|
useIsomorphicLayoutEffect(() => {
|
|
1358
1369
|
const {
|
|
1359
|
-
|
|
1360
|
-
layout,
|
|
1361
|
-
onLayout
|
|
1370
|
+
panelDataArray
|
|
1362
1371
|
} = committedValuesRef.current;
|
|
1363
|
-
if (layout.length === panelDataArray.length) {
|
|
1364
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1365
|
-
return;
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
// If this panel has been configured to persist sizing information,
|
|
1369
|
-
// default size should be restored from local storage if possible.
|
|
1370
|
-
let unsafeLayout = null;
|
|
1371
|
-
if (autoSaveId) {
|
|
1372
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1373
|
-
}
|
|
1374
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1375
|
-
if (groupSizePixels <= 0) {
|
|
1376
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1377
|
-
constraints
|
|
1378
|
-
}) => constraints))) {
|
|
1379
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
if (unsafeLayout == null) {
|
|
1384
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1385
|
-
groupSizePixels,
|
|
1386
|
-
panelDataArray
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1391
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1392
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1393
|
-
groupSizePixels,
|
|
1394
|
-
layout: unsafeLayout,
|
|
1395
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1396
|
-
});
|
|
1397
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1398
|
-
setLayout(validatedLayout);
|
|
1399
|
-
}
|
|
1400
|
-
if (onLayout) {
|
|
1401
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1402
|
-
sizePercentage,
|
|
1403
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1404
|
-
})));
|
|
1405
|
-
}
|
|
1406
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1407
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1408
|
-
useIsomorphicLayoutEffect(() => {
|
|
1409
1372
|
const constraints = panelDataArray.map(({
|
|
1410
1373
|
constraints
|
|
1411
1374
|
}) => constraints);
|
|
@@ -1429,6 +1392,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1429
1392
|
});
|
|
1430
1393
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1431
1394
|
setLayout(nextLayout);
|
|
1395
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1432
1396
|
if (onLayout) {
|
|
1433
1397
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1434
1398
|
sizePercentage,
|
|
@@ -1443,7 +1407,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1443
1407
|
resizeObserver.disconnect();
|
|
1444
1408
|
};
|
|
1445
1409
|
}
|
|
1446
|
-
}, [groupId
|
|
1410
|
+
}, [groupId]);
|
|
1447
1411
|
|
|
1448
1412
|
// DEV warnings
|
|
1449
1413
|
useEffect(() => {
|
|
@@ -1456,17 +1420,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1456
1420
|
onLayout,
|
|
1457
1421
|
panelDataArray
|
|
1458
1422
|
} = committedValuesRef.current;
|
|
1459
|
-
|
|
1460
|
-
// See issues/211
|
|
1461
|
-
if (panelDataArray.find(({
|
|
1462
|
-
id
|
|
1463
|
-
}) => id === panelData.id) == null) {
|
|
1464
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1465
|
-
panelData,
|
|
1466
|
-
type: "collapse"
|
|
1467
|
-
}]);
|
|
1468
|
-
return;
|
|
1469
|
-
}
|
|
1470
1423
|
if (panelData.constraints.collapsible) {
|
|
1471
1424
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1472
1425
|
const {
|
|
@@ -1491,6 +1444,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1491
1444
|
});
|
|
1492
1445
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1493
1446
|
setLayout(nextLayout);
|
|
1447
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1494
1448
|
if (onLayout) {
|
|
1495
1449
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1496
1450
|
sizePercentage,
|
|
@@ -1510,17 +1464,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1510
1464
|
onLayout,
|
|
1511
1465
|
panelDataArray
|
|
1512
1466
|
} = committedValuesRef.current;
|
|
1513
|
-
|
|
1514
|
-
// See issues/211
|
|
1515
|
-
if (panelDataArray.find(({
|
|
1516
|
-
id
|
|
1517
|
-
}) => id === panelData.id) == null) {
|
|
1518
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1519
|
-
panelData,
|
|
1520
|
-
type: "expand"
|
|
1521
|
-
}]);
|
|
1522
|
-
return;
|
|
1523
|
-
}
|
|
1524
1467
|
if (panelData.constraints.collapsible) {
|
|
1525
1468
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1526
1469
|
const {
|
|
@@ -1546,6 +1489,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1546
1489
|
});
|
|
1547
1490
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1548
1491
|
setLayout(nextLayout);
|
|
1492
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1549
1493
|
if (onLayout) {
|
|
1550
1494
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1551
1495
|
sizePercentage,
|
|
@@ -1576,6 +1520,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1576
1520
|
|
|
1577
1521
|
// This API should never read from committedValuesRef
|
|
1578
1522
|
const getPanelStyle = useCallback(panelData => {
|
|
1523
|
+
const {
|
|
1524
|
+
panelDataArray
|
|
1525
|
+
} = committedValuesRef.current;
|
|
1579
1526
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1580
1527
|
return computePanelFlexBoxStyle({
|
|
1581
1528
|
dragState,
|
|
@@ -1583,7 +1530,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1583
1530
|
panelData: panelDataArray,
|
|
1584
1531
|
panelIndex
|
|
1585
1532
|
});
|
|
1586
|
-
}, [dragState, layout
|
|
1533
|
+
}, [dragState, layout]);
|
|
1587
1534
|
|
|
1588
1535
|
// External APIs are safe to memoize via committed values ref
|
|
1589
1536
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1613,22 +1560,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1613
1560
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1614
1561
|
}, [groupId]);
|
|
1615
1562
|
const registerPanel = useCallback(panelData => {
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1563
|
+
const {
|
|
1564
|
+
autoSaveId,
|
|
1565
|
+
id: groupId,
|
|
1566
|
+
layout: prevLayout,
|
|
1567
|
+
onLayout,
|
|
1568
|
+
panelDataArray,
|
|
1569
|
+
storage
|
|
1570
|
+
} = committedValuesRef.current;
|
|
1571
|
+
panelDataArray.push(panelData);
|
|
1572
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1573
|
+
const orderA = panelA.order;
|
|
1574
|
+
const orderB = panelB.order;
|
|
1575
|
+
if (orderA == null && orderB == null) {
|
|
1576
|
+
return 0;
|
|
1577
|
+
} else if (orderA == null) {
|
|
1578
|
+
return -1;
|
|
1579
|
+
} else if (orderB == null) {
|
|
1580
|
+
return 1;
|
|
1581
|
+
} else {
|
|
1582
|
+
return orderA - orderB;
|
|
1583
|
+
}
|
|
1584
|
+
});
|
|
1585
|
+
|
|
1586
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1587
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1588
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1589
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
// If this panel has been configured to persist sizing information,
|
|
1594
|
+
// default size should be restored from local storage if possible.
|
|
1595
|
+
let unsafeLayout = null;
|
|
1596
|
+
if (autoSaveId) {
|
|
1597
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1598
|
+
}
|
|
1599
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1600
|
+
if (groupSizePixels <= 0) {
|
|
1601
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1602
|
+
constraints
|
|
1603
|
+
}) => constraints))) {
|
|
1604
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (unsafeLayout == null) {
|
|
1609
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1610
|
+
groupSizePixels,
|
|
1611
|
+
panelDataArray
|
|
1630
1612
|
});
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1616
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1617
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1618
|
+
groupSizePixels,
|
|
1619
|
+
layout: unsafeLayout,
|
|
1620
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1631
1621
|
});
|
|
1622
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1623
|
+
setLayout(nextLayout);
|
|
1624
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1625
|
+
if (onLayout) {
|
|
1626
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1627
|
+
sizePercentage,
|
|
1628
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1629
|
+
})));
|
|
1630
|
+
}
|
|
1631
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1632
|
+
}
|
|
1632
1633
|
}, []);
|
|
1633
1634
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1634
1635
|
return function resizeHandler(event) {
|
|
@@ -1698,6 +1699,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1698
1699
|
}
|
|
1699
1700
|
if (layoutChanged) {
|
|
1700
1701
|
setLayout(nextLayout);
|
|
1702
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1701
1703
|
if (onLayout) {
|
|
1702
1704
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1703
1705
|
sizePercentage,
|
|
@@ -1716,18 +1718,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1716
1718
|
onLayout,
|
|
1717
1719
|
panelDataArray
|
|
1718
1720
|
} = committedValuesRef.current;
|
|
1719
|
-
|
|
1720
|
-
// See issues/211
|
|
1721
|
-
if (panelDataArray.find(({
|
|
1722
|
-
id
|
|
1723
|
-
}) => id === panelData.id) == null) {
|
|
1724
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1725
|
-
panelData,
|
|
1726
|
-
mixedSizes,
|
|
1727
|
-
type: "resize"
|
|
1728
|
-
}]);
|
|
1729
|
-
return;
|
|
1730
|
-
}
|
|
1731
1721
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1732
1722
|
const {
|
|
1733
1723
|
groupSizePixels,
|
|
@@ -1747,6 +1737,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1747
1737
|
});
|
|
1748
1738
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1749
1739
|
setLayout(nextLayout);
|
|
1740
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1750
1741
|
if (onLayout) {
|
|
1751
1742
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1752
1743
|
sizePercentage,
|
|
@@ -1774,42 +1765,85 @@ function PanelGroupWithForwardedRef({
|
|
|
1774
1765
|
resetGlobalCursorStyle();
|
|
1775
1766
|
setDragState(null);
|
|
1776
1767
|
}, []);
|
|
1768
|
+
const unregisterPanelRef = useRef({
|
|
1769
|
+
pendingPanelIds: new Set(),
|
|
1770
|
+
timeout: null
|
|
1771
|
+
});
|
|
1777
1772
|
const unregisterPanel = useCallback(panelData => {
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1773
|
+
const {
|
|
1774
|
+
id: groupId,
|
|
1775
|
+
layout: prevLayout,
|
|
1776
|
+
onLayout,
|
|
1777
|
+
panelDataArray
|
|
1778
|
+
} = committedValuesRef.current;
|
|
1779
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1780
|
+
if (index >= 0) {
|
|
1781
|
+
panelDataArray.splice(index, 1);
|
|
1782
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1783
|
+
}
|
|
1784
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1785
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1789
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1790
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1791
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1792
|
+
const {
|
|
1793
|
+
pendingPanelIds
|
|
1794
|
+
} = unregisterPanelRef.current;
|
|
1795
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1796
|
+
|
|
1797
|
+
// TRICKY
|
|
1798
|
+
// Strict effects mode
|
|
1799
|
+
let unmountDueToStrictMode = false;
|
|
1800
|
+
pendingPanelIds.forEach(panelId => {
|
|
1801
|
+
pendingPanelIds.delete(panelId);
|
|
1802
|
+
if (panelDataArray.find(({
|
|
1803
|
+
id
|
|
1804
|
+
}) => id === panelId) == null) {
|
|
1805
|
+
unmountDueToStrictMode = true;
|
|
1806
|
+
|
|
1807
|
+
// TRICKY
|
|
1808
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1809
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1810
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1811
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1812
|
+
}
|
|
1813
|
+
});
|
|
1814
|
+
if (!unmountDueToStrictMode) {
|
|
1815
|
+
return;
|
|
1784
1816
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1817
|
+
if (panelDataArray.length === 0) {
|
|
1818
|
+
// The group is unmounting; skip layout calculation.
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1822
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1823
|
+
groupSizePixels,
|
|
1824
|
+
panelDataArray
|
|
1825
|
+
});
|
|
1788
1826
|
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
{
|
|
1807
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1808
|
-
break;
|
|
1809
|
-
}
|
|
1827
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1828
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1829
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1830
|
+
groupSizePixels,
|
|
1831
|
+
layout: unsafeLayout,
|
|
1832
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1833
|
+
});
|
|
1834
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1835
|
+
setLayout(nextLayout);
|
|
1836
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1837
|
+
if (onLayout) {
|
|
1838
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1839
|
+
sizePercentage,
|
|
1840
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1841
|
+
})));
|
|
1842
|
+
}
|
|
1843
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1810
1844
|
}
|
|
1811
|
-
}
|
|
1812
|
-
}, [
|
|
1845
|
+
}, 0);
|
|
1846
|
+
}, []);
|
|
1813
1847
|
const context = useMemo(() => ({
|
|
1814
1848
|
collapsePanel,
|
|
1815
1849
|
direction,
|