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
|
@@ -65,24 +65,20 @@ function useUniqueId(idFromParams = null) {
|
|
|
65
65
|
function PanelWithForwardedRef({
|
|
66
66
|
children,
|
|
67
67
|
className: classNameFromProps = "",
|
|
68
|
-
|
|
69
|
-
collapsedSizePixels,
|
|
68
|
+
collapsedSize,
|
|
70
69
|
collapsible,
|
|
71
|
-
|
|
72
|
-
defaultSizePercentage,
|
|
73
|
-
defaultSizePixels,
|
|
70
|
+
defaultSize,
|
|
74
71
|
forwardedRef,
|
|
75
72
|
id: idFromProps,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
minSizePercentage,
|
|
79
|
-
minSizePixels,
|
|
73
|
+
maxSize,
|
|
74
|
+
minSize,
|
|
80
75
|
onCollapse,
|
|
81
76
|
onExpand,
|
|
82
77
|
onResize,
|
|
83
78
|
order,
|
|
84
79
|
style: styleFromProps,
|
|
85
|
-
tagName: Type = "div"
|
|
80
|
+
tagName: Type = "div",
|
|
81
|
+
...rest
|
|
86
82
|
}) {
|
|
87
83
|
const context = useContext(PanelGroupContext);
|
|
88
84
|
if (context === null) {
|
|
@@ -107,15 +103,11 @@ function PanelWithForwardedRef({
|
|
|
107
103
|
onResize
|
|
108
104
|
},
|
|
109
105
|
constraints: {
|
|
110
|
-
|
|
111
|
-
collapsedSizePixels,
|
|
106
|
+
collapsedSize,
|
|
112
107
|
collapsible,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
maxSizePixels,
|
|
117
|
-
minSizePercentage,
|
|
118
|
-
minSizePixels
|
|
108
|
+
defaultSize,
|
|
109
|
+
maxSize,
|
|
110
|
+
minSize
|
|
119
111
|
},
|
|
120
112
|
id: panelId,
|
|
121
113
|
idIsFromProps: idFromProps !== undefined,
|
|
@@ -141,15 +133,11 @@ function PanelWithForwardedRef({
|
|
|
141
133
|
callbacks.onCollapse = onCollapse;
|
|
142
134
|
callbacks.onExpand = onExpand;
|
|
143
135
|
callbacks.onResize = onResize;
|
|
144
|
-
constraints.
|
|
145
|
-
constraints.collapsedSizePixels = collapsedSizePixels;
|
|
136
|
+
constraints.collapsedSize = collapsedSize;
|
|
146
137
|
constraints.collapsible = collapsible;
|
|
147
|
-
constraints.
|
|
148
|
-
constraints.
|
|
149
|
-
constraints.
|
|
150
|
-
constraints.maxSizePixels = maxSizePixels;
|
|
151
|
-
constraints.minSizePercentage = minSizePercentage;
|
|
152
|
-
constraints.minSizePixels = minSizePixels;
|
|
138
|
+
constraints.defaultSize = defaultSize;
|
|
139
|
+
constraints.maxSize = maxSize;
|
|
140
|
+
constraints.minSize = minSize;
|
|
153
141
|
});
|
|
154
142
|
useIsomorphicLayoutEffect(() => {
|
|
155
143
|
const panelData = panelDataRef.current;
|
|
@@ -177,19 +165,19 @@ function PanelWithForwardedRef({
|
|
|
177
165
|
isExpanded() {
|
|
178
166
|
return !isPanelCollapsed(panelDataRef.current);
|
|
179
167
|
},
|
|
180
|
-
resize:
|
|
181
|
-
resizePanel(panelDataRef.current,
|
|
168
|
+
resize: size => {
|
|
169
|
+
resizePanel(panelDataRef.current, size);
|
|
182
170
|
}
|
|
183
171
|
}), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
|
|
184
172
|
const style = getPanelStyle(panelDataRef.current);
|
|
185
173
|
return createElement(Type, {
|
|
174
|
+
...rest,
|
|
186
175
|
children,
|
|
187
176
|
className: classNameFromProps,
|
|
188
177
|
style: {
|
|
189
178
|
...style,
|
|
190
179
|
...styleFromProps
|
|
191
180
|
},
|
|
192
|
-
...dataAttributes,
|
|
193
181
|
// CSS selectors
|
|
194
182
|
"data-panel": "",
|
|
195
183
|
"data-panel-id": panelId,
|
|
@@ -206,81 +194,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
206
194
|
PanelWithForwardedRef.displayName = "Panel";
|
|
207
195
|
Panel.displayName = "forwardRef(Panel)";
|
|
208
196
|
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
|
|
214
|
-
let {
|
|
215
|
-
collapsedSizePercentage = 0,
|
|
216
|
-
collapsedSizePixels,
|
|
217
|
-
defaultSizePercentage,
|
|
218
|
-
defaultSizePixels,
|
|
219
|
-
maxSizePercentage = 100,
|
|
220
|
-
maxSizePixels,
|
|
221
|
-
minSizePercentage = 0,
|
|
222
|
-
minSizePixels
|
|
223
|
-
} = panelConstraints;
|
|
224
|
-
const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
|
|
225
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
226
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
227
|
-
return {
|
|
228
|
-
collapsedSizePercentage: 0,
|
|
229
|
-
defaultSizePercentage,
|
|
230
|
-
maxSizePercentage: 0,
|
|
231
|
-
minSizePercentage: 0
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
if (collapsedSizePixels != null) {
|
|
235
|
-
collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
|
|
236
|
-
}
|
|
237
|
-
if (defaultSizePixels != null) {
|
|
238
|
-
defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
|
|
239
|
-
}
|
|
240
|
-
if (minSizePixels != null) {
|
|
241
|
-
minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
|
|
242
|
-
}
|
|
243
|
-
if (maxSizePixels != null) {
|
|
244
|
-
maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
|
|
245
|
-
}
|
|
246
|
-
return {
|
|
247
|
-
collapsedSizePercentage,
|
|
248
|
-
defaultSizePercentage,
|
|
249
|
-
maxSizePercentage,
|
|
250
|
-
minSizePercentage
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
|
|
255
|
-
// All panel constraints, excluding the current one
|
|
256
|
-
let totalMinConstraints = 0;
|
|
257
|
-
let totalMaxConstraints = 0;
|
|
258
|
-
for (let index = 0; index < panelConstraintsArray.length; index++) {
|
|
259
|
-
if (index !== panelIndex) {
|
|
260
|
-
const {
|
|
261
|
-
collapsible
|
|
262
|
-
} = panelConstraintsArray[index];
|
|
263
|
-
const {
|
|
264
|
-
collapsedSizePercentage,
|
|
265
|
-
maxSizePercentage,
|
|
266
|
-
minSizePercentage
|
|
267
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
|
|
268
|
-
totalMaxConstraints += maxSizePercentage;
|
|
269
|
-
totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
|
|
270
|
-
}
|
|
197
|
+
function assert(expectedCondition, message = "Assertion failed!") {
|
|
198
|
+
if (!expectedCondition) {
|
|
199
|
+
console.error(message);
|
|
200
|
+
throw Error(message);
|
|
271
201
|
}
|
|
272
|
-
const {
|
|
273
|
-
collapsedSizePercentage,
|
|
274
|
-
defaultSizePercentage,
|
|
275
|
-
maxSizePercentage,
|
|
276
|
-
minSizePercentage
|
|
277
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
|
|
278
|
-
return {
|
|
279
|
-
collapsedSizePercentage,
|
|
280
|
-
defaultSizePercentage,
|
|
281
|
-
maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
|
|
282
|
-
minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
|
|
283
|
-
};
|
|
284
202
|
}
|
|
285
203
|
|
|
286
204
|
const PRECISION = 10;
|
|
@@ -302,56 +220,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
|
|
|
302
220
|
|
|
303
221
|
// Panel size must be in percentages; pixel values should be pre-converted
|
|
304
222
|
function resizePanel({
|
|
305
|
-
|
|
306
|
-
panelConstraints,
|
|
223
|
+
panelConstraints: panelConstraintsArray,
|
|
307
224
|
panelIndex,
|
|
308
225
|
size
|
|
309
226
|
}) {
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
defaultSizePixels,
|
|
313
|
-
minSizePixels,
|
|
314
|
-
maxSizePixels
|
|
315
|
-
}) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
|
|
316
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
317
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
318
|
-
return 0;
|
|
319
|
-
}
|
|
227
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
228
|
+
assert(panelConstraints != null);
|
|
320
229
|
let {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
|
|
333
|
-
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
334
|
-
size = collapsedSizePercentage;
|
|
335
|
-
} else {
|
|
336
|
-
size = minSizePercentage;
|
|
337
|
-
}
|
|
230
|
+
collapsedSize = 0,
|
|
231
|
+
collapsible,
|
|
232
|
+
maxSize = 100,
|
|
233
|
+
minSize = 0
|
|
234
|
+
} = panelConstraints;
|
|
235
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
236
|
+
if (collapsible) {
|
|
237
|
+
// Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
|
|
238
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
239
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
240
|
+
size = collapsedSize;
|
|
338
241
|
} else {
|
|
339
|
-
size =
|
|
242
|
+
size = minSize;
|
|
340
243
|
}
|
|
244
|
+
} else {
|
|
245
|
+
size = minSize;
|
|
341
246
|
}
|
|
342
247
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
248
|
+
size = Math.min(maxSize, size);
|
|
249
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
346
250
|
return size;
|
|
347
251
|
}
|
|
348
252
|
|
|
349
253
|
// All units must be in percentages; pixel values should be pre-converted
|
|
350
254
|
function adjustLayoutByDelta({
|
|
351
255
|
delta,
|
|
352
|
-
groupSizePixels,
|
|
353
256
|
layout: prevLayout,
|
|
354
|
-
panelConstraints,
|
|
257
|
+
panelConstraints: panelConstraintsArray,
|
|
355
258
|
pivotIndices,
|
|
356
259
|
trigger
|
|
357
260
|
}) {
|
|
@@ -359,6 +262,9 @@ function adjustLayoutByDelta({
|
|
|
359
262
|
return prevLayout;
|
|
360
263
|
}
|
|
361
264
|
const nextLayout = [...prevLayout];
|
|
265
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
266
|
+
assert(firstPivotIndex != null);
|
|
267
|
+
assert(secondPivotIndex != null);
|
|
362
268
|
let deltaApplied = 0;
|
|
363
269
|
|
|
364
270
|
//const DEBUG = [];
|
|
@@ -382,18 +288,23 @@ function adjustLayoutByDelta({
|
|
|
382
288
|
if (trigger === "keyboard") {
|
|
383
289
|
{
|
|
384
290
|
// Check if we should expand a collapsed panel
|
|
385
|
-
const index = delta < 0 ?
|
|
386
|
-
const
|
|
291
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
292
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
293
|
+
assert(panelConstraints);
|
|
294
|
+
|
|
387
295
|
//DEBUG.push(`edge case check 1: ${index}`);
|
|
388
296
|
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
389
|
-
if (
|
|
297
|
+
if (panelConstraints.collapsible) {
|
|
390
298
|
const prevSize = prevLayout[index];
|
|
299
|
+
assert(prevSize != null);
|
|
300
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
301
|
+
assert(panelConstraints);
|
|
391
302
|
const {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
} =
|
|
395
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
396
|
-
const localDelta =
|
|
303
|
+
collapsedSize = 0,
|
|
304
|
+
minSize = 0
|
|
305
|
+
} = panelConstraints;
|
|
306
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
|
|
307
|
+
const localDelta = minSize - prevSize;
|
|
397
308
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
398
309
|
|
|
399
310
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -406,18 +317,26 @@ function adjustLayoutByDelta({
|
|
|
406
317
|
|
|
407
318
|
{
|
|
408
319
|
// Check if we should collapse a panel at its minimum size
|
|
409
|
-
const index = delta < 0 ?
|
|
410
|
-
const
|
|
320
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
321
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
322
|
+
assert(panelConstraints);
|
|
323
|
+
const {
|
|
324
|
+
collapsible
|
|
325
|
+
} = panelConstraints;
|
|
326
|
+
|
|
411
327
|
//DEBUG.push(`edge case check 2: ${index}`);
|
|
412
|
-
//DEBUG.push(` -> collapsible? ${
|
|
413
|
-
if (
|
|
328
|
+
//DEBUG.push(` -> collapsible? ${collapsible}`);
|
|
329
|
+
if (collapsible) {
|
|
414
330
|
const prevSize = prevLayout[index];
|
|
331
|
+
assert(prevSize != null);
|
|
332
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
333
|
+
assert(panelConstraints);
|
|
415
334
|
const {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
} =
|
|
419
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
420
|
-
const localDelta = prevSize -
|
|
335
|
+
collapsedSize = 0,
|
|
336
|
+
minSize = 0
|
|
337
|
+
} = panelConstraints;
|
|
338
|
+
if (fuzzyNumbersEqual(prevSize, minSize)) {
|
|
339
|
+
const localDelta = prevSize - collapsedSize;
|
|
421
340
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
422
341
|
|
|
423
342
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -439,15 +358,15 @@ function adjustLayoutByDelta({
|
|
|
439
358
|
// as an expanding panel might change from collapsed to min size.
|
|
440
359
|
|
|
441
360
|
const increment = delta < 0 ? 1 : -1;
|
|
442
|
-
let index = delta < 0 ?
|
|
361
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
443
362
|
let maxAvailableDelta = 0;
|
|
444
363
|
|
|
445
364
|
//DEBUG.push("pre calc...");
|
|
446
365
|
while (true) {
|
|
447
366
|
const prevSize = prevLayout[index];
|
|
367
|
+
assert(prevSize != null);
|
|
448
368
|
const maxSafeSize = resizePanel({
|
|
449
|
-
|
|
450
|
-
panelConstraints,
|
|
369
|
+
panelConstraints: panelConstraintsArray,
|
|
451
370
|
panelIndex: index,
|
|
452
371
|
size: 100
|
|
453
372
|
});
|
|
@@ -456,7 +375,7 @@ function adjustLayoutByDelta({
|
|
|
456
375
|
|
|
457
376
|
maxAvailableDelta += delta;
|
|
458
377
|
index += increment;
|
|
459
|
-
if (index < 0 || index >=
|
|
378
|
+
if (index < 0 || index >= panelConstraintsArray.length) {
|
|
460
379
|
break;
|
|
461
380
|
}
|
|
462
381
|
}
|
|
@@ -471,15 +390,15 @@ function adjustLayoutByDelta({
|
|
|
471
390
|
{
|
|
472
391
|
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
473
392
|
|
|
474
|
-
const pivotIndex = delta < 0 ?
|
|
393
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
475
394
|
let index = pivotIndex;
|
|
476
|
-
while (index >= 0 && index <
|
|
395
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
477
396
|
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
478
397
|
const prevSize = prevLayout[index];
|
|
398
|
+
assert(prevSize != null);
|
|
479
399
|
const unsafeSize = prevSize - deltaRemaining;
|
|
480
400
|
const safeSize = resizePanel({
|
|
481
|
-
|
|
482
|
-
panelConstraints,
|
|
401
|
+
panelConstraints: panelConstraintsArray,
|
|
483
402
|
panelIndex: index,
|
|
484
403
|
size: unsafeSize
|
|
485
404
|
});
|
|
@@ -511,11 +430,12 @@ function adjustLayoutByDelta({
|
|
|
511
430
|
}
|
|
512
431
|
{
|
|
513
432
|
// Now distribute the applied delta to the panels in the other direction
|
|
514
|
-
const pivotIndex = delta < 0 ?
|
|
515
|
-
const
|
|
433
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
434
|
+
const prevSize = prevLayout[pivotIndex];
|
|
435
|
+
assert(prevSize != null);
|
|
436
|
+
const unsafeSize = prevSize + deltaApplied;
|
|
516
437
|
const safeSize = resizePanel({
|
|
517
|
-
|
|
518
|
-
panelConstraints,
|
|
438
|
+
panelConstraints: panelConstraintsArray,
|
|
519
439
|
panelIndex: pivotIndex,
|
|
520
440
|
size: unsafeSize
|
|
521
441
|
});
|
|
@@ -526,14 +446,14 @@ function adjustLayoutByDelta({
|
|
|
526
446
|
// Edge case where expanding or contracting one panel caused another one to change collapsed state
|
|
527
447
|
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
528
448
|
let deltaRemaining = unsafeSize - safeSize;
|
|
529
|
-
const pivotIndex = delta < 0 ?
|
|
449
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
530
450
|
let index = pivotIndex;
|
|
531
|
-
while (index >= 0 && index <
|
|
451
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
532
452
|
const prevSize = nextLayout[index];
|
|
453
|
+
assert(prevSize != null);
|
|
533
454
|
const unsafeSize = prevSize + deltaRemaining;
|
|
534
455
|
const safeSize = resizePanel({
|
|
535
|
-
|
|
536
|
-
panelConstraints,
|
|
456
|
+
panelConstraints: panelConstraintsArray,
|
|
537
457
|
panelIndex: index,
|
|
538
458
|
size: unsafeSize
|
|
539
459
|
});
|
|
@@ -557,9 +477,7 @@ function adjustLayoutByDelta({
|
|
|
557
477
|
//DEBUG.push("");
|
|
558
478
|
|
|
559
479
|
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
560
|
-
deltaApplied = 100 - totalSize;
|
|
561
480
|
//DEBUG.push(`total size: ${totalSize}`);
|
|
562
|
-
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
563
481
|
//console.log(DEBUG.join("\n"));
|
|
564
482
|
|
|
565
483
|
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
@@ -568,27 +486,7 @@ function adjustLayoutByDelta({
|
|
|
568
486
|
return nextLayout;
|
|
569
487
|
}
|
|
570
488
|
|
|
571
|
-
function assert(expectedCondition, message = "Assertion failed!") {
|
|
572
|
-
if (!expectedCondition) {
|
|
573
|
-
console.error(message);
|
|
574
|
-
throw Error(message);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
function getPercentageSizeFromMixedSizes({
|
|
579
|
-
sizePercentage,
|
|
580
|
-
sizePixels
|
|
581
|
-
}, groupSizePixels) {
|
|
582
|
-
if (sizePercentage != null) {
|
|
583
|
-
return sizePercentage;
|
|
584
|
-
} else if (sizePixels != null) {
|
|
585
|
-
return convertPixelsToPercentage(sizePixels, groupSizePixels);
|
|
586
|
-
}
|
|
587
|
-
return undefined;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
489
|
function calculateAriaValues({
|
|
591
|
-
groupSizePixels,
|
|
592
490
|
layout,
|
|
593
491
|
panelsArray,
|
|
594
492
|
pivotIndices
|
|
@@ -597,28 +495,19 @@ function calculateAriaValues({
|
|
|
597
495
|
let currentMaxSize = 100;
|
|
598
496
|
let totalMinSize = 0;
|
|
599
497
|
let totalMaxSize = 0;
|
|
498
|
+
const firstIndex = pivotIndices[0];
|
|
499
|
+
assert(firstIndex != null);
|
|
600
500
|
|
|
601
501
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
602
502
|
panelsArray.forEach((panelData, index) => {
|
|
603
|
-
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
604
503
|
const {
|
|
605
504
|
constraints
|
|
606
505
|
} = panelData;
|
|
607
506
|
const {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
minSizePercentage,
|
|
611
|
-
minSizePixels
|
|
507
|
+
maxSize = 100,
|
|
508
|
+
minSize = 0
|
|
612
509
|
} = constraints;
|
|
613
|
-
|
|
614
|
-
sizePercentage: minSizePercentage,
|
|
615
|
-
sizePixels: minSizePixels
|
|
616
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
617
|
-
const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
618
|
-
sizePercentage: maxSizePercentage,
|
|
619
|
-
sizePixels: maxSizePixels
|
|
620
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
|
|
621
|
-
if (index === pivotIndices[0]) {
|
|
510
|
+
if (index === firstIndex) {
|
|
622
511
|
currentMinSize = minSize;
|
|
623
512
|
currentMaxSize = maxSize;
|
|
624
513
|
} else {
|
|
@@ -628,7 +517,7 @@ function calculateAriaValues({
|
|
|
628
517
|
});
|
|
629
518
|
const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
630
519
|
const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
|
|
631
|
-
const valueNow = layout[
|
|
520
|
+
const valueNow = layout[firstIndex];
|
|
632
521
|
return {
|
|
633
522
|
valueMax,
|
|
634
523
|
valueMin,
|
|
@@ -659,42 +548,6 @@ function getPanelGroupElement(id) {
|
|
|
659
548
|
return null;
|
|
660
549
|
}
|
|
661
550
|
|
|
662
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
663
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
664
|
-
if (panelGroupElement == null) {
|
|
665
|
-
return NaN;
|
|
666
|
-
}
|
|
667
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
668
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
669
|
-
if (direction === "horizontal") {
|
|
670
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
671
|
-
return accumulated + handle.offsetWidth;
|
|
672
|
-
}, 0);
|
|
673
|
-
} else {
|
|
674
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
675
|
-
return accumulated + handle.offsetHeight;
|
|
676
|
-
}, 0);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
681
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
682
|
-
if (panelGroupElement == null) {
|
|
683
|
-
return NaN;
|
|
684
|
-
}
|
|
685
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
686
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
687
|
-
if (direction === "horizontal") {
|
|
688
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
689
|
-
return accumulated + handle.offsetWidth;
|
|
690
|
-
}, 0);
|
|
691
|
-
} else {
|
|
692
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
693
|
-
return accumulated + handle.offsetHeight;
|
|
694
|
-
}, 0);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
551
|
function getResizeHandleElement(id) {
|
|
699
552
|
const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
700
553
|
if (element) {
|
|
@@ -727,7 +580,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
727
580
|
didWarnAboutMissingResizeHandle: false
|
|
728
581
|
});
|
|
729
582
|
useIsomorphicLayoutEffect(() => {
|
|
730
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
731
583
|
const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
|
|
732
584
|
for (let index = 0; index < panelDataArray.length - 1; index++) {
|
|
733
585
|
const {
|
|
@@ -735,7 +587,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
735
587
|
valueMin,
|
|
736
588
|
valueNow
|
|
737
589
|
} = calculateAriaValues({
|
|
738
|
-
groupSizePixels,
|
|
739
590
|
layout,
|
|
740
591
|
panelsArray: panelDataArray,
|
|
741
592
|
pivotIndices: [index, index + 1]
|
|
@@ -752,10 +603,12 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
752
603
|
}
|
|
753
604
|
}
|
|
754
605
|
} else {
|
|
755
|
-
|
|
606
|
+
const panelData = panelDataArray[index];
|
|
607
|
+
assert(panelData);
|
|
608
|
+
resizeHandleElement.setAttribute("aria-controls", panelData.id);
|
|
756
609
|
resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
|
|
757
610
|
resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
|
|
758
|
-
resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
|
|
611
|
+
resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
|
|
759
612
|
}
|
|
760
613
|
}
|
|
761
614
|
return () => {
|
|
@@ -768,14 +621,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
768
621
|
};
|
|
769
622
|
}, [groupId, layout, panelDataArray]);
|
|
770
623
|
useEffect(() => {
|
|
624
|
+
const eagerValues = eagerValuesRef.current;
|
|
625
|
+
assert(eagerValues);
|
|
771
626
|
const {
|
|
772
627
|
panelDataArray
|
|
773
|
-
} =
|
|
628
|
+
} = eagerValues;
|
|
774
629
|
const groupElement = getPanelGroupElement(groupId);
|
|
775
630
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
776
631
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
632
|
+
assert(handles);
|
|
777
633
|
const cleanupFunctions = handles.map(handle => {
|
|
778
634
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
635
|
+
assert(handleId);
|
|
779
636
|
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
780
637
|
if (idBefore == null || idAfter == null) {
|
|
781
638
|
return () => {};
|
|
@@ -791,21 +648,16 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
791
648
|
const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
|
|
792
649
|
if (index >= 0) {
|
|
793
650
|
const panelData = panelDataArray[index];
|
|
651
|
+
assert(panelData);
|
|
794
652
|
const size = layout[index];
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
802
|
-
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
803
|
-
sizePercentage: panelData.constraints.minSizePercentage,
|
|
804
|
-
sizePixels: panelData.constraints.minSizePixels
|
|
805
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
653
|
+
const {
|
|
654
|
+
collapsedSize = 0,
|
|
655
|
+
collapsible,
|
|
656
|
+
minSize = 0
|
|
657
|
+
} = panelData.constraints;
|
|
658
|
+
if (size != null && collapsible) {
|
|
806
659
|
const nextLayout = adjustLayoutByDelta({
|
|
807
660
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
808
|
-
groupSizePixels,
|
|
809
661
|
layout,
|
|
810
662
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
811
663
|
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
@@ -859,6 +711,7 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
859
711
|
return isHorizontal ? event.clientX : event.clientY;
|
|
860
712
|
} else if (isTouchEvent(event)) {
|
|
861
713
|
const firstTouch = event.touches[0];
|
|
714
|
+
assert(firstTouch);
|
|
862
715
|
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
863
716
|
} else {
|
|
864
717
|
throw Error(`Unsupported event type "${event.type}"`);
|
|
@@ -868,12 +721,15 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
868
721
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
869
722
|
const isHorizontal = direction === "horizontal";
|
|
870
723
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
724
|
+
assert(handleElement);
|
|
871
725
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
726
|
+
assert(groupId);
|
|
872
727
|
let {
|
|
873
728
|
initialCursorPosition
|
|
874
729
|
} = initialDragState;
|
|
875
730
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
876
731
|
const groupElement = getPanelGroupElement(groupId);
|
|
732
|
+
assert(groupElement);
|
|
877
733
|
const groupRect = groupElement.getBoundingClientRect();
|
|
878
734
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
879
735
|
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
@@ -882,19 +738,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
882
738
|
}
|
|
883
739
|
|
|
884
740
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
885
|
-
function calculateDeltaPercentage(event,
|
|
741
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
886
742
|
if (isKeyDown(event)) {
|
|
887
743
|
const isHorizontal = direction === "horizontal";
|
|
888
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
889
|
-
const rect = groupElement.getBoundingClientRect();
|
|
890
|
-
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
891
744
|
let delta = 0;
|
|
892
745
|
if (event.shiftKey) {
|
|
893
746
|
delta = 100;
|
|
894
|
-
} else if (
|
|
895
|
-
delta =
|
|
896
|
-
} else if (keyboardResizeByOptions.pixels != null) {
|
|
897
|
-
delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
|
|
747
|
+
} else if (keyboardResizeBy != null) {
|
|
748
|
+
delta = keyboardResizeBy;
|
|
898
749
|
} else {
|
|
899
750
|
delta = 10;
|
|
900
751
|
}
|
|
@@ -921,37 +772,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
921
772
|
}
|
|
922
773
|
return movement;
|
|
923
774
|
} else {
|
|
775
|
+
if (initialDragState == null) {
|
|
776
|
+
return 0;
|
|
777
|
+
}
|
|
924
778
|
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
925
779
|
}
|
|
926
780
|
}
|
|
927
781
|
|
|
928
782
|
function calculateUnsafeDefaultLayout({
|
|
929
|
-
groupSizePixels,
|
|
930
783
|
panelDataArray
|
|
931
784
|
}) {
|
|
932
785
|
const layout = Array(panelDataArray.length);
|
|
933
|
-
const
|
|
786
|
+
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
934
787
|
let numPanelsWithSizes = 0;
|
|
935
788
|
let remainingSize = 100;
|
|
936
789
|
|
|
937
790
|
// Distribute default sizes first
|
|
938
791
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
792
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
793
|
+
assert(panelConstraints);
|
|
939
794
|
const {
|
|
940
|
-
|
|
941
|
-
} =
|
|
942
|
-
if (
|
|
795
|
+
defaultSize
|
|
796
|
+
} = panelConstraints;
|
|
797
|
+
if (defaultSize != null) {
|
|
943
798
|
numPanelsWithSizes++;
|
|
944
|
-
layout[index] =
|
|
945
|
-
remainingSize -=
|
|
799
|
+
layout[index] = defaultSize;
|
|
800
|
+
remainingSize -= defaultSize;
|
|
946
801
|
}
|
|
947
802
|
}
|
|
948
803
|
|
|
949
804
|
// Remaining size should be distributed evenly between panels without default sizes
|
|
950
805
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
806
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
807
|
+
assert(panelConstraints);
|
|
951
808
|
const {
|
|
952
|
-
|
|
953
|
-
} =
|
|
954
|
-
if (
|
|
809
|
+
defaultSize
|
|
810
|
+
} = panelConstraints;
|
|
811
|
+
if (defaultSize != null) {
|
|
955
812
|
continue;
|
|
956
813
|
}
|
|
957
814
|
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
@@ -963,54 +820,36 @@ function calculateUnsafeDefaultLayout({
|
|
|
963
820
|
return layout;
|
|
964
821
|
}
|
|
965
822
|
|
|
966
|
-
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
967
|
-
return percentage / 100 * groupSizePixels;
|
|
968
|
-
}
|
|
969
|
-
|
|
970
823
|
// Layout should be pre-converted into percentages
|
|
971
|
-
function callPanelCallbacks(
|
|
972
|
-
|
|
973
|
-
layout.forEach((sizePercentage, index) => {
|
|
824
|
+
function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
|
|
825
|
+
layout.forEach((size, index) => {
|
|
974
826
|
const panelData = panelsArray[index];
|
|
975
|
-
|
|
976
|
-
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
977
|
-
// The subsequent render+effects will handle the resize notification
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
827
|
+
assert(panelData);
|
|
980
828
|
const {
|
|
981
829
|
callbacks,
|
|
982
830
|
constraints,
|
|
983
831
|
id: panelId
|
|
984
832
|
} = panelData;
|
|
985
833
|
const {
|
|
834
|
+
collapsedSize = 0,
|
|
986
835
|
collapsible
|
|
987
836
|
} = constraints;
|
|
988
|
-
const
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
};
|
|
992
|
-
const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
|
|
993
|
-
if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
|
|
994
|
-
panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
|
|
837
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
|
|
838
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
839
|
+
panelIdToLastNotifiedSizeMap[panelId] = size;
|
|
995
840
|
const {
|
|
996
841
|
onCollapse,
|
|
997
842
|
onExpand,
|
|
998
843
|
onResize
|
|
999
844
|
} = callbacks;
|
|
1000
845
|
if (onResize) {
|
|
1001
|
-
onResize(
|
|
846
|
+
onResize(size, lastNotifiedSize);
|
|
1002
847
|
}
|
|
1003
848
|
if (collapsible && (onCollapse || onExpand)) {
|
|
1004
|
-
|
|
1005
|
-
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
1006
|
-
sizePercentage: constraints.collapsedSizePercentage,
|
|
1007
|
-
sizePixels: constraints.collapsedSizePixels
|
|
1008
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
1009
|
-
const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
|
|
1010
|
-
if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
|
|
849
|
+
if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
1011
850
|
onExpand();
|
|
1012
851
|
}
|
|
1013
|
-
if (onCollapse && (
|
|
852
|
+
if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
|
|
1014
853
|
onCollapse();
|
|
1015
854
|
}
|
|
1016
855
|
}
|
|
@@ -1044,9 +883,10 @@ function computePanelFlexBoxStyle({
|
|
|
1044
883
|
const size = layout[panelIndex];
|
|
1045
884
|
let flexGrow;
|
|
1046
885
|
if (panelData.length === 1) {
|
|
1047
|
-
flexGrow = "
|
|
886
|
+
flexGrow = "1";
|
|
1048
887
|
} else if (size == null) {
|
|
1049
|
-
|
|
888
|
+
// Initial render (before panels have registered themselves)
|
|
889
|
+
flexGrow = "1";
|
|
1050
890
|
} else {
|
|
1051
891
|
flexGrow = size.toPrecision(precision);
|
|
1052
892
|
}
|
|
@@ -1192,74 +1032,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1192
1032
|
}
|
|
1193
1033
|
}
|
|
1194
1034
|
|
|
1195
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1196
|
-
return constraints.some(constraints => {
|
|
1197
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
1035
|
function validatePanelConstraints({
|
|
1202
|
-
|
|
1203
|
-
panelConstraints,
|
|
1036
|
+
panelConstraints: panelConstraintsArray,
|
|
1204
1037
|
panelId,
|
|
1205
1038
|
panelIndex
|
|
1206
1039
|
}) {
|
|
1207
1040
|
{
|
|
1208
1041
|
const warnings = [];
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
} = panelConstraints[panelIndex];
|
|
1220
|
-
const conflictingUnits = [];
|
|
1221
|
-
if (collapsedSizePercentage != null && collapsedSizePixels != null) {
|
|
1222
|
-
conflictingUnits.push("collapsed size");
|
|
1223
|
-
}
|
|
1224
|
-
if (defaultSizePercentage != null && defaultSizePixels != null) {
|
|
1225
|
-
conflictingUnits.push("default size");
|
|
1226
|
-
}
|
|
1227
|
-
if (maxSizePercentage != null && maxSizePixels != null) {
|
|
1228
|
-
conflictingUnits.push("max size");
|
|
1229
|
-
}
|
|
1230
|
-
if (minSizePercentage != null && minSizePixels != null) {
|
|
1231
|
-
conflictingUnits.push("min size");
|
|
1232
|
-
}
|
|
1233
|
-
if (conflictingUnits.length > 0) {
|
|
1234
|
-
warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
|
|
1235
|
-
}
|
|
1042
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1043
|
+
assert(panelConstraints);
|
|
1044
|
+
const {
|
|
1045
|
+
collapsedSize = 0,
|
|
1046
|
+
defaultSize,
|
|
1047
|
+
maxSize = 100,
|
|
1048
|
+
minSize = 0
|
|
1049
|
+
} = panelConstraints;
|
|
1050
|
+
if (minSize > maxSize) {
|
|
1051
|
+
warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
|
|
1236
1052
|
}
|
|
1237
|
-
{
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
minSizePercentage
|
|
1243
|
-
} = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
|
|
1244
|
-
if (minSizePercentage > maxSizePercentage) {
|
|
1245
|
-
warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
|
|
1246
|
-
}
|
|
1247
|
-
if (defaultSizePercentage != null) {
|
|
1248
|
-
if (defaultSizePercentage < 0) {
|
|
1249
|
-
warnings.push("default size should not be less than 0");
|
|
1250
|
-
} else if (defaultSizePercentage < minSizePercentage) {
|
|
1251
|
-
warnings.push("default size should not be less than min size");
|
|
1252
|
-
}
|
|
1253
|
-
if (defaultSizePercentage > 100) {
|
|
1254
|
-
warnings.push("default size should not be greater than 100");
|
|
1255
|
-
} else if (defaultSizePercentage > maxSizePercentage) {
|
|
1256
|
-
warnings.push("default size should not be greater than max size");
|
|
1257
|
-
}
|
|
1053
|
+
if (defaultSize != null) {
|
|
1054
|
+
if (defaultSize < 0) {
|
|
1055
|
+
warnings.push("default size should not be less than 0");
|
|
1056
|
+
} else if (defaultSize < minSize) {
|
|
1057
|
+
warnings.push("default size should not be less than min size");
|
|
1258
1058
|
}
|
|
1259
|
-
if (
|
|
1260
|
-
warnings.push("
|
|
1059
|
+
if (defaultSize > 100) {
|
|
1060
|
+
warnings.push("default size should not be greater than 100");
|
|
1061
|
+
} else if (defaultSize > maxSize) {
|
|
1062
|
+
warnings.push("default size should not be greater than max size");
|
|
1261
1063
|
}
|
|
1262
1064
|
}
|
|
1065
|
+
if (collapsedSize > minSize) {
|
|
1066
|
+
warnings.push("collapsed size should not be greater than min size");
|
|
1067
|
+
}
|
|
1263
1068
|
if (warnings.length > 0) {
|
|
1264
1069
|
const name = panelId != null ? `Panel "${panelId}"` : "Panel";
|
|
1265
1070
|
console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
|
|
@@ -1271,20 +1076,26 @@ function validatePanelConstraints({
|
|
|
1271
1076
|
|
|
1272
1077
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1273
1078
|
function validatePanelGroupLayout({
|
|
1274
|
-
groupSizePixels,
|
|
1275
1079
|
layout: prevLayout,
|
|
1276
1080
|
panelConstraints
|
|
1277
1081
|
}) {
|
|
1278
1082
|
const nextLayout = [...prevLayout];
|
|
1083
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1279
1084
|
|
|
1280
1085
|
// Validate layout expectations
|
|
1281
1086
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1282
1087
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1283
|
-
} else if (!fuzzyNumbersEqual(
|
|
1088
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1284
1089
|
// This is not ideal so we should warn about it, but it may be recoverable in some cases
|
|
1285
1090
|
// (especially if the amount is small)
|
|
1286
1091
|
{
|
|
1287
|
-
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}
|
|
1092
|
+
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
|
|
1093
|
+
}
|
|
1094
|
+
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1095
|
+
const unsafeSize = nextLayout[index];
|
|
1096
|
+
assert(unsafeSize != null);
|
|
1097
|
+
const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
|
|
1098
|
+
nextLayout[index] = safeSize;
|
|
1288
1099
|
}
|
|
1289
1100
|
}
|
|
1290
1101
|
let remainingSize = 0;
|
|
@@ -1292,8 +1103,8 @@ function validatePanelGroupLayout({
|
|
|
1292
1103
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1293
1104
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1294
1105
|
const unsafeSize = nextLayout[index];
|
|
1106
|
+
assert(unsafeSize != null);
|
|
1295
1107
|
const safeSize = resizePanel({
|
|
1296
|
-
groupSizePixels,
|
|
1297
1108
|
panelConstraints,
|
|
1298
1109
|
panelIndex: index,
|
|
1299
1110
|
size: unsafeSize
|
|
@@ -1309,9 +1120,9 @@ function validatePanelGroupLayout({
|
|
|
1309
1120
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1310
1121
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1311
1122
|
const prevSize = nextLayout[index];
|
|
1123
|
+
assert(prevSize != null);
|
|
1312
1124
|
const unsafeSize = prevSize + remainingSize;
|
|
1313
1125
|
const safeSize = resizePanel({
|
|
1314
|
-
groupSizePixels,
|
|
1315
1126
|
panelConstraints,
|
|
1316
1127
|
panelIndex: index,
|
|
1317
1128
|
size: unsafeSize
|
|
@@ -1346,21 +1157,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1346
1157
|
autoSaveId = null,
|
|
1347
1158
|
children,
|
|
1348
1159
|
className: classNameFromProps = "",
|
|
1349
|
-
dataAttributes,
|
|
1350
1160
|
direction,
|
|
1351
1161
|
forwardedRef,
|
|
1352
|
-
id: idFromProps,
|
|
1162
|
+
id: idFromProps = null,
|
|
1353
1163
|
onLayout = null,
|
|
1354
|
-
|
|
1355
|
-
keyboardResizeByPixels = null,
|
|
1164
|
+
keyboardResizeBy = null,
|
|
1356
1165
|
storage = defaultStorage,
|
|
1357
1166
|
style: styleFromProps,
|
|
1358
|
-
tagName: Type = "div"
|
|
1167
|
+
tagName: Type = "div",
|
|
1168
|
+
...rest
|
|
1359
1169
|
}) {
|
|
1360
1170
|
const groupId = useUniqueId(idFromProps);
|
|
1361
1171
|
const [dragState, setDragState] = useState(null);
|
|
1362
1172
|
const [layout, setLayout] = useState([]);
|
|
1363
|
-
const
|
|
1173
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1364
1174
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1365
1175
|
const prevDeltaRef = useRef(0);
|
|
1366
1176
|
const committedValuesRef = useRef({
|
|
@@ -1368,8 +1178,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1368
1178
|
direction,
|
|
1369
1179
|
dragState,
|
|
1370
1180
|
id: groupId,
|
|
1371
|
-
|
|
1372
|
-
keyboardResizeByPixels,
|
|
1181
|
+
keyboardResizeBy,
|
|
1373
1182
|
onLayout,
|
|
1374
1183
|
storage
|
|
1375
1184
|
});
|
|
@@ -1385,33 +1194,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1385
1194
|
useImperativeHandle(forwardedRef, () => ({
|
|
1386
1195
|
getId: () => committedValuesRef.current.id,
|
|
1387
1196
|
getLayout: () => {
|
|
1388
|
-
const {
|
|
1389
|
-
id: groupId
|
|
1390
|
-
} = committedValuesRef.current;
|
|
1391
1197
|
const {
|
|
1392
1198
|
layout
|
|
1393
1199
|
} = eagerValuesRef.current;
|
|
1394
|
-
|
|
1395
|
-
return layout.map(sizePercentage => {
|
|
1396
|
-
return {
|
|
1397
|
-
sizePercentage,
|
|
1398
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1399
|
-
};
|
|
1400
|
-
});
|
|
1200
|
+
return layout;
|
|
1401
1201
|
},
|
|
1402
|
-
setLayout:
|
|
1202
|
+
setLayout: unsafeLayout => {
|
|
1403
1203
|
const {
|
|
1404
|
-
id: groupId,
|
|
1405
1204
|
onLayout
|
|
1406
1205
|
} = committedValuesRef.current;
|
|
1407
1206
|
const {
|
|
1408
1207
|
layout: prevLayout,
|
|
1409
1208
|
panelDataArray
|
|
1410
1209
|
} = eagerValuesRef.current;
|
|
1411
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1412
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1413
1210
|
const safeLayout = validatePanelGroupLayout({
|
|
1414
|
-
groupSizePixels,
|
|
1415
1211
|
layout: unsafeLayout,
|
|
1416
1212
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1417
1213
|
});
|
|
@@ -1419,12 +1215,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1419
1215
|
setLayout(safeLayout);
|
|
1420
1216
|
eagerValuesRef.current.layout = safeLayout;
|
|
1421
1217
|
if (onLayout) {
|
|
1422
|
-
onLayout(safeLayout
|
|
1423
|
-
sizePercentage,
|
|
1424
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1425
|
-
})));
|
|
1218
|
+
onLayout(safeLayout);
|
|
1426
1219
|
}
|
|
1427
|
-
callPanelCallbacks(
|
|
1220
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1428
1221
|
}
|
|
1429
1222
|
}
|
|
1430
1223
|
}), []);
|
|
@@ -1435,11 +1228,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1435
1228
|
committedValuesRef.current.id = groupId;
|
|
1436
1229
|
committedValuesRef.current.onLayout = onLayout;
|
|
1437
1230
|
committedValuesRef.current.storage = storage;
|
|
1438
|
-
|
|
1439
|
-
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1440
|
-
// TODO [217] Move these values into a separate ref
|
|
1441
1231
|
});
|
|
1442
|
-
|
|
1443
1232
|
useWindowSplitterPanelGroupBehavior({
|
|
1444
1233
|
committedValuesRef,
|
|
1445
1234
|
eagerValuesRef,
|
|
@@ -1458,57 +1247,16 @@ function PanelGroupWithForwardedRef({
|
|
|
1458
1247
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1459
1248
|
return;
|
|
1460
1249
|
}
|
|
1250
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1461
1251
|
|
|
1462
1252
|
// Limit the frequency of localStorage updates.
|
|
1463
|
-
if (
|
|
1464
|
-
|
|
1253
|
+
if (debouncedSave == null) {
|
|
1254
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1255
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1465
1256
|
}
|
|
1466
|
-
|
|
1257
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1467
1258
|
}
|
|
1468
1259
|
}, [autoSaveId, layout, storage]);
|
|
1469
|
-
useIsomorphicLayoutEffect(() => {
|
|
1470
|
-
const {
|
|
1471
|
-
layout: prevLayout,
|
|
1472
|
-
panelDataArray
|
|
1473
|
-
} = eagerValuesRef.current;
|
|
1474
|
-
const constraints = panelDataArray.map(({
|
|
1475
|
-
constraints
|
|
1476
|
-
}) => constraints);
|
|
1477
|
-
if (!shouldMonitorPixelBasedConstraints(constraints)) {
|
|
1478
|
-
// Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
if (typeof ResizeObserver === "undefined") {
|
|
1482
|
-
console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
|
|
1483
|
-
} else {
|
|
1484
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
1485
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1486
|
-
const {
|
|
1487
|
-
onLayout
|
|
1488
|
-
} = committedValuesRef.current;
|
|
1489
|
-
const nextLayout = validatePanelGroupLayout({
|
|
1490
|
-
groupSizePixels,
|
|
1491
|
-
layout: prevLayout,
|
|
1492
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1493
|
-
});
|
|
1494
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
1495
|
-
setLayout(nextLayout);
|
|
1496
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
1497
|
-
if (onLayout) {
|
|
1498
|
-
onLayout(nextLayout.map(sizePercentage => ({
|
|
1499
|
-
sizePercentage,
|
|
1500
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1501
|
-
})));
|
|
1502
|
-
}
|
|
1503
|
-
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1504
|
-
}
|
|
1505
|
-
});
|
|
1506
|
-
resizeObserver.observe(getPanelGroupElement(groupId));
|
|
1507
|
-
return () => {
|
|
1508
|
-
resizeObserver.disconnect();
|
|
1509
|
-
};
|
|
1510
|
-
}
|
|
1511
|
-
}, [groupId]);
|
|
1512
1260
|
|
|
1513
1261
|
// DEV warnings
|
|
1514
1262
|
useEffect(() => {
|
|
@@ -1539,12 +1287,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1539
1287
|
}
|
|
1540
1288
|
if (!didLogPanelConstraintsWarning) {
|
|
1541
1289
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1542
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1543
1290
|
for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
|
|
1291
|
+
const panelData = panelDataArray[panelIndex];
|
|
1292
|
+
assert(panelData);
|
|
1544
1293
|
const isValid = validatePanelConstraints({
|
|
1545
|
-
groupSizePixels,
|
|
1546
1294
|
panelConstraints,
|
|
1547
|
-
panelId:
|
|
1295
|
+
panelId: panelData.id,
|
|
1548
1296
|
panelIndex
|
|
1549
1297
|
});
|
|
1550
1298
|
if (!isValid) {
|
|
@@ -1568,20 +1316,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1568
1316
|
if (panelData.constraints.collapsible) {
|
|
1569
1317
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1570
1318
|
const {
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
pivotIndices
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
if (
|
|
1319
|
+
collapsedSize = 0,
|
|
1320
|
+
panelSize,
|
|
1321
|
+
pivotIndices
|
|
1322
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1323
|
+
assert(panelSize != null);
|
|
1324
|
+
if (panelSize !== collapsedSize) {
|
|
1577
1325
|
// Store size before collapse;
|
|
1578
1326
|
// This is the size that gets restored if the expand() API is used.
|
|
1579
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1327
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1580
1328
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1581
|
-
const delta = isLastPanel ?
|
|
1329
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1582
1330
|
const nextLayout = adjustLayoutByDelta({
|
|
1583
1331
|
delta,
|
|
1584
|
-
groupSizePixels,
|
|
1585
1332
|
layout: prevLayout,
|
|
1586
1333
|
panelConstraints: panelConstraintsArray,
|
|
1587
1334
|
pivotIndices,
|
|
@@ -1591,16 +1338,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1591
1338
|
setLayout(nextLayout);
|
|
1592
1339
|
eagerValuesRef.current.layout = nextLayout;
|
|
1593
1340
|
if (onLayout) {
|
|
1594
|
-
onLayout(nextLayout
|
|
1595
|
-
sizePercentage,
|
|
1596
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1597
|
-
})));
|
|
1341
|
+
onLayout(nextLayout);
|
|
1598
1342
|
}
|
|
1599
|
-
callPanelCallbacks(
|
|
1343
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1600
1344
|
}
|
|
1601
1345
|
}
|
|
1602
1346
|
}
|
|
1603
|
-
}, [
|
|
1347
|
+
}, []);
|
|
1604
1348
|
|
|
1605
1349
|
// External APIs are safe to memoize via committed values ref
|
|
1606
1350
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1614,21 +1358,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1614
1358
|
if (panelData.constraints.collapsible) {
|
|
1615
1359
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1616
1360
|
const {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
pivotIndices
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1361
|
+
collapsedSize = 0,
|
|
1362
|
+
panelSize,
|
|
1363
|
+
minSize = 0,
|
|
1364
|
+
pivotIndices
|
|
1365
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1366
|
+
if (panelSize === collapsedSize) {
|
|
1624
1367
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1625
|
-
const
|
|
1626
|
-
const
|
|
1368
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1369
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1627
1370
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1628
|
-
const delta = isLastPanel ?
|
|
1371
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1629
1372
|
const nextLayout = adjustLayoutByDelta({
|
|
1630
1373
|
delta,
|
|
1631
|
-
groupSizePixels,
|
|
1632
1374
|
layout: prevLayout,
|
|
1633
1375
|
panelConstraints: panelConstraintsArray,
|
|
1634
1376
|
pivotIndices,
|
|
@@ -1638,16 +1380,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1638
1380
|
setLayout(nextLayout);
|
|
1639
1381
|
eagerValuesRef.current.layout = nextLayout;
|
|
1640
1382
|
if (onLayout) {
|
|
1641
|
-
onLayout(nextLayout
|
|
1642
|
-
sizePercentage,
|
|
1643
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1644
|
-
})));
|
|
1383
|
+
onLayout(nextLayout);
|
|
1645
1384
|
}
|
|
1646
|
-
callPanelCallbacks(
|
|
1385
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1647
1386
|
}
|
|
1648
1387
|
}
|
|
1649
1388
|
}
|
|
1650
|
-
}, [
|
|
1389
|
+
}, []);
|
|
1651
1390
|
|
|
1652
1391
|
// External APIs are safe to memoize via committed values ref
|
|
1653
1392
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1656,14 +1395,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1656
1395
|
panelDataArray
|
|
1657
1396
|
} = eagerValuesRef.current;
|
|
1658
1397
|
const {
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
return
|
|
1663
|
-
|
|
1664
|
-
sizePixels: panelSizePixels
|
|
1665
|
-
};
|
|
1666
|
-
}, [groupId]);
|
|
1398
|
+
panelSize
|
|
1399
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1400
|
+
assert(panelSize != null);
|
|
1401
|
+
return panelSize;
|
|
1402
|
+
}, []);
|
|
1667
1403
|
|
|
1668
1404
|
// This API should never read from committedValuesRef
|
|
1669
1405
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1686,12 +1422,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1686
1422
|
panelDataArray
|
|
1687
1423
|
} = eagerValuesRef.current;
|
|
1688
1424
|
const {
|
|
1689
|
-
|
|
1425
|
+
collapsedSize,
|
|
1690
1426
|
collapsible,
|
|
1691
|
-
|
|
1692
|
-
} = panelDataHelper(
|
|
1693
|
-
return collapsible === true &&
|
|
1694
|
-
}, [
|
|
1427
|
+
panelSize
|
|
1428
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1429
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1430
|
+
}, []);
|
|
1695
1431
|
|
|
1696
1432
|
// External APIs are safe to memoize via committed values ref
|
|
1697
1433
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1700,12 +1436,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1700
1436
|
panelDataArray
|
|
1701
1437
|
} = eagerValuesRef.current;
|
|
1702
1438
|
const {
|
|
1703
|
-
|
|
1439
|
+
collapsedSize = 0,
|
|
1704
1440
|
collapsible,
|
|
1705
|
-
|
|
1706
|
-
} = panelDataHelper(
|
|
1707
|
-
|
|
1708
|
-
|
|
1441
|
+
panelSize
|
|
1442
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1443
|
+
assert(panelSize != null);
|
|
1444
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1445
|
+
}, []);
|
|
1709
1446
|
const registerPanel = useCallback(panelData => {
|
|
1710
1447
|
const {
|
|
1711
1448
|
autoSaveId,
|
|
@@ -1745,18 +1482,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1745
1482
|
if (autoSaveId) {
|
|
1746
1483
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1747
1484
|
}
|
|
1748
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1749
|
-
if (groupSizePixels <= 0) {
|
|
1750
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1751
|
-
constraints
|
|
1752
|
-
}) => constraints))) {
|
|
1753
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1754
|
-
return;
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
1485
|
if (unsafeLayout == null) {
|
|
1758
1486
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1759
|
-
groupSizePixels,
|
|
1760
1487
|
panelDataArray
|
|
1761
1488
|
});
|
|
1762
1489
|
}
|
|
@@ -1764,7 +1491,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1764
1491
|
// Validate even saved layouts in case something has changed since last render
|
|
1765
1492
|
// e.g. for pixel groups, this could be the size of the window
|
|
1766
1493
|
const nextLayout = validatePanelGroupLayout({
|
|
1767
|
-
groupSizePixels,
|
|
1768
1494
|
layout: unsafeLayout,
|
|
1769
1495
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1770
1496
|
});
|
|
@@ -1776,12 +1502,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1776
1502
|
eagerValuesRef.current.layout = nextLayout;
|
|
1777
1503
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1778
1504
|
if (onLayout) {
|
|
1779
|
-
onLayout(nextLayout
|
|
1780
|
-
sizePercentage,
|
|
1781
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1782
|
-
})));
|
|
1505
|
+
onLayout(nextLayout);
|
|
1783
1506
|
}
|
|
1784
|
-
callPanelCallbacks(
|
|
1507
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1785
1508
|
}
|
|
1786
1509
|
}, []);
|
|
1787
1510
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1791,8 +1514,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1791
1514
|
direction,
|
|
1792
1515
|
dragState,
|
|
1793
1516
|
id: groupId,
|
|
1794
|
-
|
|
1795
|
-
keyboardResizeByPixels,
|
|
1517
|
+
keyboardResizeBy,
|
|
1796
1518
|
onLayout
|
|
1797
1519
|
} = committedValuesRef.current;
|
|
1798
1520
|
const {
|
|
@@ -1803,10 +1525,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1803
1525
|
initialLayout
|
|
1804
1526
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1805
1527
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1806
|
-
let delta = calculateDeltaPercentage(event,
|
|
1807
|
-
percentage: keyboardResizeByPercentage,
|
|
1808
|
-
pixels: keyboardResizeByPixels
|
|
1809
|
-
});
|
|
1528
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1810
1529
|
if (delta === 0) {
|
|
1811
1530
|
return;
|
|
1812
1531
|
}
|
|
@@ -1816,11 +1535,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1816
1535
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1817
1536
|
delta = -delta;
|
|
1818
1537
|
}
|
|
1819
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1820
1538
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1821
1539
|
const nextLayout = adjustLayoutByDelta({
|
|
1822
1540
|
delta,
|
|
1823
|
-
groupSizePixels,
|
|
1824
1541
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1825
1542
|
panelConstraints,
|
|
1826
1543
|
pivotIndices,
|
|
@@ -1856,18 +1573,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1856
1573
|
setLayout(nextLayout);
|
|
1857
1574
|
eagerValuesRef.current.layout = nextLayout;
|
|
1858
1575
|
if (onLayout) {
|
|
1859
|
-
onLayout(nextLayout
|
|
1860
|
-
sizePercentage,
|
|
1861
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1862
|
-
})));
|
|
1576
|
+
onLayout(nextLayout);
|
|
1863
1577
|
}
|
|
1864
|
-
callPanelCallbacks(
|
|
1578
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1865
1579
|
}
|
|
1866
1580
|
};
|
|
1867
1581
|
}, []);
|
|
1868
1582
|
|
|
1869
1583
|
// External APIs are safe to memoize via committed values ref
|
|
1870
|
-
const resizePanel = useCallback((panelData,
|
|
1584
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1871
1585
|
const {
|
|
1872
1586
|
onLayout
|
|
1873
1587
|
} = committedValuesRef.current;
|
|
@@ -1877,16 +1591,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1877
1591
|
} = eagerValuesRef.current;
|
|
1878
1592
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1879
1593
|
const {
|
|
1880
|
-
|
|
1881
|
-
panelSizePercentage,
|
|
1594
|
+
panelSize,
|
|
1882
1595
|
pivotIndices
|
|
1883
|
-
} = panelDataHelper(
|
|
1884
|
-
|
|
1596
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1597
|
+
assert(panelSize != null);
|
|
1885
1598
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1886
|
-
const delta = isLastPanel ?
|
|
1599
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1887
1600
|
const nextLayout = adjustLayoutByDelta({
|
|
1888
1601
|
delta,
|
|
1889
|
-
groupSizePixels,
|
|
1890
1602
|
layout: prevLayout,
|
|
1891
1603
|
panelConstraints: panelConstraintsArray,
|
|
1892
1604
|
pivotIndices,
|
|
@@ -1896,14 +1608,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1896
1608
|
setLayout(nextLayout);
|
|
1897
1609
|
eagerValuesRef.current.layout = nextLayout;
|
|
1898
1610
|
if (onLayout) {
|
|
1899
|
-
onLayout(nextLayout
|
|
1900
|
-
sizePercentage,
|
|
1901
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1902
|
-
})));
|
|
1611
|
+
onLayout(nextLayout);
|
|
1903
1612
|
}
|
|
1904
|
-
callPanelCallbacks(
|
|
1613
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1905
1614
|
}
|
|
1906
|
-
}, [
|
|
1615
|
+
}, []);
|
|
1907
1616
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1908
1617
|
const {
|
|
1909
1618
|
direction
|
|
@@ -1912,6 +1621,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1912
1621
|
layout
|
|
1913
1622
|
} = eagerValuesRef.current;
|
|
1914
1623
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1624
|
+
assert(handleElement);
|
|
1915
1625
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1916
1626
|
setDragState({
|
|
1917
1627
|
dragHandleId,
|
|
@@ -1930,7 +1640,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1930
1640
|
});
|
|
1931
1641
|
const unregisterPanel = useCallback(panelData => {
|
|
1932
1642
|
const {
|
|
1933
|
-
id: groupId,
|
|
1934
1643
|
onLayout
|
|
1935
1644
|
} = committedValuesRef.current;
|
|
1936
1645
|
const {
|
|
@@ -1953,7 +1662,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1953
1662
|
const {
|
|
1954
1663
|
pendingPanelIds
|
|
1955
1664
|
} = unregisterPanelRef.current;
|
|
1956
|
-
const map =
|
|
1665
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1957
1666
|
|
|
1958
1667
|
// TRICKY
|
|
1959
1668
|
// Strict effects mode
|
|
@@ -1979,16 +1688,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1979
1688
|
// The group is unmounting; skip layout calculation.
|
|
1980
1689
|
return;
|
|
1981
1690
|
}
|
|
1982
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1983
1691
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1984
|
-
groupSizePixels,
|
|
1985
1692
|
panelDataArray
|
|
1986
1693
|
});
|
|
1987
1694
|
|
|
1988
1695
|
// Validate even saved layouts in case something has changed since last render
|
|
1989
1696
|
// e.g. for pixel groups, this could be the size of the window
|
|
1990
1697
|
const nextLayout = validatePanelGroupLayout({
|
|
1991
|
-
groupSizePixels,
|
|
1992
1698
|
layout: unsafeLayout,
|
|
1993
1699
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1994
1700
|
});
|
|
@@ -1996,12 +1702,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1996
1702
|
setLayout(nextLayout);
|
|
1997
1703
|
eagerValuesRef.current.layout = nextLayout;
|
|
1998
1704
|
if (onLayout) {
|
|
1999
|
-
onLayout(nextLayout
|
|
2000
|
-
sizePercentage,
|
|
2001
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
2002
|
-
})));
|
|
1705
|
+
onLayout(nextLayout);
|
|
2003
1706
|
}
|
|
2004
|
-
callPanelCallbacks(
|
|
1707
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
2005
1708
|
}
|
|
2006
1709
|
}, 0);
|
|
2007
1710
|
}, []);
|
|
@@ -2032,13 +1735,13 @@ function PanelGroupWithForwardedRef({
|
|
|
2032
1735
|
return createElement(PanelGroupContext.Provider, {
|
|
2033
1736
|
value: context
|
|
2034
1737
|
}, createElement(Type, {
|
|
1738
|
+
...rest,
|
|
2035
1739
|
children,
|
|
2036
1740
|
className: classNameFromProps,
|
|
2037
1741
|
style: {
|
|
2038
1742
|
...style,
|
|
2039
1743
|
...styleFromProps
|
|
2040
1744
|
},
|
|
2041
|
-
...dataAttributes,
|
|
2042
1745
|
// CSS selectors
|
|
2043
1746
|
"data-panel-group": "",
|
|
2044
1747
|
"data-panel-group-direction": direction,
|
|
@@ -2051,22 +1754,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
2051
1754
|
}));
|
|
2052
1755
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
2053
1756
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
2054
|
-
function panelDataHelper(
|
|
1757
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
2055
1758
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
2056
1759
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
2057
1760
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
2058
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
2059
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
2060
1761
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
2061
1762
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
2062
|
-
const
|
|
2063
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1763
|
+
const panelSize = layout[panelIndex];
|
|
2064
1764
|
return {
|
|
2065
|
-
...
|
|
2066
|
-
|
|
2067
|
-
panelSizePercentage,
|
|
2068
|
-
panelSizePixels,
|
|
2069
|
-
groupSizePixels,
|
|
1765
|
+
...panelConstraints,
|
|
1766
|
+
panelSize,
|
|
2070
1767
|
pivotIndices
|
|
2071
1768
|
};
|
|
2072
1769
|
}
|
|
@@ -2106,6 +1803,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2106
1803
|
{
|
|
2107
1804
|
event.preventDefault();
|
|
2108
1805
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1806
|
+
assert(groupId);
|
|
2109
1807
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
2110
1808
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
2111
1809
|
assert(index !== null);
|
|
@@ -2126,12 +1824,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2126
1824
|
function PanelResizeHandle({
|
|
2127
1825
|
children = null,
|
|
2128
1826
|
className: classNameFromProps = "",
|
|
2129
|
-
dataAttributes,
|
|
2130
1827
|
disabled = false,
|
|
2131
|
-
id: idFromProps
|
|
1828
|
+
id: idFromProps,
|
|
2132
1829
|
onDragging,
|
|
2133
1830
|
style: styleFromProps = {},
|
|
2134
|
-
|
|
1831
|
+
tabIndex = 0,
|
|
1832
|
+
tagName: Type = "div",
|
|
1833
|
+
...rest
|
|
2135
1834
|
}) {
|
|
2136
1835
|
const divElementRef = useRef(null);
|
|
2137
1836
|
|
|
@@ -2161,8 +1860,9 @@ function PanelResizeHandle({
|
|
|
2161
1860
|
const stopDraggingAndBlur = useCallback(() => {
|
|
2162
1861
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
2163
1862
|
// That would cause the PanelGroup to think it was still active.
|
|
2164
|
-
const
|
|
2165
|
-
|
|
1863
|
+
const divElement = divElementRef.current;
|
|
1864
|
+
assert(divElement);
|
|
1865
|
+
divElement.blur();
|
|
2166
1866
|
stopDragging();
|
|
2167
1867
|
const {
|
|
2168
1868
|
onDragging
|
|
@@ -2190,6 +1890,7 @@ function PanelResizeHandle({
|
|
|
2190
1890
|
resizeHandler(event);
|
|
2191
1891
|
};
|
|
2192
1892
|
const divElement = divElementRef.current;
|
|
1893
|
+
assert(divElement);
|
|
2193
1894
|
const targetDocument = divElement.ownerDocument;
|
|
2194
1895
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2195
1896
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2217,15 +1918,18 @@ function PanelResizeHandle({
|
|
|
2217
1918
|
userSelect: "none"
|
|
2218
1919
|
};
|
|
2219
1920
|
return createElement(Type, {
|
|
1921
|
+
...rest,
|
|
2220
1922
|
children,
|
|
2221
1923
|
className: classNameFromProps,
|
|
2222
1924
|
onBlur: () => setIsFocused(false),
|
|
2223
1925
|
onFocus: () => setIsFocused(true),
|
|
2224
1926
|
onMouseDown: event => {
|
|
2225
1927
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1928
|
+
const callbacks = callbacksRef.current;
|
|
1929
|
+
assert(callbacks);
|
|
2226
1930
|
const {
|
|
2227
1931
|
onDragging
|
|
2228
|
-
} =
|
|
1932
|
+
} = callbacks;
|
|
2229
1933
|
if (onDragging) {
|
|
2230
1934
|
onDragging(true);
|
|
2231
1935
|
}
|
|
@@ -2235,9 +1939,11 @@ function PanelResizeHandle({
|
|
|
2235
1939
|
onTouchEnd: stopDraggingAndBlur,
|
|
2236
1940
|
onTouchStart: event => {
|
|
2237
1941
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1942
|
+
const callbacks = callbacksRef.current;
|
|
1943
|
+
assert(callbacks);
|
|
2238
1944
|
const {
|
|
2239
1945
|
onDragging
|
|
2240
|
-
} =
|
|
1946
|
+
} = callbacks;
|
|
2241
1947
|
if (onDragging) {
|
|
2242
1948
|
onDragging(true);
|
|
2243
1949
|
}
|
|
@@ -2248,8 +1954,7 @@ function PanelResizeHandle({
|
|
|
2248
1954
|
...style,
|
|
2249
1955
|
...styleFromProps
|
|
2250
1956
|
},
|
|
2251
|
-
tabIndex
|
|
2252
|
-
...dataAttributes,
|
|
1957
|
+
tabIndex,
|
|
2253
1958
|
// CSS selectors
|
|
2254
1959
|
"data-panel-group-direction": direction,
|
|
2255
1960
|
"data-panel-group-id": groupId,
|
|
@@ -2264,3 +1969,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
|
2264
1969
|
exports.Panel = Panel;
|
|
2265
1970
|
exports.PanelGroup = PanelGroup;
|
|
2266
1971
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
1972
|
+
exports.assert = assert;
|