react-resizable-panels 0.0.62 → 1.0.0-rc.1
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/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +9 -0
- package/dist/declarations/src/Panel.d.ts +19 -34
- package/dist/declarations/src/PanelGroup.d.ts +9 -13
- package/dist/declarations/src/PanelResizeHandle.d.ts +5 -7
- package/dist/declarations/src/index.d.ts +2 -2
- package/dist/declarations/src/types.d.ts +0 -7
- package/dist/declarations/src/utils/assert.d.ts +1 -0
- package/dist/declarations/src/vendor/react.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +255 -519
- package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +281 -575
- package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.esm.js +281 -576
- package/dist/react-resizable-panels.browser.esm.js +255 -520
- package/dist/react-resizable-panels.cjs.js +255 -519
- package/dist/react-resizable-panels.cjs.js.map +1 -0
- package/dist/react-resizable-panels.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.cjs.js +283 -577
- package/dist/react-resizable-panels.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.esm.js +283 -578
- package/dist/react-resizable-panels.development.node.cjs.js +269 -503
- package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.node.esm.js +269 -504
- package/dist/react-resizable-panels.esm.js +255 -520
- package/dist/react-resizable-panels.esm.js.map +1 -0
- package/dist/react-resizable-panels.node.cjs.js +241 -445
- package/dist/react-resizable-panels.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.node.esm.js +241 -446
- package/package.json +1 -1
- package/src/Panel.test.tsx +74 -73
- package/src/Panel.ts +44 -68
- package/src/PanelGroup.test.tsx +43 -42
- package/src/PanelGroup.ts +189 -403
- package/src/PanelGroupContext.ts +2 -3
- package/src/PanelResizeHandle.test.tsx +68 -0
- package/src/PanelResizeHandle.ts +31 -22
- package/src/hooks/useWindowSplitterBehavior.ts +2 -1
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +22 -33
- package/src/index.ts +4 -3
- package/src/types.ts +0 -9
- package/src/utils/adjustLayoutByDelta.test.ts +206 -336
- package/src/utils/adjustLayoutByDelta.ts +59 -51
- package/src/utils/assert.ts +1 -1
- package/src/utils/calculateAriaValues.test.ts +6 -11
- package/src/utils/calculateAriaValues.ts +7 -29
- package/src/utils/calculateDeltaPercentage.ts +8 -15
- package/src/utils/calculateDragOffsetPercentage.ts +11 -5
- package/src/utils/calculateUnsafeDefaultLayout.test.ts +4 -9
- package/src/utils/calculateUnsafeDefaultLayout.ts +13 -18
- package/src/utils/callPanelCallbacks.ts +11 -46
- package/src/utils/computePanelFlexBoxStyle.ts +3 -2
- package/src/utils/getResizeEventCursorPosition.ts +2 -0
- package/src/utils/resizePanel.test.ts +6 -52
- package/src/utils/resizePanel.ts +24 -46
- package/src/utils/test-utils.ts +6 -7
- package/src/utils/validatePanelConstraints.test.ts +12 -65
- package/src/utils/validatePanelConstraints.ts +26 -67
- package/src/utils/validatePanelGroupLayout.test.ts +27 -142
- package/src/utils/validatePanelGroupLayout.ts +17 -13
- package/src/vendor/react.ts +2 -0
- package/src/utils/computePercentagePanelConstraints.test.ts +0 -98
- package/src/utils/computePercentagePanelConstraints.ts +0 -56
- package/src/utils/convertPercentageToPixels.test.ts +0 -9
- package/src/utils/convertPercentageToPixels.ts +0 -6
- package/src/utils/convertPixelConstraintsToPercentages.test.ts +0 -47
- package/src/utils/convertPixelConstraintsToPercentages.ts +0 -72
- package/src/utils/convertPixelsToPercentage.test.ts +0 -9
- package/src/utils/convertPixelsToPercentage.ts +0 -6
- package/src/utils/getPercentageSizeFromMixedSizes.test.ts +0 -47
- package/src/utils/getPercentageSizeFromMixedSizes.ts +0 -15
- package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +0 -23
- package/src/utils/shouldMonitorPixelBasedConstraints.ts +0 -13
|
@@ -41,24 +41,20 @@ function useUniqueId(idFromParams = null) {
|
|
|
41
41
|
function PanelWithForwardedRef({
|
|
42
42
|
children,
|
|
43
43
|
className: classNameFromProps = "",
|
|
44
|
-
|
|
45
|
-
collapsedSizePixels,
|
|
44
|
+
collapsedSize,
|
|
46
45
|
collapsible,
|
|
47
|
-
|
|
48
|
-
defaultSizePercentage,
|
|
49
|
-
defaultSizePixels,
|
|
46
|
+
defaultSize,
|
|
50
47
|
forwardedRef,
|
|
51
48
|
id: idFromProps,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
minSizePercentage,
|
|
55
|
-
minSizePixels,
|
|
49
|
+
maxSize,
|
|
50
|
+
minSize,
|
|
56
51
|
onCollapse,
|
|
57
52
|
onExpand,
|
|
58
53
|
onResize,
|
|
59
54
|
order,
|
|
60
55
|
style: styleFromProps,
|
|
61
|
-
tagName: Type = "div"
|
|
56
|
+
tagName: Type = "div",
|
|
57
|
+
...rest
|
|
62
58
|
}) {
|
|
63
59
|
const context = useContext(PanelGroupContext);
|
|
64
60
|
if (context === null) {
|
|
@@ -83,15 +79,11 @@ function PanelWithForwardedRef({
|
|
|
83
79
|
onResize
|
|
84
80
|
},
|
|
85
81
|
constraints: {
|
|
86
|
-
|
|
87
|
-
collapsedSizePixels,
|
|
82
|
+
collapsedSize,
|
|
88
83
|
collapsible,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
maxSizePixels,
|
|
93
|
-
minSizePercentage,
|
|
94
|
-
minSizePixels
|
|
84
|
+
defaultSize,
|
|
85
|
+
maxSize,
|
|
86
|
+
minSize
|
|
95
87
|
},
|
|
96
88
|
id: panelId,
|
|
97
89
|
idIsFromProps: idFromProps !== undefined,
|
|
@@ -117,15 +109,11 @@ function PanelWithForwardedRef({
|
|
|
117
109
|
callbacks.onCollapse = onCollapse;
|
|
118
110
|
callbacks.onExpand = onExpand;
|
|
119
111
|
callbacks.onResize = onResize;
|
|
120
|
-
constraints.
|
|
121
|
-
constraints.collapsedSizePixels = collapsedSizePixels;
|
|
112
|
+
constraints.collapsedSize = collapsedSize;
|
|
122
113
|
constraints.collapsible = collapsible;
|
|
123
|
-
constraints.
|
|
124
|
-
constraints.
|
|
125
|
-
constraints.
|
|
126
|
-
constraints.maxSizePixels = maxSizePixels;
|
|
127
|
-
constraints.minSizePercentage = minSizePercentage;
|
|
128
|
-
constraints.minSizePixels = minSizePixels;
|
|
114
|
+
constraints.defaultSize = defaultSize;
|
|
115
|
+
constraints.maxSize = maxSize;
|
|
116
|
+
constraints.minSize = minSize;
|
|
129
117
|
});
|
|
130
118
|
useIsomorphicLayoutEffect(() => {
|
|
131
119
|
const panelData = panelDataRef.current;
|
|
@@ -153,19 +141,19 @@ function PanelWithForwardedRef({
|
|
|
153
141
|
isExpanded() {
|
|
154
142
|
return !isPanelCollapsed(panelDataRef.current);
|
|
155
143
|
},
|
|
156
|
-
resize:
|
|
157
|
-
resizePanel(panelDataRef.current,
|
|
144
|
+
resize: size => {
|
|
145
|
+
resizePanel(panelDataRef.current, size);
|
|
158
146
|
}
|
|
159
147
|
}), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
|
|
160
148
|
const style = getPanelStyle(panelDataRef.current);
|
|
161
149
|
return createElement(Type, {
|
|
150
|
+
...rest,
|
|
162
151
|
children,
|
|
163
152
|
className: classNameFromProps,
|
|
164
153
|
style: {
|
|
165
154
|
...style,
|
|
166
155
|
...styleFromProps
|
|
167
156
|
},
|
|
168
|
-
...dataAttributes,
|
|
169
157
|
// CSS selectors
|
|
170
158
|
"data-panel": "",
|
|
171
159
|
"data-panel-id": panelId,
|
|
@@ -182,81 +170,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
182
170
|
PanelWithForwardedRef.displayName = "Panel";
|
|
183
171
|
Panel.displayName = "forwardRef(Panel)";
|
|
184
172
|
|
|
185
|
-
function
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
|
|
190
|
-
let {
|
|
191
|
-
collapsedSizePercentage = 0,
|
|
192
|
-
collapsedSizePixels,
|
|
193
|
-
defaultSizePercentage,
|
|
194
|
-
defaultSizePixels,
|
|
195
|
-
maxSizePercentage = 100,
|
|
196
|
-
maxSizePixels,
|
|
197
|
-
minSizePercentage = 0,
|
|
198
|
-
minSizePixels
|
|
199
|
-
} = panelConstraints;
|
|
200
|
-
const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
|
|
201
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
202
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
203
|
-
return {
|
|
204
|
-
collapsedSizePercentage: 0,
|
|
205
|
-
defaultSizePercentage,
|
|
206
|
-
maxSizePercentage: 0,
|
|
207
|
-
minSizePercentage: 0
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
if (collapsedSizePixels != null) {
|
|
211
|
-
collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
|
|
212
|
-
}
|
|
213
|
-
if (defaultSizePixels != null) {
|
|
214
|
-
defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
|
|
215
|
-
}
|
|
216
|
-
if (minSizePixels != null) {
|
|
217
|
-
minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
|
|
218
|
-
}
|
|
219
|
-
if (maxSizePixels != null) {
|
|
220
|
-
maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
|
|
221
|
-
}
|
|
222
|
-
return {
|
|
223
|
-
collapsedSizePercentage,
|
|
224
|
-
defaultSizePercentage,
|
|
225
|
-
maxSizePercentage,
|
|
226
|
-
minSizePercentage
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
|
|
231
|
-
// All panel constraints, excluding the current one
|
|
232
|
-
let totalMinConstraints = 0;
|
|
233
|
-
let totalMaxConstraints = 0;
|
|
234
|
-
for (let index = 0; index < panelConstraintsArray.length; index++) {
|
|
235
|
-
if (index !== panelIndex) {
|
|
236
|
-
const {
|
|
237
|
-
collapsible
|
|
238
|
-
} = panelConstraintsArray[index];
|
|
239
|
-
const {
|
|
240
|
-
collapsedSizePercentage,
|
|
241
|
-
maxSizePercentage,
|
|
242
|
-
minSizePercentage
|
|
243
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
|
|
244
|
-
totalMaxConstraints += maxSizePercentage;
|
|
245
|
-
totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
|
|
246
|
-
}
|
|
173
|
+
function assert(expectedCondition, message = "Assertion failed!") {
|
|
174
|
+
if (!expectedCondition) {
|
|
175
|
+
console.error(message);
|
|
176
|
+
throw Error(message);
|
|
247
177
|
}
|
|
248
|
-
const {
|
|
249
|
-
collapsedSizePercentage,
|
|
250
|
-
defaultSizePercentage,
|
|
251
|
-
maxSizePercentage,
|
|
252
|
-
minSizePercentage
|
|
253
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
|
|
254
|
-
return {
|
|
255
|
-
collapsedSizePercentage,
|
|
256
|
-
defaultSizePercentage,
|
|
257
|
-
maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
|
|
258
|
-
minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
|
|
259
|
-
};
|
|
260
178
|
}
|
|
261
179
|
|
|
262
180
|
const PRECISION = 10;
|
|
@@ -278,56 +196,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
|
|
|
278
196
|
|
|
279
197
|
// Panel size must be in percentages; pixel values should be pre-converted
|
|
280
198
|
function resizePanel({
|
|
281
|
-
|
|
282
|
-
panelConstraints,
|
|
199
|
+
panelConstraints: panelConstraintsArray,
|
|
283
200
|
panelIndex,
|
|
284
201
|
size
|
|
285
202
|
}) {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
defaultSizePixels,
|
|
289
|
-
minSizePixels,
|
|
290
|
-
maxSizePixels
|
|
291
|
-
}) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
|
|
292
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
293
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
294
|
-
return 0;
|
|
295
|
-
}
|
|
203
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
204
|
+
assert(panelConstraints != null);
|
|
296
205
|
let {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
|
|
309
|
-
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
310
|
-
size = collapsedSizePercentage;
|
|
311
|
-
} else {
|
|
312
|
-
size = minSizePercentage;
|
|
313
|
-
}
|
|
206
|
+
collapsedSize = 0,
|
|
207
|
+
collapsible,
|
|
208
|
+
maxSize = 100,
|
|
209
|
+
minSize = 0
|
|
210
|
+
} = panelConstraints;
|
|
211
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
212
|
+
if (collapsible) {
|
|
213
|
+
// Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
|
|
214
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
215
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
216
|
+
size = collapsedSize;
|
|
314
217
|
} else {
|
|
315
|
-
size =
|
|
218
|
+
size = minSize;
|
|
316
219
|
}
|
|
220
|
+
} else {
|
|
221
|
+
size = minSize;
|
|
317
222
|
}
|
|
318
223
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
224
|
+
size = Math.min(maxSize, size);
|
|
225
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
322
226
|
return size;
|
|
323
227
|
}
|
|
324
228
|
|
|
325
229
|
// All units must be in percentages; pixel values should be pre-converted
|
|
326
230
|
function adjustLayoutByDelta({
|
|
327
231
|
delta,
|
|
328
|
-
groupSizePixels,
|
|
329
232
|
layout: prevLayout,
|
|
330
|
-
panelConstraints,
|
|
233
|
+
panelConstraints: panelConstraintsArray,
|
|
331
234
|
pivotIndices,
|
|
332
235
|
trigger
|
|
333
236
|
}) {
|
|
@@ -335,6 +238,9 @@ function adjustLayoutByDelta({
|
|
|
335
238
|
return prevLayout;
|
|
336
239
|
}
|
|
337
240
|
const nextLayout = [...prevLayout];
|
|
241
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
242
|
+
assert(firstPivotIndex != null);
|
|
243
|
+
assert(secondPivotIndex != null);
|
|
338
244
|
let deltaApplied = 0;
|
|
339
245
|
|
|
340
246
|
//const DEBUG = [];
|
|
@@ -358,18 +264,23 @@ function adjustLayoutByDelta({
|
|
|
358
264
|
if (trigger === "keyboard") {
|
|
359
265
|
{
|
|
360
266
|
// Check if we should expand a collapsed panel
|
|
361
|
-
const index = delta < 0 ?
|
|
362
|
-
const
|
|
267
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
268
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
269
|
+
assert(panelConstraints);
|
|
270
|
+
|
|
363
271
|
//DEBUG.push(`edge case check 1: ${index}`);
|
|
364
272
|
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
365
|
-
if (
|
|
273
|
+
if (panelConstraints.collapsible) {
|
|
366
274
|
const prevSize = prevLayout[index];
|
|
275
|
+
assert(prevSize != null);
|
|
276
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
277
|
+
assert(panelConstraints);
|
|
367
278
|
const {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
} =
|
|
371
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
372
|
-
const localDelta =
|
|
279
|
+
collapsedSize = 0,
|
|
280
|
+
minSize = 0
|
|
281
|
+
} = panelConstraints;
|
|
282
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
|
|
283
|
+
const localDelta = minSize - prevSize;
|
|
373
284
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
374
285
|
|
|
375
286
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -382,18 +293,26 @@ function adjustLayoutByDelta({
|
|
|
382
293
|
|
|
383
294
|
{
|
|
384
295
|
// Check if we should collapse a panel at its minimum size
|
|
385
|
-
const index = delta < 0 ?
|
|
386
|
-
const
|
|
296
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
297
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
298
|
+
assert(panelConstraints);
|
|
299
|
+
const {
|
|
300
|
+
collapsible
|
|
301
|
+
} = panelConstraints;
|
|
302
|
+
|
|
387
303
|
//DEBUG.push(`edge case check 2: ${index}`);
|
|
388
|
-
//DEBUG.push(` -> collapsible? ${
|
|
389
|
-
if (
|
|
304
|
+
//DEBUG.push(` -> collapsible? ${collapsible}`);
|
|
305
|
+
if (collapsible) {
|
|
390
306
|
const prevSize = prevLayout[index];
|
|
307
|
+
assert(prevSize != null);
|
|
308
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
309
|
+
assert(panelConstraints);
|
|
391
310
|
const {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
} =
|
|
395
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
396
|
-
const localDelta = prevSize -
|
|
311
|
+
collapsedSize = 0,
|
|
312
|
+
minSize = 0
|
|
313
|
+
} = panelConstraints;
|
|
314
|
+
if (fuzzyNumbersEqual(prevSize, minSize)) {
|
|
315
|
+
const localDelta = prevSize - collapsedSize;
|
|
397
316
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
398
317
|
|
|
399
318
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -415,15 +334,15 @@ function adjustLayoutByDelta({
|
|
|
415
334
|
// as an expanding panel might change from collapsed to min size.
|
|
416
335
|
|
|
417
336
|
const increment = delta < 0 ? 1 : -1;
|
|
418
|
-
let index = delta < 0 ?
|
|
337
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
419
338
|
let maxAvailableDelta = 0;
|
|
420
339
|
|
|
421
340
|
//DEBUG.push("pre calc...");
|
|
422
341
|
while (true) {
|
|
423
342
|
const prevSize = prevLayout[index];
|
|
343
|
+
assert(prevSize != null);
|
|
424
344
|
const maxSafeSize = resizePanel({
|
|
425
|
-
|
|
426
|
-
panelConstraints,
|
|
345
|
+
panelConstraints: panelConstraintsArray,
|
|
427
346
|
panelIndex: index,
|
|
428
347
|
size: 100
|
|
429
348
|
});
|
|
@@ -432,7 +351,7 @@ function adjustLayoutByDelta({
|
|
|
432
351
|
|
|
433
352
|
maxAvailableDelta += delta;
|
|
434
353
|
index += increment;
|
|
435
|
-
if (index < 0 || index >=
|
|
354
|
+
if (index < 0 || index >= panelConstraintsArray.length) {
|
|
436
355
|
break;
|
|
437
356
|
}
|
|
438
357
|
}
|
|
@@ -447,15 +366,15 @@ function adjustLayoutByDelta({
|
|
|
447
366
|
{
|
|
448
367
|
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
449
368
|
|
|
450
|
-
const pivotIndex = delta < 0 ?
|
|
369
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
451
370
|
let index = pivotIndex;
|
|
452
|
-
while (index >= 0 && index <
|
|
371
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
453
372
|
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
454
373
|
const prevSize = prevLayout[index];
|
|
374
|
+
assert(prevSize != null);
|
|
455
375
|
const unsafeSize = prevSize - deltaRemaining;
|
|
456
376
|
const safeSize = resizePanel({
|
|
457
|
-
|
|
458
|
-
panelConstraints,
|
|
377
|
+
panelConstraints: panelConstraintsArray,
|
|
459
378
|
panelIndex: index,
|
|
460
379
|
size: unsafeSize
|
|
461
380
|
});
|
|
@@ -487,11 +406,12 @@ function adjustLayoutByDelta({
|
|
|
487
406
|
}
|
|
488
407
|
{
|
|
489
408
|
// Now distribute the applied delta to the panels in the other direction
|
|
490
|
-
const pivotIndex = delta < 0 ?
|
|
491
|
-
const
|
|
409
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
410
|
+
const prevSize = prevLayout[pivotIndex];
|
|
411
|
+
assert(prevSize != null);
|
|
412
|
+
const unsafeSize = prevSize + deltaApplied;
|
|
492
413
|
const safeSize = resizePanel({
|
|
493
|
-
|
|
494
|
-
panelConstraints,
|
|
414
|
+
panelConstraints: panelConstraintsArray,
|
|
495
415
|
panelIndex: pivotIndex,
|
|
496
416
|
size: unsafeSize
|
|
497
417
|
});
|
|
@@ -502,14 +422,14 @@ function adjustLayoutByDelta({
|
|
|
502
422
|
// Edge case where expanding or contracting one panel caused another one to change collapsed state
|
|
503
423
|
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
504
424
|
let deltaRemaining = unsafeSize - safeSize;
|
|
505
|
-
const pivotIndex = delta < 0 ?
|
|
425
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
506
426
|
let index = pivotIndex;
|
|
507
|
-
while (index >= 0 && index <
|
|
427
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
508
428
|
const prevSize = nextLayout[index];
|
|
429
|
+
assert(prevSize != null);
|
|
509
430
|
const unsafeSize = prevSize + deltaRemaining;
|
|
510
431
|
const safeSize = resizePanel({
|
|
511
|
-
|
|
512
|
-
panelConstraints,
|
|
432
|
+
panelConstraints: panelConstraintsArray,
|
|
513
433
|
panelIndex: index,
|
|
514
434
|
size: unsafeSize
|
|
515
435
|
});
|
|
@@ -533,9 +453,7 @@ function adjustLayoutByDelta({
|
|
|
533
453
|
//DEBUG.push("");
|
|
534
454
|
|
|
535
455
|
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
536
|
-
deltaApplied = 100 - totalSize;
|
|
537
456
|
//DEBUG.push(`total size: ${totalSize}`);
|
|
538
|
-
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
539
457
|
//console.log(DEBUG.join("\n"));
|
|
540
458
|
|
|
541
459
|
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
@@ -544,27 +462,7 @@ function adjustLayoutByDelta({
|
|
|
544
462
|
return nextLayout;
|
|
545
463
|
}
|
|
546
464
|
|
|
547
|
-
function assert(expectedCondition, message = "Assertion failed!") {
|
|
548
|
-
if (!expectedCondition) {
|
|
549
|
-
console.error(message);
|
|
550
|
-
throw Error(message);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
function getPercentageSizeFromMixedSizes({
|
|
555
|
-
sizePercentage,
|
|
556
|
-
sizePixels
|
|
557
|
-
}, groupSizePixels) {
|
|
558
|
-
if (sizePercentage != null) {
|
|
559
|
-
return sizePercentage;
|
|
560
|
-
} else if (sizePixels != null) {
|
|
561
|
-
return convertPixelsToPercentage(sizePixels, groupSizePixels);
|
|
562
|
-
}
|
|
563
|
-
return undefined;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
465
|
function calculateAriaValues({
|
|
567
|
-
groupSizePixels,
|
|
568
466
|
layout,
|
|
569
467
|
panelsArray,
|
|
570
468
|
pivotIndices
|
|
@@ -573,28 +471,19 @@ function calculateAriaValues({
|
|
|
573
471
|
let currentMaxSize = 100;
|
|
574
472
|
let totalMinSize = 0;
|
|
575
473
|
let totalMaxSize = 0;
|
|
474
|
+
const firstIndex = pivotIndices[0];
|
|
475
|
+
assert(firstIndex != null);
|
|
576
476
|
|
|
577
477
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
578
478
|
panelsArray.forEach((panelData, index) => {
|
|
579
|
-
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
580
479
|
const {
|
|
581
480
|
constraints
|
|
582
481
|
} = panelData;
|
|
583
482
|
const {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
minSizePercentage,
|
|
587
|
-
minSizePixels
|
|
483
|
+
maxSize = 100,
|
|
484
|
+
minSize = 0
|
|
588
485
|
} = constraints;
|
|
589
|
-
|
|
590
|
-
sizePercentage: minSizePercentage,
|
|
591
|
-
sizePixels: minSizePixels
|
|
592
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
593
|
-
const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
594
|
-
sizePercentage: maxSizePercentage,
|
|
595
|
-
sizePixels: maxSizePixels
|
|
596
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
|
|
597
|
-
if (index === pivotIndices[0]) {
|
|
486
|
+
if (index === firstIndex) {
|
|
598
487
|
currentMinSize = minSize;
|
|
599
488
|
currentMaxSize = maxSize;
|
|
600
489
|
} else {
|
|
@@ -604,7 +493,7 @@ function calculateAriaValues({
|
|
|
604
493
|
});
|
|
605
494
|
const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
606
495
|
const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
|
|
607
|
-
const valueNow = layout[
|
|
496
|
+
const valueNow = layout[firstIndex];
|
|
608
497
|
return {
|
|
609
498
|
valueMax,
|
|
610
499
|
valueMin,
|
|
@@ -635,42 +524,6 @@ function getPanelGroupElement(id) {
|
|
|
635
524
|
return null;
|
|
636
525
|
}
|
|
637
526
|
|
|
638
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
639
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
640
|
-
if (panelGroupElement == null) {
|
|
641
|
-
return NaN;
|
|
642
|
-
}
|
|
643
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
644
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
645
|
-
if (direction === "horizontal") {
|
|
646
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
647
|
-
return accumulated + handle.offsetWidth;
|
|
648
|
-
}, 0);
|
|
649
|
-
} else {
|
|
650
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
651
|
-
return accumulated + handle.offsetHeight;
|
|
652
|
-
}, 0);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
657
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
658
|
-
if (panelGroupElement == null) {
|
|
659
|
-
return NaN;
|
|
660
|
-
}
|
|
661
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
662
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
663
|
-
if (direction === "horizontal") {
|
|
664
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
665
|
-
return accumulated + handle.offsetWidth;
|
|
666
|
-
}, 0);
|
|
667
|
-
} else {
|
|
668
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
669
|
-
return accumulated + handle.offsetHeight;
|
|
670
|
-
}, 0);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
527
|
function getResizeHandleElement(id) {
|
|
675
528
|
const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
676
529
|
if (element) {
|
|
@@ -703,7 +556,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
703
556
|
didWarnAboutMissingResizeHandle: false
|
|
704
557
|
});
|
|
705
558
|
useIsomorphicLayoutEffect(() => {
|
|
706
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
707
559
|
const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
|
|
708
560
|
for (let index = 0; index < panelDataArray.length - 1; index++) {
|
|
709
561
|
const {
|
|
@@ -711,7 +563,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
711
563
|
valueMin,
|
|
712
564
|
valueNow
|
|
713
565
|
} = calculateAriaValues({
|
|
714
|
-
groupSizePixels,
|
|
715
566
|
layout,
|
|
716
567
|
panelsArray: panelDataArray,
|
|
717
568
|
pivotIndices: [index, index + 1]
|
|
@@ -728,10 +579,12 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
728
579
|
}
|
|
729
580
|
}
|
|
730
581
|
} else {
|
|
731
|
-
|
|
582
|
+
const panelData = panelDataArray[index];
|
|
583
|
+
assert(panelData);
|
|
584
|
+
resizeHandleElement.setAttribute("aria-controls", panelData.id);
|
|
732
585
|
resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
|
|
733
586
|
resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
|
|
734
|
-
resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
|
|
587
|
+
resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
|
|
735
588
|
}
|
|
736
589
|
}
|
|
737
590
|
return () => {
|
|
@@ -744,14 +597,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
744
597
|
};
|
|
745
598
|
}, [groupId, layout, panelDataArray]);
|
|
746
599
|
useEffect(() => {
|
|
600
|
+
const eagerValues = eagerValuesRef.current;
|
|
601
|
+
assert(eagerValues);
|
|
747
602
|
const {
|
|
748
603
|
panelDataArray
|
|
749
|
-
} =
|
|
604
|
+
} = eagerValues;
|
|
750
605
|
const groupElement = getPanelGroupElement(groupId);
|
|
751
606
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
752
607
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
608
|
+
assert(handles);
|
|
753
609
|
const cleanupFunctions = handles.map(handle => {
|
|
754
610
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
611
|
+
assert(handleId);
|
|
755
612
|
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
756
613
|
if (idBefore == null || idAfter == null) {
|
|
757
614
|
return () => {};
|
|
@@ -767,21 +624,16 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
767
624
|
const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
|
|
768
625
|
if (index >= 0) {
|
|
769
626
|
const panelData = panelDataArray[index];
|
|
627
|
+
assert(panelData);
|
|
770
628
|
const size = layout[index];
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
778
|
-
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
779
|
-
sizePercentage: panelData.constraints.minSizePercentage,
|
|
780
|
-
sizePixels: panelData.constraints.minSizePixels
|
|
781
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
629
|
+
const {
|
|
630
|
+
collapsedSize = 0,
|
|
631
|
+
collapsible,
|
|
632
|
+
minSize = 0
|
|
633
|
+
} = panelData.constraints;
|
|
634
|
+
if (size != null && collapsible) {
|
|
782
635
|
const nextLayout = adjustLayoutByDelta({
|
|
783
636
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
784
|
-
groupSizePixels,
|
|
785
637
|
layout,
|
|
786
638
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
787
639
|
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
@@ -835,6 +687,7 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
835
687
|
return isHorizontal ? event.clientX : event.clientY;
|
|
836
688
|
} else if (isTouchEvent(event)) {
|
|
837
689
|
const firstTouch = event.touches[0];
|
|
690
|
+
assert(firstTouch);
|
|
838
691
|
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
839
692
|
} else {
|
|
840
693
|
throw Error(`Unsupported event type "${event.type}"`);
|
|
@@ -844,12 +697,15 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
844
697
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
845
698
|
const isHorizontal = direction === "horizontal";
|
|
846
699
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
700
|
+
assert(handleElement);
|
|
847
701
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
702
|
+
assert(groupId);
|
|
848
703
|
let {
|
|
849
704
|
initialCursorPosition
|
|
850
705
|
} = initialDragState;
|
|
851
706
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
852
707
|
const groupElement = getPanelGroupElement(groupId);
|
|
708
|
+
assert(groupElement);
|
|
853
709
|
const groupRect = groupElement.getBoundingClientRect();
|
|
854
710
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
855
711
|
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
@@ -858,19 +714,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
858
714
|
}
|
|
859
715
|
|
|
860
716
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
861
|
-
function calculateDeltaPercentage(event,
|
|
717
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
862
718
|
if (isKeyDown(event)) {
|
|
863
719
|
const isHorizontal = direction === "horizontal";
|
|
864
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
865
|
-
const rect = groupElement.getBoundingClientRect();
|
|
866
|
-
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
867
720
|
let delta = 0;
|
|
868
721
|
if (event.shiftKey) {
|
|
869
722
|
delta = 100;
|
|
870
|
-
} else if (
|
|
871
|
-
delta =
|
|
872
|
-
} else if (keyboardResizeByOptions.pixels != null) {
|
|
873
|
-
delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
|
|
723
|
+
} else if (keyboardResizeBy != null) {
|
|
724
|
+
delta = keyboardResizeBy;
|
|
874
725
|
} else {
|
|
875
726
|
delta = 10;
|
|
876
727
|
}
|
|
@@ -897,37 +748,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
897
748
|
}
|
|
898
749
|
return movement;
|
|
899
750
|
} else {
|
|
751
|
+
if (initialDragState == null) {
|
|
752
|
+
return 0;
|
|
753
|
+
}
|
|
900
754
|
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
901
755
|
}
|
|
902
756
|
}
|
|
903
757
|
|
|
904
758
|
function calculateUnsafeDefaultLayout({
|
|
905
|
-
groupSizePixels,
|
|
906
759
|
panelDataArray
|
|
907
760
|
}) {
|
|
908
761
|
const layout = Array(panelDataArray.length);
|
|
909
|
-
const
|
|
762
|
+
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
910
763
|
let numPanelsWithSizes = 0;
|
|
911
764
|
let remainingSize = 100;
|
|
912
765
|
|
|
913
766
|
// Distribute default sizes first
|
|
914
767
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
768
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
769
|
+
assert(panelConstraints);
|
|
915
770
|
const {
|
|
916
|
-
|
|
917
|
-
} =
|
|
918
|
-
if (
|
|
771
|
+
defaultSize
|
|
772
|
+
} = panelConstraints;
|
|
773
|
+
if (defaultSize != null) {
|
|
919
774
|
numPanelsWithSizes++;
|
|
920
|
-
layout[index] =
|
|
921
|
-
remainingSize -=
|
|
775
|
+
layout[index] = defaultSize;
|
|
776
|
+
remainingSize -= defaultSize;
|
|
922
777
|
}
|
|
923
778
|
}
|
|
924
779
|
|
|
925
780
|
// Remaining size should be distributed evenly between panels without default sizes
|
|
926
781
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
782
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
783
|
+
assert(panelConstraints);
|
|
927
784
|
const {
|
|
928
|
-
|
|
929
|
-
} =
|
|
930
|
-
if (
|
|
785
|
+
defaultSize
|
|
786
|
+
} = panelConstraints;
|
|
787
|
+
if (defaultSize != null) {
|
|
931
788
|
continue;
|
|
932
789
|
}
|
|
933
790
|
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
@@ -939,54 +796,36 @@ function calculateUnsafeDefaultLayout({
|
|
|
939
796
|
return layout;
|
|
940
797
|
}
|
|
941
798
|
|
|
942
|
-
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
943
|
-
return percentage / 100 * groupSizePixels;
|
|
944
|
-
}
|
|
945
|
-
|
|
946
799
|
// Layout should be pre-converted into percentages
|
|
947
|
-
function callPanelCallbacks(
|
|
948
|
-
|
|
949
|
-
layout.forEach((sizePercentage, index) => {
|
|
800
|
+
function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
|
|
801
|
+
layout.forEach((size, index) => {
|
|
950
802
|
const panelData = panelsArray[index];
|
|
951
|
-
|
|
952
|
-
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
953
|
-
// The subsequent render+effects will handle the resize notification
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
803
|
+
assert(panelData);
|
|
956
804
|
const {
|
|
957
805
|
callbacks,
|
|
958
806
|
constraints,
|
|
959
807
|
id: panelId
|
|
960
808
|
} = panelData;
|
|
961
809
|
const {
|
|
810
|
+
collapsedSize = 0,
|
|
962
811
|
collapsible
|
|
963
812
|
} = constraints;
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
};
|
|
968
|
-
const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
|
|
969
|
-
if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
|
|
970
|
-
panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
|
|
813
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
|
|
814
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
815
|
+
panelIdToLastNotifiedSizeMap[panelId] = size;
|
|
971
816
|
const {
|
|
972
817
|
onCollapse,
|
|
973
818
|
onExpand,
|
|
974
819
|
onResize
|
|
975
820
|
} = callbacks;
|
|
976
821
|
if (onResize) {
|
|
977
|
-
onResize(
|
|
822
|
+
onResize(size, lastNotifiedSize);
|
|
978
823
|
}
|
|
979
824
|
if (collapsible && (onCollapse || onExpand)) {
|
|
980
|
-
|
|
981
|
-
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
982
|
-
sizePercentage: constraints.collapsedSizePercentage,
|
|
983
|
-
sizePixels: constraints.collapsedSizePixels
|
|
984
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
985
|
-
const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
|
|
986
|
-
if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
|
|
825
|
+
if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
987
826
|
onExpand();
|
|
988
827
|
}
|
|
989
|
-
if (onCollapse && (
|
|
828
|
+
if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
|
|
990
829
|
onCollapse();
|
|
991
830
|
}
|
|
992
831
|
}
|
|
@@ -1020,9 +859,10 @@ function computePanelFlexBoxStyle({
|
|
|
1020
859
|
const size = layout[panelIndex];
|
|
1021
860
|
let flexGrow;
|
|
1022
861
|
if (panelData.length === 1) {
|
|
1023
|
-
flexGrow = "
|
|
862
|
+
flexGrow = "1";
|
|
1024
863
|
} else if (size == null) {
|
|
1025
|
-
|
|
864
|
+
// Initial render (before panels have registered themselves)
|
|
865
|
+
flexGrow = "1";
|
|
1026
866
|
} else {
|
|
1027
867
|
flexGrow = size.toPrecision(precision);
|
|
1028
868
|
}
|
|
@@ -1168,74 +1008,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1168
1008
|
}
|
|
1169
1009
|
}
|
|
1170
1010
|
|
|
1171
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1172
|
-
return constraints.some(constraints => {
|
|
1173
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1174
|
-
});
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
1011
|
function validatePanelConstraints({
|
|
1178
|
-
|
|
1179
|
-
panelConstraints,
|
|
1012
|
+
panelConstraints: panelConstraintsArray,
|
|
1180
1013
|
panelId,
|
|
1181
1014
|
panelIndex
|
|
1182
1015
|
}) {
|
|
1183
1016
|
{
|
|
1184
1017
|
const warnings = [];
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
} = panelConstraints[panelIndex];
|
|
1196
|
-
const conflictingUnits = [];
|
|
1197
|
-
if (collapsedSizePercentage != null && collapsedSizePixels != null) {
|
|
1198
|
-
conflictingUnits.push("collapsed size");
|
|
1199
|
-
}
|
|
1200
|
-
if (defaultSizePercentage != null && defaultSizePixels != null) {
|
|
1201
|
-
conflictingUnits.push("default size");
|
|
1202
|
-
}
|
|
1203
|
-
if (maxSizePercentage != null && maxSizePixels != null) {
|
|
1204
|
-
conflictingUnits.push("max size");
|
|
1205
|
-
}
|
|
1206
|
-
if (minSizePercentage != null && minSizePixels != null) {
|
|
1207
|
-
conflictingUnits.push("min size");
|
|
1208
|
-
}
|
|
1209
|
-
if (conflictingUnits.length > 0) {
|
|
1210
|
-
warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
|
|
1211
|
-
}
|
|
1018
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1019
|
+
assert(panelConstraints);
|
|
1020
|
+
const {
|
|
1021
|
+
collapsedSize = 0,
|
|
1022
|
+
defaultSize,
|
|
1023
|
+
maxSize = 100,
|
|
1024
|
+
minSize = 0
|
|
1025
|
+
} = panelConstraints;
|
|
1026
|
+
if (minSize > maxSize) {
|
|
1027
|
+
warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
|
|
1212
1028
|
}
|
|
1213
|
-
{
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
minSizePercentage
|
|
1219
|
-
} = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
|
|
1220
|
-
if (minSizePercentage > maxSizePercentage) {
|
|
1221
|
-
warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
|
|
1222
|
-
}
|
|
1223
|
-
if (defaultSizePercentage != null) {
|
|
1224
|
-
if (defaultSizePercentage < 0) {
|
|
1225
|
-
warnings.push("default size should not be less than 0");
|
|
1226
|
-
} else if (defaultSizePercentage < minSizePercentage) {
|
|
1227
|
-
warnings.push("default size should not be less than min size");
|
|
1228
|
-
}
|
|
1229
|
-
if (defaultSizePercentage > 100) {
|
|
1230
|
-
warnings.push("default size should not be greater than 100");
|
|
1231
|
-
} else if (defaultSizePercentage > maxSizePercentage) {
|
|
1232
|
-
warnings.push("default size should not be greater than max size");
|
|
1233
|
-
}
|
|
1029
|
+
if (defaultSize != null) {
|
|
1030
|
+
if (defaultSize < 0) {
|
|
1031
|
+
warnings.push("default size should not be less than 0");
|
|
1032
|
+
} else if (defaultSize < minSize) {
|
|
1033
|
+
warnings.push("default size should not be less than min size");
|
|
1234
1034
|
}
|
|
1235
|
-
if (
|
|
1236
|
-
warnings.push("
|
|
1035
|
+
if (defaultSize > 100) {
|
|
1036
|
+
warnings.push("default size should not be greater than 100");
|
|
1037
|
+
} else if (defaultSize > maxSize) {
|
|
1038
|
+
warnings.push("default size should not be greater than max size");
|
|
1237
1039
|
}
|
|
1238
1040
|
}
|
|
1041
|
+
if (collapsedSize > minSize) {
|
|
1042
|
+
warnings.push("collapsed size should not be greater than min size");
|
|
1043
|
+
}
|
|
1239
1044
|
if (warnings.length > 0) {
|
|
1240
1045
|
const name = panelId != null ? `Panel "${panelId}"` : "Panel";
|
|
1241
1046
|
console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
|
|
@@ -1247,20 +1052,26 @@ function validatePanelConstraints({
|
|
|
1247
1052
|
|
|
1248
1053
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1249
1054
|
function validatePanelGroupLayout({
|
|
1250
|
-
groupSizePixels,
|
|
1251
1055
|
layout: prevLayout,
|
|
1252
1056
|
panelConstraints
|
|
1253
1057
|
}) {
|
|
1254
1058
|
const nextLayout = [...prevLayout];
|
|
1059
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1255
1060
|
|
|
1256
1061
|
// Validate layout expectations
|
|
1257
1062
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1258
1063
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1259
|
-
} else if (!fuzzyNumbersEqual(
|
|
1064
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1260
1065
|
// This is not ideal so we should warn about it, but it may be recoverable in some cases
|
|
1261
1066
|
// (especially if the amount is small)
|
|
1262
1067
|
{
|
|
1263
|
-
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}
|
|
1068
|
+
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
|
|
1069
|
+
}
|
|
1070
|
+
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1071
|
+
const unsafeSize = nextLayout[index];
|
|
1072
|
+
assert(unsafeSize != null);
|
|
1073
|
+
const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
|
|
1074
|
+
nextLayout[index] = safeSize;
|
|
1264
1075
|
}
|
|
1265
1076
|
}
|
|
1266
1077
|
let remainingSize = 0;
|
|
@@ -1268,8 +1079,8 @@ function validatePanelGroupLayout({
|
|
|
1268
1079
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1269
1080
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1270
1081
|
const unsafeSize = nextLayout[index];
|
|
1082
|
+
assert(unsafeSize != null);
|
|
1271
1083
|
const safeSize = resizePanel({
|
|
1272
|
-
groupSizePixels,
|
|
1273
1084
|
panelConstraints,
|
|
1274
1085
|
panelIndex: index,
|
|
1275
1086
|
size: unsafeSize
|
|
@@ -1285,9 +1096,9 @@ function validatePanelGroupLayout({
|
|
|
1285
1096
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1286
1097
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1287
1098
|
const prevSize = nextLayout[index];
|
|
1099
|
+
assert(prevSize != null);
|
|
1288
1100
|
const unsafeSize = prevSize + remainingSize;
|
|
1289
1101
|
const safeSize = resizePanel({
|
|
1290
|
-
groupSizePixels,
|
|
1291
1102
|
panelConstraints,
|
|
1292
1103
|
panelIndex: index,
|
|
1293
1104
|
size: unsafeSize
|
|
@@ -1322,21 +1133,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1322
1133
|
autoSaveId = null,
|
|
1323
1134
|
children,
|
|
1324
1135
|
className: classNameFromProps = "",
|
|
1325
|
-
dataAttributes,
|
|
1326
1136
|
direction,
|
|
1327
1137
|
forwardedRef,
|
|
1328
|
-
id: idFromProps,
|
|
1138
|
+
id: idFromProps = null,
|
|
1329
1139
|
onLayout = null,
|
|
1330
|
-
|
|
1331
|
-
keyboardResizeByPixels = null,
|
|
1140
|
+
keyboardResizeBy = null,
|
|
1332
1141
|
storage = defaultStorage,
|
|
1333
1142
|
style: styleFromProps,
|
|
1334
|
-
tagName: Type = "div"
|
|
1143
|
+
tagName: Type = "div",
|
|
1144
|
+
...rest
|
|
1335
1145
|
}) {
|
|
1336
1146
|
const groupId = useUniqueId(idFromProps);
|
|
1337
1147
|
const [dragState, setDragState] = useState(null);
|
|
1338
1148
|
const [layout, setLayout] = useState([]);
|
|
1339
|
-
const
|
|
1149
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1340
1150
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1341
1151
|
const prevDeltaRef = useRef(0);
|
|
1342
1152
|
const committedValuesRef = useRef({
|
|
@@ -1344,8 +1154,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1344
1154
|
direction,
|
|
1345
1155
|
dragState,
|
|
1346
1156
|
id: groupId,
|
|
1347
|
-
|
|
1348
|
-
keyboardResizeByPixels,
|
|
1157
|
+
keyboardResizeBy,
|
|
1349
1158
|
onLayout,
|
|
1350
1159
|
storage
|
|
1351
1160
|
});
|
|
@@ -1361,33 +1170,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1361
1170
|
useImperativeHandle(forwardedRef, () => ({
|
|
1362
1171
|
getId: () => committedValuesRef.current.id,
|
|
1363
1172
|
getLayout: () => {
|
|
1364
|
-
const {
|
|
1365
|
-
id: groupId
|
|
1366
|
-
} = committedValuesRef.current;
|
|
1367
1173
|
const {
|
|
1368
1174
|
layout
|
|
1369
1175
|
} = eagerValuesRef.current;
|
|
1370
|
-
|
|
1371
|
-
return layout.map(sizePercentage => {
|
|
1372
|
-
return {
|
|
1373
|
-
sizePercentage,
|
|
1374
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1375
|
-
};
|
|
1376
|
-
});
|
|
1176
|
+
return layout;
|
|
1377
1177
|
},
|
|
1378
|
-
setLayout:
|
|
1178
|
+
setLayout: unsafeLayout => {
|
|
1379
1179
|
const {
|
|
1380
|
-
id: groupId,
|
|
1381
1180
|
onLayout
|
|
1382
1181
|
} = committedValuesRef.current;
|
|
1383
1182
|
const {
|
|
1384
1183
|
layout: prevLayout,
|
|
1385
1184
|
panelDataArray
|
|
1386
1185
|
} = eagerValuesRef.current;
|
|
1387
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1388
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1389
1186
|
const safeLayout = validatePanelGroupLayout({
|
|
1390
|
-
groupSizePixels,
|
|
1391
1187
|
layout: unsafeLayout,
|
|
1392
1188
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1393
1189
|
});
|
|
@@ -1395,12 +1191,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1395
1191
|
setLayout(safeLayout);
|
|
1396
1192
|
eagerValuesRef.current.layout = safeLayout;
|
|
1397
1193
|
if (onLayout) {
|
|
1398
|
-
onLayout(safeLayout
|
|
1399
|
-
sizePercentage,
|
|
1400
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1401
|
-
})));
|
|
1194
|
+
onLayout(safeLayout);
|
|
1402
1195
|
}
|
|
1403
|
-
callPanelCallbacks(
|
|
1196
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1404
1197
|
}
|
|
1405
1198
|
}
|
|
1406
1199
|
}), []);
|
|
@@ -1411,11 +1204,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1411
1204
|
committedValuesRef.current.id = groupId;
|
|
1412
1205
|
committedValuesRef.current.onLayout = onLayout;
|
|
1413
1206
|
committedValuesRef.current.storage = storage;
|
|
1414
|
-
|
|
1415
|
-
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1416
|
-
// TODO [217] Move these values into a separate ref
|
|
1417
1207
|
});
|
|
1418
|
-
|
|
1419
1208
|
useWindowSplitterPanelGroupBehavior({
|
|
1420
1209
|
committedValuesRef,
|
|
1421
1210
|
eagerValuesRef,
|
|
@@ -1434,57 +1223,16 @@ function PanelGroupWithForwardedRef({
|
|
|
1434
1223
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1435
1224
|
return;
|
|
1436
1225
|
}
|
|
1226
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1437
1227
|
|
|
1438
1228
|
// Limit the frequency of localStorage updates.
|
|
1439
|
-
if (
|
|
1440
|
-
|
|
1229
|
+
if (debouncedSave == null) {
|
|
1230
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1231
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1441
1232
|
}
|
|
1442
|
-
|
|
1233
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1443
1234
|
}
|
|
1444
1235
|
}, [autoSaveId, layout, storage]);
|
|
1445
|
-
useIsomorphicLayoutEffect(() => {
|
|
1446
|
-
const {
|
|
1447
|
-
layout: prevLayout,
|
|
1448
|
-
panelDataArray
|
|
1449
|
-
} = eagerValuesRef.current;
|
|
1450
|
-
const constraints = panelDataArray.map(({
|
|
1451
|
-
constraints
|
|
1452
|
-
}) => constraints);
|
|
1453
|
-
if (!shouldMonitorPixelBasedConstraints(constraints)) {
|
|
1454
|
-
// Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
|
|
1455
|
-
return;
|
|
1456
|
-
}
|
|
1457
|
-
if (typeof ResizeObserver === "undefined") {
|
|
1458
|
-
console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
|
|
1459
|
-
} else {
|
|
1460
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
1461
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1462
|
-
const {
|
|
1463
|
-
onLayout
|
|
1464
|
-
} = committedValuesRef.current;
|
|
1465
|
-
const nextLayout = validatePanelGroupLayout({
|
|
1466
|
-
groupSizePixels,
|
|
1467
|
-
layout: prevLayout,
|
|
1468
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1469
|
-
});
|
|
1470
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
1471
|
-
setLayout(nextLayout);
|
|
1472
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
1473
|
-
if (onLayout) {
|
|
1474
|
-
onLayout(nextLayout.map(sizePercentage => ({
|
|
1475
|
-
sizePercentage,
|
|
1476
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1477
|
-
})));
|
|
1478
|
-
}
|
|
1479
|
-
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1480
|
-
}
|
|
1481
|
-
});
|
|
1482
|
-
resizeObserver.observe(getPanelGroupElement(groupId));
|
|
1483
|
-
return () => {
|
|
1484
|
-
resizeObserver.disconnect();
|
|
1485
|
-
};
|
|
1486
|
-
}
|
|
1487
|
-
}, [groupId]);
|
|
1488
1236
|
|
|
1489
1237
|
// DEV warnings
|
|
1490
1238
|
useEffect(() => {
|
|
@@ -1515,12 +1263,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1515
1263
|
}
|
|
1516
1264
|
if (!didLogPanelConstraintsWarning) {
|
|
1517
1265
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1518
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1519
1266
|
for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
|
|
1267
|
+
const panelData = panelDataArray[panelIndex];
|
|
1268
|
+
assert(panelData);
|
|
1520
1269
|
const isValid = validatePanelConstraints({
|
|
1521
|
-
groupSizePixels,
|
|
1522
1270
|
panelConstraints,
|
|
1523
|
-
panelId:
|
|
1271
|
+
panelId: panelData.id,
|
|
1524
1272
|
panelIndex
|
|
1525
1273
|
});
|
|
1526
1274
|
if (!isValid) {
|
|
@@ -1544,20 +1292,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1544
1292
|
if (panelData.constraints.collapsible) {
|
|
1545
1293
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1546
1294
|
const {
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
pivotIndices
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
if (
|
|
1295
|
+
collapsedSize = 0,
|
|
1296
|
+
panelSize,
|
|
1297
|
+
pivotIndices
|
|
1298
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1299
|
+
assert(panelSize != null);
|
|
1300
|
+
if (panelSize !== collapsedSize) {
|
|
1553
1301
|
// Store size before collapse;
|
|
1554
1302
|
// This is the size that gets restored if the expand() API is used.
|
|
1555
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1303
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1556
1304
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1557
|
-
const delta = isLastPanel ?
|
|
1305
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1558
1306
|
const nextLayout = adjustLayoutByDelta({
|
|
1559
1307
|
delta,
|
|
1560
|
-
groupSizePixels,
|
|
1561
1308
|
layout: prevLayout,
|
|
1562
1309
|
panelConstraints: panelConstraintsArray,
|
|
1563
1310
|
pivotIndices,
|
|
@@ -1567,16 +1314,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1567
1314
|
setLayout(nextLayout);
|
|
1568
1315
|
eagerValuesRef.current.layout = nextLayout;
|
|
1569
1316
|
if (onLayout) {
|
|
1570
|
-
onLayout(nextLayout
|
|
1571
|
-
sizePercentage,
|
|
1572
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1573
|
-
})));
|
|
1317
|
+
onLayout(nextLayout);
|
|
1574
1318
|
}
|
|
1575
|
-
callPanelCallbacks(
|
|
1319
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1576
1320
|
}
|
|
1577
1321
|
}
|
|
1578
1322
|
}
|
|
1579
|
-
}, [
|
|
1323
|
+
}, []);
|
|
1580
1324
|
|
|
1581
1325
|
// External APIs are safe to memoize via committed values ref
|
|
1582
1326
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1590,21 +1334,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1590
1334
|
if (panelData.constraints.collapsible) {
|
|
1591
1335
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1592
1336
|
const {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
pivotIndices
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1337
|
+
collapsedSize = 0,
|
|
1338
|
+
panelSize,
|
|
1339
|
+
minSize = 0,
|
|
1340
|
+
pivotIndices
|
|
1341
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1342
|
+
if (panelSize === collapsedSize) {
|
|
1600
1343
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1601
|
-
const
|
|
1602
|
-
const
|
|
1344
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1345
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1603
1346
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1604
|
-
const delta = isLastPanel ?
|
|
1347
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1605
1348
|
const nextLayout = adjustLayoutByDelta({
|
|
1606
1349
|
delta,
|
|
1607
|
-
groupSizePixels,
|
|
1608
1350
|
layout: prevLayout,
|
|
1609
1351
|
panelConstraints: panelConstraintsArray,
|
|
1610
1352
|
pivotIndices,
|
|
@@ -1614,16 +1356,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1614
1356
|
setLayout(nextLayout);
|
|
1615
1357
|
eagerValuesRef.current.layout = nextLayout;
|
|
1616
1358
|
if (onLayout) {
|
|
1617
|
-
onLayout(nextLayout
|
|
1618
|
-
sizePercentage,
|
|
1619
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1620
|
-
})));
|
|
1359
|
+
onLayout(nextLayout);
|
|
1621
1360
|
}
|
|
1622
|
-
callPanelCallbacks(
|
|
1361
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1623
1362
|
}
|
|
1624
1363
|
}
|
|
1625
1364
|
}
|
|
1626
|
-
}, [
|
|
1365
|
+
}, []);
|
|
1627
1366
|
|
|
1628
1367
|
// External APIs are safe to memoize via committed values ref
|
|
1629
1368
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1632,14 +1371,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1632
1371
|
panelDataArray
|
|
1633
1372
|
} = eagerValuesRef.current;
|
|
1634
1373
|
const {
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
return
|
|
1639
|
-
|
|
1640
|
-
sizePixels: panelSizePixels
|
|
1641
|
-
};
|
|
1642
|
-
}, [groupId]);
|
|
1374
|
+
panelSize
|
|
1375
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1376
|
+
assert(panelSize != null);
|
|
1377
|
+
return panelSize;
|
|
1378
|
+
}, []);
|
|
1643
1379
|
|
|
1644
1380
|
// This API should never read from committedValuesRef
|
|
1645
1381
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1662,12 +1398,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1662
1398
|
panelDataArray
|
|
1663
1399
|
} = eagerValuesRef.current;
|
|
1664
1400
|
const {
|
|
1665
|
-
|
|
1401
|
+
collapsedSize,
|
|
1666
1402
|
collapsible,
|
|
1667
|
-
|
|
1668
|
-
} = panelDataHelper(
|
|
1669
|
-
return collapsible === true &&
|
|
1670
|
-
}, [
|
|
1403
|
+
panelSize
|
|
1404
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1405
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1406
|
+
}, []);
|
|
1671
1407
|
|
|
1672
1408
|
// External APIs are safe to memoize via committed values ref
|
|
1673
1409
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1676,12 +1412,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1676
1412
|
panelDataArray
|
|
1677
1413
|
} = eagerValuesRef.current;
|
|
1678
1414
|
const {
|
|
1679
|
-
|
|
1415
|
+
collapsedSize = 0,
|
|
1680
1416
|
collapsible,
|
|
1681
|
-
|
|
1682
|
-
} = panelDataHelper(
|
|
1683
|
-
|
|
1684
|
-
|
|
1417
|
+
panelSize
|
|
1418
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1419
|
+
assert(panelSize != null);
|
|
1420
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1421
|
+
}, []);
|
|
1685
1422
|
const registerPanel = useCallback(panelData => {
|
|
1686
1423
|
const {
|
|
1687
1424
|
autoSaveId,
|
|
@@ -1721,18 +1458,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1721
1458
|
if (autoSaveId) {
|
|
1722
1459
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1723
1460
|
}
|
|
1724
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1725
|
-
if (groupSizePixels <= 0) {
|
|
1726
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1727
|
-
constraints
|
|
1728
|
-
}) => constraints))) {
|
|
1729
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1730
|
-
return;
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
1461
|
if (unsafeLayout == null) {
|
|
1734
1462
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1735
|
-
groupSizePixels,
|
|
1736
1463
|
panelDataArray
|
|
1737
1464
|
});
|
|
1738
1465
|
}
|
|
@@ -1740,7 +1467,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1740
1467
|
// Validate even saved layouts in case something has changed since last render
|
|
1741
1468
|
// e.g. for pixel groups, this could be the size of the window
|
|
1742
1469
|
const nextLayout = validatePanelGroupLayout({
|
|
1743
|
-
groupSizePixels,
|
|
1744
1470
|
layout: unsafeLayout,
|
|
1745
1471
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1746
1472
|
});
|
|
@@ -1752,12 +1478,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1752
1478
|
eagerValuesRef.current.layout = nextLayout;
|
|
1753
1479
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1754
1480
|
if (onLayout) {
|
|
1755
|
-
onLayout(nextLayout
|
|
1756
|
-
sizePercentage,
|
|
1757
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1758
|
-
})));
|
|
1481
|
+
onLayout(nextLayout);
|
|
1759
1482
|
}
|
|
1760
|
-
callPanelCallbacks(
|
|
1483
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1761
1484
|
}
|
|
1762
1485
|
}, []);
|
|
1763
1486
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1767,8 +1490,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1767
1490
|
direction,
|
|
1768
1491
|
dragState,
|
|
1769
1492
|
id: groupId,
|
|
1770
|
-
|
|
1771
|
-
keyboardResizeByPixels,
|
|
1493
|
+
keyboardResizeBy,
|
|
1772
1494
|
onLayout
|
|
1773
1495
|
} = committedValuesRef.current;
|
|
1774
1496
|
const {
|
|
@@ -1779,10 +1501,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1779
1501
|
initialLayout
|
|
1780
1502
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1781
1503
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1782
|
-
let delta = calculateDeltaPercentage(event,
|
|
1783
|
-
percentage: keyboardResizeByPercentage,
|
|
1784
|
-
pixels: keyboardResizeByPixels
|
|
1785
|
-
});
|
|
1504
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1786
1505
|
if (delta === 0) {
|
|
1787
1506
|
return;
|
|
1788
1507
|
}
|
|
@@ -1792,11 +1511,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1792
1511
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1793
1512
|
delta = -delta;
|
|
1794
1513
|
}
|
|
1795
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1796
1514
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1797
1515
|
const nextLayout = adjustLayoutByDelta({
|
|
1798
1516
|
delta,
|
|
1799
|
-
groupSizePixels,
|
|
1800
1517
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1801
1518
|
panelConstraints,
|
|
1802
1519
|
pivotIndices,
|
|
@@ -1832,18 +1549,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1832
1549
|
setLayout(nextLayout);
|
|
1833
1550
|
eagerValuesRef.current.layout = nextLayout;
|
|
1834
1551
|
if (onLayout) {
|
|
1835
|
-
onLayout(nextLayout
|
|
1836
|
-
sizePercentage,
|
|
1837
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1838
|
-
})));
|
|
1552
|
+
onLayout(nextLayout);
|
|
1839
1553
|
}
|
|
1840
|
-
callPanelCallbacks(
|
|
1554
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1841
1555
|
}
|
|
1842
1556
|
};
|
|
1843
1557
|
}, []);
|
|
1844
1558
|
|
|
1845
1559
|
// External APIs are safe to memoize via committed values ref
|
|
1846
|
-
const resizePanel = useCallback((panelData,
|
|
1560
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1847
1561
|
const {
|
|
1848
1562
|
onLayout
|
|
1849
1563
|
} = committedValuesRef.current;
|
|
@@ -1853,16 +1567,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1853
1567
|
} = eagerValuesRef.current;
|
|
1854
1568
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1855
1569
|
const {
|
|
1856
|
-
|
|
1857
|
-
panelSizePercentage,
|
|
1570
|
+
panelSize,
|
|
1858
1571
|
pivotIndices
|
|
1859
|
-
} = panelDataHelper(
|
|
1860
|
-
|
|
1572
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1573
|
+
assert(panelSize != null);
|
|
1861
1574
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1862
|
-
const delta = isLastPanel ?
|
|
1575
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1863
1576
|
const nextLayout = adjustLayoutByDelta({
|
|
1864
1577
|
delta,
|
|
1865
|
-
groupSizePixels,
|
|
1866
1578
|
layout: prevLayout,
|
|
1867
1579
|
panelConstraints: panelConstraintsArray,
|
|
1868
1580
|
pivotIndices,
|
|
@@ -1872,14 +1584,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1872
1584
|
setLayout(nextLayout);
|
|
1873
1585
|
eagerValuesRef.current.layout = nextLayout;
|
|
1874
1586
|
if (onLayout) {
|
|
1875
|
-
onLayout(nextLayout
|
|
1876
|
-
sizePercentage,
|
|
1877
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1878
|
-
})));
|
|
1587
|
+
onLayout(nextLayout);
|
|
1879
1588
|
}
|
|
1880
|
-
callPanelCallbacks(
|
|
1589
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1881
1590
|
}
|
|
1882
|
-
}, [
|
|
1591
|
+
}, []);
|
|
1883
1592
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1884
1593
|
const {
|
|
1885
1594
|
direction
|
|
@@ -1888,6 +1597,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1888
1597
|
layout
|
|
1889
1598
|
} = eagerValuesRef.current;
|
|
1890
1599
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1600
|
+
assert(handleElement);
|
|
1891
1601
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1892
1602
|
setDragState({
|
|
1893
1603
|
dragHandleId,
|
|
@@ -1906,7 +1616,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1906
1616
|
});
|
|
1907
1617
|
const unregisterPanel = useCallback(panelData => {
|
|
1908
1618
|
const {
|
|
1909
|
-
id: groupId,
|
|
1910
1619
|
onLayout
|
|
1911
1620
|
} = committedValuesRef.current;
|
|
1912
1621
|
const {
|
|
@@ -1929,7 +1638,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1929
1638
|
const {
|
|
1930
1639
|
pendingPanelIds
|
|
1931
1640
|
} = unregisterPanelRef.current;
|
|
1932
|
-
const map =
|
|
1641
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1933
1642
|
|
|
1934
1643
|
// TRICKY
|
|
1935
1644
|
// Strict effects mode
|
|
@@ -1955,16 +1664,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1955
1664
|
// The group is unmounting; skip layout calculation.
|
|
1956
1665
|
return;
|
|
1957
1666
|
}
|
|
1958
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1959
1667
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1960
|
-
groupSizePixels,
|
|
1961
1668
|
panelDataArray
|
|
1962
1669
|
});
|
|
1963
1670
|
|
|
1964
1671
|
// Validate even saved layouts in case something has changed since last render
|
|
1965
1672
|
// e.g. for pixel groups, this could be the size of the window
|
|
1966
1673
|
const nextLayout = validatePanelGroupLayout({
|
|
1967
|
-
groupSizePixels,
|
|
1968
1674
|
layout: unsafeLayout,
|
|
1969
1675
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1970
1676
|
});
|
|
@@ -1972,12 +1678,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1972
1678
|
setLayout(nextLayout);
|
|
1973
1679
|
eagerValuesRef.current.layout = nextLayout;
|
|
1974
1680
|
if (onLayout) {
|
|
1975
|
-
onLayout(nextLayout
|
|
1976
|
-
sizePercentage,
|
|
1977
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1978
|
-
})));
|
|
1681
|
+
onLayout(nextLayout);
|
|
1979
1682
|
}
|
|
1980
|
-
callPanelCallbacks(
|
|
1683
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1981
1684
|
}
|
|
1982
1685
|
}, 0);
|
|
1983
1686
|
}, []);
|
|
@@ -2008,13 +1711,13 @@ function PanelGroupWithForwardedRef({
|
|
|
2008
1711
|
return createElement(PanelGroupContext.Provider, {
|
|
2009
1712
|
value: context
|
|
2010
1713
|
}, createElement(Type, {
|
|
1714
|
+
...rest,
|
|
2011
1715
|
children,
|
|
2012
1716
|
className: classNameFromProps,
|
|
2013
1717
|
style: {
|
|
2014
1718
|
...style,
|
|
2015
1719
|
...styleFromProps
|
|
2016
1720
|
},
|
|
2017
|
-
...dataAttributes,
|
|
2018
1721
|
// CSS selectors
|
|
2019
1722
|
"data-panel-group": "",
|
|
2020
1723
|
"data-panel-group-direction": direction,
|
|
@@ -2027,22 +1730,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
2027
1730
|
}));
|
|
2028
1731
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
2029
1732
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
2030
|
-
function panelDataHelper(
|
|
1733
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
2031
1734
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
2032
1735
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
2033
1736
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
2034
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
2035
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
2036
1737
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
2037
1738
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
2038
|
-
const
|
|
2039
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1739
|
+
const panelSize = layout[panelIndex];
|
|
2040
1740
|
return {
|
|
2041
|
-
...
|
|
2042
|
-
|
|
2043
|
-
panelSizePercentage,
|
|
2044
|
-
panelSizePixels,
|
|
2045
|
-
groupSizePixels,
|
|
1741
|
+
...panelConstraints,
|
|
1742
|
+
panelSize,
|
|
2046
1743
|
pivotIndices
|
|
2047
1744
|
};
|
|
2048
1745
|
}
|
|
@@ -2082,6 +1779,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2082
1779
|
{
|
|
2083
1780
|
event.preventDefault();
|
|
2084
1781
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1782
|
+
assert(groupId);
|
|
2085
1783
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
2086
1784
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
2087
1785
|
assert(index !== null);
|
|
@@ -2102,12 +1800,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2102
1800
|
function PanelResizeHandle({
|
|
2103
1801
|
children = null,
|
|
2104
1802
|
className: classNameFromProps = "",
|
|
2105
|
-
dataAttributes,
|
|
2106
1803
|
disabled = false,
|
|
2107
|
-
id: idFromProps
|
|
1804
|
+
id: idFromProps,
|
|
2108
1805
|
onDragging,
|
|
2109
1806
|
style: styleFromProps = {},
|
|
2110
|
-
|
|
1807
|
+
tabIndex = 0,
|
|
1808
|
+
tagName: Type = "div",
|
|
1809
|
+
...rest
|
|
2111
1810
|
}) {
|
|
2112
1811
|
const divElementRef = useRef(null);
|
|
2113
1812
|
|
|
@@ -2137,8 +1836,9 @@ function PanelResizeHandle({
|
|
|
2137
1836
|
const stopDraggingAndBlur = useCallback(() => {
|
|
2138
1837
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
2139
1838
|
// That would cause the PanelGroup to think it was still active.
|
|
2140
|
-
const
|
|
2141
|
-
|
|
1839
|
+
const divElement = divElementRef.current;
|
|
1840
|
+
assert(divElement);
|
|
1841
|
+
divElement.blur();
|
|
2142
1842
|
stopDragging();
|
|
2143
1843
|
const {
|
|
2144
1844
|
onDragging
|
|
@@ -2166,6 +1866,7 @@ function PanelResizeHandle({
|
|
|
2166
1866
|
resizeHandler(event);
|
|
2167
1867
|
};
|
|
2168
1868
|
const divElement = divElementRef.current;
|
|
1869
|
+
assert(divElement);
|
|
2169
1870
|
const targetDocument = divElement.ownerDocument;
|
|
2170
1871
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2171
1872
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2193,15 +1894,18 @@ function PanelResizeHandle({
|
|
|
2193
1894
|
userSelect: "none"
|
|
2194
1895
|
};
|
|
2195
1896
|
return createElement(Type, {
|
|
1897
|
+
...rest,
|
|
2196
1898
|
children,
|
|
2197
1899
|
className: classNameFromProps,
|
|
2198
1900
|
onBlur: () => setIsFocused(false),
|
|
2199
1901
|
onFocus: () => setIsFocused(true),
|
|
2200
1902
|
onMouseDown: event => {
|
|
2201
1903
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1904
|
+
const callbacks = callbacksRef.current;
|
|
1905
|
+
assert(callbacks);
|
|
2202
1906
|
const {
|
|
2203
1907
|
onDragging
|
|
2204
|
-
} =
|
|
1908
|
+
} = callbacks;
|
|
2205
1909
|
if (onDragging) {
|
|
2206
1910
|
onDragging(true);
|
|
2207
1911
|
}
|
|
@@ -2211,9 +1915,11 @@ function PanelResizeHandle({
|
|
|
2211
1915
|
onTouchEnd: stopDraggingAndBlur,
|
|
2212
1916
|
onTouchStart: event => {
|
|
2213
1917
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1918
|
+
const callbacks = callbacksRef.current;
|
|
1919
|
+
assert(callbacks);
|
|
2214
1920
|
const {
|
|
2215
1921
|
onDragging
|
|
2216
|
-
} =
|
|
1922
|
+
} = callbacks;
|
|
2217
1923
|
if (onDragging) {
|
|
2218
1924
|
onDragging(true);
|
|
2219
1925
|
}
|
|
@@ -2224,8 +1930,7 @@ function PanelResizeHandle({
|
|
|
2224
1930
|
...style,
|
|
2225
1931
|
...styleFromProps
|
|
2226
1932
|
},
|
|
2227
|
-
tabIndex
|
|
2228
|
-
...dataAttributes,
|
|
1933
|
+
tabIndex,
|
|
2229
1934
|
// CSS selectors
|
|
2230
1935
|
"data-panel-group-direction": direction,
|
|
2231
1936
|
"data-panel-group-id": groupId,
|
|
@@ -2237,4 +1942,4 @@ function PanelResizeHandle({
|
|
|
2237
1942
|
}
|
|
2238
1943
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
2239
1944
|
|
|
2240
|
-
export { Panel, PanelGroup, PanelResizeHandle };
|
|
1945
|
+
export { Panel, PanelGroup, PanelResizeHandle, assert };
|