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
|
@@ -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
|
|
@@ -687,6 +689,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
687
689
|
|
|
688
690
|
function useWindowSplitterPanelGroupBehavior({
|
|
689
691
|
committedValuesRef,
|
|
692
|
+
eagerValuesRef,
|
|
690
693
|
groupId,
|
|
691
694
|
layout,
|
|
692
695
|
panelDataArray,
|
|
@@ -729,7 +732,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
729
732
|
useEffect(() => {
|
|
730
733
|
const {
|
|
731
734
|
panelDataArray
|
|
732
|
-
} =
|
|
735
|
+
} = eagerValuesRef.current;
|
|
733
736
|
const groupElement = getPanelGroupElement(groupId);
|
|
734
737
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
735
738
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -787,7 +790,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
787
790
|
return () => {
|
|
788
791
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
789
792
|
};
|
|
790
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
793
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
791
794
|
}
|
|
792
795
|
|
|
793
796
|
function areEqual(arrayA, arrayB) {
|
|
@@ -1072,6 +1075,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
1072
1075
|
return callable;
|
|
1073
1076
|
}
|
|
1074
1077
|
|
|
1078
|
+
function getPanelElementsForGroup(groupId) {
|
|
1079
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1075
1082
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
1076
1083
|
// or on a browser with cookies/storage disabled.
|
|
1077
1084
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1221,7 +1228,7 @@ const defaultStorage = {
|
|
|
1221
1228
|
};
|
|
1222
1229
|
const debounceMap = {};
|
|
1223
1230
|
function PanelGroupWithForwardedRef({
|
|
1224
|
-
autoSaveId,
|
|
1231
|
+
autoSaveId = null,
|
|
1225
1232
|
children,
|
|
1226
1233
|
className: classNameFromProps = "",
|
|
1227
1234
|
dataAttributes,
|
|
@@ -1238,20 +1245,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1238
1245
|
const groupId = useUniqueId(idFromProps);
|
|
1239
1246
|
const [dragState, setDragState] = useState(null);
|
|
1240
1247
|
const [layout, setLayout] = useState([]);
|
|
1241
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1242
1248
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1243
1249
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1244
1250
|
const prevDeltaRef = useRef(0);
|
|
1245
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1246
1251
|
const committedValuesRef = useRef({
|
|
1252
|
+
autoSaveId,
|
|
1247
1253
|
direction,
|
|
1248
1254
|
dragState,
|
|
1249
1255
|
id: groupId,
|
|
1250
1256
|
keyboardResizeByPercentage,
|
|
1251
1257
|
keyboardResizeByPixels,
|
|
1252
|
-
layout,
|
|
1253
1258
|
onLayout,
|
|
1254
|
-
|
|
1259
|
+
storage
|
|
1260
|
+
});
|
|
1261
|
+
const eagerValuesRef = useRef({
|
|
1262
|
+
layout,
|
|
1263
|
+
panelDataArray: []
|
|
1255
1264
|
});
|
|
1256
1265
|
useRef({
|
|
1257
1266
|
didLogIdAndOrderWarning: false,
|
|
@@ -1262,9 +1271,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1262
1271
|
getId: () => committedValuesRef.current.id,
|
|
1263
1272
|
getLayout: () => {
|
|
1264
1273
|
const {
|
|
1265
|
-
id: groupId
|
|
1266
|
-
layout
|
|
1274
|
+
id: groupId
|
|
1267
1275
|
} = committedValuesRef.current;
|
|
1276
|
+
const {
|
|
1277
|
+
layout
|
|
1278
|
+
} = eagerValuesRef.current;
|
|
1268
1279
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1269
1280
|
return layout.map(sizePercentage => {
|
|
1270
1281
|
return {
|
|
@@ -1276,10 +1287,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1276
1287
|
setLayout: mixedSizes => {
|
|
1277
1288
|
const {
|
|
1278
1289
|
id: groupId,
|
|
1290
|
+
onLayout
|
|
1291
|
+
} = committedValuesRef.current;
|
|
1292
|
+
const {
|
|
1279
1293
|
layout: prevLayout,
|
|
1280
|
-
onLayout,
|
|
1281
1294
|
panelDataArray
|
|
1282
|
-
} =
|
|
1295
|
+
} = eagerValuesRef.current;
|
|
1283
1296
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1284
1297
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1285
1298
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1289,6 +1302,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1289
1302
|
});
|
|
1290
1303
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1291
1304
|
setLayout(safeLayout);
|
|
1305
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1292
1306
|
if (onLayout) {
|
|
1293
1307
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1294
1308
|
sizePercentage,
|
|
@@ -1300,21 +1314,30 @@ function PanelGroupWithForwardedRef({
|
|
|
1300
1314
|
}
|
|
1301
1315
|
}), []);
|
|
1302
1316
|
useIsomorphicLayoutEffect(() => {
|
|
1317
|
+
committedValuesRef.current.autoSaveId = autoSaveId;
|
|
1303
1318
|
committedValuesRef.current.direction = direction;
|
|
1304
1319
|
committedValuesRef.current.dragState = dragState;
|
|
1305
1320
|
committedValuesRef.current.id = groupId;
|
|
1306
|
-
committedValuesRef.current.layout = layout;
|
|
1307
1321
|
committedValuesRef.current.onLayout = onLayout;
|
|
1308
|
-
committedValuesRef.current.
|
|
1322
|
+
committedValuesRef.current.storage = storage;
|
|
1323
|
+
|
|
1324
|
+
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1325
|
+
// TODO [217] Move these values into a separate ref
|
|
1309
1326
|
});
|
|
1327
|
+
|
|
1310
1328
|
useWindowSplitterPanelGroupBehavior({
|
|
1311
1329
|
committedValuesRef,
|
|
1330
|
+
eagerValuesRef,
|
|
1312
1331
|
groupId,
|
|
1313
1332
|
layout,
|
|
1314
|
-
panelDataArray,
|
|
1333
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1315
1334
|
setLayout
|
|
1316
1335
|
});
|
|
1317
1336
|
useEffect(() => {
|
|
1337
|
+
const {
|
|
1338
|
+
panelDataArray
|
|
1339
|
+
} = eagerValuesRef.current;
|
|
1340
|
+
|
|
1318
1341
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1319
1342
|
if (autoSaveId) {
|
|
1320
1343
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1327,63 +1350,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1327
1350
|
}
|
|
1328
1351
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1329
1352
|
}
|
|
1330
|
-
}, [autoSaveId, layout,
|
|
1331
|
-
|
|
1332
|
-
// Once all panels have registered themselves,
|
|
1333
|
-
// Compute the initial sizes based on default weights.
|
|
1334
|
-
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
1353
|
+
}, [autoSaveId, layout, storage]);
|
|
1335
1354
|
useIsomorphicLayoutEffect(() => {
|
|
1336
1355
|
const {
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
} = committedValuesRef.current;
|
|
1341
|
-
if (layout.length === panelDataArray.length) {
|
|
1342
|
-
// Only compute (or restore) default layout once per panel configuration.
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
// If this panel has been configured to persist sizing information,
|
|
1347
|
-
// default size should be restored from local storage if possible.
|
|
1348
|
-
let unsafeLayout = null;
|
|
1349
|
-
if (autoSaveId) {
|
|
1350
|
-
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1351
|
-
}
|
|
1352
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1353
|
-
if (groupSizePixels <= 0) {
|
|
1354
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1355
|
-
constraints
|
|
1356
|
-
}) => constraints))) {
|
|
1357
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1358
|
-
return;
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
if (unsafeLayout == null) {
|
|
1362
|
-
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1363
|
-
groupSizePixels,
|
|
1364
|
-
panelDataArray
|
|
1365
|
-
});
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
// Validate even saved layouts in case something has changed since last render
|
|
1369
|
-
// e.g. for pixel groups, this could be the size of the window
|
|
1370
|
-
const validatedLayout = validatePanelGroupLayout({
|
|
1371
|
-
groupSizePixels,
|
|
1372
|
-
layout: unsafeLayout,
|
|
1373
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1374
|
-
});
|
|
1375
|
-
if (!areEqual(layout, validatedLayout)) {
|
|
1376
|
-
setLayout(validatedLayout);
|
|
1377
|
-
}
|
|
1378
|
-
if (onLayout) {
|
|
1379
|
-
onLayout(validatedLayout.map(sizePercentage => ({
|
|
1380
|
-
sizePercentage,
|
|
1381
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1382
|
-
})));
|
|
1383
|
-
}
|
|
1384
|
-
callPanelCallbacks(groupId, panelDataArray, validatedLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1385
|
-
}, [autoSaveId, layout, panelDataArray, storage]);
|
|
1386
|
-
useIsomorphicLayoutEffect(() => {
|
|
1356
|
+
layout: prevLayout,
|
|
1357
|
+
panelDataArray
|
|
1358
|
+
} = eagerValuesRef.current;
|
|
1387
1359
|
const constraints = panelDataArray.map(({
|
|
1388
1360
|
constraints
|
|
1389
1361
|
}) => constraints);
|
|
@@ -1397,7 +1369,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1397
1369
|
const resizeObserver = new ResizeObserver(() => {
|
|
1398
1370
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1399
1371
|
const {
|
|
1400
|
-
layout: prevLayout,
|
|
1401
1372
|
onLayout
|
|
1402
1373
|
} = committedValuesRef.current;
|
|
1403
1374
|
const nextLayout = validatePanelGroupLayout({
|
|
@@ -1407,6 +1378,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1407
1378
|
});
|
|
1408
1379
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1409
1380
|
setLayout(nextLayout);
|
|
1381
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1410
1382
|
if (onLayout) {
|
|
1411
1383
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1412
1384
|
sizePercentage,
|
|
@@ -1421,7 +1393,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1421
1393
|
resizeObserver.disconnect();
|
|
1422
1394
|
};
|
|
1423
1395
|
}
|
|
1424
|
-
}, [groupId
|
|
1396
|
+
}, [groupId]);
|
|
1425
1397
|
|
|
1426
1398
|
// DEV warnings
|
|
1427
1399
|
useEffect(() => {
|
|
@@ -1429,22 +1401,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1429
1401
|
|
|
1430
1402
|
// External APIs are safe to memoize via committed values ref
|
|
1431
1403
|
const collapsePanel = useCallback(panelData => {
|
|
1404
|
+
const {
|
|
1405
|
+
onLayout
|
|
1406
|
+
} = committedValuesRef.current;
|
|
1432
1407
|
const {
|
|
1433
1408
|
layout: prevLayout,
|
|
1434
|
-
onLayout,
|
|
1435
1409
|
panelDataArray
|
|
1436
|
-
} =
|
|
1437
|
-
|
|
1438
|
-
// See issues/211
|
|
1439
|
-
if (panelDataArray.find(({
|
|
1440
|
-
id
|
|
1441
|
-
}) => id === panelData.id) == null) {
|
|
1442
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1443
|
-
panelData,
|
|
1444
|
-
type: "collapse"
|
|
1445
|
-
}]);
|
|
1446
|
-
return;
|
|
1447
|
-
}
|
|
1410
|
+
} = eagerValuesRef.current;
|
|
1448
1411
|
if (panelData.constraints.collapsible) {
|
|
1449
1412
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1450
1413
|
const {
|
|
@@ -1469,6 +1432,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1469
1432
|
});
|
|
1470
1433
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1471
1434
|
setLayout(nextLayout);
|
|
1435
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1472
1436
|
if (onLayout) {
|
|
1473
1437
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1474
1438
|
sizePercentage,
|
|
@@ -1483,22 +1447,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1483
1447
|
|
|
1484
1448
|
// External APIs are safe to memoize via committed values ref
|
|
1485
1449
|
const expandPanel = useCallback(panelData => {
|
|
1450
|
+
const {
|
|
1451
|
+
onLayout
|
|
1452
|
+
} = committedValuesRef.current;
|
|
1486
1453
|
const {
|
|
1487
1454
|
layout: prevLayout,
|
|
1488
|
-
onLayout,
|
|
1489
1455
|
panelDataArray
|
|
1490
|
-
} =
|
|
1491
|
-
|
|
1492
|
-
// See issues/211
|
|
1493
|
-
if (panelDataArray.find(({
|
|
1494
|
-
id
|
|
1495
|
-
}) => id === panelData.id) == null) {
|
|
1496
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1497
|
-
panelData,
|
|
1498
|
-
type: "expand"
|
|
1499
|
-
}]);
|
|
1500
|
-
return;
|
|
1501
|
-
}
|
|
1456
|
+
} = eagerValuesRef.current;
|
|
1502
1457
|
if (panelData.constraints.collapsible) {
|
|
1503
1458
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1504
1459
|
const {
|
|
@@ -1524,6 +1479,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1524
1479
|
});
|
|
1525
1480
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1526
1481
|
setLayout(nextLayout);
|
|
1482
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1527
1483
|
if (onLayout) {
|
|
1528
1484
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1529
1485
|
sizePercentage,
|
|
@@ -1541,7 +1497,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1541
1497
|
const {
|
|
1542
1498
|
layout,
|
|
1543
1499
|
panelDataArray
|
|
1544
|
-
} =
|
|
1500
|
+
} = eagerValuesRef.current;
|
|
1545
1501
|
const {
|
|
1546
1502
|
panelSizePercentage,
|
|
1547
1503
|
panelSizePixels
|
|
@@ -1554,6 +1510,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1554
1510
|
|
|
1555
1511
|
// This API should never read from committedValuesRef
|
|
1556
1512
|
const getPanelStyle = useCallback(panelData => {
|
|
1513
|
+
const {
|
|
1514
|
+
panelDataArray
|
|
1515
|
+
} = eagerValuesRef.current;
|
|
1557
1516
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1558
1517
|
return computePanelFlexBoxStyle({
|
|
1559
1518
|
dragState,
|
|
@@ -1561,14 +1520,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1561
1520
|
panelData: panelDataArray,
|
|
1562
1521
|
panelIndex
|
|
1563
1522
|
});
|
|
1564
|
-
}, [dragState, layout
|
|
1523
|
+
}, [dragState, layout]);
|
|
1565
1524
|
|
|
1566
1525
|
// External APIs are safe to memoize via committed values ref
|
|
1567
1526
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1568
1527
|
const {
|
|
1569
1528
|
layout,
|
|
1570
1529
|
panelDataArray
|
|
1571
|
-
} =
|
|
1530
|
+
} = eagerValuesRef.current;
|
|
1572
1531
|
const {
|
|
1573
1532
|
collapsedSizePercentage,
|
|
1574
1533
|
collapsible,
|
|
@@ -1582,7 +1541,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1582
1541
|
const {
|
|
1583
1542
|
layout,
|
|
1584
1543
|
panelDataArray
|
|
1585
|
-
} =
|
|
1544
|
+
} = eagerValuesRef.current;
|
|
1586
1545
|
const {
|
|
1587
1546
|
collapsedSizePercentage,
|
|
1588
1547
|
collapsible,
|
|
@@ -1591,22 +1550,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1591
1550
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1592
1551
|
}, [groupId]);
|
|
1593
1552
|
const registerPanel = useCallback(panelData => {
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1553
|
+
const {
|
|
1554
|
+
autoSaveId,
|
|
1555
|
+
id: groupId,
|
|
1556
|
+
onLayout,
|
|
1557
|
+
storage
|
|
1558
|
+
} = committedValuesRef.current;
|
|
1559
|
+
const {
|
|
1560
|
+
layout: prevLayout,
|
|
1561
|
+
panelDataArray
|
|
1562
|
+
} = eagerValuesRef.current;
|
|
1563
|
+
panelDataArray.push(panelData);
|
|
1564
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1565
|
+
const orderA = panelA.order;
|
|
1566
|
+
const orderB = panelB.order;
|
|
1567
|
+
if (orderA == null && orderB == null) {
|
|
1568
|
+
return 0;
|
|
1569
|
+
} else if (orderA == null) {
|
|
1570
|
+
return -1;
|
|
1571
|
+
} else if (orderB == null) {
|
|
1572
|
+
return 1;
|
|
1573
|
+
} else {
|
|
1574
|
+
return orderA - orderB;
|
|
1575
|
+
}
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1579
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1580
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1581
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// If this panel has been configured to persist sizing information,
|
|
1586
|
+
// default size should be restored from local storage if possible.
|
|
1587
|
+
let unsafeLayout = null;
|
|
1588
|
+
if (autoSaveId) {
|
|
1589
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1590
|
+
}
|
|
1591
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1592
|
+
if (groupSizePixels <= 0) {
|
|
1593
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1594
|
+
constraints
|
|
1595
|
+
}) => constraints))) {
|
|
1596
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (unsafeLayout == null) {
|
|
1601
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1602
|
+
groupSizePixels,
|
|
1603
|
+
panelDataArray
|
|
1608
1604
|
});
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1608
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1609
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1610
|
+
groupSizePixels,
|
|
1611
|
+
layout: unsafeLayout,
|
|
1612
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1609
1613
|
});
|
|
1614
|
+
|
|
1615
|
+
// Offscreen mode makes this a bit weird;
|
|
1616
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1617
|
+
// but the overall layout doesn't change between these two cases.
|
|
1618
|
+
setLayout(nextLayout);
|
|
1619
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1620
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1621
|
+
if (onLayout) {
|
|
1622
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1623
|
+
sizePercentage,
|
|
1624
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1625
|
+
})));
|
|
1626
|
+
}
|
|
1627
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1628
|
+
}
|
|
1610
1629
|
}, []);
|
|
1611
1630
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1612
1631
|
return function resizeHandler(event) {
|
|
@@ -1617,10 +1636,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1617
1636
|
id: groupId,
|
|
1618
1637
|
keyboardResizeByPercentage,
|
|
1619
1638
|
keyboardResizeByPixels,
|
|
1620
|
-
onLayout
|
|
1621
|
-
panelDataArray,
|
|
1622
|
-
layout: prevLayout
|
|
1639
|
+
onLayout
|
|
1623
1640
|
} = committedValuesRef.current;
|
|
1641
|
+
const {
|
|
1642
|
+
layout: prevLayout,
|
|
1643
|
+
panelDataArray
|
|
1644
|
+
} = eagerValuesRef.current;
|
|
1624
1645
|
const {
|
|
1625
1646
|
initialLayout
|
|
1626
1647
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1676,6 +1697,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1676
1697
|
}
|
|
1677
1698
|
if (layoutChanged) {
|
|
1678
1699
|
setLayout(nextLayout);
|
|
1700
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1679
1701
|
if (onLayout) {
|
|
1680
1702
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1681
1703
|
sizePercentage,
|
|
@@ -1689,23 +1711,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1689
1711
|
|
|
1690
1712
|
// External APIs are safe to memoize via committed values ref
|
|
1691
1713
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1714
|
+
const {
|
|
1715
|
+
onLayout
|
|
1716
|
+
} = committedValuesRef.current;
|
|
1692
1717
|
const {
|
|
1693
1718
|
layout: prevLayout,
|
|
1694
|
-
onLayout,
|
|
1695
1719
|
panelDataArray
|
|
1696
|
-
} =
|
|
1697
|
-
|
|
1698
|
-
// See issues/211
|
|
1699
|
-
if (panelDataArray.find(({
|
|
1700
|
-
id
|
|
1701
|
-
}) => id === panelData.id) == null) {
|
|
1702
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1703
|
-
panelData,
|
|
1704
|
-
mixedSizes,
|
|
1705
|
-
type: "resize"
|
|
1706
|
-
}]);
|
|
1707
|
-
return;
|
|
1708
|
-
}
|
|
1720
|
+
} = eagerValuesRef.current;
|
|
1709
1721
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1710
1722
|
const {
|
|
1711
1723
|
groupSizePixels,
|
|
@@ -1725,6 +1737,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1725
1737
|
});
|
|
1726
1738
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1727
1739
|
setLayout(nextLayout);
|
|
1740
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1728
1741
|
if (onLayout) {
|
|
1729
1742
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1730
1743
|
sizePercentage,
|
|
@@ -1736,9 +1749,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1736
1749
|
}, [groupId]);
|
|
1737
1750
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1738
1751
|
const {
|
|
1739
|
-
direction
|
|
1740
|
-
layout
|
|
1752
|
+
direction
|
|
1741
1753
|
} = committedValuesRef.current;
|
|
1754
|
+
const {
|
|
1755
|
+
layout
|
|
1756
|
+
} = eagerValuesRef.current;
|
|
1742
1757
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1743
1758
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1744
1759
|
setDragState({
|
|
@@ -1752,42 +1767,87 @@ function PanelGroupWithForwardedRef({
|
|
|
1752
1767
|
resetGlobalCursorStyle();
|
|
1753
1768
|
setDragState(null);
|
|
1754
1769
|
}, []);
|
|
1770
|
+
const unregisterPanelRef = useRef({
|
|
1771
|
+
pendingPanelIds: new Set(),
|
|
1772
|
+
timeout: null
|
|
1773
|
+
});
|
|
1755
1774
|
const unregisterPanel = useCallback(panelData => {
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1775
|
+
const {
|
|
1776
|
+
id: groupId,
|
|
1777
|
+
onLayout
|
|
1778
|
+
} = committedValuesRef.current;
|
|
1779
|
+
const {
|
|
1780
|
+
layout: prevLayout,
|
|
1781
|
+
panelDataArray
|
|
1782
|
+
} = eagerValuesRef.current;
|
|
1783
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1784
|
+
if (index >= 0) {
|
|
1785
|
+
panelDataArray.splice(index, 1);
|
|
1786
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1787
|
+
}
|
|
1788
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1789
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1793
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1794
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1795
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1796
|
+
const {
|
|
1797
|
+
pendingPanelIds
|
|
1798
|
+
} = unregisterPanelRef.current;
|
|
1799
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1800
|
+
|
|
1801
|
+
// TRICKY
|
|
1802
|
+
// Strict effects mode
|
|
1803
|
+
let unmountDueToStrictMode = false;
|
|
1804
|
+
pendingPanelIds.forEach(panelId => {
|
|
1805
|
+
pendingPanelIds.delete(panelId);
|
|
1806
|
+
if (panelDataArray.find(({
|
|
1807
|
+
id
|
|
1808
|
+
}) => id === panelId) == null) {
|
|
1809
|
+
unmountDueToStrictMode = true;
|
|
1810
|
+
|
|
1811
|
+
// TRICKY
|
|
1812
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1813
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1814
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1815
|
+
delete map[panelData.id];
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
if (!unmountDueToStrictMode) {
|
|
1819
|
+
return;
|
|
1762
1820
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1821
|
+
if (panelDataArray.length === 0) {
|
|
1822
|
+
// The group is unmounting; skip layout calculation.
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1826
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1827
|
+
groupSizePixels,
|
|
1828
|
+
panelDataArray
|
|
1829
|
+
});
|
|
1766
1830
|
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
{
|
|
1785
|
-
resizePanel(current.panelData, current.mixedSizes);
|
|
1786
|
-
break;
|
|
1787
|
-
}
|
|
1831
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1832
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1833
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1834
|
+
groupSizePixels,
|
|
1835
|
+
layout: unsafeLayout,
|
|
1836
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1837
|
+
});
|
|
1838
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1839
|
+
setLayout(nextLayout);
|
|
1840
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1841
|
+
if (onLayout) {
|
|
1842
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1843
|
+
sizePercentage,
|
|
1844
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1845
|
+
})));
|
|
1846
|
+
}
|
|
1847
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1788
1848
|
}
|
|
1789
|
-
}
|
|
1790
|
-
}, [
|
|
1849
|
+
}, 0);
|
|
1850
|
+
}, []);
|
|
1791
1851
|
const context = useMemo(() => ({
|
|
1792
1852
|
collapsePanel,
|
|
1793
1853
|
direction,
|