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