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
|
@@ -67,6 +67,7 @@ function PanelWithForwardedRef({
|
|
|
67
67
|
expandPanel,
|
|
68
68
|
getPanelSize,
|
|
69
69
|
getPanelStyle,
|
|
70
|
+
groupId,
|
|
70
71
|
isPanelCollapsed,
|
|
71
72
|
registerPanel,
|
|
72
73
|
resizePanel,
|
|
@@ -143,6 +144,7 @@ function PanelWithForwardedRef({
|
|
|
143
144
|
// CSS selectors
|
|
144
145
|
"data-panel": "",
|
|
145
146
|
"data-panel-id": panelId,
|
|
147
|
+
"data-panel-group-id": groupId,
|
|
146
148
|
// e2e test attributes
|
|
147
149
|
"data-panel-collapsible": collapsible || undefined ,
|
|
148
150
|
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
|
|
@@ -617,6 +619,7 @@ function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
|
617
619
|
|
|
618
620
|
function useWindowSplitterPanelGroupBehavior({
|
|
619
621
|
committedValuesRef,
|
|
622
|
+
eagerValuesRef,
|
|
620
623
|
groupId,
|
|
621
624
|
layout,
|
|
622
625
|
panelDataArray,
|
|
@@ -628,7 +631,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
628
631
|
useEffect(() => {
|
|
629
632
|
const {
|
|
630
633
|
panelDataArray
|
|
631
|
-
} =
|
|
634
|
+
} = eagerValuesRef.current;
|
|
632
635
|
const groupElement = getPanelGroupElement(groupId);
|
|
633
636
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
634
637
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
@@ -686,7 +689,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
686
689
|
return () => {
|
|
687
690
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
688
691
|
};
|
|
689
|
-
}, [committedValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
692
|
+
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
690
693
|
}
|
|
691
694
|
|
|
692
695
|
function areEqual(arrayA, arrayB) {
|
|
@@ -783,6 +786,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
783
786
|
}
|
|
784
787
|
}
|
|
785
788
|
|
|
789
|
+
function calculateUnsafeDefaultLayout({
|
|
790
|
+
groupSizePixels,
|
|
791
|
+
panelDataArray
|
|
792
|
+
}) {
|
|
793
|
+
const layout = Array(panelDataArray.length);
|
|
794
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
795
|
+
let numPanelsWithSizes = 0;
|
|
796
|
+
let remainingSize = 100;
|
|
797
|
+
|
|
798
|
+
// Distribute default sizes first
|
|
799
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
800
|
+
const {
|
|
801
|
+
defaultSizePercentage
|
|
802
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
803
|
+
if (defaultSizePercentage != null) {
|
|
804
|
+
numPanelsWithSizes++;
|
|
805
|
+
layout[index] = defaultSizePercentage;
|
|
806
|
+
remainingSize -= defaultSizePercentage;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
811
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
812
|
+
const {
|
|
813
|
+
defaultSizePercentage
|
|
814
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
815
|
+
if (defaultSizePercentage != null) {
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
819
|
+
const size = remainingSize / numRemainingPanels;
|
|
820
|
+
numPanelsWithSizes++;
|
|
821
|
+
layout[index] = size;
|
|
822
|
+
remainingSize -= size;
|
|
823
|
+
}
|
|
824
|
+
return layout;
|
|
825
|
+
}
|
|
826
|
+
|
|
786
827
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
787
828
|
return percentage / 100 * groupSizePixels;
|
|
788
829
|
}
|
|
@@ -933,6 +974,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
933
974
|
return callable;
|
|
934
975
|
}
|
|
935
976
|
|
|
977
|
+
function getPanelElementsForGroup(groupId) {
|
|
978
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
979
|
+
}
|
|
980
|
+
|
|
936
981
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
937
982
|
// or on a browser with cookies/storage disabled.
|
|
938
983
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -988,6 +1033,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
988
1033
|
} catch (error) {}
|
|
989
1034
|
return null;
|
|
990
1035
|
}
|
|
1036
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1037
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1038
|
+
if (state) {
|
|
1039
|
+
var _state$key;
|
|
1040
|
+
const key = getSerializationKey(panels);
|
|
1041
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1042
|
+
}
|
|
1043
|
+
return null;
|
|
1044
|
+
}
|
|
991
1045
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
992
1046
|
const key = getSerializationKey(panels);
|
|
993
1047
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -999,6 +1053,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
999
1053
|
}
|
|
1000
1054
|
}
|
|
1001
1055
|
|
|
1056
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1057
|
+
return constraints.some(constraints => {
|
|
1058
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1002
1062
|
function validatePanelConstraints({
|
|
1003
1063
|
groupSizePixels,
|
|
1004
1064
|
panelConstraints,
|
|
@@ -1144,7 +1204,7 @@ const defaultStorage = {
|
|
|
1144
1204
|
};
|
|
1145
1205
|
const debounceMap = {};
|
|
1146
1206
|
function PanelGroupWithForwardedRef({
|
|
1147
|
-
autoSaveId,
|
|
1207
|
+
autoSaveId = null,
|
|
1148
1208
|
children,
|
|
1149
1209
|
className: classNameFromProps = "",
|
|
1150
1210
|
dataAttributes,
|
|
@@ -1161,20 +1221,22 @@ function PanelGroupWithForwardedRef({
|
|
|
1161
1221
|
const groupId = useUniqueId(idFromProps);
|
|
1162
1222
|
const [dragState, setDragState] = useState(null);
|
|
1163
1223
|
const [layout, setLayout] = useState([]);
|
|
1164
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1165
1224
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1166
1225
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1167
1226
|
const prevDeltaRef = useRef(0);
|
|
1168
|
-
const [imperativeApiQueue, setImperativeApiQueue] = useState([]);
|
|
1169
1227
|
const committedValuesRef = useRef({
|
|
1228
|
+
autoSaveId,
|
|
1170
1229
|
direction,
|
|
1171
1230
|
dragState,
|
|
1172
1231
|
id: groupId,
|
|
1173
1232
|
keyboardResizeByPercentage,
|
|
1174
1233
|
keyboardResizeByPixels,
|
|
1175
|
-
layout,
|
|
1176
1234
|
onLayout,
|
|
1177
|
-
|
|
1235
|
+
storage
|
|
1236
|
+
});
|
|
1237
|
+
const eagerValuesRef = useRef({
|
|
1238
|
+
layout,
|
|
1239
|
+
panelDataArray: []
|
|
1178
1240
|
});
|
|
1179
1241
|
const devWarningsRef = useRef({
|
|
1180
1242
|
didLogIdAndOrderWarning: false,
|
|
@@ -1185,9 +1247,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1185
1247
|
getId: () => committedValuesRef.current.id,
|
|
1186
1248
|
getLayout: () => {
|
|
1187
1249
|
const {
|
|
1188
|
-
id: groupId
|
|
1189
|
-
layout
|
|
1250
|
+
id: groupId
|
|
1190
1251
|
} = committedValuesRef.current;
|
|
1252
|
+
const {
|
|
1253
|
+
layout
|
|
1254
|
+
} = eagerValuesRef.current;
|
|
1191
1255
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1192
1256
|
return layout.map(sizePercentage => {
|
|
1193
1257
|
return {
|
|
@@ -1199,10 +1263,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1199
1263
|
setLayout: mixedSizes => {
|
|
1200
1264
|
const {
|
|
1201
1265
|
id: groupId,
|
|
1266
|
+
onLayout
|
|
1267
|
+
} = committedValuesRef.current;
|
|
1268
|
+
const {
|
|
1202
1269
|
layout: prevLayout,
|
|
1203
|
-
onLayout,
|
|
1204
1270
|
panelDataArray
|
|
1205
|
-
} =
|
|
1271
|
+
} = eagerValuesRef.current;
|
|
1206
1272
|
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1207
1273
|
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1208
1274
|
const safeLayout = validatePanelGroupLayout({
|
|
@@ -1212,6 +1278,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1212
1278
|
});
|
|
1213
1279
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1214
1280
|
setLayout(safeLayout);
|
|
1281
|
+
eagerValuesRef.current.layout = safeLayout;
|
|
1215
1282
|
if (onLayout) {
|
|
1216
1283
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1217
1284
|
sizePercentage,
|
|
@@ -1222,14 +1289,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1222
1289
|
}
|
|
1223
1290
|
}
|
|
1224
1291
|
}), []);
|
|
1292
|
+
|
|
1225
1293
|
useWindowSplitterPanelGroupBehavior({
|
|
1226
1294
|
committedValuesRef,
|
|
1295
|
+
eagerValuesRef,
|
|
1227
1296
|
groupId,
|
|
1228
1297
|
layout,
|
|
1229
|
-
panelDataArray,
|
|
1298
|
+
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1230
1299
|
setLayout
|
|
1231
1300
|
});
|
|
1232
1301
|
useEffect(() => {
|
|
1302
|
+
const {
|
|
1303
|
+
panelDataArray
|
|
1304
|
+
} = eagerValuesRef.current;
|
|
1305
|
+
|
|
1233
1306
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1234
1307
|
if (autoSaveId) {
|
|
1235
1308
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1242,20 +1315,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1242
1315
|
}
|
|
1243
1316
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1244
1317
|
}
|
|
1245
|
-
}, [autoSaveId, layout,
|
|
1318
|
+
}, [autoSaveId, layout, storage]);
|
|
1246
1319
|
|
|
1247
1320
|
// DEV warnings
|
|
1248
1321
|
useEffect(() => {
|
|
1249
1322
|
{
|
|
1323
|
+
const {
|
|
1324
|
+
panelDataArray
|
|
1325
|
+
} = eagerValuesRef.current;
|
|
1250
1326
|
const {
|
|
1251
1327
|
didLogIdAndOrderWarning,
|
|
1252
1328
|
didLogPanelConstraintsWarning,
|
|
1253
1329
|
prevPanelIds
|
|
1254
1330
|
} = devWarningsRef.current;
|
|
1255
1331
|
if (!didLogIdAndOrderWarning) {
|
|
1256
|
-
const {
|
|
1257
|
-
panelDataArray
|
|
1258
|
-
} = committedValuesRef.current;
|
|
1259
1332
|
const panelIds = panelDataArray.map(({
|
|
1260
1333
|
id
|
|
1261
1334
|
}) => id);
|
|
@@ -1292,22 +1365,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1292
1365
|
|
|
1293
1366
|
// External APIs are safe to memoize via committed values ref
|
|
1294
1367
|
const collapsePanel = useCallback(panelData => {
|
|
1368
|
+
const {
|
|
1369
|
+
onLayout
|
|
1370
|
+
} = committedValuesRef.current;
|
|
1295
1371
|
const {
|
|
1296
1372
|
layout: prevLayout,
|
|
1297
|
-
onLayout,
|
|
1298
1373
|
panelDataArray
|
|
1299
|
-
} =
|
|
1300
|
-
|
|
1301
|
-
// See issues/211
|
|
1302
|
-
if (panelDataArray.find(({
|
|
1303
|
-
id
|
|
1304
|
-
}) => id === panelData.id) == null) {
|
|
1305
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1306
|
-
panelData,
|
|
1307
|
-
type: "collapse"
|
|
1308
|
-
}]);
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1374
|
+
} = eagerValuesRef.current;
|
|
1311
1375
|
if (panelData.constraints.collapsible) {
|
|
1312
1376
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1313
1377
|
const {
|
|
@@ -1332,6 +1396,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1332
1396
|
});
|
|
1333
1397
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1334
1398
|
setLayout(nextLayout);
|
|
1399
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1335
1400
|
if (onLayout) {
|
|
1336
1401
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1337
1402
|
sizePercentage,
|
|
@@ -1346,22 +1411,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1346
1411
|
|
|
1347
1412
|
// External APIs are safe to memoize via committed values ref
|
|
1348
1413
|
const expandPanel = useCallback(panelData => {
|
|
1414
|
+
const {
|
|
1415
|
+
onLayout
|
|
1416
|
+
} = committedValuesRef.current;
|
|
1349
1417
|
const {
|
|
1350
1418
|
layout: prevLayout,
|
|
1351
|
-
onLayout,
|
|
1352
1419
|
panelDataArray
|
|
1353
|
-
} =
|
|
1354
|
-
|
|
1355
|
-
// See issues/211
|
|
1356
|
-
if (panelDataArray.find(({
|
|
1357
|
-
id
|
|
1358
|
-
}) => id === panelData.id) == null) {
|
|
1359
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1360
|
-
panelData,
|
|
1361
|
-
type: "expand"
|
|
1362
|
-
}]);
|
|
1363
|
-
return;
|
|
1364
|
-
}
|
|
1420
|
+
} = eagerValuesRef.current;
|
|
1365
1421
|
if (panelData.constraints.collapsible) {
|
|
1366
1422
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1367
1423
|
const {
|
|
@@ -1387,6 +1443,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1387
1443
|
});
|
|
1388
1444
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1389
1445
|
setLayout(nextLayout);
|
|
1446
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1390
1447
|
if (onLayout) {
|
|
1391
1448
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1392
1449
|
sizePercentage,
|
|
@@ -1404,7 +1461,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1404
1461
|
const {
|
|
1405
1462
|
layout,
|
|
1406
1463
|
panelDataArray
|
|
1407
|
-
} =
|
|
1464
|
+
} = eagerValuesRef.current;
|
|
1408
1465
|
const {
|
|
1409
1466
|
panelSizePercentage,
|
|
1410
1467
|
panelSizePixels
|
|
@@ -1417,6 +1474,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1417
1474
|
|
|
1418
1475
|
// This API should never read from committedValuesRef
|
|
1419
1476
|
const getPanelStyle = useCallback(panelData => {
|
|
1477
|
+
const {
|
|
1478
|
+
panelDataArray
|
|
1479
|
+
} = eagerValuesRef.current;
|
|
1420
1480
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1421
1481
|
return computePanelFlexBoxStyle({
|
|
1422
1482
|
dragState,
|
|
@@ -1424,14 +1484,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1424
1484
|
panelData: panelDataArray,
|
|
1425
1485
|
panelIndex
|
|
1426
1486
|
});
|
|
1427
|
-
}, [dragState, layout
|
|
1487
|
+
}, [dragState, layout]);
|
|
1428
1488
|
|
|
1429
1489
|
// External APIs are safe to memoize via committed values ref
|
|
1430
1490
|
const isPanelCollapsed = useCallback(panelData => {
|
|
1431
1491
|
const {
|
|
1432
1492
|
layout,
|
|
1433
1493
|
panelDataArray
|
|
1434
|
-
} =
|
|
1494
|
+
} = eagerValuesRef.current;
|
|
1435
1495
|
const {
|
|
1436
1496
|
collapsedSizePercentage,
|
|
1437
1497
|
collapsible,
|
|
@@ -1445,7 +1505,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1445
1505
|
const {
|
|
1446
1506
|
layout,
|
|
1447
1507
|
panelDataArray
|
|
1448
|
-
} =
|
|
1508
|
+
} = eagerValuesRef.current;
|
|
1449
1509
|
const {
|
|
1450
1510
|
collapsedSizePercentage,
|
|
1451
1511
|
collapsible,
|
|
@@ -1454,22 +1514,82 @@ function PanelGroupWithForwardedRef({
|
|
|
1454
1514
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1455
1515
|
}, [groupId]);
|
|
1456
1516
|
const registerPanel = useCallback(panelData => {
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1517
|
+
const {
|
|
1518
|
+
autoSaveId,
|
|
1519
|
+
id: groupId,
|
|
1520
|
+
onLayout,
|
|
1521
|
+
storage
|
|
1522
|
+
} = committedValuesRef.current;
|
|
1523
|
+
const {
|
|
1524
|
+
layout: prevLayout,
|
|
1525
|
+
panelDataArray
|
|
1526
|
+
} = eagerValuesRef.current;
|
|
1527
|
+
panelDataArray.push(panelData);
|
|
1528
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1529
|
+
const orderA = panelA.order;
|
|
1530
|
+
const orderB = panelB.order;
|
|
1531
|
+
if (orderA == null && orderB == null) {
|
|
1532
|
+
return 0;
|
|
1533
|
+
} else if (orderA == null) {
|
|
1534
|
+
return -1;
|
|
1535
|
+
} else if (orderB == null) {
|
|
1536
|
+
return 1;
|
|
1537
|
+
} else {
|
|
1538
|
+
return orderA - orderB;
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
|
|
1542
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1543
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1544
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1545
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
// If this panel has been configured to persist sizing information,
|
|
1550
|
+
// default size should be restored from local storage if possible.
|
|
1551
|
+
let unsafeLayout = null;
|
|
1552
|
+
if (autoSaveId) {
|
|
1553
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1554
|
+
}
|
|
1555
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1556
|
+
if (groupSizePixels <= 0) {
|
|
1557
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1558
|
+
constraints
|
|
1559
|
+
}) => constraints))) {
|
|
1560
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
if (unsafeLayout == null) {
|
|
1565
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1566
|
+
groupSizePixels,
|
|
1567
|
+
panelDataArray
|
|
1471
1568
|
});
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1572
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1573
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1574
|
+
groupSizePixels,
|
|
1575
|
+
layout: unsafeLayout,
|
|
1576
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1472
1577
|
});
|
|
1578
|
+
|
|
1579
|
+
// Offscreen mode makes this a bit weird;
|
|
1580
|
+
// Panels unregister when hidden and re-register when shown again,
|
|
1581
|
+
// but the overall layout doesn't change between these two cases.
|
|
1582
|
+
setLayout(nextLayout);
|
|
1583
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1584
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1585
|
+
if (onLayout) {
|
|
1586
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1587
|
+
sizePercentage,
|
|
1588
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1589
|
+
})));
|
|
1590
|
+
}
|
|
1591
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1592
|
+
}
|
|
1473
1593
|
}, []);
|
|
1474
1594
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1475
1595
|
return function resizeHandler(event) {
|
|
@@ -1480,10 +1600,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1480
1600
|
id: groupId,
|
|
1481
1601
|
keyboardResizeByPercentage,
|
|
1482
1602
|
keyboardResizeByPixels,
|
|
1483
|
-
onLayout
|
|
1484
|
-
panelDataArray,
|
|
1485
|
-
layout: prevLayout
|
|
1603
|
+
onLayout
|
|
1486
1604
|
} = committedValuesRef.current;
|
|
1605
|
+
const {
|
|
1606
|
+
layout: prevLayout,
|
|
1607
|
+
panelDataArray
|
|
1608
|
+
} = eagerValuesRef.current;
|
|
1487
1609
|
const {
|
|
1488
1610
|
initialLayout
|
|
1489
1611
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
@@ -1539,6 +1661,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1539
1661
|
}
|
|
1540
1662
|
if (layoutChanged) {
|
|
1541
1663
|
setLayout(nextLayout);
|
|
1664
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1542
1665
|
if (onLayout) {
|
|
1543
1666
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1544
1667
|
sizePercentage,
|
|
@@ -1552,23 +1675,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1552
1675
|
|
|
1553
1676
|
// External APIs are safe to memoize via committed values ref
|
|
1554
1677
|
const resizePanel = useCallback((panelData, mixedSizes) => {
|
|
1678
|
+
const {
|
|
1679
|
+
onLayout
|
|
1680
|
+
} = committedValuesRef.current;
|
|
1555
1681
|
const {
|
|
1556
1682
|
layout: prevLayout,
|
|
1557
|
-
onLayout,
|
|
1558
1683
|
panelDataArray
|
|
1559
|
-
} =
|
|
1560
|
-
|
|
1561
|
-
// See issues/211
|
|
1562
|
-
if (panelDataArray.find(({
|
|
1563
|
-
id
|
|
1564
|
-
}) => id === panelData.id) == null) {
|
|
1565
|
-
setImperativeApiQueue(prev => [...prev, {
|
|
1566
|
-
panelData,
|
|
1567
|
-
mixedSizes,
|
|
1568
|
-
type: "resize"
|
|
1569
|
-
}]);
|
|
1570
|
-
return;
|
|
1571
|
-
}
|
|
1684
|
+
} = eagerValuesRef.current;
|
|
1572
1685
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1573
1686
|
const {
|
|
1574
1687
|
groupSizePixels,
|
|
@@ -1588,6 +1701,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1588
1701
|
});
|
|
1589
1702
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1590
1703
|
setLayout(nextLayout);
|
|
1704
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1591
1705
|
if (onLayout) {
|
|
1592
1706
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1593
1707
|
sizePercentage,
|
|
@@ -1599,9 +1713,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1599
1713
|
}, [groupId]);
|
|
1600
1714
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1601
1715
|
const {
|
|
1602
|
-
direction
|
|
1603
|
-
layout
|
|
1716
|
+
direction
|
|
1604
1717
|
} = committedValuesRef.current;
|
|
1718
|
+
const {
|
|
1719
|
+
layout
|
|
1720
|
+
} = eagerValuesRef.current;
|
|
1605
1721
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1606
1722
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1607
1723
|
setDragState({
|
|
@@ -1615,16 +1731,86 @@ function PanelGroupWithForwardedRef({
|
|
|
1615
1731
|
resetGlobalCursorStyle();
|
|
1616
1732
|
setDragState(null);
|
|
1617
1733
|
}, []);
|
|
1734
|
+
const unregisterPanelRef = useRef({
|
|
1735
|
+
pendingPanelIds: new Set(),
|
|
1736
|
+
timeout: null
|
|
1737
|
+
});
|
|
1618
1738
|
const unregisterPanel = useCallback(panelData => {
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1739
|
+
const {
|
|
1740
|
+
id: groupId,
|
|
1741
|
+
onLayout
|
|
1742
|
+
} = committedValuesRef.current;
|
|
1743
|
+
const {
|
|
1744
|
+
layout: prevLayout,
|
|
1745
|
+
panelDataArray
|
|
1746
|
+
} = eagerValuesRef.current;
|
|
1747
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1748
|
+
if (index >= 0) {
|
|
1749
|
+
panelDataArray.splice(index, 1);
|
|
1750
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1751
|
+
}
|
|
1752
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1753
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1757
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1758
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1759
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1760
|
+
const {
|
|
1761
|
+
pendingPanelIds
|
|
1762
|
+
} = unregisterPanelRef.current;
|
|
1763
|
+
const map = panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1764
|
+
|
|
1765
|
+
// TRICKY
|
|
1766
|
+
// Strict effects mode
|
|
1767
|
+
let unmountDueToStrictMode = false;
|
|
1768
|
+
pendingPanelIds.forEach(panelId => {
|
|
1769
|
+
pendingPanelIds.delete(panelId);
|
|
1770
|
+
if (panelDataArray.find(({
|
|
1771
|
+
id
|
|
1772
|
+
}) => id === panelId) == null) {
|
|
1773
|
+
unmountDueToStrictMode = true;
|
|
1774
|
+
|
|
1775
|
+
// TRICKY
|
|
1776
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1777
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1778
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1779
|
+
delete map[panelData.id];
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
if (!unmountDueToStrictMode) {
|
|
1783
|
+
return;
|
|
1625
1784
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1785
|
+
if (panelDataArray.length === 0) {
|
|
1786
|
+
// The group is unmounting; skip layout calculation.
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1789
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1790
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1791
|
+
groupSizePixels,
|
|
1792
|
+
panelDataArray
|
|
1793
|
+
});
|
|
1794
|
+
|
|
1795
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1796
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1797
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1798
|
+
groupSizePixels,
|
|
1799
|
+
layout: unsafeLayout,
|
|
1800
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1801
|
+
});
|
|
1802
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1803
|
+
setLayout(nextLayout);
|
|
1804
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
1805
|
+
if (onLayout) {
|
|
1806
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1807
|
+
sizePercentage,
|
|
1808
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1809
|
+
})));
|
|
1810
|
+
}
|
|
1811
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1812
|
+
}
|
|
1813
|
+
}, 0);
|
|
1628
1814
|
}, []);
|
|
1629
1815
|
const context = useMemo(() => ({
|
|
1630
1816
|
collapsePanel,
|