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