react-resizable-panels 0.0.58 → 0.0.60
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 +12 -0
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +189 -98
- package/dist/react-resizable-panels.browser.development.cjs.js +192 -101
- package/dist/react-resizable-panels.browser.development.esm.js +192 -101
- package/dist/react-resizable-panels.browser.esm.js +189 -98
- package/dist/react-resizable-panels.cjs.js +189 -98
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +192 -101
- package/dist/react-resizable-panels.development.esm.js +192 -101
- package/dist/react-resizable-panels.development.node.cjs.js +237 -49
- package/dist/react-resizable-panels.development.node.esm.js +237 -49
- package/dist/react-resizable-panels.esm.js +189 -98
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +234 -46
- package/dist/react-resizable-panels.node.esm.js +234 -46
- package/package.json +1 -1
- package/src/Panel.ts +2 -0
- package/src/PanelGroup.ts +221 -97
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +15 -15
- 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,
|
|
@@ -132,6 +133,7 @@ function PanelWithForwardedRef({
|
|
|
132
133
|
// CSS selectors
|
|
133
134
|
"data-panel": "",
|
|
134
135
|
"data-panel-id": panelId,
|
|
136
|
+
"data-panel-group-id": groupId,
|
|
135
137
|
// e2e test attributes
|
|
136
138
|
"data-panel-collapsible": undefined,
|
|
137
139
|
"data-panel-size": undefined
|
|
@@ -144,8 +146,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
144
146
|
PanelWithForwardedRef.displayName = "Panel";
|
|
145
147
|
Panel.displayName = "forwardRef(Panel)";
|
|
146
148
|
|
|
147
|
-
const PRECISION = 10;
|
|
148
|
-
|
|
149
149
|
function convertPixelsToPercentage(pixels, groupSizePixels) {
|
|
150
150
|
return pixels / groupSizePixels * 100;
|
|
151
151
|
}
|
|
@@ -223,6 +223,8 @@ function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, gr
|
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
const PRECISION = 10;
|
|
227
|
+
|
|
226
228
|
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
227
229
|
actual = parseFloat(actual.toFixed(fractionDigits));
|
|
228
230
|
expected = parseFloat(expected.toFixed(fractionDigits));
|
|
@@ -616,15 +618,10 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
616
618
|
});
|
|
617
619
|
useEffect(() => {
|
|
618
620
|
const {
|
|
619
|
-
direction,
|
|
620
621
|
panelDataArray
|
|
621
622
|
} = committedValuesRef.current;
|
|
622
623
|
const groupElement = getPanelGroupElement(groupId);
|
|
623
624
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
624
|
-
const {
|
|
625
|
-
height,
|
|
626
|
-
width
|
|
627
|
-
} = groupElement.getBoundingClientRect();
|
|
628
625
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
629
626
|
const cleanupFunctions = handles.map(handle => {
|
|
630
627
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
@@ -644,21 +641,19 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
644
641
|
if (index >= 0) {
|
|
645
642
|
const panelData = panelDataArray[index];
|
|
646
643
|
const size = layout[index];
|
|
647
|
-
if (size != null) {
|
|
648
|
-
var _getPercentageSizeFro;
|
|
644
|
+
if (size != null && panelData.constraints.collapsible) {
|
|
645
|
+
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
649
646
|
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
650
|
-
const
|
|
647
|
+
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
648
|
+
sizePercentage: panelData.constraints.collapsedSizePercentage,
|
|
649
|
+
sizePixels: panelData.constraints.collapsedSizePixels
|
|
650
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
651
|
+
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
651
652
|
sizePercentage: panelData.constraints.minSizePercentage,
|
|
652
653
|
sizePixels: panelData.constraints.minSizePixels
|
|
653
|
-
}, groupSizePixels)) !== null &&
|
|
654
|
-
let delta = 0;
|
|
655
|
-
if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
|
|
656
|
-
delta = direction === "horizontal" ? width : height;
|
|
657
|
-
} else {
|
|
658
|
-
delta = -(direction === "horizontal" ? width : height);
|
|
659
|
-
}
|
|
654
|
+
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
660
655
|
const nextLayout = adjustLayoutByDelta({
|
|
661
|
-
delta,
|
|
656
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
662
657
|
groupSizePixels,
|
|
663
658
|
layout,
|
|
664
659
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
@@ -779,6 +774,44 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
779
774
|
}
|
|
780
775
|
}
|
|
781
776
|
|
|
777
|
+
function calculateUnsafeDefaultLayout({
|
|
778
|
+
groupSizePixels,
|
|
779
|
+
panelDataArray
|
|
780
|
+
}) {
|
|
781
|
+
const layout = Array(panelDataArray.length);
|
|
782
|
+
const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
783
|
+
let numPanelsWithSizes = 0;
|
|
784
|
+
let remainingSize = 100;
|
|
785
|
+
|
|
786
|
+
// Distribute default sizes first
|
|
787
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
788
|
+
const {
|
|
789
|
+
defaultSizePercentage
|
|
790
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
791
|
+
if (defaultSizePercentage != null) {
|
|
792
|
+
numPanelsWithSizes++;
|
|
793
|
+
layout[index] = defaultSizePercentage;
|
|
794
|
+
remainingSize -= defaultSizePercentage;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// Remaining size should be distributed evenly between panels without default sizes
|
|
799
|
+
for (let index = 0; index < panelDataArray.length; index++) {
|
|
800
|
+
const {
|
|
801
|
+
defaultSizePercentage
|
|
802
|
+
} = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
|
|
803
|
+
if (defaultSizePercentage != null) {
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
807
|
+
const size = remainingSize / numRemainingPanels;
|
|
808
|
+
numPanelsWithSizes++;
|
|
809
|
+
layout[index] = size;
|
|
810
|
+
remainingSize -= size;
|
|
811
|
+
}
|
|
812
|
+
return layout;
|
|
813
|
+
}
|
|
814
|
+
|
|
782
815
|
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
783
816
|
return percentage / 100 * groupSizePixels;
|
|
784
817
|
}
|
|
@@ -929,6 +962,10 @@ function debounce(callback, durationMs = 10) {
|
|
|
929
962
|
return callable;
|
|
930
963
|
}
|
|
931
964
|
|
|
965
|
+
function getPanelElementsForGroup(groupId) {
|
|
966
|
+
return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
967
|
+
}
|
|
968
|
+
|
|
932
969
|
// PanelGroup might be rendering in a server-side environment where localStorage is not available
|
|
933
970
|
// or on a browser with cookies/storage disabled.
|
|
934
971
|
// In either case, this function avoids accessing localStorage until needed,
|
|
@@ -984,6 +1021,15 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
|
|
|
984
1021
|
} catch (error) {}
|
|
985
1022
|
return null;
|
|
986
1023
|
}
|
|
1024
|
+
function loadPanelLayout(autoSaveId, panels, storage) {
|
|
1025
|
+
const state = loadSerializedPanelGroupState(autoSaveId, storage);
|
|
1026
|
+
if (state) {
|
|
1027
|
+
var _state$key;
|
|
1028
|
+
const key = getSerializationKey(panels);
|
|
1029
|
+
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
1030
|
+
}
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
987
1033
|
function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
988
1034
|
const key = getSerializationKey(panels);
|
|
989
1035
|
const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
|
|
@@ -995,6 +1041,12 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
995
1041
|
}
|
|
996
1042
|
}
|
|
997
1043
|
|
|
1044
|
+
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1045
|
+
return constraints.some(constraints => {
|
|
1046
|
+
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
|
|
998
1050
|
// All units must be in percentages; pixel values should be pre-converted
|
|
999
1051
|
function validatePanelGroupLayout({
|
|
1000
1052
|
groupSizePixels,
|
|
@@ -1063,7 +1115,7 @@ const defaultStorage = {
|
|
|
1063
1115
|
};
|
|
1064
1116
|
const debounceMap = {};
|
|
1065
1117
|
function PanelGroupWithForwardedRef({
|
|
1066
|
-
autoSaveId,
|
|
1118
|
+
autoSaveId = null,
|
|
1067
1119
|
children,
|
|
1068
1120
|
className: classNameFromProps = "",
|
|
1069
1121
|
dataAttributes,
|
|
@@ -1080,11 +1132,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1080
1132
|
const groupId = useUniqueId(idFromProps);
|
|
1081
1133
|
const [dragState, setDragState] = useState(null);
|
|
1082
1134
|
const [layout, setLayout] = useState([]);
|
|
1083
|
-
const [panelDataArray, setPanelDataArray] = useState([]);
|
|
1084
1135
|
const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
|
|
1085
1136
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1086
1137
|
const prevDeltaRef = useRef(0);
|
|
1087
1138
|
const committedValuesRef = useRef({
|
|
1139
|
+
autoSaveId,
|
|
1088
1140
|
direction,
|
|
1089
1141
|
dragState,
|
|
1090
1142
|
id: groupId,
|
|
@@ -1092,7 +1144,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1092
1144
|
keyboardResizeByPixels,
|
|
1093
1145
|
layout,
|
|
1094
1146
|
onLayout,
|
|
1095
|
-
panelDataArray
|
|
1147
|
+
panelDataArray: [],
|
|
1148
|
+
storage
|
|
1096
1149
|
});
|
|
1097
1150
|
useRef({
|
|
1098
1151
|
didLogIdAndOrderWarning: false,
|
|
@@ -1130,6 +1183,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1130
1183
|
});
|
|
1131
1184
|
if (!areEqual(prevLayout, safeLayout)) {
|
|
1132
1185
|
setLayout(safeLayout);
|
|
1186
|
+
committedValuesRef.current.layout = safeLayout;
|
|
1133
1187
|
if (onLayout) {
|
|
1134
1188
|
onLayout(safeLayout.map(sizePercentage => ({
|
|
1135
1189
|
sizePercentage,
|
|
@@ -1140,14 +1194,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1140
1194
|
}
|
|
1141
1195
|
}
|
|
1142
1196
|
}), []);
|
|
1197
|
+
|
|
1143
1198
|
useWindowSplitterPanelGroupBehavior({
|
|
1144
1199
|
committedValuesRef,
|
|
1145
1200
|
groupId,
|
|
1146
1201
|
layout,
|
|
1147
|
-
panelDataArray,
|
|
1202
|
+
panelDataArray: committedValuesRef.current.panelDataArray,
|
|
1148
1203
|
setLayout
|
|
1149
1204
|
});
|
|
1150
1205
|
useEffect(() => {
|
|
1206
|
+
const {
|
|
1207
|
+
panelDataArray
|
|
1208
|
+
} = committedValuesRef.current;
|
|
1209
|
+
|
|
1151
1210
|
// If this panel has been configured to persist sizing information, save sizes to local storage.
|
|
1152
1211
|
if (autoSaveId) {
|
|
1153
1212
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
@@ -1160,7 +1219,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1160
1219
|
}
|
|
1161
1220
|
debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
|
|
1162
1221
|
}
|
|
1163
|
-
}, [autoSaveId, layout,
|
|
1222
|
+
}, [autoSaveId, layout, storage]);
|
|
1164
1223
|
|
|
1165
1224
|
// DEV warnings
|
|
1166
1225
|
useEffect(() => {
|
|
@@ -1197,6 +1256,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1197
1256
|
});
|
|
1198
1257
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1199
1258
|
setLayout(nextLayout);
|
|
1259
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1200
1260
|
if (onLayout) {
|
|
1201
1261
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1202
1262
|
sizePercentage,
|
|
@@ -1241,6 +1301,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1241
1301
|
});
|
|
1242
1302
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1243
1303
|
setLayout(nextLayout);
|
|
1304
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1244
1305
|
if (onLayout) {
|
|
1245
1306
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1246
1307
|
sizePercentage,
|
|
@@ -1271,6 +1332,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1271
1332
|
|
|
1272
1333
|
// This API should never read from committedValuesRef
|
|
1273
1334
|
const getPanelStyle = useCallback(panelData => {
|
|
1335
|
+
const {
|
|
1336
|
+
panelDataArray
|
|
1337
|
+
} = committedValuesRef.current;
|
|
1274
1338
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1275
1339
|
return computePanelFlexBoxStyle({
|
|
1276
1340
|
dragState,
|
|
@@ -1278,7 +1342,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1278
1342
|
panelData: panelDataArray,
|
|
1279
1343
|
panelIndex
|
|
1280
1344
|
});
|
|
1281
|
-
}, [dragState, layout
|
|
1345
|
+
}, [dragState, layout]);
|
|
1282
1346
|
|
|
1283
1347
|
// External APIs are safe to memoize via committed values ref
|
|
1284
1348
|
const isPanelCollapsed = useCallback(panelData => {
|
|
@@ -1308,22 +1372,76 @@ function PanelGroupWithForwardedRef({
|
|
|
1308
1372
|
return !collapsible || panelSizePercentage > collapsedSizePercentage;
|
|
1309
1373
|
}, [groupId]);
|
|
1310
1374
|
const registerPanel = useCallback(panelData => {
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1375
|
+
const {
|
|
1376
|
+
autoSaveId,
|
|
1377
|
+
id: groupId,
|
|
1378
|
+
layout: prevLayout,
|
|
1379
|
+
onLayout,
|
|
1380
|
+
panelDataArray,
|
|
1381
|
+
storage
|
|
1382
|
+
} = committedValuesRef.current;
|
|
1383
|
+
panelDataArray.push(panelData);
|
|
1384
|
+
panelDataArray.sort((panelA, panelB) => {
|
|
1385
|
+
const orderA = panelA.order;
|
|
1386
|
+
const orderB = panelB.order;
|
|
1387
|
+
if (orderA == null && orderB == null) {
|
|
1388
|
+
return 0;
|
|
1389
|
+
} else if (orderA == null) {
|
|
1390
|
+
return -1;
|
|
1391
|
+
} else if (orderB == null) {
|
|
1392
|
+
return 1;
|
|
1393
|
+
} else {
|
|
1394
|
+
return orderA - orderB;
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
// Wait until all panels have registered before we try to compute layout;
|
|
1399
|
+
// doing it earlier is both wasteful and may trigger misleading warnings in development mode.
|
|
1400
|
+
const panelElements = getPanelElementsForGroup(groupId);
|
|
1401
|
+
if (panelElements.length !== panelDataArray.length) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// If this panel has been configured to persist sizing information,
|
|
1406
|
+
// default size should be restored from local storage if possible.
|
|
1407
|
+
let unsafeLayout = null;
|
|
1408
|
+
if (autoSaveId) {
|
|
1409
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1410
|
+
}
|
|
1411
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1412
|
+
if (groupSizePixels <= 0) {
|
|
1413
|
+
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1414
|
+
constraints
|
|
1415
|
+
}) => constraints))) {
|
|
1416
|
+
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
if (unsafeLayout == null) {
|
|
1421
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1422
|
+
groupSizePixels,
|
|
1423
|
+
panelDataArray
|
|
1325
1424
|
});
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1428
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1429
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1430
|
+
groupSizePixels,
|
|
1431
|
+
layout: unsafeLayout,
|
|
1432
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1326
1433
|
});
|
|
1434
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1435
|
+
setLayout(nextLayout);
|
|
1436
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1437
|
+
if (onLayout) {
|
|
1438
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1439
|
+
sizePercentage,
|
|
1440
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1441
|
+
})));
|
|
1442
|
+
}
|
|
1443
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1444
|
+
}
|
|
1327
1445
|
}, []);
|
|
1328
1446
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1329
1447
|
return function resizeHandler(event) {
|
|
@@ -1393,6 +1511,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1393
1511
|
}
|
|
1394
1512
|
if (layoutChanged) {
|
|
1395
1513
|
setLayout(nextLayout);
|
|
1514
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1396
1515
|
if (onLayout) {
|
|
1397
1516
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1398
1517
|
sizePercentage,
|
|
@@ -1430,6 +1549,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1430
1549
|
});
|
|
1431
1550
|
if (!compareLayouts(prevLayout, nextLayout)) {
|
|
1432
1551
|
setLayout(nextLayout);
|
|
1552
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1433
1553
|
if (onLayout) {
|
|
1434
1554
|
onLayout(nextLayout.map(sizePercentage => ({
|
|
1435
1555
|
sizePercentage,
|
|
@@ -1457,16 +1577,84 @@ function PanelGroupWithForwardedRef({
|
|
|
1457
1577
|
resetGlobalCursorStyle();
|
|
1458
1578
|
setDragState(null);
|
|
1459
1579
|
}, []);
|
|
1580
|
+
const unregisterPanelRef = useRef({
|
|
1581
|
+
pendingPanelIds: new Set(),
|
|
1582
|
+
timeout: null
|
|
1583
|
+
});
|
|
1460
1584
|
const unregisterPanel = useCallback(panelData => {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1585
|
+
const {
|
|
1586
|
+
id: groupId,
|
|
1587
|
+
layout: prevLayout,
|
|
1588
|
+
onLayout,
|
|
1589
|
+
panelDataArray
|
|
1590
|
+
} = committedValuesRef.current;
|
|
1591
|
+
const index = panelDataArray.indexOf(panelData);
|
|
1592
|
+
if (index >= 0) {
|
|
1593
|
+
panelDataArray.splice(index, 1);
|
|
1594
|
+
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
1595
|
+
}
|
|
1596
|
+
if (unregisterPanelRef.current.timeout != null) {
|
|
1597
|
+
clearTimeout(unregisterPanelRef.current.timeout);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
// Batch panel unmounts so that we only calculate layout once;
|
|
1601
|
+
// This is more efficient and avoids misleading warnings in development mode.
|
|
1602
|
+
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
1603
|
+
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
1604
|
+
const {
|
|
1605
|
+
pendingPanelIds
|
|
1606
|
+
} = unregisterPanelRef.current;
|
|
1607
|
+
panelIdToLastNotifiedMixedSizesMapRef.current;
|
|
1608
|
+
|
|
1609
|
+
// TRICKY
|
|
1610
|
+
// Strict effects mode
|
|
1611
|
+
let unmountDueToStrictMode = false;
|
|
1612
|
+
pendingPanelIds.forEach(panelId => {
|
|
1613
|
+
pendingPanelIds.delete(panelId);
|
|
1614
|
+
if (panelDataArray.find(({
|
|
1615
|
+
id
|
|
1616
|
+
}) => id === panelId) == null) {
|
|
1617
|
+
unmountDueToStrictMode = true;
|
|
1618
|
+
|
|
1619
|
+
// TRICKY
|
|
1620
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
1621
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
1622
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
1623
|
+
delete panelIdToLastNotifiedMixedSizesMapRef.current[panelData.id];
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
if (!unmountDueToStrictMode) {
|
|
1627
|
+
return;
|
|
1467
1628
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1629
|
+
if (panelDataArray.length === 0) {
|
|
1630
|
+
// The group is unmounting; skip layout calculation.
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1634
|
+
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1635
|
+
groupSizePixels,
|
|
1636
|
+
panelDataArray
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
// Validate even saved layouts in case something has changed since last render
|
|
1640
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1641
|
+
const nextLayout = validatePanelGroupLayout({
|
|
1642
|
+
groupSizePixels,
|
|
1643
|
+
layout: unsafeLayout,
|
|
1644
|
+
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1645
|
+
});
|
|
1646
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
1647
|
+
setLayout(nextLayout);
|
|
1648
|
+
committedValuesRef.current.layout = nextLayout;
|
|
1649
|
+
if (onLayout) {
|
|
1650
|
+
onLayout(nextLayout.map(sizePercentage => ({
|
|
1651
|
+
sizePercentage,
|
|
1652
|
+
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1653
|
+
})));
|
|
1654
|
+
}
|
|
1655
|
+
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1656
|
+
}
|
|
1657
|
+
}, 0);
|
|
1470
1658
|
}, []);
|
|
1471
1659
|
const context = useMemo(() => ({
|
|
1472
1660
|
collapsePanel,
|
package/package.json
CHANGED
package/src/Panel.ts
CHANGED
|
@@ -115,6 +115,7 @@ export function PanelWithForwardedRef({
|
|
|
115
115
|
expandPanel,
|
|
116
116
|
getPanelSize,
|
|
117
117
|
getPanelStyle,
|
|
118
|
+
groupId,
|
|
118
119
|
isPanelCollapsed,
|
|
119
120
|
registerPanel,
|
|
120
121
|
resizePanel,
|
|
@@ -250,6 +251,7 @@ export function PanelWithForwardedRef({
|
|
|
250
251
|
// CSS selectors
|
|
251
252
|
"data-panel": "",
|
|
252
253
|
"data-panel-id": panelId,
|
|
254
|
+
"data-panel-group-id": groupId,
|
|
253
255
|
|
|
254
256
|
// e2e test attributes
|
|
255
257
|
"data-panel-collapsible": isDevelopment
|