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