react-resizable-panels 0.0.63 → 1.0.0-rc.2
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 +5 -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 +253 -518
- package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +279 -574
- package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.esm.js +279 -575
- package/dist/react-resizable-panels.browser.esm.js +253 -519
- package/dist/react-resizable-panels.cjs.d.ts +88 -1
- package/dist/react-resizable-panels.cjs.d.ts.map +1 -1
- package/dist/react-resizable-panels.cjs.js +1481 -1983
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.cjs.js +281 -576
- package/dist/react-resizable-panels.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.esm.js +281 -577
- package/dist/react-resizable-panels.development.node.cjs.js +267 -502
- package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.node.esm.js +267 -503
- package/dist/react-resizable-panels.esm.js +1476 -1959
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +239 -444
- package/dist/react-resizable-panels.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.node.esm.js +239 -445
- 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 +221 -411
- 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/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
|
}
|
|
@@ -1193,74 +1032,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1193
1032
|
}
|
|
1194
1033
|
}
|
|
1195
1034
|
|
|
1196
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1197
|
-
return constraints.some(constraints => {
|
|
1198
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1199
|
-
});
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
1035
|
function validatePanelConstraints({
|
|
1203
|
-
|
|
1204
|
-
panelConstraints,
|
|
1036
|
+
panelConstraints: panelConstraintsArray,
|
|
1205
1037
|
panelId,
|
|
1206
1038
|
panelIndex
|
|
1207
1039
|
}) {
|
|
1208
1040
|
{
|
|
1209
1041
|
const warnings = [];
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
} = panelConstraints[panelIndex];
|
|
1221
|
-
const conflictingUnits = [];
|
|
1222
|
-
if (collapsedSizePercentage != null && collapsedSizePixels != null) {
|
|
1223
|
-
conflictingUnits.push("collapsed size");
|
|
1224
|
-
}
|
|
1225
|
-
if (defaultSizePercentage != null && defaultSizePixels != null) {
|
|
1226
|
-
conflictingUnits.push("default size");
|
|
1227
|
-
}
|
|
1228
|
-
if (maxSizePercentage != null && maxSizePixels != null) {
|
|
1229
|
-
conflictingUnits.push("max size");
|
|
1230
|
-
}
|
|
1231
|
-
if (minSizePercentage != null && minSizePixels != null) {
|
|
1232
|
-
conflictingUnits.push("min size");
|
|
1233
|
-
}
|
|
1234
|
-
if (conflictingUnits.length > 0) {
|
|
1235
|
-
warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
|
|
1236
|
-
}
|
|
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}%)`);
|
|
1237
1052
|
}
|
|
1238
|
-
{
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
minSizePercentage
|
|
1244
|
-
} = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
|
|
1245
|
-
if (minSizePercentage > maxSizePercentage) {
|
|
1246
|
-
warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
|
|
1247
|
-
}
|
|
1248
|
-
if (defaultSizePercentage != null) {
|
|
1249
|
-
if (defaultSizePercentage < 0) {
|
|
1250
|
-
warnings.push("default size should not be less than 0");
|
|
1251
|
-
} else if (defaultSizePercentage < minSizePercentage) {
|
|
1252
|
-
warnings.push("default size should not be less than min size");
|
|
1253
|
-
}
|
|
1254
|
-
if (defaultSizePercentage > 100) {
|
|
1255
|
-
warnings.push("default size should not be greater than 100");
|
|
1256
|
-
} else if (defaultSizePercentage > maxSizePercentage) {
|
|
1257
|
-
warnings.push("default size should not be greater than max size");
|
|
1258
|
-
}
|
|
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");
|
|
1259
1058
|
}
|
|
1260
|
-
if (
|
|
1261
|
-
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");
|
|
1262
1063
|
}
|
|
1263
1064
|
}
|
|
1065
|
+
if (collapsedSize > minSize) {
|
|
1066
|
+
warnings.push("collapsed size should not be greater than min size");
|
|
1067
|
+
}
|
|
1264
1068
|
if (warnings.length > 0) {
|
|
1265
1069
|
const name = panelId != null ? `Panel "${panelId}"` : "Panel";
|
|
1266
1070
|
console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
|
|
@@ -1272,20 +1076,26 @@ function validatePanelConstraints({
|
|
|
1272
1076
|
|
|
1273
1077
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1274
1078
|
function validatePanelGroupLayout({
|
|
1275
|
-
groupSizePixels,
|
|
1276
1079
|
layout: prevLayout,
|
|
1277
1080
|
panelConstraints
|
|
1278
1081
|
}) {
|
|
1279
1082
|
const nextLayout = [...prevLayout];
|
|
1083
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1280
1084
|
|
|
1281
1085
|
// Validate layout expectations
|
|
1282
1086
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1283
1087
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1284
|
-
} else if (!fuzzyNumbersEqual(
|
|
1088
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1285
1089
|
// This is not ideal so we should warn about it, but it may be recoverable in some cases
|
|
1286
1090
|
// (especially if the amount is small)
|
|
1287
1091
|
{
|
|
1288
|
-
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;
|
|
1289
1099
|
}
|
|
1290
1100
|
}
|
|
1291
1101
|
let remainingSize = 0;
|
|
@@ -1293,8 +1103,8 @@ function validatePanelGroupLayout({
|
|
|
1293
1103
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1294
1104
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1295
1105
|
const unsafeSize = nextLayout[index];
|
|
1106
|
+
assert(unsafeSize != null);
|
|
1296
1107
|
const safeSize = resizePanel({
|
|
1297
|
-
groupSizePixels,
|
|
1298
1108
|
panelConstraints,
|
|
1299
1109
|
panelIndex: index,
|
|
1300
1110
|
size: unsafeSize
|
|
@@ -1310,9 +1120,9 @@ function validatePanelGroupLayout({
|
|
|
1310
1120
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1311
1121
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1312
1122
|
const prevSize = nextLayout[index];
|
|
1123
|
+
assert(prevSize != null);
|
|
1313
1124
|
const unsafeSize = prevSize + remainingSize;
|
|
1314
1125
|
const safeSize = resizePanel({
|
|
1315
|
-
groupSizePixels,
|
|
1316
1126
|
panelConstraints,
|
|
1317
1127
|
panelIndex: index,
|
|
1318
1128
|
size: unsafeSize
|
|
@@ -1347,21 +1157,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1347
1157
|
autoSaveId = null,
|
|
1348
1158
|
children,
|
|
1349
1159
|
className: classNameFromProps = "",
|
|
1350
|
-
dataAttributes,
|
|
1351
1160
|
direction,
|
|
1352
1161
|
forwardedRef,
|
|
1353
|
-
id: idFromProps,
|
|
1162
|
+
id: idFromProps = null,
|
|
1354
1163
|
onLayout = null,
|
|
1355
|
-
|
|
1356
|
-
keyboardResizeByPixels = null,
|
|
1164
|
+
keyboardResizeBy = null,
|
|
1357
1165
|
storage = defaultStorage,
|
|
1358
1166
|
style: styleFromProps,
|
|
1359
|
-
tagName: Type = "div"
|
|
1167
|
+
tagName: Type = "div",
|
|
1168
|
+
...rest
|
|
1360
1169
|
}) {
|
|
1361
1170
|
const groupId = useUniqueId(idFromProps);
|
|
1362
1171
|
const [dragState, setDragState] = useState(null);
|
|
1363
1172
|
const [layout, setLayout] = useState([]);
|
|
1364
|
-
const
|
|
1173
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1365
1174
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1366
1175
|
const prevDeltaRef = useRef(0);
|
|
1367
1176
|
const committedValuesRef = useRef({
|
|
@@ -1369,8 +1178,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1369
1178
|
direction,
|
|
1370
1179
|
dragState,
|
|
1371
1180
|
id: groupId,
|
|
1372
|
-
|
|
1373
|
-
keyboardResizeByPixels,
|
|
1181
|
+
keyboardResizeBy,
|
|
1374
1182
|
onLayout,
|
|
1375
1183
|
storage
|
|
1376
1184
|
});
|
|
@@ -1386,33 +1194,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1386
1194
|
useImperativeHandle(forwardedRef, () => ({
|
|
1387
1195
|
getId: () => committedValuesRef.current.id,
|
|
1388
1196
|
getLayout: () => {
|
|
1389
|
-
const {
|
|
1390
|
-
id: groupId
|
|
1391
|
-
} = committedValuesRef.current;
|
|
1392
1197
|
const {
|
|
1393
1198
|
layout
|
|
1394
1199
|
} = eagerValuesRef.current;
|
|
1395
|
-
|
|
1396
|
-
return layout.map(sizePercentage => {
|
|
1397
|
-
return {
|
|
1398
|
-
sizePercentage,
|
|
1399
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1400
|
-
};
|
|
1401
|
-
});
|
|
1200
|
+
return layout;
|
|
1402
1201
|
},
|
|
1403
|
-
setLayout:
|
|
1202
|
+
setLayout: unsafeLayout => {
|
|
1404
1203
|
const {
|
|
1405
|
-
id: groupId,
|
|
1406
1204
|
onLayout
|
|
1407
1205
|
} = committedValuesRef.current;
|
|
1408
1206
|
const {
|
|
1409
1207
|
layout: prevLayout,
|
|
1410
1208
|
panelDataArray
|
|
1411
1209
|
} = eagerValuesRef.current;
|
|
1412
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1413
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1414
1210
|
const safeLayout = validatePanelGroupLayout({
|
|
1415
|
-
groupSizePixels,
|
|
1416
1211
|
layout: unsafeLayout,
|
|
1417
1212
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1418
1213
|
});
|
|
@@ -1420,12 +1215,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1420
1215
|
setLayout(safeLayout);
|
|
1421
1216
|
eagerValuesRef.current.layout = safeLayout;
|
|
1422
1217
|
if (onLayout) {
|
|
1423
|
-
onLayout(safeLayout
|
|
1424
|
-
sizePercentage,
|
|
1425
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1426
|
-
})));
|
|
1218
|
+
onLayout(safeLayout);
|
|
1427
1219
|
}
|
|
1428
|
-
callPanelCallbacks(
|
|
1220
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1429
1221
|
}
|
|
1430
1222
|
}
|
|
1431
1223
|
}), []);
|
|
@@ -1436,11 +1228,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1436
1228
|
committedValuesRef.current.id = groupId;
|
|
1437
1229
|
committedValuesRef.current.onLayout = onLayout;
|
|
1438
1230
|
committedValuesRef.current.storage = storage;
|
|
1439
|
-
|
|
1440
|
-
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1441
|
-
// TODO [217] Move these values into a separate ref
|
|
1442
1231
|
});
|
|
1443
|
-
|
|
1444
1232
|
useWindowSplitterPanelGroupBehavior({
|
|
1445
1233
|
committedValuesRef,
|
|
1446
1234
|
eagerValuesRef,
|
|
@@ -1459,57 +1247,16 @@ function PanelGroupWithForwardedRef({
|
|
|
1459
1247
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1460
1248
|
return;
|
|
1461
1249
|
}
|
|
1250
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1462
1251
|
|
|
1463
1252
|
// Limit the frequency of localStorage updates.
|
|
1464
|
-
if (
|
|
1465
|
-
|
|
1253
|
+
if (debouncedSave == null) {
|
|
1254
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1255
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1466
1256
|
}
|
|
1467
|
-
|
|
1257
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1468
1258
|
}
|
|
1469
1259
|
}, [autoSaveId, layout, storage]);
|
|
1470
|
-
useIsomorphicLayoutEffect(() => {
|
|
1471
|
-
const {
|
|
1472
|
-
layout: prevLayout,
|
|
1473
|
-
panelDataArray
|
|
1474
|
-
} = eagerValuesRef.current;
|
|
1475
|
-
const constraints = panelDataArray.map(({
|
|
1476
|
-
constraints
|
|
1477
|
-
}) => constraints);
|
|
1478
|
-
if (!shouldMonitorPixelBasedConstraints(constraints)) {
|
|
1479
|
-
// Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
|
|
1480
|
-
return;
|
|
1481
|
-
}
|
|
1482
|
-
if (typeof ResizeObserver === "undefined") {
|
|
1483
|
-
console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
|
|
1484
|
-
} else {
|
|
1485
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
1486
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1487
|
-
const {
|
|
1488
|
-
onLayout
|
|
1489
|
-
} = committedValuesRef.current;
|
|
1490
|
-
const nextLayout = validatePanelGroupLayout({
|
|
1491
|
-
groupSizePixels,
|
|
1492
|
-
layout: prevLayout,
|
|
1493
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1494
|
-
});
|
|
1495
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
1496
|
-
setLayout(nextLayout);
|
|
1497
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
1498
|
-
if (onLayout) {
|
|
1499
|
-
onLayout(nextLayout.map(sizePercentage => ({
|
|
1500
|
-
sizePercentage,
|
|
1501
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1502
|
-
})));
|
|
1503
|
-
}
|
|
1504
|
-
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1505
|
-
}
|
|
1506
|
-
});
|
|
1507
|
-
resizeObserver.observe(getPanelGroupElement(groupId));
|
|
1508
|
-
return () => {
|
|
1509
|
-
resizeObserver.disconnect();
|
|
1510
|
-
};
|
|
1511
|
-
}
|
|
1512
|
-
}, [groupId]);
|
|
1513
1260
|
|
|
1514
1261
|
// DEV warnings
|
|
1515
1262
|
useEffect(() => {
|
|
@@ -1540,12 +1287,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1540
1287
|
}
|
|
1541
1288
|
if (!didLogPanelConstraintsWarning) {
|
|
1542
1289
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1543
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1544
1290
|
for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
|
|
1291
|
+
const panelData = panelDataArray[panelIndex];
|
|
1292
|
+
assert(panelData);
|
|
1545
1293
|
const isValid = validatePanelConstraints({
|
|
1546
|
-
groupSizePixels,
|
|
1547
1294
|
panelConstraints,
|
|
1548
|
-
panelId:
|
|
1295
|
+
panelId: panelData.id,
|
|
1549
1296
|
panelIndex
|
|
1550
1297
|
});
|
|
1551
1298
|
if (!isValid) {
|
|
@@ -1569,20 +1316,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1569
1316
|
if (panelData.constraints.collapsible) {
|
|
1570
1317
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1571
1318
|
const {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
pivotIndices
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
if (
|
|
1319
|
+
collapsedSize = 0,
|
|
1320
|
+
panelSize,
|
|
1321
|
+
pivotIndices
|
|
1322
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1323
|
+
assert(panelSize != null);
|
|
1324
|
+
if (panelSize !== collapsedSize) {
|
|
1578
1325
|
// Store size before collapse;
|
|
1579
1326
|
// This is the size that gets restored if the expand() API is used.
|
|
1580
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1327
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1581
1328
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1582
|
-
const delta = isLastPanel ?
|
|
1329
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1583
1330
|
const nextLayout = adjustLayoutByDelta({
|
|
1584
1331
|
delta,
|
|
1585
|
-
groupSizePixels,
|
|
1586
1332
|
layout: prevLayout,
|
|
1587
1333
|
panelConstraints: panelConstraintsArray,
|
|
1588
1334
|
pivotIndices,
|
|
@@ -1592,16 +1338,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1592
1338
|
setLayout(nextLayout);
|
|
1593
1339
|
eagerValuesRef.current.layout = nextLayout;
|
|
1594
1340
|
if (onLayout) {
|
|
1595
|
-
onLayout(nextLayout
|
|
1596
|
-
sizePercentage,
|
|
1597
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1598
|
-
})));
|
|
1341
|
+
onLayout(nextLayout);
|
|
1599
1342
|
}
|
|
1600
|
-
callPanelCallbacks(
|
|
1343
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1601
1344
|
}
|
|
1602
1345
|
}
|
|
1603
1346
|
}
|
|
1604
|
-
}, [
|
|
1347
|
+
}, []);
|
|
1605
1348
|
|
|
1606
1349
|
// External APIs are safe to memoize via committed values ref
|
|
1607
1350
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1615,21 +1358,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1615
1358
|
if (panelData.constraints.collapsible) {
|
|
1616
1359
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1617
1360
|
const {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
pivotIndices
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1361
|
+
collapsedSize = 0,
|
|
1362
|
+
panelSize,
|
|
1363
|
+
minSize = 0,
|
|
1364
|
+
pivotIndices
|
|
1365
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1366
|
+
if (panelSize === collapsedSize) {
|
|
1625
1367
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1626
|
-
const
|
|
1627
|
-
const
|
|
1368
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1369
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1628
1370
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1629
|
-
const delta = isLastPanel ?
|
|
1371
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1630
1372
|
const nextLayout = adjustLayoutByDelta({
|
|
1631
1373
|
delta,
|
|
1632
|
-
groupSizePixels,
|
|
1633
1374
|
layout: prevLayout,
|
|
1634
1375
|
panelConstraints: panelConstraintsArray,
|
|
1635
1376
|
pivotIndices,
|
|
@@ -1639,16 +1380,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1639
1380
|
setLayout(nextLayout);
|
|
1640
1381
|
eagerValuesRef.current.layout = nextLayout;
|
|
1641
1382
|
if (onLayout) {
|
|
1642
|
-
onLayout(nextLayout
|
|
1643
|
-
sizePercentage,
|
|
1644
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1645
|
-
})));
|
|
1383
|
+
onLayout(nextLayout);
|
|
1646
1384
|
}
|
|
1647
|
-
callPanelCallbacks(
|
|
1385
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1648
1386
|
}
|
|
1649
1387
|
}
|
|
1650
1388
|
}
|
|
1651
|
-
}, [
|
|
1389
|
+
}, []);
|
|
1652
1390
|
|
|
1653
1391
|
// External APIs are safe to memoize via committed values ref
|
|
1654
1392
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1657,14 +1395,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1657
1395
|
panelDataArray
|
|
1658
1396
|
} = eagerValuesRef.current;
|
|
1659
1397
|
const {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
return
|
|
1664
|
-
|
|
1665
|
-
sizePixels: panelSizePixels
|
|
1666
|
-
};
|
|
1667
|
-
}, [groupId]);
|
|
1398
|
+
panelSize
|
|
1399
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1400
|
+
assert(panelSize != null);
|
|
1401
|
+
return panelSize;
|
|
1402
|
+
}, []);
|
|
1668
1403
|
|
|
1669
1404
|
// This API should never read from committedValuesRef
|
|
1670
1405
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1687,12 +1422,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1687
1422
|
panelDataArray
|
|
1688
1423
|
} = eagerValuesRef.current;
|
|
1689
1424
|
const {
|
|
1690
|
-
|
|
1425
|
+
collapsedSize,
|
|
1691
1426
|
collapsible,
|
|
1692
|
-
|
|
1693
|
-
} = panelDataHelper(
|
|
1694
|
-
return collapsible === true &&
|
|
1695
|
-
}, [
|
|
1427
|
+
panelSize
|
|
1428
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1429
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1430
|
+
}, []);
|
|
1696
1431
|
|
|
1697
1432
|
// External APIs are safe to memoize via committed values ref
|
|
1698
1433
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1701,12 +1436,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1701
1436
|
panelDataArray
|
|
1702
1437
|
} = eagerValuesRef.current;
|
|
1703
1438
|
const {
|
|
1704
|
-
|
|
1439
|
+
collapsedSize = 0,
|
|
1705
1440
|
collapsible,
|
|
1706
|
-
|
|
1707
|
-
} = panelDataHelper(
|
|
1708
|
-
|
|
1709
|
-
|
|
1441
|
+
panelSize
|
|
1442
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1443
|
+
assert(panelSize != null);
|
|
1444
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1445
|
+
}, []);
|
|
1710
1446
|
const registerPanel = useCallback(panelData => {
|
|
1711
1447
|
const {
|
|
1712
1448
|
autoSaveId,
|
|
@@ -1746,18 +1482,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1746
1482
|
if (autoSaveId) {
|
|
1747
1483
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1748
1484
|
}
|
|
1749
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1750
|
-
if (groupSizePixels <= 0) {
|
|
1751
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1752
|
-
constraints
|
|
1753
|
-
}) => constraints))) {
|
|
1754
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1755
|
-
return;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
1485
|
if (unsafeLayout == null) {
|
|
1759
1486
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1760
|
-
groupSizePixels,
|
|
1761
1487
|
panelDataArray
|
|
1762
1488
|
});
|
|
1763
1489
|
}
|
|
@@ -1765,7 +1491,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1765
1491
|
// Validate even saved layouts in case something has changed since last render
|
|
1766
1492
|
// e.g. for pixel groups, this could be the size of the window
|
|
1767
1493
|
const nextLayout = validatePanelGroupLayout({
|
|
1768
|
-
groupSizePixels,
|
|
1769
1494
|
layout: unsafeLayout,
|
|
1770
1495
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1771
1496
|
});
|
|
@@ -1777,12 +1502,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1777
1502
|
eagerValuesRef.current.layout = nextLayout;
|
|
1778
1503
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1779
1504
|
if (onLayout) {
|
|
1780
|
-
onLayout(nextLayout
|
|
1781
|
-
sizePercentage,
|
|
1782
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1783
|
-
})));
|
|
1505
|
+
onLayout(nextLayout);
|
|
1784
1506
|
}
|
|
1785
|
-
callPanelCallbacks(
|
|
1507
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1786
1508
|
}
|
|
1787
1509
|
}, []);
|
|
1788
1510
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1792,8 +1514,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1792
1514
|
direction,
|
|
1793
1515
|
dragState,
|
|
1794
1516
|
id: groupId,
|
|
1795
|
-
|
|
1796
|
-
keyboardResizeByPixels,
|
|
1517
|
+
keyboardResizeBy,
|
|
1797
1518
|
onLayout
|
|
1798
1519
|
} = committedValuesRef.current;
|
|
1799
1520
|
const {
|
|
@@ -1804,10 +1525,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1804
1525
|
initialLayout
|
|
1805
1526
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1806
1527
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1807
|
-
let delta = calculateDeltaPercentage(event,
|
|
1808
|
-
percentage: keyboardResizeByPercentage,
|
|
1809
|
-
pixels: keyboardResizeByPixels
|
|
1810
|
-
});
|
|
1528
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1811
1529
|
if (delta === 0) {
|
|
1812
1530
|
return;
|
|
1813
1531
|
}
|
|
@@ -1817,11 +1535,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1817
1535
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1818
1536
|
delta = -delta;
|
|
1819
1537
|
}
|
|
1820
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1821
1538
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1822
1539
|
const nextLayout = adjustLayoutByDelta({
|
|
1823
1540
|
delta,
|
|
1824
|
-
groupSizePixels,
|
|
1825
1541
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1826
1542
|
panelConstraints,
|
|
1827
1543
|
pivotIndices,
|
|
@@ -1857,18 +1573,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1857
1573
|
setLayout(nextLayout);
|
|
1858
1574
|
eagerValuesRef.current.layout = nextLayout;
|
|
1859
1575
|
if (onLayout) {
|
|
1860
|
-
onLayout(nextLayout
|
|
1861
|
-
sizePercentage,
|
|
1862
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1863
|
-
})));
|
|
1576
|
+
onLayout(nextLayout);
|
|
1864
1577
|
}
|
|
1865
|
-
callPanelCallbacks(
|
|
1578
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1866
1579
|
}
|
|
1867
1580
|
};
|
|
1868
1581
|
}, []);
|
|
1869
1582
|
|
|
1870
1583
|
// External APIs are safe to memoize via committed values ref
|
|
1871
|
-
const resizePanel = useCallback((panelData,
|
|
1584
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1872
1585
|
const {
|
|
1873
1586
|
onLayout
|
|
1874
1587
|
} = committedValuesRef.current;
|
|
@@ -1878,16 +1591,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1878
1591
|
} = eagerValuesRef.current;
|
|
1879
1592
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1880
1593
|
const {
|
|
1881
|
-
|
|
1882
|
-
panelSizePercentage,
|
|
1594
|
+
panelSize,
|
|
1883
1595
|
pivotIndices
|
|
1884
|
-
} = panelDataHelper(
|
|
1885
|
-
|
|
1596
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1597
|
+
assert(panelSize != null);
|
|
1886
1598
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1887
|
-
const delta = isLastPanel ?
|
|
1599
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1888
1600
|
const nextLayout = adjustLayoutByDelta({
|
|
1889
1601
|
delta,
|
|
1890
|
-
groupSizePixels,
|
|
1891
1602
|
layout: prevLayout,
|
|
1892
1603
|
panelConstraints: panelConstraintsArray,
|
|
1893
1604
|
pivotIndices,
|
|
@@ -1897,14 +1608,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1897
1608
|
setLayout(nextLayout);
|
|
1898
1609
|
eagerValuesRef.current.layout = nextLayout;
|
|
1899
1610
|
if (onLayout) {
|
|
1900
|
-
onLayout(nextLayout
|
|
1901
|
-
sizePercentage,
|
|
1902
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1903
|
-
})));
|
|
1611
|
+
onLayout(nextLayout);
|
|
1904
1612
|
}
|
|
1905
|
-
callPanelCallbacks(
|
|
1613
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1906
1614
|
}
|
|
1907
|
-
}, [
|
|
1615
|
+
}, []);
|
|
1908
1616
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1909
1617
|
const {
|
|
1910
1618
|
direction
|
|
@@ -1913,6 +1621,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1913
1621
|
layout
|
|
1914
1622
|
} = eagerValuesRef.current;
|
|
1915
1623
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1624
|
+
assert(handleElement);
|
|
1916
1625
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1917
1626
|
setDragState({
|
|
1918
1627
|
dragHandleId,
|
|
@@ -1931,7 +1640,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1931
1640
|
});
|
|
1932
1641
|
const unregisterPanel = useCallback(panelData => {
|
|
1933
1642
|
const {
|
|
1934
|
-
id: groupId,
|
|
1935
1643
|
onLayout
|
|
1936
1644
|
} = committedValuesRef.current;
|
|
1937
1645
|
const {
|
|
@@ -1954,7 +1662,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1954
1662
|
const {
|
|
1955
1663
|
pendingPanelIds
|
|
1956
1664
|
} = unregisterPanelRef.current;
|
|
1957
|
-
const map =
|
|
1665
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1958
1666
|
|
|
1959
1667
|
// TRICKY
|
|
1960
1668
|
// Strict effects mode
|
|
@@ -1963,7 +1671,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1963
1671
|
pendingPanelIds.delete(panelId);
|
|
1964
1672
|
if (panelDataArray.find(({
|
|
1965
1673
|
id
|
|
1966
|
-
}) => id === panelId)
|
|
1674
|
+
}) => id === panelId) != null) {
|
|
1967
1675
|
unmountDueToStrictMode = true;
|
|
1968
1676
|
|
|
1969
1677
|
// TRICKY
|
|
@@ -1980,16 +1688,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1980
1688
|
// The group is unmounting; skip layout calculation.
|
|
1981
1689
|
return;
|
|
1982
1690
|
}
|
|
1983
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1984
1691
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1985
|
-
groupSizePixels,
|
|
1986
1692
|
panelDataArray
|
|
1987
1693
|
});
|
|
1988
1694
|
|
|
1989
1695
|
// Validate even saved layouts in case something has changed since last render
|
|
1990
1696
|
// e.g. for pixel groups, this could be the size of the window
|
|
1991
1697
|
const nextLayout = validatePanelGroupLayout({
|
|
1992
|
-
groupSizePixels,
|
|
1993
1698
|
layout: unsafeLayout,
|
|
1994
1699
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1995
1700
|
});
|
|
@@ -1997,12 +1702,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1997
1702
|
setLayout(nextLayout);
|
|
1998
1703
|
eagerValuesRef.current.layout = nextLayout;
|
|
1999
1704
|
if (onLayout) {
|
|
2000
|
-
onLayout(nextLayout
|
|
2001
|
-
sizePercentage,
|
|
2002
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
2003
|
-
})));
|
|
1705
|
+
onLayout(nextLayout);
|
|
2004
1706
|
}
|
|
2005
|
-
callPanelCallbacks(
|
|
1707
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
2006
1708
|
}
|
|
2007
1709
|
}, 0);
|
|
2008
1710
|
}, []);
|
|
@@ -2033,13 +1735,13 @@ function PanelGroupWithForwardedRef({
|
|
|
2033
1735
|
return createElement(PanelGroupContext.Provider, {
|
|
2034
1736
|
value: context
|
|
2035
1737
|
}, createElement(Type, {
|
|
1738
|
+
...rest,
|
|
2036
1739
|
children,
|
|
2037
1740
|
className: classNameFromProps,
|
|
2038
1741
|
style: {
|
|
2039
1742
|
...style,
|
|
2040
1743
|
...styleFromProps
|
|
2041
1744
|
},
|
|
2042
|
-
...dataAttributes,
|
|
2043
1745
|
// CSS selectors
|
|
2044
1746
|
"data-panel-group": "",
|
|
2045
1747
|
"data-panel-group-direction": direction,
|
|
@@ -2052,22 +1754,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
2052
1754
|
}));
|
|
2053
1755
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
2054
1756
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
2055
|
-
function panelDataHelper(
|
|
1757
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
2056
1758
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
2057
1759
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
2058
1760
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
2059
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
2060
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
2061
1761
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
2062
1762
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
2063
|
-
const
|
|
2064
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1763
|
+
const panelSize = layout[panelIndex];
|
|
2065
1764
|
return {
|
|
2066
|
-
...
|
|
2067
|
-
|
|
2068
|
-
panelSizePercentage,
|
|
2069
|
-
panelSizePixels,
|
|
2070
|
-
groupSizePixels,
|
|
1765
|
+
...panelConstraints,
|
|
1766
|
+
panelSize,
|
|
2071
1767
|
pivotIndices
|
|
2072
1768
|
};
|
|
2073
1769
|
}
|
|
@@ -2107,6 +1803,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2107
1803
|
{
|
|
2108
1804
|
event.preventDefault();
|
|
2109
1805
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1806
|
+
assert(groupId);
|
|
2110
1807
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
2111
1808
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
2112
1809
|
assert(index !== null);
|
|
@@ -2127,12 +1824,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
2127
1824
|
function PanelResizeHandle({
|
|
2128
1825
|
children = null,
|
|
2129
1826
|
className: classNameFromProps = "",
|
|
2130
|
-
dataAttributes,
|
|
2131
1827
|
disabled = false,
|
|
2132
|
-
id: idFromProps
|
|
1828
|
+
id: idFromProps,
|
|
2133
1829
|
onDragging,
|
|
2134
1830
|
style: styleFromProps = {},
|
|
2135
|
-
|
|
1831
|
+
tabIndex = 0,
|
|
1832
|
+
tagName: Type = "div",
|
|
1833
|
+
...rest
|
|
2136
1834
|
}) {
|
|
2137
1835
|
const divElementRef = useRef(null);
|
|
2138
1836
|
|
|
@@ -2162,8 +1860,9 @@ function PanelResizeHandle({
|
|
|
2162
1860
|
const stopDraggingAndBlur = useCallback(() => {
|
|
2163
1861
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
2164
1862
|
// That would cause the PanelGroup to think it was still active.
|
|
2165
|
-
const
|
|
2166
|
-
|
|
1863
|
+
const divElement = divElementRef.current;
|
|
1864
|
+
assert(divElement);
|
|
1865
|
+
divElement.blur();
|
|
2167
1866
|
stopDragging();
|
|
2168
1867
|
const {
|
|
2169
1868
|
onDragging
|
|
@@ -2191,6 +1890,7 @@ function PanelResizeHandle({
|
|
|
2191
1890
|
resizeHandler(event);
|
|
2192
1891
|
};
|
|
2193
1892
|
const divElement = divElementRef.current;
|
|
1893
|
+
assert(divElement);
|
|
2194
1894
|
const targetDocument = divElement.ownerDocument;
|
|
2195
1895
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2196
1896
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2218,15 +1918,18 @@ function PanelResizeHandle({
|
|
|
2218
1918
|
userSelect: "none"
|
|
2219
1919
|
};
|
|
2220
1920
|
return createElement(Type, {
|
|
1921
|
+
...rest,
|
|
2221
1922
|
children,
|
|
2222
1923
|
className: classNameFromProps,
|
|
2223
1924
|
onBlur: () => setIsFocused(false),
|
|
2224
1925
|
onFocus: () => setIsFocused(true),
|
|
2225
1926
|
onMouseDown: event => {
|
|
2226
1927
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1928
|
+
const callbacks = callbacksRef.current;
|
|
1929
|
+
assert(callbacks);
|
|
2227
1930
|
const {
|
|
2228
1931
|
onDragging
|
|
2229
|
-
} =
|
|
1932
|
+
} = callbacks;
|
|
2230
1933
|
if (onDragging) {
|
|
2231
1934
|
onDragging(true);
|
|
2232
1935
|
}
|
|
@@ -2236,9 +1939,11 @@ function PanelResizeHandle({
|
|
|
2236
1939
|
onTouchEnd: stopDraggingAndBlur,
|
|
2237
1940
|
onTouchStart: event => {
|
|
2238
1941
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1942
|
+
const callbacks = callbacksRef.current;
|
|
1943
|
+
assert(callbacks);
|
|
2239
1944
|
const {
|
|
2240
1945
|
onDragging
|
|
2241
|
-
} =
|
|
1946
|
+
} = callbacks;
|
|
2242
1947
|
if (onDragging) {
|
|
2243
1948
|
onDragging(true);
|
|
2244
1949
|
}
|
|
@@ -2249,8 +1954,7 @@ function PanelResizeHandle({
|
|
|
2249
1954
|
...style,
|
|
2250
1955
|
...styleFromProps
|
|
2251
1956
|
},
|
|
2252
|
-
tabIndex
|
|
2253
|
-
...dataAttributes,
|
|
1957
|
+
tabIndex,
|
|
2254
1958
|
// CSS selectors
|
|
2255
1959
|
"data-panel-group-direction": direction,
|
|
2256
1960
|
"data-panel-group-id": groupId,
|
|
@@ -2265,3 +1969,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
|
2265
1969
|
exports.Panel = Panel;
|
|
2266
1970
|
exports.PanelGroup = PanelGroup;
|
|
2267
1971
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
1972
|
+
exports.assert = assert;
|