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
|
@@ -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
|
|
@@ -711,6 +713,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
711
713
|
|
|
712
714
|
function useWindowSplitterPanelGroupBehavior({
|
|
713
715
|
committedValuesRef,
|
|
716
|
+
eagerValuesRef,
|
|
714
717
|
groupId,
|
|
715
718
|
layout,
|
|
716
719
|
panelDataArray,
|
|
@@ -753,7 +756,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
753
756
|
useEffect(() => {
|
|
754
757
|
const {
|
|
755
758
|
panelDataArray
|
|
756
|
-
} =
|
|
759
|
+
} = eagerValuesRef.current;
|
|
757
760
|
const groupElement = getPanelGroupElement(groupId);
|
|
758
761
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
759
762
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -811,7 +814,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
811
814
|
return () => {
|
|
812
815
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
813
816
|
};
|
|
814
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
817
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
815
818
|
}
|
|
816
819
|
|
|
817
820
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1096,6 +1099,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1096
1099
|
return callable;
|
|
1097
1100
|
}
|
|
1098
1101
|
|
|
1102
|
+
function getPanelElementsForGroup(groupId) {
|
|
1103
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1099
1106
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1100
1107
|
// or on a browser with cookies/storage disabled.
|
|
1101
1108
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1245,7 +1252,7 @@ const defaultStorage = {
|
|
|
1245
1252
|
};
|
|
1246
1253
|
const debounceMap = {};
|
|
1247
1254
|
function PanelGroupWithForwardedRef({
|
|
1248
|
-
autoSaveId,
|
|
1255
|
+
autoSaveId = null,
|
|
1249
1256
|
children,
|
|
1250
1257
|
className: classNameFromProps = "",
|
|
1251
1258
|
dataAttributes,
|
|
@@ -1262,20 +1269,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1262
1269
|
const groupId = useUniqueId(idFromProps);
|
|
1263
1270
|
const [dragState, setDragState] = useState(null);
|
|
1264
1271
|
const [layout, setLayout] = useState([]);
|
|
1265
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1266
1272
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1267
1273
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1268
1274
|
const prevDeltaRef = useRef(0);
|
|
1269
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1270
1275
|
const committedValuesRef = useRef({
|
|
1276
|
+
autoSaveId,
|
|
1271
1277
|
direction,
|
|
1272
1278
|
dragState,
|
|
1273
1279
|
id: groupId,
|
|
1274
1280
|
keyboardResizeByPercentage,
|
|
1275
1281
|
keyboardResizeByPixels,
|
|
1276
|
-
layout,
|
|
1277
1282
|
onLayout,
|
|
1278
|
-
|
|
1283
|
+
storage
|
|
1284
|
+
});
|
|
1285
|
+
const eagerValuesRef = useRef({
|
|
1286
|
+
layout,
|
|
1287
|
+
panelDataArray: []
|
|
1279
1288
|
});
|
|
1280
1289
|
useRef({
|
|
1281
1290
|
didLogIdAndOrderWarning: false,
|
|
@@ -1286,9 +1295,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1286
1295
|
getId: () => committedValuesRef.current.id,
|
|
1287
1296
|
getLayout: () => {
|
|
1288
1297
|
const {
|
|
1289
|
-
id: groupId
|
|
1290
|
-
layout
|
|
1298
|
+
id: groupId
|
|
1291
1299
|
} = committedValuesRef.current;
|
|
1300
|
+
const {
|
|
1301
|
+
layout
|
|
1302
|
+
} = eagerValuesRef.current;
|
|
1292
1303
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1293
1304
|
return layout.map(sizePercentage => {
|
|
1294
1305
|
return {
|
|
@@ -1300,10 +1311,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1300
1311
|
setLayout: mixedSizes => {
|
|
1301
1312
|
const {
|
|
1302
1313
|
id: groupId,
|
|
1314
|
+
onLayout
|
|
1315
|
+
} = committedValuesRef.current;
|
|
1316
|
+
const {
|
|
1303
1317
|
layout: prevLayout,
|
|
1304
|
-
onLayout,
|
|
1305
1318
|
panelDataArray
|
|
1306
|
-
} =
|
|
1319
|
+
} = eagerValuesRef.current;
|
|
1307
1320
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1308
1321
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1309
1322
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1313,6 +1326,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1313
1326
|
});
|
|
1314
1327
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1315
1328
|
setLayout(safeLayout);
|
|
1329
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1316
1330
|
if (onLayout) {
|
|
1317
1331
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1318
1332
|
sizePercentage,
|
|
@@ -1324,21 +1338,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1324
1338
|
}
|
|
1325
1339
|
}), []);
|
|
1326
1340
|
useIsomorphicLayoutEffect(() => {
|
|
1341
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1327
1342
|
committedValuesRef.current.direction = direction;
|
|
1328
1343
|
committedValuesRef.current.dragState = dragState;
|
|
1329
1344
|
committedValuesRef.current.id = groupId;
|
|
1330
|
-
committedValuesRef.current.layout = layout;
|
|
1331
1345
|
committedValuesRef.current.onLayout = onLayout;
|
|
1332
|
-
committedValuesRef.current.
|
|
1346
|
+
committedValuesRef.current.storage = storage;
|
|
1347
|
+
|
|
1348
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1349
|
+
// TODO [217] Move these values into a separate ref
|
|
1333
1350
|
});
|
|
1351
|
+
|
|
1334
1352
|
useWindowSplitterPanelGroupBehavior({
|
|
1335
1353
|
committedValuesRef,
|
|
1354
|
+
eagerValuesRef,
|
|
1336
1355
|
groupId,
|
|
1337
1356
|
layout,
|
|
1338
|
-
panelDataArray,
|
|
1357
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1339
1358
|
setLayout
|
|
1340
1359
|
});
|
|
1341
1360
|
useEffect(() => {
|
|
1361
|
+
const {
|
|
1362
|
+
panelDataArray
|
|
1363
|
+
} = eagerValuesRef.current;
|
|
1364
|
+
|
|
1342
1365
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1343
1366
|
if (autoSaveId) {
|
|
1344
1367
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1351,63 +1374,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1351
1374
|
}
|
|
1352
1375
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1353
1376
|
}
|
|
1354
|
-
}, [autoSaveId, layout,
|
|
1355
|
-
|
|
1356
|
-
// Once all panels have registered themselves,
|
|
1357
|
-
// Compute the initial sizes based on default weights.
|
|
1358
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1377
|
+
}, [autoSaveId, layout, storage]);
|
|
1359
1378
|
useIsomorphicLayoutEffect(() => {
|
|
1360
1379
|
const {
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
} = committedValuesRef.current;
|
|
1365
|
-
if (layout.length === panelDataArray.length) {
|
|
1366
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
// If this panel has been configured to persist sizing information,
|
|
1371
|
-
// default size should be restored from local storage if possible.
|
|
1372
|
-
let unsafeLayout = null;
|
|
1373
|
-
if (autoSaveId) {
|
|
1374
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1375
|
-
}
|
|
1376
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1377
|
-
if (groupSizePixels <= 0) {
|
|
1378
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1379
|
-
constraints
|
|
1380
|
-
}) => constraints))) {
|
|
1381
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1382
|
-
return;
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
if (unsafeLayout == null) {
|
|
1386
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1387
|
-
groupSizePixels,
|
|
1388
|
-
panelDataArray
|
|
1389
|
-
});
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1393
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1394
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1395
|
-
groupSizePixels,
|
|
1396
|
-
layout: unsafeLayout,
|
|
1397
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1398
|
-
});
|
|
1399
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1400
|
-
setLayout(validatedLayout);
|
|
1401
|
-
}
|
|
1402
|
-
if (onLayout) {
|
|
1403
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1404
|
-
sizePercentage,
|
|
1405
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1406
|
-
})));
|
|
1407
|
-
}
|
|
1408
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1409
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1410
|
-
useIsomorphicLayoutEffect(() => {
|
|
1380
|
+
layout: prevLayout,
|
|
1381
|
+
panelDataArray
|
|
1382
|
+
} = eagerValuesRef.current;
|
|
1411
1383
|
const constraints = panelDataArray.map(({
|
|
1412
1384
|
constraints
|
|
1413
1385
|
}) => constraints);
|
|
@@ -1421,7 +1393,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1421
1393
|
const resizeObserver = new ResizeObserver(() => {
|
|
1422
1394
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1423
1395
|
const {
|
|
1424
|
-
layout: prevLayout,
|
|
1425
1396
|
onLayout
|
|
1426
1397
|
} = committedValuesRef.current;
|
|
1427
1398
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1431,6 +1402,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1431
1402
|
});
|
|
1432
1403
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1433
1404
|
setLayout(nextLayout);
|
|
1405
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1434
1406
|
if (onLayout) {
|
|
1435
1407
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1436
1408
|
sizePercentage,
|
|
@@ -1445,7 +1417,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1445
1417
|
resizeObserver.disconnect();
|
|
1446
1418
|
};
|
|
1447
1419
|
}
|
|
1448
|
-
}, [groupId
|
|
1420
|
+
}, [groupId]);
|
|
1449
1421
|
|
|
1450
1422
|
// DEV warnings
|
|
1451
1423
|
useEffect(() => {
|
|
@@ -1453,22 +1425,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1453
1425
|
|
|
1454
1426
|
// External APIs are safe to memoize via committed values ref
|
|
1455
1427
|
const collapsePanel = useCallback(panelData => {
|
|
1428
|
+
const {
|
|
1429
|
+
onLayout
|
|
1430
|
+
} = committedValuesRef.current;
|
|
1456
1431
|
const {
|
|
1457
1432
|
layout: prevLayout,
|
|
1458
|
-
onLayout,
|
|
1459
1433
|
panelDataArray
|
|
1460
|
-
} =
|
|
1461
|
-
|
|
1462
|
-
// See issues/211
|
|
1463
|
-
if (panelDataArray.find(({
|
|
1464
|
-
id
|
|
1465
|
-
}) => id === panelData.id) == null) {
|
|
1466
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1467
|
-
panelData,
|
|
1468
|
-
type: "collapse"
|
|
1469
|
-
}]);
|
|
1470
|
-
return;
|
|
1471
|
-
}
|
|
1434
|
+
} = eagerValuesRef.current;
|
|
1472
1435
|
if (panelData.constraints.collapsible) {
|
|
1473
1436
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1474
1437
|
const {
|
|
@@ -1493,6 +1456,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1493
1456
|
});
|
|
1494
1457
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1495
1458
|
setLayout(nextLayout);
|
|
1459
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1496
1460
|
if (onLayout) {
|
|
1497
1461
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1498
1462
|
sizePercentage,
|
|
@@ -1507,22 +1471,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1507
1471
|
|
|
1508
1472
|
// External APIs are safe to memoize via committed values ref
|
|
1509
1473
|
const expandPanel = useCallback(panelData => {
|
|
1474
|
+
const {
|
|
1475
|
+
onLayout
|
|
1476
|
+
} = committedValuesRef.current;
|
|
1510
1477
|
const {
|
|
1511
1478
|
layout: prevLayout,
|
|
1512
|
-
onLayout,
|
|
1513
1479
|
panelDataArray
|
|
1514
|
-
} =
|
|
1515
|
-
|
|
1516
|
-
// See issues/211
|
|
1517
|
-
if (panelDataArray.find(({
|
|
1518
|
-
id
|
|
1519
|
-
}) => id === panelData.id) == null) {
|
|
1520
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1521
|
-
panelData,
|
|
1522
|
-
type: "expand"
|
|
1523
|
-
}]);
|
|
1524
|
-
return;
|
|
1525
|
-
}
|
|
1480
|
+
} = eagerValuesRef.current;
|
|
1526
1481
|
if (panelData.constraints.collapsible) {
|
|
1527
1482
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1528
1483
|
const {
|
|
@@ -1548,6 +1503,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1548
1503
|
});
|
|
1549
1504
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1550
1505
|
setLayout(nextLayout);
|
|
1506
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1551
1507
|
if (onLayout) {
|
|
1552
1508
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1553
1509
|
sizePercentage,
|
|
@@ -1565,7 +1521,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1565
1521
|
const {
|
|
1566
1522
|
layout,
|
|
1567
1523
|
panelDataArray
|
|
1568
|
-
} =
|
|
1524
|
+
} = eagerValuesRef.current;
|
|
1569
1525
|
const {
|
|
1570
1526
|
panelSizePercentage,
|
|
1571
1527
|
panelSizePixels
|
|
@@ -1578,6 +1534,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1578
1534
|
|
|
1579
1535
|
// This API should never read from committedValuesRef
|
|
1580
1536
|
const getPanelStyle = useCallback(panelData => {
|
|
1537
|
+
const {
|
|
1538
|
+
panelDataArray
|
|
1539
|
+
} = eagerValuesRef.current;
|
|
1581
1540
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1582
1541
|
return computePanelFlexBoxStyle({
|
|
1583
1542
|
dragState,
|
|
@@ -1585,14 +1544,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1585
1544
|
panelData: panelDataArray,
|
|
1586
1545
|
panelIndex
|
|
1587
1546
|
});
|
|
1588
|
-
}, [dragState, layout
|
|
1547
|
+
}, [dragState, layout]);
|
|
1589
1548
|
|
|
1590
1549
|
// External APIs are safe to memoize via committed values ref
|
|
1591
1550
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1592
1551
|
const {
|
|
1593
1552
|
layout,
|
|
1594
1553
|
panelDataArray
|
|
1595
|
-
} =
|
|
1554
|
+
} = eagerValuesRef.current;
|
|
1596
1555
|
const {
|
|
1597
1556
|
collapsedSizePercentage,
|
|
1598
1557
|
collapsible,
|
|
@@ -1606,7 +1565,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1606
1565
|
const {
|
|
1607
1566
|
layout,
|
|
1608
1567
|
panelDataArray
|
|
1609
|
-
} =
|
|
1568
|
+
} = eagerValuesRef.current;
|
|
1610
1569
|
const {
|
|
1611
1570
|
collapsedSizePercentage,
|
|
1612
1571
|
collapsible,
|
|
@@ -1615,22 +1574,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1615
1574
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1616
1575
|
}, [groupId]);
|
|
1617
1576
|
const registerPanel = useCallback(panelData => {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1577
|
+
const {
|
|
1578
|
+
autoSaveId,
|
|
1579
|
+
id: groupId,
|
|
1580
|
+
onLayout,
|
|
1581
|
+
storage
|
|
1582
|
+
} = committedValuesRef.current;
|
|
1583
|
+
const {
|
|
1584
|
+
layout: prevLayout,
|
|
1585
|
+
panelDataArray
|
|
1586
|
+
} = eagerValuesRef.current;
|
|
1587
|
+
panelDataArray.push(panelData);
|
|
1588
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1589
|
+
const orderA = panelA.order;
|
|
1590
|
+
const orderB = panelB.order;
|
|
1591
|
+
if (orderA == null && orderB == null) {
|
|
1592
|
+
return 0;
|
|
1593
|
+
} else if (orderA == null) {
|
|
1594
|
+
return -1;
|
|
1595
|
+
} else if (orderB == null) {
|
|
1596
|
+
return 1;
|
|
1597
|
+
} else {
|
|
1598
|
+
return orderA - orderB;
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1602
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1603
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1604
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1605
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// If this panel has been configured to persist sizing information,
|
|
1610
|
+
// default size should be restored from local storage if possible.
|
|
1611
|
+
let unsafeLayout = null;
|
|
1612
|
+
if (autoSaveId) {
|
|
1613
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1614
|
+
}
|
|
1615
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1616
|
+
if (groupSizePixels <= 0) {
|
|
1617
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1618
|
+
constraints
|
|
1619
|
+
}) => constraints))) {
|
|
1620
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
if (unsafeLayout == null) {
|
|
1625
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1626
|
+
groupSizePixels,
|
|
1627
|
+
panelDataArray
|
|
1632
1628
|
});
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1632
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1633
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1634
|
+
groupSizePixels,
|
|
1635
|
+
layout: unsafeLayout,
|
|
1636
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1633
1637
|
});
|
|
1638
|
+
|
|
1639
|
+
// Offscreen mode makes this a bit weird;
|
|
1640
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1641
|
+
// but the overall layout doesn't change between these two cases.
|
|
1642
|
+
setLayout(nextLayout);
|
|
1643
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1644
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1645
|
+
if (onLayout) {
|
|
1646
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1647
|
+
sizePercentage,
|
|
1648
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1649
|
+
})));
|
|
1650
|
+
}
|
|
1651
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1652
|
+
}
|
|
1634
1653
|
}, []);
|
|
1635
1654
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1636
1655
|
return function resizeHandler(event) {
|
|
@@ -1641,10 +1660,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1641
1660
|
id: groupId,
|
|
1642
1661
|
keyboardResizeByPercentage,
|
|
1643
1662
|
keyboardResizeByPixels,
|
|
1644
|
-
onLayout
|
|
1645
|
-
panelDataArray,
|
|
1646
|
-
layout: prevLayout
|
|
1663
|
+
onLayout
|
|
1647
1664
|
} = committedValuesRef.current;
|
|
1665
|
+
const {
|
|
1666
|
+
layout: prevLayout,
|
|
1667
|
+
panelDataArray
|
|
1668
|
+
} = eagerValuesRef.current;
|
|
1648
1669
|
const {
|
|
1649
1670
|
initialLayout
|
|
1650
1671
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1700,6 +1721,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1700
1721
|
}
|
|
1701
1722
|
if (layoutChanged) {
|
|
1702
1723
|
setLayout(nextLayout);
|
|
1724
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1703
1725
|
if (onLayout) {
|
|
1704
1726
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1705
1727
|
sizePercentage,
|
|
@@ -1713,23 +1735,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1713
1735
|
|
|
1714
1736
|
// External APIs are safe to memoize via committed values ref
|
|
1715
1737
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1738
|
+
const {
|
|
1739
|
+
onLayout
|
|
1740
|
+
} = committedValuesRef.current;
|
|
1716
1741
|
const {
|
|
1717
1742
|
layout: prevLayout,
|
|
1718
|
-
onLayout,
|
|
1719
1743
|
panelDataArray
|
|
1720
|
-
} =
|
|
1721
|
-
|
|
1722
|
-
// See issues/211
|
|
1723
|
-
if (panelDataArray.find(({
|
|
1724
|
-
id
|
|
1725
|
-
}) => id === panelData.id) == null) {
|
|
1726
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1727
|
-
panelData,
|
|
1728
|
-
mixedSizes,
|
|
1729
|
-
type: "resize"
|
|
1730
|
-
}]);
|
|
1731
|
-
return;
|
|
1732
|
-
}
|
|
1744
|
+
} = eagerValuesRef.current;
|
|
1733
1745
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1734
1746
|
const {
|
|
1735
1747
|
groupSizePixels,
|
|
@@ -1749,6 +1761,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1749
1761
|
});
|
|
1750
1762
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1751
1763
|
setLayout(nextLayout);
|
|
1764
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1752
1765
|
if (onLayout) {
|
|
1753
1766
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1754
1767
|
sizePercentage,
|
|
@@ -1760,9 +1773,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1760
1773
|
}, [groupId]);
|
|
1761
1774
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1762
1775
|
const {
|
|
1763
|
-
direction
|
|
1764
|
-
layout
|
|
1776
|
+
direction
|
|
1765
1777
|
} = committedValuesRef.current;
|
|
1778
|
+
const {
|
|
1779
|
+
layout
|
|
1780
|
+
} = eagerValuesRef.current;
|
|
1766
1781
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1767
1782
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1768
1783
|
setDragState({
|
|
@@ -1776,42 +1791,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1776
1791
|
resetGlobalCursorStyle();
|
|
1777
1792
|
setDragState(null);
|
|
1778
1793
|
}, []);
|
|
1794
|
+
const unregisterPanelRef = useRef({
|
|
1795
|
+
pendingPanelIds: new Set(),
|
|
1796
|
+
timeout: null
|
|
1797
|
+
});
|
|
1779
1798
|
const unregisterPanel = useCallback(panelData => {
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1799
|
+
const {
|
|
1800
|
+
id: groupId,
|
|
1801
|
+
onLayout
|
|
1802
|
+
} = committedValuesRef.current;
|
|
1803
|
+
const {
|
|
1804
|
+
layout: prevLayout,
|
|
1805
|
+
panelDataArray
|
|
1806
|
+
} = eagerValuesRef.current;
|
|
1807
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1808
|
+
if (index >= 0) {
|
|
1809
|
+
panelDataArray.splice(index, 1);
|
|
1810
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1811
|
+
}
|
|
1812
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1813
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1817
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1818
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1819
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1820
|
+
const {
|
|
1821
|
+
pendingPanelIds
|
|
1822
|
+
} = unregisterPanelRef.current;
|
|
1823
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1824
|
+
|
|
1825
|
+
// TRICKY
|
|
1826
|
+
// Strict effects mode
|
|
1827
|
+
let unmountDueToStrictMode = false;
|
|
1828
|
+
pendingPanelIds.forEach(panelId => {
|
|
1829
|
+
pendingPanelIds.delete(panelId);
|
|
1830
|
+
if (panelDataArray.find(({
|
|
1831
|
+
id
|
|
1832
|
+
}) => id === panelId) == null) {
|
|
1833
|
+
unmountDueToStrictMode = true;
|
|
1834
|
+
|
|
1835
|
+
// TRICKY
|
|
1836
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1837
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1838
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1839
|
+
delete map[panelData.id];
|
|
1840
|
+
}
|
|
1841
|
+
});
|
|
1842
|
+
if (!unmountDueToStrictMode) {
|
|
1843
|
+
return;
|
|
1786
1844
|
}
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1845
|
+
if (panelDataArray.length === 0) {
|
|
1846
|
+
// The group is unmounting; skip layout calculation.
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1850
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1851
|
+
groupSizePixels,
|
|
1852
|
+
panelDataArray
|
|
1853
|
+
});
|
|
1790
1854
|
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
{
|
|
1809
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1810
|
-
break;
|
|
1811
|
-
}
|
|
1855
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1856
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1857
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1858
|
+
groupSizePixels,
|
|
1859
|
+
layout: unsafeLayout,
|
|
1860
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1861
|
+
});
|
|
1862
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1863
|
+
setLayout(nextLayout);
|
|
1864
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1865
|
+
if (onLayout) {
|
|
1866
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1867
|
+
sizePercentage,
|
|
1868
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1869
|
+
})));
|
|
1870
|
+
}
|
|
1871
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1812
1872
|
}
|
|
1813
|
-
}
|
|
1814
|
-
}, [
|
|
1873
|
+
}, 0);
|
|
1874
|
+
}, []);
|
|
1815
1875
|
const context = useMemo(() => ({
|
|
1816
1876
|
collapsePanel,
|
|
1817
1877
|
direction,
|