react-resizable-panels 0.0.63 → 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 +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 +252 -517
- package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +278 -573
- package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.esm.js +278 -574
- package/dist/react-resizable-panels.browser.esm.js +252 -518
- package/dist/react-resizable-panels.cjs.js +252 -517
- 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 +280 -575
- package/dist/react-resizable-panels.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.esm.js +280 -576
- package/dist/react-resizable-panels.development.node.cjs.js +266 -501
- package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.node.esm.js +266 -502
- package/dist/react-resizable-panels.esm.js +252 -518
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +238 -443
- package/dist/react-resizable-panels.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.node.esm.js +238 -444
- 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/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
|
@@ -67,24 +67,20 @@ function useUniqueId(idFromParams = null) {
|
|
|
67
67
|
function PanelWithForwardedRef({
|
|
68
68
|
children,
|
|
69
69
|
className: classNameFromProps = "",
|
|
70
|
-
|
|
71
|
-
collapsedSizePixels,
|
|
70
|
+
collapsedSize,
|
|
72
71
|
collapsible,
|
|
73
|
-
|
|
74
|
-
defaultSizePercentage,
|
|
75
|
-
defaultSizePixels,
|
|
72
|
+
defaultSize,
|
|
76
73
|
forwardedRef,
|
|
77
74
|
id: idFromProps,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
minSizePercentage,
|
|
81
|
-
minSizePixels,
|
|
75
|
+
maxSize,
|
|
76
|
+
minSize,
|
|
82
77
|
onCollapse,
|
|
83
78
|
onExpand,
|
|
84
79
|
onResize,
|
|
85
80
|
order,
|
|
86
81
|
style: styleFromProps,
|
|
87
|
-
tagName: Type = "div"
|
|
82
|
+
tagName: Type = "div",
|
|
83
|
+
...rest
|
|
88
84
|
}) {
|
|
89
85
|
const context = useContext(PanelGroupContext);
|
|
90
86
|
if (context === null) {
|
|
@@ -109,15 +105,11 @@ function PanelWithForwardedRef({
|
|
|
109
105
|
onResize
|
|
110
106
|
},
|
|
111
107
|
constraints: {
|
|
112
|
-
|
|
113
|
-
collapsedSizePixels,
|
|
108
|
+
collapsedSize,
|
|
114
109
|
collapsible,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
maxSizePixels,
|
|
119
|
-
minSizePercentage,
|
|
120
|
-
minSizePixels
|
|
110
|
+
defaultSize,
|
|
111
|
+
maxSize,
|
|
112
|
+
minSize
|
|
121
113
|
},
|
|
122
114
|
id: panelId,
|
|
123
115
|
idIsFromProps: idFromProps !== undefined,
|
|
@@ -137,15 +129,11 @@ function PanelWithForwardedRef({
|
|
|
137
129
|
callbacks.onCollapse = onCollapse;
|
|
138
130
|
callbacks.onExpand = onExpand;
|
|
139
131
|
callbacks.onResize = onResize;
|
|
140
|
-
constraints.
|
|
141
|
-
constraints.collapsedSizePixels = collapsedSizePixels;
|
|
132
|
+
constraints.collapsedSize = collapsedSize;
|
|
142
133
|
constraints.collapsible = collapsible;
|
|
143
|
-
constraints.
|
|
144
|
-
constraints.
|
|
145
|
-
constraints.
|
|
146
|
-
constraints.maxSizePixels = maxSizePixels;
|
|
147
|
-
constraints.minSizePercentage = minSizePercentage;
|
|
148
|
-
constraints.minSizePixels = minSizePixels;
|
|
134
|
+
constraints.defaultSize = defaultSize;
|
|
135
|
+
constraints.maxSize = maxSize;
|
|
136
|
+
constraints.minSize = minSize;
|
|
149
137
|
});
|
|
150
138
|
useIsomorphicLayoutEffect(() => {
|
|
151
139
|
const panelData = panelDataRef.current;
|
|
@@ -173,19 +161,19 @@ function PanelWithForwardedRef({
|
|
|
173
161
|
isExpanded() {
|
|
174
162
|
return !isPanelCollapsed(panelDataRef.current);
|
|
175
163
|
},
|
|
176
|
-
resize:
|
|
177
|
-
resizePanel(panelDataRef.current,
|
|
164
|
+
resize: size => {
|
|
165
|
+
resizePanel(panelDataRef.current, size);
|
|
178
166
|
}
|
|
179
167
|
}), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
|
|
180
168
|
const style = getPanelStyle(panelDataRef.current);
|
|
181
169
|
return createElement(Type, {
|
|
170
|
+
...rest,
|
|
182
171
|
children,
|
|
183
172
|
className: classNameFromProps,
|
|
184
173
|
style: {
|
|
185
174
|
...style,
|
|
186
175
|
...styleFromProps
|
|
187
176
|
},
|
|
188
|
-
...dataAttributes,
|
|
189
177
|
// CSS selectors
|
|
190
178
|
"data-panel": "",
|
|
191
179
|
"data-panel-id": panelId,
|
|
@@ -202,81 +190,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
202
190
|
PanelWithForwardedRef.displayName = "Panel";
|
|
203
191
|
Panel.displayName = "forwardRef(Panel)";
|
|
204
192
|
|
|
205
|
-
function
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
|
|
210
|
-
let {
|
|
211
|
-
collapsedSizePercentage = 0,
|
|
212
|
-
collapsedSizePixels,
|
|
213
|
-
defaultSizePercentage,
|
|
214
|
-
defaultSizePixels,
|
|
215
|
-
maxSizePercentage = 100,
|
|
216
|
-
maxSizePixels,
|
|
217
|
-
minSizePercentage = 0,
|
|
218
|
-
minSizePixels
|
|
219
|
-
} = panelConstraints;
|
|
220
|
-
const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
|
|
221
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
222
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
223
|
-
return {
|
|
224
|
-
collapsedSizePercentage: 0,
|
|
225
|
-
defaultSizePercentage,
|
|
226
|
-
maxSizePercentage: 0,
|
|
227
|
-
minSizePercentage: 0
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
if (collapsedSizePixels != null) {
|
|
231
|
-
collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
|
|
232
|
-
}
|
|
233
|
-
if (defaultSizePixels != null) {
|
|
234
|
-
defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
|
|
235
|
-
}
|
|
236
|
-
if (minSizePixels != null) {
|
|
237
|
-
minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
|
|
238
|
-
}
|
|
239
|
-
if (maxSizePixels != null) {
|
|
240
|
-
maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
collapsedSizePercentage,
|
|
244
|
-
defaultSizePercentage,
|
|
245
|
-
maxSizePercentage,
|
|
246
|
-
minSizePercentage
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
|
|
251
|
-
// All panel constraints, excluding the current one
|
|
252
|
-
let totalMinConstraints = 0;
|
|
253
|
-
let totalMaxConstraints = 0;
|
|
254
|
-
for (let index = 0; index < panelConstraintsArray.length; index++) {
|
|
255
|
-
if (index !== panelIndex) {
|
|
256
|
-
const {
|
|
257
|
-
collapsible
|
|
258
|
-
} = panelConstraintsArray[index];
|
|
259
|
-
const {
|
|
260
|
-
collapsedSizePercentage,
|
|
261
|
-
maxSizePercentage,
|
|
262
|
-
minSizePercentage
|
|
263
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
|
|
264
|
-
totalMaxConstraints += maxSizePercentage;
|
|
265
|
-
totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
|
|
266
|
-
}
|
|
193
|
+
function assert(expectedCondition, message = "Assertion failed!") {
|
|
194
|
+
if (!expectedCondition) {
|
|
195
|
+
console.error(message);
|
|
196
|
+
throw Error(message);
|
|
267
197
|
}
|
|
268
|
-
const {
|
|
269
|
-
collapsedSizePercentage,
|
|
270
|
-
defaultSizePercentage,
|
|
271
|
-
maxSizePercentage,
|
|
272
|
-
minSizePercentage
|
|
273
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
|
|
274
|
-
return {
|
|
275
|
-
collapsedSizePercentage,
|
|
276
|
-
defaultSizePercentage,
|
|
277
|
-
maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
|
|
278
|
-
minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
|
|
279
|
-
};
|
|
280
198
|
}
|
|
281
199
|
|
|
282
200
|
const PRECISION = 10;
|
|
@@ -298,56 +216,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
|
|
|
298
216
|
|
|
299
217
|
// Panel size must be in percentages; pixel values should be pre-converted
|
|
300
218
|
function resizePanel({
|
|
301
|
-
|
|
302
|
-
panelConstraints,
|
|
219
|
+
panelConstraints: panelConstraintsArray,
|
|
303
220
|
panelIndex,
|
|
304
221
|
size
|
|
305
222
|
}) {
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
defaultSizePixels,
|
|
309
|
-
minSizePixels,
|
|
310
|
-
maxSizePixels
|
|
311
|
-
}) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
|
|
312
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
313
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
314
|
-
return 0;
|
|
315
|
-
}
|
|
223
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
224
|
+
assert(panelConstraints != null);
|
|
316
225
|
let {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
|
|
329
|
-
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
330
|
-
size = collapsedSizePercentage;
|
|
331
|
-
} else {
|
|
332
|
-
size = minSizePercentage;
|
|
333
|
-
}
|
|
226
|
+
collapsedSize = 0,
|
|
227
|
+
collapsible,
|
|
228
|
+
maxSize = 100,
|
|
229
|
+
minSize = 0
|
|
230
|
+
} = panelConstraints;
|
|
231
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
232
|
+
if (collapsible) {
|
|
233
|
+
// Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
|
|
234
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
235
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
236
|
+
size = collapsedSize;
|
|
334
237
|
} else {
|
|
335
|
-
size =
|
|
238
|
+
size = minSize;
|
|
336
239
|
}
|
|
240
|
+
} else {
|
|
241
|
+
size = minSize;
|
|
337
242
|
}
|
|
338
243
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
244
|
+
size = Math.min(maxSize, size);
|
|
245
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
342
246
|
return size;
|
|
343
247
|
}
|
|
344
248
|
|
|
345
249
|
// All units must be in percentages; pixel values should be pre-converted
|
|
346
250
|
function adjustLayoutByDelta({
|
|
347
251
|
delta,
|
|
348
|
-
groupSizePixels,
|
|
349
252
|
layout: prevLayout,
|
|
350
|
-
panelConstraints,
|
|
253
|
+
panelConstraints: panelConstraintsArray,
|
|
351
254
|
pivotIndices,
|
|
352
255
|
trigger
|
|
353
256
|
}) {
|
|
@@ -355,6 +258,9 @@ function adjustLayoutByDelta({
|
|
|
355
258
|
return prevLayout;
|
|
356
259
|
}
|
|
357
260
|
const nextLayout = [...prevLayout];
|
|
261
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
262
|
+
assert(firstPivotIndex != null);
|
|
263
|
+
assert(secondPivotIndex != null);
|
|
358
264
|
let deltaApplied = 0;
|
|
359
265
|
|
|
360
266
|
//const DEBUG = [];
|
|
@@ -378,18 +284,23 @@ function adjustLayoutByDelta({
|
|
|
378
284
|
if (trigger === "keyboard") {
|
|
379
285
|
{
|
|
380
286
|
// Check if we should expand a collapsed panel
|
|
381
|
-
const index = delta < 0 ?
|
|
382
|
-
const
|
|
287
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
288
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
289
|
+
assert(panelConstraints);
|
|
290
|
+
|
|
383
291
|
//DEBUG.push(`edge case check 1: ${index}`);
|
|
384
292
|
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
385
|
-
if (
|
|
293
|
+
if (panelConstraints.collapsible) {
|
|
386
294
|
const prevSize = prevLayout[index];
|
|
295
|
+
assert(prevSize != null);
|
|
296
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
297
|
+
assert(panelConstraints);
|
|
387
298
|
const {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
} =
|
|
391
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
392
|
-
const localDelta =
|
|
299
|
+
collapsedSize = 0,
|
|
300
|
+
minSize = 0
|
|
301
|
+
} = panelConstraints;
|
|
302
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
|
|
303
|
+
const localDelta = minSize - prevSize;
|
|
393
304
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
394
305
|
|
|
395
306
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -402,18 +313,26 @@ function adjustLayoutByDelta({
|
|
|
402
313
|
|
|
403
314
|
{
|
|
404
315
|
// Check if we should collapse a panel at its minimum size
|
|
405
|
-
const index = delta < 0 ?
|
|
406
|
-
const
|
|
316
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
317
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
318
|
+
assert(panelConstraints);
|
|
319
|
+
const {
|
|
320
|
+
collapsible
|
|
321
|
+
} = panelConstraints;
|
|
322
|
+
|
|
407
323
|
//DEBUG.push(`edge case check 2: ${index}`);
|
|
408
|
-
//DEBUG.push(` -> collapsible? ${
|
|
409
|
-
if (
|
|
324
|
+
//DEBUG.push(` -> collapsible? ${collapsible}`);
|
|
325
|
+
if (collapsible) {
|
|
410
326
|
const prevSize = prevLayout[index];
|
|
327
|
+
assert(prevSize != null);
|
|
328
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
329
|
+
assert(panelConstraints);
|
|
411
330
|
const {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
} =
|
|
415
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
416
|
-
const localDelta = prevSize -
|
|
331
|
+
collapsedSize = 0,
|
|
332
|
+
minSize = 0
|
|
333
|
+
} = panelConstraints;
|
|
334
|
+
if (fuzzyNumbersEqual(prevSize, minSize)) {
|
|
335
|
+
const localDelta = prevSize - collapsedSize;
|
|
417
336
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
418
337
|
|
|
419
338
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -435,15 +354,15 @@ function adjustLayoutByDelta({
|
|
|
435
354
|
// as an expanding panel might change from collapsed to min size.
|
|
436
355
|
|
|
437
356
|
const increment = delta < 0 ? 1 : -1;
|
|
438
|
-
let index = delta < 0 ?
|
|
357
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
439
358
|
let maxAvailableDelta = 0;
|
|
440
359
|
|
|
441
360
|
//DEBUG.push("pre calc...");
|
|
442
361
|
while (true) {
|
|
443
362
|
const prevSize = prevLayout[index];
|
|
363
|
+
assert(prevSize != null);
|
|
444
364
|
const maxSafeSize = resizePanel({
|
|
445
|
-
|
|
446
|
-
panelConstraints,
|
|
365
|
+
panelConstraints: panelConstraintsArray,
|
|
447
366
|
panelIndex: index,
|
|
448
367
|
size: 100
|
|
449
368
|
});
|
|
@@ -452,7 +371,7 @@ function adjustLayoutByDelta({
|
|
|
452
371
|
|
|
453
372
|
maxAvailableDelta += delta;
|
|
454
373
|
index += increment;
|
|
455
|
-
if (index < 0 || index >=
|
|
374
|
+
if (index < 0 || index >= panelConstraintsArray.length) {
|
|
456
375
|
break;
|
|
457
376
|
}
|
|
458
377
|
}
|
|
@@ -467,15 +386,15 @@ function adjustLayoutByDelta({
|
|
|
467
386
|
{
|
|
468
387
|
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
469
388
|
|
|
470
|
-
const pivotIndex = delta < 0 ?
|
|
389
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
471
390
|
let index = pivotIndex;
|
|
472
|
-
while (index >= 0 && index <
|
|
391
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
473
392
|
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
474
393
|
const prevSize = prevLayout[index];
|
|
394
|
+
assert(prevSize != null);
|
|
475
395
|
const unsafeSize = prevSize - deltaRemaining;
|
|
476
396
|
const safeSize = resizePanel({
|
|
477
|
-
|
|
478
|
-
panelConstraints,
|
|
397
|
+
panelConstraints: panelConstraintsArray,
|
|
479
398
|
panelIndex: index,
|
|
480
399
|
size: unsafeSize
|
|
481
400
|
});
|
|
@@ -507,11 +426,12 @@ function adjustLayoutByDelta({
|
|
|
507
426
|
}
|
|
508
427
|
{
|
|
509
428
|
// Now distribute the applied delta to the panels in the other direction
|
|
510
|
-
const pivotIndex = delta < 0 ?
|
|
511
|
-
const
|
|
429
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
430
|
+
const prevSize = prevLayout[pivotIndex];
|
|
431
|
+
assert(prevSize != null);
|
|
432
|
+
const unsafeSize = prevSize + deltaApplied;
|
|
512
433
|
const safeSize = resizePanel({
|
|
513
|
-
|
|
514
|
-
panelConstraints,
|
|
434
|
+
panelConstraints: panelConstraintsArray,
|
|
515
435
|
panelIndex: pivotIndex,
|
|
516
436
|
size: unsafeSize
|
|
517
437
|
});
|
|
@@ -522,14 +442,14 @@ function adjustLayoutByDelta({
|
|
|
522
442
|
// Edge case where expanding or contracting one panel caused another one to change collapsed state
|
|
523
443
|
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
524
444
|
let deltaRemaining = unsafeSize - safeSize;
|
|
525
|
-
const pivotIndex = delta < 0 ?
|
|
445
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
526
446
|
let index = pivotIndex;
|
|
527
|
-
while (index >= 0 && index <
|
|
447
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
528
448
|
const prevSize = nextLayout[index];
|
|
449
|
+
assert(prevSize != null);
|
|
529
450
|
const unsafeSize = prevSize + deltaRemaining;
|
|
530
451
|
const safeSize = resizePanel({
|
|
531
|
-
|
|
532
|
-
panelConstraints,
|
|
452
|
+
panelConstraints: panelConstraintsArray,
|
|
533
453
|
panelIndex: index,
|
|
534
454
|
size: unsafeSize
|
|
535
455
|
});
|
|
@@ -553,9 +473,7 @@ function adjustLayoutByDelta({
|
|
|
553
473
|
//DEBUG.push("");
|
|
554
474
|
|
|
555
475
|
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
556
|
-
deltaApplied = 100 - totalSize;
|
|
557
476
|
//DEBUG.push(`total size: ${totalSize}`);
|
|
558
|
-
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
559
477
|
//console.log(DEBUG.join("\n"));
|
|
560
478
|
|
|
561
479
|
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
@@ -564,27 +482,7 @@ function adjustLayoutByDelta({
|
|
|
564
482
|
return nextLayout;
|
|
565
483
|
}
|
|
566
484
|
|
|
567
|
-
function assert(expectedCondition, message = "Assertion failed!") {
|
|
568
|
-
if (!expectedCondition) {
|
|
569
|
-
console.error(message);
|
|
570
|
-
throw Error(message);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
function getPercentageSizeFromMixedSizes({
|
|
575
|
-
sizePercentage,
|
|
576
|
-
sizePixels
|
|
577
|
-
}, groupSizePixels) {
|
|
578
|
-
if (sizePercentage != null) {
|
|
579
|
-
return sizePercentage;
|
|
580
|
-
} else if (sizePixels != null) {
|
|
581
|
-
return convertPixelsToPercentage(sizePixels, groupSizePixels);
|
|
582
|
-
}
|
|
583
|
-
return undefined;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
485
|
function calculateAriaValues({
|
|
587
|
-
groupSizePixels,
|
|
588
486
|
layout,
|
|
589
487
|
panelsArray,
|
|
590
488
|
pivotIndices
|
|
@@ -593,28 +491,19 @@ function calculateAriaValues({
|
|
|
593
491
|
let currentMaxSize = 100;
|
|
594
492
|
let totalMinSize = 0;
|
|
595
493
|
let totalMaxSize = 0;
|
|
494
|
+
const firstIndex = pivotIndices[0];
|
|
495
|
+
assert(firstIndex != null);
|
|
596
496
|
|
|
597
497
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
598
498
|
panelsArray.forEach((panelData, index) => {
|
|
599
|
-
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
600
499
|
const {
|
|
601
500
|
constraints
|
|
602
501
|
} = panelData;
|
|
603
502
|
const {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
minSizePercentage,
|
|
607
|
-
minSizePixels
|
|
503
|
+
maxSize = 100,
|
|
504
|
+
minSize = 0
|
|
608
505
|
} = constraints;
|
|
609
|
-
|
|
610
|
-
sizePercentage: minSizePercentage,
|
|
611
|
-
sizePixels: minSizePixels
|
|
612
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
613
|
-
const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
614
|
-
sizePercentage: maxSizePercentage,
|
|
615
|
-
sizePixels: maxSizePixels
|
|
616
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
|
|
617
|
-
if (index === pivotIndices[0]) {
|
|
506
|
+
if (index === firstIndex) {
|
|
618
507
|
currentMinSize = minSize;
|
|
619
508
|
currentMaxSize = maxSize;
|
|
620
509
|
} else {
|
|
@@ -624,7 +513,7 @@ function calculateAriaValues({
|
|
|
624
513
|
});
|
|
625
514
|
const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
626
515
|
const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
|
|
627
|
-
const valueNow = layout[
|
|
516
|
+
const valueNow = layout[firstIndex];
|
|
628
517
|
return {
|
|
629
518
|
valueMax,
|
|
630
519
|
valueMin,
|
|
@@ -655,42 +544,6 @@ function getPanelGroupElement(id) {
|
|
|
655
544
|
return null;
|
|
656
545
|
}
|
|
657
546
|
|
|
658
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
659
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
660
|
-
if (panelGroupElement == null) {
|
|
661
|
-
return NaN;
|
|
662
|
-
}
|
|
663
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
664
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
665
|
-
if (direction === "horizontal") {
|
|
666
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
667
|
-
return accumulated + handle.offsetWidth;
|
|
668
|
-
}, 0);
|
|
669
|
-
} else {
|
|
670
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
671
|
-
return accumulated + handle.offsetHeight;
|
|
672
|
-
}, 0);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
677
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
678
|
-
if (panelGroupElement == null) {
|
|
679
|
-
return NaN;
|
|
680
|
-
}
|
|
681
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
682
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
683
|
-
if (direction === "horizontal") {
|
|
684
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
685
|
-
return accumulated + handle.offsetWidth;
|
|
686
|
-
}, 0);
|
|
687
|
-
} else {
|
|
688
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
689
|
-
return accumulated + handle.offsetHeight;
|
|
690
|
-
}, 0);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
|
|
694
547
|
function getResizeHandleElement(id) {
|
|
695
548
|
const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
696
549
|
if (element) {
|
|
@@ -723,7 +576,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
723
576
|
didWarnAboutMissingResizeHandle: false
|
|
724
577
|
});
|
|
725
578
|
useIsomorphicLayoutEffect(() => {
|
|
726
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
727
579
|
const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
|
|
728
580
|
for (let index = 0; index < panelDataArray.length - 1; index++) {
|
|
729
581
|
const {
|
|
@@ -731,17 +583,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
731
583
|
valueMin,
|
|
732
584
|
valueNow
|
|
733
585
|
} = calculateAriaValues({
|
|
734
|
-
groupSizePixels,
|
|
735
586
|
layout,
|
|
736
587
|
panelsArray: panelDataArray,
|
|
737
588
|
pivotIndices: [index, index + 1]
|
|
738
589
|
});
|
|
739
590
|
const resizeHandleElement = resizeHandleElements[index];
|
|
740
591
|
if (resizeHandleElement == null) ; else {
|
|
741
|
-
|
|
592
|
+
const panelData = panelDataArray[index];
|
|
593
|
+
assert(panelData);
|
|
594
|
+
resizeHandleElement.setAttribute("aria-controls", panelData.id);
|
|
742
595
|
resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
|
|
743
596
|
resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
|
|
744
|
-
resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
|
|
597
|
+
resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
|
|
745
598
|
}
|
|
746
599
|
}
|
|
747
600
|
return () => {
|
|
@@ -754,14 +607,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
754
607
|
};
|
|
755
608
|
}, [groupId, layout, panelDataArray]);
|
|
756
609
|
useEffect(() => {
|
|
610
|
+
const eagerValues = eagerValuesRef.current;
|
|
611
|
+
assert(eagerValues);
|
|
757
612
|
const {
|
|
758
613
|
panelDataArray
|
|
759
|
-
} =
|
|
614
|
+
} = eagerValues;
|
|
760
615
|
const groupElement = getPanelGroupElement(groupId);
|
|
761
616
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
762
617
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
618
|
+
assert(handles);
|
|
763
619
|
const cleanupFunctions = handles.map(handle => {
|
|
764
620
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
621
|
+
assert(handleId);
|
|
765
622
|
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
766
623
|
if (idBefore == null || idAfter == null) {
|
|
767
624
|
return () => {};
|
|
@@ -777,21 +634,16 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
777
634
|
const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
|
|
778
635
|
if (index >= 0) {
|
|
779
636
|
const panelData = panelDataArray[index];
|
|
637
|
+
assert(panelData);
|
|
780
638
|
const size = layout[index];
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
788
|
-
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
789
|
-
sizePercentage: panelData.constraints.minSizePercentage,
|
|
790
|
-
sizePixels: panelData.constraints.minSizePixels
|
|
791
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
639
|
+
const {
|
|
640
|
+
collapsedSize = 0,
|
|
641
|
+
collapsible,
|
|
642
|
+
minSize = 0
|
|
643
|
+
} = panelData.constraints;
|
|
644
|
+
if (size != null && collapsible) {
|
|
792
645
|
const nextLayout = adjustLayoutByDelta({
|
|
793
646
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
794
|
-
groupSizePixels,
|
|
795
647
|
layout,
|
|
796
648
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
797
649
|
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
@@ -845,6 +697,7 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
845
697
|
return isHorizontal ? event.clientX : event.clientY;
|
|
846
698
|
} else if (isTouchEvent(event)) {
|
|
847
699
|
const firstTouch = event.touches[0];
|
|
700
|
+
assert(firstTouch);
|
|
848
701
|
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
849
702
|
} else {
|
|
850
703
|
throw Error(`Unsupported event type "${event.type}"`);
|
|
@@ -854,12 +707,15 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
854
707
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
855
708
|
const isHorizontal = direction === "horizontal";
|
|
856
709
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
710
|
+
assert(handleElement);
|
|
857
711
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
712
|
+
assert(groupId);
|
|
858
713
|
let {
|
|
859
714
|
initialCursorPosition
|
|
860
715
|
} = initialDragState;
|
|
861
716
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
862
717
|
const groupElement = getPanelGroupElement(groupId);
|
|
718
|
+
assert(groupElement);
|
|
863
719
|
const groupRect = groupElement.getBoundingClientRect();
|
|
864
720
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
865
721
|
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
@@ -868,19 +724,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
868
724
|
}
|
|
869
725
|
|
|
870
726
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
871
|
-
function calculateDeltaPercentage(event,
|
|
727
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
872
728
|
if (isKeyDown(event)) {
|
|
873
729
|
const isHorizontal = direction === "horizontal";
|
|
874
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
875
|
-
const rect = groupElement.getBoundingClientRect();
|
|
876
|
-
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
877
730
|
let delta = 0;
|
|
878
731
|
if (event.shiftKey) {
|
|
879
732
|
delta = 100;
|
|
880
|
-
} else if (
|
|
881
|
-
delta =
|
|
882
|
-
} else if (keyboardResizeByOptions.pixels != null) {
|
|
883
|
-
delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
|
|
733
|
+
} else if (keyboardResizeBy != null) {
|
|
734
|
+
delta = keyboardResizeBy;
|
|
884
735
|
} else {
|
|
885
736
|
delta = 10;
|
|
886
737
|
}
|
|
@@ -907,37 +758,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
907
758
|
}
|
|
908
759
|
return movement;
|
|
909
760
|
} else {
|
|
761
|
+
if (initialDragState == null) {
|
|
762
|
+
return 0;
|
|
763
|
+
}
|
|
910
764
|
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
911
765
|
}
|
|
912
766
|
}
|
|
913
767
|
|
|
914
768
|
function calculateUnsafeDefaultLayout({
|
|
915
|
-
groupSizePixels,
|
|
916
769
|
panelDataArray
|
|
917
770
|
}) {
|
|
918
771
|
const layout = Array(panelDataArray.length);
|
|
919
|
-
const
|
|
772
|
+
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
920
773
|
let numPanelsWithSizes = 0;
|
|
921
774
|
let remainingSize = 100;
|
|
922
775
|
|
|
923
776
|
// Distribute default sizes first
|
|
924
777
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
778
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
779
|
+
assert(panelConstraints);
|
|
925
780
|
const {
|
|
926
|
-
|
|
927
|
-
} =
|
|
928
|
-
if (
|
|
781
|
+
defaultSize
|
|
782
|
+
} = panelConstraints;
|
|
783
|
+
if (defaultSize != null) {
|
|
929
784
|
numPanelsWithSizes++;
|
|
930
|
-
layout[index] =
|
|
931
|
-
remainingSize -=
|
|
785
|
+
layout[index] = defaultSize;
|
|
786
|
+
remainingSize -= defaultSize;
|
|
932
787
|
}
|
|
933
788
|
}
|
|
934
789
|
|
|
935
790
|
// Remaining size should be distributed evenly between panels without default sizes
|
|
936
791
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
792
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
793
|
+
assert(panelConstraints);
|
|
937
794
|
const {
|
|
938
|
-
|
|
939
|
-
} =
|
|
940
|
-
if (
|
|
795
|
+
defaultSize
|
|
796
|
+
} = panelConstraints;
|
|
797
|
+
if (defaultSize != null) {
|
|
941
798
|
continue;
|
|
942
799
|
}
|
|
943
800
|
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
@@ -949,54 +806,36 @@ function calculateUnsafeDefaultLayout({
|
|
|
949
806
|
return layout;
|
|
950
807
|
}
|
|
951
808
|
|
|
952
|
-
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
953
|
-
return percentage / 100 * groupSizePixels;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
809
|
// Layout should be pre-converted into percentages
|
|
957
|
-
function callPanelCallbacks(
|
|
958
|
-
|
|
959
|
-
layout.forEach((sizePercentage, index) => {
|
|
810
|
+
function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
|
|
811
|
+
layout.forEach((size, index) => {
|
|
960
812
|
const panelData = panelsArray[index];
|
|
961
|
-
|
|
962
|
-
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
963
|
-
// The subsequent render+effects will handle the resize notification
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
813
|
+
assert(panelData);
|
|
966
814
|
const {
|
|
967
815
|
callbacks,
|
|
968
816
|
constraints,
|
|
969
817
|
id: panelId
|
|
970
818
|
} = panelData;
|
|
971
819
|
const {
|
|
820
|
+
collapsedSize = 0,
|
|
972
821
|
collapsible
|
|
973
822
|
} = constraints;
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
};
|
|
978
|
-
const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
|
|
979
|
-
if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
|
|
980
|
-
panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
|
|
823
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
|
|
824
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
825
|
+
panelIdToLastNotifiedSizeMap[panelId] = size;
|
|
981
826
|
const {
|
|
982
827
|
onCollapse,
|
|
983
828
|
onExpand,
|
|
984
829
|
onResize
|
|
985
830
|
} = callbacks;
|
|
986
831
|
if (onResize) {
|
|
987
|
-
onResize(
|
|
832
|
+
onResize(size, lastNotifiedSize);
|
|
988
833
|
}
|
|
989
834
|
if (collapsible && (onCollapse || onExpand)) {
|
|
990
|
-
|
|
991
|
-
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
992
|
-
sizePercentage: constraints.collapsedSizePercentage,
|
|
993
|
-
sizePixels: constraints.collapsedSizePixels
|
|
994
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
995
|
-
const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
|
|
996
|
-
if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
|
|
835
|
+
if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
997
836
|
onExpand();
|
|
998
837
|
}
|
|
999
|
-
if (onCollapse && (
|
|
838
|
+
if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
|
|
1000
839
|
onCollapse();
|
|
1001
840
|
}
|
|
1002
841
|
}
|
|
@@ -1179,31 +1018,32 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1179
1018
|
}
|
|
1180
1019
|
}
|
|
1181
1020
|
|
|
1182
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1183
|
-
return constraints.some(constraints => {
|
|
1184
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1185
|
-
});
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
1021
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1189
1022
|
function validatePanelGroupLayout({
|
|
1190
|
-
groupSizePixels,
|
|
1191
1023
|
layout: prevLayout,
|
|
1192
1024
|
panelConstraints
|
|
1193
1025
|
}) {
|
|
1194
1026
|
const nextLayout = [...prevLayout];
|
|
1027
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1195
1028
|
|
|
1196
1029
|
// Validate layout expectations
|
|
1197
1030
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1198
1031
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1199
|
-
} else if (!fuzzyNumbersEqual(
|
|
1032
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1033
|
+
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1034
|
+
const unsafeSize = nextLayout[index];
|
|
1035
|
+
assert(unsafeSize != null);
|
|
1036
|
+
const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
|
|
1037
|
+
nextLayout[index] = safeSize;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1200
1040
|
let remainingSize = 0;
|
|
1201
1041
|
|
|
1202
1042
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1203
1043
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1204
1044
|
const unsafeSize = nextLayout[index];
|
|
1045
|
+
assert(unsafeSize != null);
|
|
1205
1046
|
const safeSize = resizePanel({
|
|
1206
|
-
groupSizePixels,
|
|
1207
1047
|
panelConstraints,
|
|
1208
1048
|
panelIndex: index,
|
|
1209
1049
|
size: unsafeSize
|
|
@@ -1219,9 +1059,9 @@ function validatePanelGroupLayout({
|
|
|
1219
1059
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1220
1060
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1221
1061
|
const prevSize = nextLayout[index];
|
|
1062
|
+
assert(prevSize != null);
|
|
1222
1063
|
const unsafeSize = prevSize + remainingSize;
|
|
1223
1064
|
const safeSize = resizePanel({
|
|
1224
|
-
groupSizePixels,
|
|
1225
1065
|
panelConstraints,
|
|
1226
1066
|
panelIndex: index,
|
|
1227
1067
|
size: unsafeSize
|
|
@@ -1256,21 +1096,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1256
1096
|
autoSaveId = null,
|
|
1257
1097
|
children,
|
|
1258
1098
|
className: classNameFromProps = "",
|
|
1259
|
-
dataAttributes,
|
|
1260
1099
|
direction,
|
|
1261
1100
|
forwardedRef,
|
|
1262
|
-
id: idFromProps,
|
|
1101
|
+
id: idFromProps = null,
|
|
1263
1102
|
onLayout = null,
|
|
1264
|
-
|
|
1265
|
-
keyboardResizeByPixels = null,
|
|
1103
|
+
keyboardResizeBy = null,
|
|
1266
1104
|
storage = defaultStorage,
|
|
1267
1105
|
style: styleFromProps,
|
|
1268
|
-
tagName: Type = "div"
|
|
1106
|
+
tagName: Type = "div",
|
|
1107
|
+
...rest
|
|
1269
1108
|
}) {
|
|
1270
1109
|
const groupId = useUniqueId(idFromProps);
|
|
1271
1110
|
const [dragState, setDragState] = useState(null);
|
|
1272
1111
|
const [layout, setLayout] = useState([]);
|
|
1273
|
-
const
|
|
1112
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1274
1113
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1275
1114
|
const prevDeltaRef = useRef(0);
|
|
1276
1115
|
const committedValuesRef = useRef({
|
|
@@ -1278,8 +1117,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1278
1117
|
direction,
|
|
1279
1118
|
dragState,
|
|
1280
1119
|
id: groupId,
|
|
1281
|
-
|
|
1282
|
-
keyboardResizeByPixels,
|
|
1120
|
+
keyboardResizeBy,
|
|
1283
1121
|
onLayout,
|
|
1284
1122
|
storage
|
|
1285
1123
|
});
|
|
@@ -1295,33 +1133,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1295
1133
|
useImperativeHandle(forwardedRef, () => ({
|
|
1296
1134
|
getId: () => committedValuesRef.current.id,
|
|
1297
1135
|
getLayout: () => {
|
|
1298
|
-
const {
|
|
1299
|
-
id: groupId
|
|
1300
|
-
} = committedValuesRef.current;
|
|
1301
1136
|
const {
|
|
1302
1137
|
layout
|
|
1303
1138
|
} = eagerValuesRef.current;
|
|
1304
|
-
|
|
1305
|
-
return layout.map(sizePercentage => {
|
|
1306
|
-
return {
|
|
1307
|
-
sizePercentage,
|
|
1308
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1309
|
-
};
|
|
1310
|
-
});
|
|
1139
|
+
return layout;
|
|
1311
1140
|
},
|
|
1312
|
-
setLayout:
|
|
1141
|
+
setLayout: unsafeLayout => {
|
|
1313
1142
|
const {
|
|
1314
|
-
id: groupId,
|
|
1315
1143
|
onLayout
|
|
1316
1144
|
} = committedValuesRef.current;
|
|
1317
1145
|
const {
|
|
1318
1146
|
layout: prevLayout,
|
|
1319
1147
|
panelDataArray
|
|
1320
1148
|
} = eagerValuesRef.current;
|
|
1321
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1322
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1323
1149
|
const safeLayout = validatePanelGroupLayout({
|
|
1324
|
-
groupSizePixels,
|
|
1325
1150
|
layout: unsafeLayout,
|
|
1326
1151
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1327
1152
|
});
|
|
@@ -1329,12 +1154,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1329
1154
|
setLayout(safeLayout);
|
|
1330
1155
|
eagerValuesRef.current.layout = safeLayout;
|
|
1331
1156
|
if (onLayout) {
|
|
1332
|
-
onLayout(safeLayout
|
|
1333
|
-
sizePercentage,
|
|
1334
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1335
|
-
})));
|
|
1157
|
+
onLayout(safeLayout);
|
|
1336
1158
|
}
|
|
1337
|
-
callPanelCallbacks(
|
|
1159
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1338
1160
|
}
|
|
1339
1161
|
}
|
|
1340
1162
|
}), []);
|
|
@@ -1345,11 +1167,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1345
1167
|
committedValuesRef.current.id = groupId;
|
|
1346
1168
|
committedValuesRef.current.onLayout = onLayout;
|
|
1347
1169
|
committedValuesRef.current.storage = storage;
|
|
1348
|
-
|
|
1349
|
-
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1350
|
-
// TODO [217] Move these values into a separate ref
|
|
1351
1170
|
});
|
|
1352
|
-
|
|
1353
1171
|
useWindowSplitterPanelGroupBehavior({
|
|
1354
1172
|
committedValuesRef,
|
|
1355
1173
|
eagerValuesRef,
|
|
@@ -1368,57 +1186,16 @@ function PanelGroupWithForwardedRef({
|
|
|
1368
1186
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1369
1187
|
return;
|
|
1370
1188
|
}
|
|
1189
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1371
1190
|
|
|
1372
1191
|
// Limit the frequency of localStorage updates.
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1192
|
+
if (debouncedSave == null) {
|
|
1193
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1194
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1375
1195
|
}
|
|
1376
|
-
|
|
1196
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1377
1197
|
}
|
|
1378
1198
|
}, [autoSaveId, layout, storage]);
|
|
1379
|
-
useIsomorphicLayoutEffect(() => {
|
|
1380
|
-
const {
|
|
1381
|
-
layout: prevLayout,
|
|
1382
|
-
panelDataArray
|
|
1383
|
-
} = eagerValuesRef.current;
|
|
1384
|
-
const constraints = panelDataArray.map(({
|
|
1385
|
-
constraints
|
|
1386
|
-
}) => constraints);
|
|
1387
|
-
if (!shouldMonitorPixelBasedConstraints(constraints)) {
|
|
1388
|
-
// Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
|
|
1389
|
-
return;
|
|
1390
|
-
}
|
|
1391
|
-
if (typeof ResizeObserver === "undefined") {
|
|
1392
|
-
console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
|
|
1393
|
-
} else {
|
|
1394
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
1395
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1396
|
-
const {
|
|
1397
|
-
onLayout
|
|
1398
|
-
} = committedValuesRef.current;
|
|
1399
|
-
const nextLayout = validatePanelGroupLayout({
|
|
1400
|
-
groupSizePixels,
|
|
1401
|
-
layout: prevLayout,
|
|
1402
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1403
|
-
});
|
|
1404
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
1405
|
-
setLayout(nextLayout);
|
|
1406
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
1407
|
-
if (onLayout) {
|
|
1408
|
-
onLayout(nextLayout.map(sizePercentage => ({
|
|
1409
|
-
sizePercentage,
|
|
1410
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1411
|
-
})));
|
|
1412
|
-
}
|
|
1413
|
-
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1414
|
-
}
|
|
1415
|
-
});
|
|
1416
|
-
resizeObserver.observe(getPanelGroupElement(groupId));
|
|
1417
|
-
return () => {
|
|
1418
|
-
resizeObserver.disconnect();
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
}, [groupId]);
|
|
1422
1199
|
|
|
1423
1200
|
// DEV warnings
|
|
1424
1201
|
useEffect(() => {
|
|
@@ -1436,20 +1213,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1436
1213
|
if (panelData.constraints.collapsible) {
|
|
1437
1214
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1438
1215
|
const {
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
pivotIndices
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
if (
|
|
1216
|
+
collapsedSize = 0,
|
|
1217
|
+
panelSize,
|
|
1218
|
+
pivotIndices
|
|
1219
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1220
|
+
assert(panelSize != null);
|
|
1221
|
+
if (panelSize !== collapsedSize) {
|
|
1445
1222
|
// Store size before collapse;
|
|
1446
1223
|
// This is the size that gets restored if the expand() API is used.
|
|
1447
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1224
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1448
1225
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1449
|
-
const delta = isLastPanel ?
|
|
1226
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1450
1227
|
const nextLayout = adjustLayoutByDelta({
|
|
1451
1228
|
delta,
|
|
1452
|
-
groupSizePixels,
|
|
1453
1229
|
layout: prevLayout,
|
|
1454
1230
|
panelConstraints: panelConstraintsArray,
|
|
1455
1231
|
pivotIndices,
|
|
@@ -1459,16 +1235,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1459
1235
|
setLayout(nextLayout);
|
|
1460
1236
|
eagerValuesRef.current.layout = nextLayout;
|
|
1461
1237
|
if (onLayout) {
|
|
1462
|
-
onLayout(nextLayout
|
|
1463
|
-
sizePercentage,
|
|
1464
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1465
|
-
})));
|
|
1238
|
+
onLayout(nextLayout);
|
|
1466
1239
|
}
|
|
1467
|
-
callPanelCallbacks(
|
|
1240
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1468
1241
|
}
|
|
1469
1242
|
}
|
|
1470
1243
|
}
|
|
1471
|
-
}, [
|
|
1244
|
+
}, []);
|
|
1472
1245
|
|
|
1473
1246
|
// External APIs are safe to memoize via committed values ref
|
|
1474
1247
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1482,21 +1255,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1482
1255
|
if (panelData.constraints.collapsible) {
|
|
1483
1256
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1484
1257
|
const {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
pivotIndices
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1258
|
+
collapsedSize = 0,
|
|
1259
|
+
panelSize,
|
|
1260
|
+
minSize = 0,
|
|
1261
|
+
pivotIndices
|
|
1262
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1263
|
+
if (panelSize === collapsedSize) {
|
|
1492
1264
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1493
|
-
const
|
|
1494
|
-
const
|
|
1265
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1266
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1495
1267
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1496
|
-
const delta = isLastPanel ?
|
|
1268
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1497
1269
|
const nextLayout = adjustLayoutByDelta({
|
|
1498
1270
|
delta,
|
|
1499
|
-
groupSizePixels,
|
|
1500
1271
|
layout: prevLayout,
|
|
1501
1272
|
panelConstraints: panelConstraintsArray,
|
|
1502
1273
|
pivotIndices,
|
|
@@ -1506,16 +1277,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1506
1277
|
setLayout(nextLayout);
|
|
1507
1278
|
eagerValuesRef.current.layout = nextLayout;
|
|
1508
1279
|
if (onLayout) {
|
|
1509
|
-
onLayout(nextLayout
|
|
1510
|
-
sizePercentage,
|
|
1511
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1512
|
-
})));
|
|
1280
|
+
onLayout(nextLayout);
|
|
1513
1281
|
}
|
|
1514
|
-
callPanelCallbacks(
|
|
1282
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1515
1283
|
}
|
|
1516
1284
|
}
|
|
1517
1285
|
}
|
|
1518
|
-
}, [
|
|
1286
|
+
}, []);
|
|
1519
1287
|
|
|
1520
1288
|
// External APIs are safe to memoize via committed values ref
|
|
1521
1289
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1524,14 +1292,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1524
1292
|
panelDataArray
|
|
1525
1293
|
} = eagerValuesRef.current;
|
|
1526
1294
|
const {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
return
|
|
1531
|
-
|
|
1532
|
-
sizePixels: panelSizePixels
|
|
1533
|
-
};
|
|
1534
|
-
}, [groupId]);
|
|
1295
|
+
panelSize
|
|
1296
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1297
|
+
assert(panelSize != null);
|
|
1298
|
+
return panelSize;
|
|
1299
|
+
}, []);
|
|
1535
1300
|
|
|
1536
1301
|
// This API should never read from committedValuesRef
|
|
1537
1302
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1554,12 +1319,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1554
1319
|
panelDataArray
|
|
1555
1320
|
} = eagerValuesRef.current;
|
|
1556
1321
|
const {
|
|
1557
|
-
|
|
1322
|
+
collapsedSize,
|
|
1558
1323
|
collapsible,
|
|
1559
|
-
|
|
1560
|
-
} = panelDataHelper(
|
|
1561
|
-
return collapsible === true &&
|
|
1562
|
-
}, [
|
|
1324
|
+
panelSize
|
|
1325
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1326
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1327
|
+
}, []);
|
|
1563
1328
|
|
|
1564
1329
|
// External APIs are safe to memoize via committed values ref
|
|
1565
1330
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1568,12 +1333,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1568
1333
|
panelDataArray
|
|
1569
1334
|
} = eagerValuesRef.current;
|
|
1570
1335
|
const {
|
|
1571
|
-
|
|
1336
|
+
collapsedSize = 0,
|
|
1572
1337
|
collapsible,
|
|
1573
|
-
|
|
1574
|
-
} = panelDataHelper(
|
|
1575
|
-
|
|
1576
|
-
|
|
1338
|
+
panelSize
|
|
1339
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1340
|
+
assert(panelSize != null);
|
|
1341
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1342
|
+
}, []);
|
|
1577
1343
|
const registerPanel = useCallback(panelData => {
|
|
1578
1344
|
const {
|
|
1579
1345
|
autoSaveId,
|
|
@@ -1613,18 +1379,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1613
1379
|
if (autoSaveId) {
|
|
1614
1380
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1615
1381
|
}
|
|
1616
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1617
|
-
if (groupSizePixels <= 0) {
|
|
1618
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1619
|
-
constraints
|
|
1620
|
-
}) => constraints))) {
|
|
1621
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1622
|
-
return;
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
1382
|
if (unsafeLayout == null) {
|
|
1626
1383
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1627
|
-
groupSizePixels,
|
|
1628
1384
|
panelDataArray
|
|
1629
1385
|
});
|
|
1630
1386
|
}
|
|
@@ -1632,7 +1388,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1632
1388
|
// Validate even saved layouts in case something has changed since last render
|
|
1633
1389
|
// e.g. for pixel groups, this could be the size of the window
|
|
1634
1390
|
const nextLayout = validatePanelGroupLayout({
|
|
1635
|
-
groupSizePixels,
|
|
1636
1391
|
layout: unsafeLayout,
|
|
1637
1392
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1638
1393
|
});
|
|
@@ -1644,12 +1399,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1644
1399
|
eagerValuesRef.current.layout = nextLayout;
|
|
1645
1400
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1646
1401
|
if (onLayout) {
|
|
1647
|
-
onLayout(nextLayout
|
|
1648
|
-
sizePercentage,
|
|
1649
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1650
|
-
})));
|
|
1402
|
+
onLayout(nextLayout);
|
|
1651
1403
|
}
|
|
1652
|
-
callPanelCallbacks(
|
|
1404
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1653
1405
|
}
|
|
1654
1406
|
}, []);
|
|
1655
1407
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1659,8 +1411,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1659
1411
|
direction,
|
|
1660
1412
|
dragState,
|
|
1661
1413
|
id: groupId,
|
|
1662
|
-
|
|
1663
|
-
keyboardResizeByPixels,
|
|
1414
|
+
keyboardResizeBy,
|
|
1664
1415
|
onLayout
|
|
1665
1416
|
} = committedValuesRef.current;
|
|
1666
1417
|
const {
|
|
@@ -1671,10 +1422,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1671
1422
|
initialLayout
|
|
1672
1423
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1673
1424
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1674
|
-
let delta = calculateDeltaPercentage(event,
|
|
1675
|
-
percentage: keyboardResizeByPercentage,
|
|
1676
|
-
pixels: keyboardResizeByPixels
|
|
1677
|
-
});
|
|
1425
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1678
1426
|
if (delta === 0) {
|
|
1679
1427
|
return;
|
|
1680
1428
|
}
|
|
@@ -1684,11 +1432,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1684
1432
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1685
1433
|
delta = -delta;
|
|
1686
1434
|
}
|
|
1687
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1688
1435
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1689
1436
|
const nextLayout = adjustLayoutByDelta({
|
|
1690
1437
|
delta,
|
|
1691
|
-
groupSizePixels,
|
|
1692
1438
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1693
1439
|
panelConstraints,
|
|
1694
1440
|
pivotIndices,
|
|
@@ -1724,18 +1470,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1724
1470
|
setLayout(nextLayout);
|
|
1725
1471
|
eagerValuesRef.current.layout = nextLayout;
|
|
1726
1472
|
if (onLayout) {
|
|
1727
|
-
onLayout(nextLayout
|
|
1728
|
-
sizePercentage,
|
|
1729
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1730
|
-
})));
|
|
1473
|
+
onLayout(nextLayout);
|
|
1731
1474
|
}
|
|
1732
|
-
callPanelCallbacks(
|
|
1475
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1733
1476
|
}
|
|
1734
1477
|
};
|
|
1735
1478
|
}, []);
|
|
1736
1479
|
|
|
1737
1480
|
// External APIs are safe to memoize via committed values ref
|
|
1738
|
-
const resizePanel = useCallback((panelData,
|
|
1481
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1739
1482
|
const {
|
|
1740
1483
|
onLayout
|
|
1741
1484
|
} = committedValuesRef.current;
|
|
@@ -1745,16 +1488,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1745
1488
|
} = eagerValuesRef.current;
|
|
1746
1489
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1747
1490
|
const {
|
|
1748
|
-
|
|
1749
|
-
panelSizePercentage,
|
|
1491
|
+
panelSize,
|
|
1750
1492
|
pivotIndices
|
|
1751
|
-
} = panelDataHelper(
|
|
1752
|
-
|
|
1493
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1494
|
+
assert(panelSize != null);
|
|
1753
1495
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1754
|
-
const delta = isLastPanel ?
|
|
1496
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1755
1497
|
const nextLayout = adjustLayoutByDelta({
|
|
1756
1498
|
delta,
|
|
1757
|
-
groupSizePixels,
|
|
1758
1499
|
layout: prevLayout,
|
|
1759
1500
|
panelConstraints: panelConstraintsArray,
|
|
1760
1501
|
pivotIndices,
|
|
@@ -1764,14 +1505,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1764
1505
|
setLayout(nextLayout);
|
|
1765
1506
|
eagerValuesRef.current.layout = nextLayout;
|
|
1766
1507
|
if (onLayout) {
|
|
1767
|
-
onLayout(nextLayout
|
|
1768
|
-
sizePercentage,
|
|
1769
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1770
|
-
})));
|
|
1508
|
+
onLayout(nextLayout);
|
|
1771
1509
|
}
|
|
1772
|
-
callPanelCallbacks(
|
|
1510
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1773
1511
|
}
|
|
1774
|
-
}, [
|
|
1512
|
+
}, []);
|
|
1775
1513
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1776
1514
|
const {
|
|
1777
1515
|
direction
|
|
@@ -1780,6 +1518,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1780
1518
|
layout
|
|
1781
1519
|
} = eagerValuesRef.current;
|
|
1782
1520
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1521
|
+
assert(handleElement);
|
|
1783
1522
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1784
1523
|
setDragState({
|
|
1785
1524
|
dragHandleId,
|
|
@@ -1798,7 +1537,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1798
1537
|
});
|
|
1799
1538
|
const unregisterPanel = useCallback(panelData => {
|
|
1800
1539
|
const {
|
|
1801
|
-
id: groupId,
|
|
1802
1540
|
onLayout
|
|
1803
1541
|
} = committedValuesRef.current;
|
|
1804
1542
|
const {
|
|
@@ -1821,7 +1559,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1821
1559
|
const {
|
|
1822
1560
|
pendingPanelIds
|
|
1823
1561
|
} = unregisterPanelRef.current;
|
|
1824
|
-
const map =
|
|
1562
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1825
1563
|
|
|
1826
1564
|
// TRICKY
|
|
1827
1565
|
// Strict effects mode
|
|
@@ -1847,16 +1585,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1847
1585
|
// The group is unmounting; skip layout calculation.
|
|
1848
1586
|
return;
|
|
1849
1587
|
}
|
|
1850
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1851
1588
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1852
|
-
groupSizePixels,
|
|
1853
1589
|
panelDataArray
|
|
1854
1590
|
});
|
|
1855
1591
|
|
|
1856
1592
|
// Validate even saved layouts in case something has changed since last render
|
|
1857
1593
|
// e.g. for pixel groups, this could be the size of the window
|
|
1858
1594
|
const nextLayout = validatePanelGroupLayout({
|
|
1859
|
-
groupSizePixels,
|
|
1860
1595
|
layout: unsafeLayout,
|
|
1861
1596
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1862
1597
|
});
|
|
@@ -1864,12 +1599,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1864
1599
|
setLayout(nextLayout);
|
|
1865
1600
|
eagerValuesRef.current.layout = nextLayout;
|
|
1866
1601
|
if (onLayout) {
|
|
1867
|
-
onLayout(nextLayout
|
|
1868
|
-
sizePercentage,
|
|
1869
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1870
|
-
})));
|
|
1602
|
+
onLayout(nextLayout);
|
|
1871
1603
|
}
|
|
1872
|
-
callPanelCallbacks(
|
|
1604
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1873
1605
|
}
|
|
1874
1606
|
}, 0);
|
|
1875
1607
|
}, []);
|
|
@@ -1900,13 +1632,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1900
1632
|
return createElement(PanelGroupContext.Provider, {
|
|
1901
1633
|
value: context
|
|
1902
1634
|
}, createElement(Type, {
|
|
1635
|
+
...rest,
|
|
1903
1636
|
children,
|
|
1904
1637
|
className: classNameFromProps,
|
|
1905
1638
|
style: {
|
|
1906
1639
|
...style,
|
|
1907
1640
|
...styleFromProps
|
|
1908
1641
|
},
|
|
1909
|
-
...dataAttributes,
|
|
1910
1642
|
// CSS selectors
|
|
1911
1643
|
"data-panel-group": "",
|
|
1912
1644
|
"data-panel-group-direction": direction,
|
|
@@ -1919,22 +1651,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
1919
1651
|
}));
|
|
1920
1652
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
1921
1653
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
1922
|
-
function panelDataHelper(
|
|
1654
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
1923
1655
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1924
1656
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1925
1657
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1926
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1927
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
1928
1658
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
1929
1659
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
1930
|
-
const
|
|
1931
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1660
|
+
const panelSize = layout[panelIndex];
|
|
1932
1661
|
return {
|
|
1933
|
-
...
|
|
1934
|
-
|
|
1935
|
-
panelSizePercentage,
|
|
1936
|
-
panelSizePixels,
|
|
1937
|
-
groupSizePixels,
|
|
1662
|
+
...panelConstraints,
|
|
1663
|
+
panelSize,
|
|
1938
1664
|
pivotIndices
|
|
1939
1665
|
};
|
|
1940
1666
|
}
|
|
@@ -1974,6 +1700,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1974
1700
|
{
|
|
1975
1701
|
event.preventDefault();
|
|
1976
1702
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1703
|
+
assert(groupId);
|
|
1977
1704
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
1978
1705
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
1979
1706
|
assert(index !== null);
|
|
@@ -1994,12 +1721,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1994
1721
|
function PanelResizeHandle({
|
|
1995
1722
|
children = null,
|
|
1996
1723
|
className: classNameFromProps = "",
|
|
1997
|
-
dataAttributes,
|
|
1998
1724
|
disabled = false,
|
|
1999
|
-
id: idFromProps
|
|
1725
|
+
id: idFromProps,
|
|
2000
1726
|
onDragging,
|
|
2001
1727
|
style: styleFromProps = {},
|
|
2002
|
-
|
|
1728
|
+
tabIndex = 0,
|
|
1729
|
+
tagName: Type = "div",
|
|
1730
|
+
...rest
|
|
2003
1731
|
}) {
|
|
2004
1732
|
const divElementRef = useRef(null);
|
|
2005
1733
|
|
|
@@ -2029,8 +1757,9 @@ function PanelResizeHandle({
|
|
|
2029
1757
|
const stopDraggingAndBlur = useCallback(() => {
|
|
2030
1758
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
2031
1759
|
// That would cause the PanelGroup to think it was still active.
|
|
2032
|
-
const
|
|
2033
|
-
|
|
1760
|
+
const divElement = divElementRef.current;
|
|
1761
|
+
assert(divElement);
|
|
1762
|
+
divElement.blur();
|
|
2034
1763
|
stopDragging();
|
|
2035
1764
|
const {
|
|
2036
1765
|
onDragging
|
|
@@ -2058,6 +1787,7 @@ function PanelResizeHandle({
|
|
|
2058
1787
|
resizeHandler(event);
|
|
2059
1788
|
};
|
|
2060
1789
|
const divElement = divElementRef.current;
|
|
1790
|
+
assert(divElement);
|
|
2061
1791
|
const targetDocument = divElement.ownerDocument;
|
|
2062
1792
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2063
1793
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2085,15 +1815,18 @@ function PanelResizeHandle({
|
|
|
2085
1815
|
userSelect: "none"
|
|
2086
1816
|
};
|
|
2087
1817
|
return createElement(Type, {
|
|
1818
|
+
...rest,
|
|
2088
1819
|
children,
|
|
2089
1820
|
className: classNameFromProps,
|
|
2090
1821
|
onBlur: () => setIsFocused(false),
|
|
2091
1822
|
onFocus: () => setIsFocused(true),
|
|
2092
1823
|
onMouseDown: event => {
|
|
2093
1824
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1825
|
+
const callbacks = callbacksRef.current;
|
|
1826
|
+
assert(callbacks);
|
|
2094
1827
|
const {
|
|
2095
1828
|
onDragging
|
|
2096
|
-
} =
|
|
1829
|
+
} = callbacks;
|
|
2097
1830
|
if (onDragging) {
|
|
2098
1831
|
onDragging(true);
|
|
2099
1832
|
}
|
|
@@ -2103,9 +1836,11 @@ function PanelResizeHandle({
|
|
|
2103
1836
|
onTouchEnd: stopDraggingAndBlur,
|
|
2104
1837
|
onTouchStart: event => {
|
|
2105
1838
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1839
|
+
const callbacks = callbacksRef.current;
|
|
1840
|
+
assert(callbacks);
|
|
2106
1841
|
const {
|
|
2107
1842
|
onDragging
|
|
2108
|
-
} =
|
|
1843
|
+
} = callbacks;
|
|
2109
1844
|
if (onDragging) {
|
|
2110
1845
|
onDragging(true);
|
|
2111
1846
|
}
|
|
@@ -2116,8 +1851,7 @@ function PanelResizeHandle({
|
|
|
2116
1851
|
...style,
|
|
2117
1852
|
...styleFromProps
|
|
2118
1853
|
},
|
|
2119
|
-
tabIndex
|
|
2120
|
-
...dataAttributes,
|
|
1854
|
+
tabIndex,
|
|
2121
1855
|
// CSS selectors
|
|
2122
1856
|
"data-panel-group-direction": direction,
|
|
2123
1857
|
"data-panel-group-id": groupId,
|
|
@@ -2132,3 +1866,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
|
2132
1866
|
exports.Panel = Panel;
|
|
2133
1867
|
exports.PanelGroup = PanelGroup;
|
|
2134
1868
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
1869
|
+
exports.assert = assert;
|