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
|
@@ -91,6 +91,7 @@ function PanelWithForwardedRef({
|
|
|
91
91
|
expandPanel,
|
|
92
92
|
getPanelSize,
|
|
93
93
|
getPanelStyle,
|
|
94
|
+
groupId,
|
|
94
95
|
isPanelCollapsed,
|
|
95
96
|
registerPanel,
|
|
96
97
|
resizePanel,
|
|
@@ -167,6 +168,7 @@ function PanelWithForwardedRef({
|
|
|
167
168
|
// CSS selectors
|
|
168
169
|
"data-panel": "",
|
|
169
170
|
"data-panel-id": panelId,
|
|
171
|
+
"data-panel-group-id": groupId,
|
|
170
172
|
// e2e test attributes
|
|
171
173
|
"data-panel-collapsible": collapsible || undefined ,
|
|
172
174
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -641,6 +643,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
641
643
|
|
|
642
644
|
function useWindowSplitterPanelGroupBehavior({
|
|
643
645
|
committedValuesRef,
|
|
646
|
+
eagerValuesRef,
|
|
644
647
|
groupId,
|
|
645
648
|
layout,
|
|
646
649
|
panelDataArray,
|
|
@@ -652,7 +655,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
652
655
|
useEffect(() => {
|
|
653
656
|
const {
|
|
654
657
|
panelDataArray
|
|
655
|
-
} =
|
|
658
|
+
} = eagerValuesRef.current;
|
|
656
659
|
const groupElement = getPanelGroupElement(groupId);
|
|
657
660
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
658
661
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -710,7 +713,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
710
713
|
return () => {
|
|
711
714
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
712
715
|
};
|
|
713
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
716
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
714
717
|
}
|
|
715
718
|
|
|
716
719
|
function areEqual(arrayA, arrayB) {
|
|
@@ -807,6 +810,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
807
810
|
}
|
|
808
811
|
}
|
|
809
812
|
|
|
813
|
+
function calculateUnsafeDefaultLayout({
|
|
814
|
+
groupSizePixels,
|
|
815
|
+
panelDataArray
|
|
816
|
+
}) {
|
|
817
|
+
const layout = Array(panelDataArray.length);
|
|
818
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
819
|
+
let numPanelsWithSizes = 0;
|
|
820
|
+
let remainingSize = 100;
|
|
821
|
+
|
|
822
|
+
// Distribute default sizes first
|
|
823
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
824
|
+
const {
|
|
825
|
+
defaultSizePercentage
|
|
826
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
827
|
+
if (defaultSizePercentage != null) {
|
|
828
|
+
numPanelsWithSizes++;
|
|
829
|
+
layout[index] = defaultSizePercentage;
|
|
830
|
+
remainingSize -= defaultSizePercentage;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
835
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
836
|
+
const {
|
|
837
|
+
defaultSizePercentage
|
|
838
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
839
|
+
if (defaultSizePercentage != null) {
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
843
|
+
const size = remainingSize / numRemainingPanels;
|
|
844
|
+
numPanelsWithSizes++;
|
|
845
|
+
layout[index] = size;
|
|
846
|
+
remainingSize -= size;
|
|
847
|
+
}
|
|
848
|
+
return layout;
|
|
849
|
+
}
|
|
850
|
+
|
|
810
851
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
811
852
|
return percentage / 100 * groupSizePixels;
|
|
812
853
|
}
|
|
@@ -957,6 +998,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
957
998
|
return callable;
|
|
958
999
|
}
|
|
959
1000
|
|
|
1001
|
+
function getPanelElementsForGroup(groupId) {
|
|
1002
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1003
|
+
}
|
|
1004
|
+
|
|
960
1005
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
961
1006
|
// or on a browser with cookies/storage disabled.
|
|
962
1007
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -1012,6 +1057,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
1012
1057
|
} catch (error) {}
|
|
1013
1058
|
return null;
|
|
1014
1059
|
}
|
|
1060
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1061
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1062
|
+
if (state) {
|
|
1063
|
+
var _state$key;
|
|
1064
|
+
const key = getSerializationKey(panels);
|
|
1065
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1066
|
+
}
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1015
1069
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
1016
1070
|
const key = getSerializationKey(panels);
|
|
1017
1071
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -1023,6 +1077,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1023
1077
|
}
|
|
1024
1078
|
}
|
|
1025
1079
|
|
|
1080
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1081
|
+
return constraints.some(constraints => {
|
|
1082
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1026
1086
|
function validatePanelConstraints({
|
|
1027
1087
|
groupSizePixels,
|
|
1028
1088
|
panelConstraints,
|
|
@@ -1168,7 +1228,7 @@ const defaultStorage = {
|
|
|
1168
1228
|
};
|
|
1169
1229
|
const debounceMap = {};
|
|
1170
1230
|
function PanelGroupWithForwardedRef({
|
|
1171
|
-
autoSaveId,
|
|
1231
|
+
autoSaveId = null,
|
|
1172
1232
|
children,
|
|
1173
1233
|
className: classNameFromProps = "",
|
|
1174
1234
|
dataAttributes,
|
|
@@ -1185,20 +1245,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1185
1245
|
const groupId = useUniqueId(idFromProps);
|
|
1186
1246
|
const [dragState, setDragState] = useState(null);
|
|
1187
1247
|
const [layout, setLayout] = useState([]);
|
|
1188
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1189
1248
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1190
1249
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1191
1250
|
const prevDeltaRef = useRef(0);
|
|
1192
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1193
1251
|
const committedValuesRef = useRef({
|
|
1252
|
+
autoSaveId,
|
|
1194
1253
|
direction,
|
|
1195
1254
|
dragState,
|
|
1196
1255
|
id: groupId,
|
|
1197
1256
|
keyboardResizeByPercentage,
|
|
1198
1257
|
keyboardResizeByPixels,
|
|
1199
|
-
layout,
|
|
1200
1258
|
onLayout,
|
|
1201
|
-
|
|
1259
|
+
storage
|
|
1260
|
+
});
|
|
1261
|
+
const eagerValuesRef = useRef({
|
|
1262
|
+
layout,
|
|
1263
|
+
panelDataArray: []
|
|
1202
1264
|
});
|
|
1203
1265
|
const devWarningsRef = useRef({
|
|
1204
1266
|
didLogIdAndOrderWarning: false,
|
|
@@ -1209,9 +1271,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1209
1271
|
getId: () => committedValuesRef.current.id,
|
|
1210
1272
|
getLayout: () => {
|
|
1211
1273
|
const {
|
|
1212
|
-
id: groupId
|
|
1213
|
-
layout
|
|
1274
|
+
id: groupId
|
|
1214
1275
|
} = committedValuesRef.current;
|
|
1276
|
+
const {
|
|
1277
|
+
layout
|
|
1278
|
+
} = eagerValuesRef.current;
|
|
1215
1279
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1216
1280
|
return layout.map(sizePercentage => {
|
|
1217
1281
|
return {
|
|
@@ -1223,10 +1287,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1223
1287
|
setLayout: mixedSizes => {
|
|
1224
1288
|
const {
|
|
1225
1289
|
id: groupId,
|
|
1290
|
+
onLayout
|
|
1291
|
+
} = committedValuesRef.current;
|
|
1292
|
+
const {
|
|
1226
1293
|
layout: prevLayout,
|
|
1227
|
-
onLayout,
|
|
1228
1294
|
panelDataArray
|
|
1229
|
-
} =
|
|
1295
|
+
} = eagerValuesRef.current;
|
|
1230
1296
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1231
1297
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1232
1298
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1236,6 +1302,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1236
1302
|
});
|
|
1237
1303
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1238
1304
|
setLayout(safeLayout);
|
|
1305
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1239
1306
|
if (onLayout) {
|
|
1240
1307
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1241
1308
|
sizePercentage,
|
|
@@ -1246,14 +1313,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1246
1313
|
}
|
|
1247
1314
|
}
|
|
1248
1315
|
}), []);
|
|
1316
|
+
|
|
1249
1317
|
useWindowSplitterPanelGroupBehavior({
|
|
1250
1318
|
committedValuesRef,
|
|
1319
|
+
eagerValuesRef,
|
|
1251
1320
|
groupId,
|
|
1252
1321
|
layout,
|
|
1253
|
-
panelDataArray,
|
|
1322
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1254
1323
|
setLayout
|
|
1255
1324
|
});
|
|
1256
1325
|
useEffect(() => {
|
|
1326
|
+
const {
|
|
1327
|
+
panelDataArray
|
|
1328
|
+
} = eagerValuesRef.current;
|
|
1329
|
+
|
|
1257
1330
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1258
1331
|
if (autoSaveId) {
|
|
1259
1332
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1266,20 +1339,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1266
1339
|
}
|
|
1267
1340
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1268
1341
|
}
|
|
1269
|
-
}, [autoSaveId, layout,
|
|
1342
|
+
}, [autoSaveId, layout, storage]);
|
|
1270
1343
|
|
|
1271
1344
|
// DEV warnings
|
|
1272
1345
|
useEffect(() => {
|
|
1273
1346
|
{
|
|
1347
|
+
const {
|
|
1348
|
+
panelDataArray
|
|
1349
|
+
} = eagerValuesRef.current;
|
|
1274
1350
|
const {
|
|
1275
1351
|
didLogIdAndOrderWarning,
|
|
1276
1352
|
didLogPanelConstraintsWarning,
|
|
1277
1353
|
prevPanelIds
|
|
1278
1354
|
} = devWarningsRef.current;
|
|
1279
1355
|
if (!didLogIdAndOrderWarning) {
|
|
1280
|
-
const {
|
|
1281
|
-
panelDataArray
|
|
1282
|
-
} = committedValuesRef.current;
|
|
1283
1356
|
const panelIds = panelDataArray.map(({
|
|
1284
1357
|
id
|
|
1285
1358
|
}) => id);
|
|
@@ -1316,22 +1389,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1316
1389
|
|
|
1317
1390
|
// External APIs are safe to memoize via committed values ref
|
|
1318
1391
|
const collapsePanel = useCallback(panelData => {
|
|
1392
|
+
const {
|
|
1393
|
+
onLayout
|
|
1394
|
+
} = committedValuesRef.current;
|
|
1319
1395
|
const {
|
|
1320
1396
|
layout: prevLayout,
|
|
1321
|
-
onLayout,
|
|
1322
1397
|
panelDataArray
|
|
1323
|
-
} =
|
|
1324
|
-
|
|
1325
|
-
// See issues/211
|
|
1326
|
-
if (panelDataArray.find(({
|
|
1327
|
-
id
|
|
1328
|
-
}) => id === panelData.id) == null) {
|
|
1329
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1330
|
-
panelData,
|
|
1331
|
-
type: "collapse"
|
|
1332
|
-
}]);
|
|
1333
|
-
return;
|
|
1334
|
-
}
|
|
1398
|
+
} = eagerValuesRef.current;
|
|
1335
1399
|
if (panelData.constraints.collapsible) {
|
|
1336
1400
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1337
1401
|
const {
|
|
@@ -1356,6 +1420,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1356
1420
|
});
|
|
1357
1421
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1358
1422
|
setLayout(nextLayout);
|
|
1423
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1359
1424
|
if (onLayout) {
|
|
1360
1425
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1361
1426
|
sizePercentage,
|
|
@@ -1370,22 +1435,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1370
1435
|
|
|
1371
1436
|
// External APIs are safe to memoize via committed values ref
|
|
1372
1437
|
const expandPanel = useCallback(panelData => {
|
|
1438
|
+
const {
|
|
1439
|
+
onLayout
|
|
1440
|
+
} = committedValuesRef.current;
|
|
1373
1441
|
const {
|
|
1374
1442
|
layout: prevLayout,
|
|
1375
|
-
onLayout,
|
|
1376
1443
|
panelDataArray
|
|
1377
|
-
} =
|
|
1378
|
-
|
|
1379
|
-
// See issues/211
|
|
1380
|
-
if (panelDataArray.find(({
|
|
1381
|
-
id
|
|
1382
|
-
}) => id === panelData.id) == null) {
|
|
1383
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1384
|
-
panelData,
|
|
1385
|
-
type: "expand"
|
|
1386
|
-
}]);
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1444
|
+
} = eagerValuesRef.current;
|
|
1389
1445
|
if (panelData.constraints.collapsible) {
|
|
1390
1446
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1391
1447
|
const {
|
|
@@ -1411,6 +1467,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1411
1467
|
});
|
|
1412
1468
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1413
1469
|
setLayout(nextLayout);
|
|
1470
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1414
1471
|
if (onLayout) {
|
|
1415
1472
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1416
1473
|
sizePercentage,
|
|
@@ -1428,7 +1485,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1428
1485
|
const {
|
|
1429
1486
|
layout,
|
|
1430
1487
|
panelDataArray
|
|
1431
|
-
} =
|
|
1488
|
+
} = eagerValuesRef.current;
|
|
1432
1489
|
const {
|
|
1433
1490
|
panelSizePercentage,
|
|
1434
1491
|
panelSizePixels
|
|
@@ -1441,6 +1498,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1441
1498
|
|
|
1442
1499
|
// This API should never read from committedValuesRef
|
|
1443
1500
|
const getPanelStyle = useCallback(panelData => {
|
|
1501
|
+
const {
|
|
1502
|
+
panelDataArray
|
|
1503
|
+
} = eagerValuesRef.current;
|
|
1444
1504
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1445
1505
|
return computePanelFlexBoxStyle({
|
|
1446
1506
|
dragState,
|
|
@@ -1448,14 +1508,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1448
1508
|
panelData: panelDataArray,
|
|
1449
1509
|
panelIndex
|
|
1450
1510
|
});
|
|
1451
|
-
}, [dragState, layout
|
|
1511
|
+
}, [dragState, layout]);
|
|
1452
1512
|
|
|
1453
1513
|
// External APIs are safe to memoize via committed values ref
|
|
1454
1514
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1455
1515
|
const {
|
|
1456
1516
|
layout,
|
|
1457
1517
|
panelDataArray
|
|
1458
|
-
} =
|
|
1518
|
+
} = eagerValuesRef.current;
|
|
1459
1519
|
const {
|
|
1460
1520
|
collapsedSizePercentage,
|
|
1461
1521
|
collapsible,
|
|
@@ -1469,7 +1529,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1469
1529
|
const {
|
|
1470
1530
|
layout,
|
|
1471
1531
|
panelDataArray
|
|
1472
|
-
} =
|
|
1532
|
+
} = eagerValuesRef.current;
|
|
1473
1533
|
const {
|
|
1474
1534
|
collapsedSizePercentage,
|
|
1475
1535
|
collapsible,
|
|
@@ -1478,22 +1538,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1478
1538
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1479
1539
|
}, [groupId]);
|
|
1480
1540
|
const registerPanel = useCallback(panelData => {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1541
|
+
const {
|
|
1542
|
+
autoSaveId,
|
|
1543
|
+
id: groupId,
|
|
1544
|
+
onLayout,
|
|
1545
|
+
storage
|
|
1546
|
+
} = committedValuesRef.current;
|
|
1547
|
+
const {
|
|
1548
|
+
layout: prevLayout,
|
|
1549
|
+
panelDataArray
|
|
1550
|
+
} = eagerValuesRef.current;
|
|
1551
|
+
panelDataArray.push(panelData);
|
|
1552
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1553
|
+
const orderA = panelA.order;
|
|
1554
|
+
const orderB = panelB.order;
|
|
1555
|
+
if (orderA == null && orderB == null) {
|
|
1556
|
+
return 0;
|
|
1557
|
+
} else if (orderA == null) {
|
|
1558
|
+
return -1;
|
|
1559
|
+
} else if (orderB == null) {
|
|
1560
|
+
return 1;
|
|
1561
|
+
} else {
|
|
1562
|
+
return orderA - orderB;
|
|
1563
|
+
}
|
|
1564
|
+
});
|
|
1565
|
+
|
|
1566
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1567
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1568
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1569
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
// If this panel has been configured to persist sizing information,
|
|
1574
|
+
// default size should be restored from local storage if possible.
|
|
1575
|
+
let unsafeLayout = null;
|
|
1576
|
+
if (autoSaveId) {
|
|
1577
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1578
|
+
}
|
|
1579
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1580
|
+
if (groupSizePixels <= 0) {
|
|
1581
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1582
|
+
constraints
|
|
1583
|
+
}) => constraints))) {
|
|
1584
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
if (unsafeLayout == null) {
|
|
1589
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1590
|
+
groupSizePixels,
|
|
1591
|
+
panelDataArray
|
|
1495
1592
|
});
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1596
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1597
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1598
|
+
groupSizePixels,
|
|
1599
|
+
layout: unsafeLayout,
|
|
1600
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1496
1601
|
});
|
|
1602
|
+
|
|
1603
|
+
// Offscreen mode makes this a bit weird;
|
|
1604
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1605
|
+
// but the overall layout doesn't change between these two cases.
|
|
1606
|
+
setLayout(nextLayout);
|
|
1607
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1608
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1609
|
+
if (onLayout) {
|
|
1610
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1611
|
+
sizePercentage,
|
|
1612
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1613
|
+
})));
|
|
1614
|
+
}
|
|
1615
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1616
|
+
}
|
|
1497
1617
|
}, []);
|
|
1498
1618
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1499
1619
|
return function resizeHandler(event) {
|
|
@@ -1504,10 +1624,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1504
1624
|
id: groupId,
|
|
1505
1625
|
keyboardResizeByPercentage,
|
|
1506
1626
|
keyboardResizeByPixels,
|
|
1507
|
-
onLayout
|
|
1508
|
-
panelDataArray,
|
|
1509
|
-
layout: prevLayout
|
|
1627
|
+
onLayout
|
|
1510
1628
|
} = committedValuesRef.current;
|
|
1629
|
+
const {
|
|
1630
|
+
layout: prevLayout,
|
|
1631
|
+
panelDataArray
|
|
1632
|
+
} = eagerValuesRef.current;
|
|
1511
1633
|
const {
|
|
1512
1634
|
initialLayout
|
|
1513
1635
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1563,6 +1685,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1563
1685
|
}
|
|
1564
1686
|
if (layoutChanged) {
|
|
1565
1687
|
setLayout(nextLayout);
|
|
1688
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1566
1689
|
if (onLayout) {
|
|
1567
1690
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1568
1691
|
sizePercentage,
|
|
@@ -1576,23 +1699,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1576
1699
|
|
|
1577
1700
|
// External APIs are safe to memoize via committed values ref
|
|
1578
1701
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1702
|
+
const {
|
|
1703
|
+
onLayout
|
|
1704
|
+
} = committedValuesRef.current;
|
|
1579
1705
|
const {
|
|
1580
1706
|
layout: prevLayout,
|
|
1581
|
-
onLayout,
|
|
1582
1707
|
panelDataArray
|
|
1583
|
-
} =
|
|
1584
|
-
|
|
1585
|
-
// See issues/211
|
|
1586
|
-
if (panelDataArray.find(({
|
|
1587
|
-
id
|
|
1588
|
-
}) => id === panelData.id) == null) {
|
|
1589
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1590
|
-
panelData,
|
|
1591
|
-
mixedSizes,
|
|
1592
|
-
type: "resize"
|
|
1593
|
-
}]);
|
|
1594
|
-
return;
|
|
1595
|
-
}
|
|
1708
|
+
} = eagerValuesRef.current;
|
|
1596
1709
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1597
1710
|
const {
|
|
1598
1711
|
groupSizePixels,
|
|
@@ -1612,6 +1725,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1612
1725
|
});
|
|
1613
1726
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1614
1727
|
setLayout(nextLayout);
|
|
1728
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1615
1729
|
if (onLayout) {
|
|
1616
1730
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1617
1731
|
sizePercentage,
|
|
@@ -1623,9 +1737,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1623
1737
|
}, [groupId]);
|
|
1624
1738
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1625
1739
|
const {
|
|
1626
|
-
direction
|
|
1627
|
-
layout
|
|
1740
|
+
direction
|
|
1628
1741
|
} = committedValuesRef.current;
|
|
1742
|
+
const {
|
|
1743
|
+
layout
|
|
1744
|
+
} = eagerValuesRef.current;
|
|
1629
1745
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1630
1746
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1631
1747
|
setDragState({
|
|
@@ -1639,16 +1755,86 @@ function PanelGroupWithForwardedRef({
|
|
|
1639
1755
|
resetGlobalCursorStyle();
|
|
1640
1756
|
setDragState(null);
|
|
1641
1757
|
}, []);
|
|
1758
|
+
const unregisterPanelRef = useRef({
|
|
1759
|
+
pendingPanelIds: new Set(),
|
|
1760
|
+
timeout: null
|
|
1761
|
+
});
|
|
1642
1762
|
const unregisterPanel = useCallback(panelData => {
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1763
|
+
const {
|
|
1764
|
+
id: groupId,
|
|
1765
|
+
onLayout
|
|
1766
|
+
} = committedValuesRef.current;
|
|
1767
|
+
const {
|
|
1768
|
+
layout: prevLayout,
|
|
1769
|
+
panelDataArray
|
|
1770
|
+
} = eagerValuesRef.current;
|
|
1771
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1772
|
+
if (index >= 0) {
|
|
1773
|
+
panelDataArray.splice(index, 1);
|
|
1774
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1775
|
+
}
|
|
1776
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1777
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1781
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1782
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1783
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1784
|
+
const {
|
|
1785
|
+
pendingPanelIds
|
|
1786
|
+
} = unregisterPanelRef.current;
|
|
1787
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1788
|
+
|
|
1789
|
+
// TRICKY
|
|
1790
|
+
// Strict effects mode
|
|
1791
|
+
let unmountDueToStrictMode = false;
|
|
1792
|
+
pendingPanelIds.forEach(panelId => {
|
|
1793
|
+
pendingPanelIds.delete(panelId);
|
|
1794
|
+
if (panelDataArray.find(({
|
|
1795
|
+
id
|
|
1796
|
+
}) => id === panelId) == null) {
|
|
1797
|
+
unmountDueToStrictMode = true;
|
|
1798
|
+
|
|
1799
|
+
// TRICKY
|
|
1800
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1801
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1802
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1803
|
+
delete map[panelData.id];
|
|
1804
|
+
}
|
|
1805
|
+
});
|
|
1806
|
+
if (!unmountDueToStrictMode) {
|
|
1807
|
+
return;
|
|
1649
1808
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1809
|
+
if (panelDataArray.length === 0) {
|
|
1810
|
+
// The group is unmounting; skip layout calculation.
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1814
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1815
|
+
groupSizePixels,
|
|
1816
|
+
panelDataArray
|
|
1817
|
+
});
|
|
1818
|
+
|
|
1819
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1820
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1821
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1822
|
+
groupSizePixels,
|
|
1823
|
+
layout: unsafeLayout,
|
|
1824
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1825
|
+
});
|
|
1826
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1827
|
+
setLayout(nextLayout);
|
|
1828
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1829
|
+
if (onLayout) {
|
|
1830
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1831
|
+
sizePercentage,
|
|
1832
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1833
|
+
})));
|
|
1834
|
+
}
|
|
1835
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1836
|
+
}
|
|
1837
|
+
}, 0);
|
|
1652
1838
|
}, []);
|
|
1653
1839
|
const context = useMemo(() => ({
|
|
1654
1840
|
collapsePanel,
|