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
|
@@ -63,24 +63,20 @@ function useUniqueId(idFromParams = null) {
|
|
|
63
63
|
function PanelWithForwardedRef({
|
|
64
64
|
children,
|
|
65
65
|
className: classNameFromProps = "",
|
|
66
|
-
|
|
67
|
-
collapsedSizePixels,
|
|
66
|
+
collapsedSize,
|
|
68
67
|
collapsible,
|
|
69
|
-
|
|
70
|
-
defaultSizePercentage,
|
|
71
|
-
defaultSizePixels,
|
|
68
|
+
defaultSize,
|
|
72
69
|
forwardedRef,
|
|
73
70
|
id: idFromProps,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
minSizePercentage,
|
|
77
|
-
minSizePixels,
|
|
71
|
+
maxSize,
|
|
72
|
+
minSize,
|
|
78
73
|
onCollapse,
|
|
79
74
|
onExpand,
|
|
80
75
|
onResize,
|
|
81
76
|
order,
|
|
82
77
|
style: styleFromProps,
|
|
83
|
-
tagName: Type = "div"
|
|
78
|
+
tagName: Type = "div",
|
|
79
|
+
...rest
|
|
84
80
|
}) {
|
|
85
81
|
const context = useContext(PanelGroupContext);
|
|
86
82
|
if (context === null) {
|
|
@@ -105,15 +101,11 @@ function PanelWithForwardedRef({
|
|
|
105
101
|
onResize
|
|
106
102
|
},
|
|
107
103
|
constraints: {
|
|
108
|
-
|
|
109
|
-
collapsedSizePixels,
|
|
104
|
+
collapsedSize,
|
|
110
105
|
collapsible,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
maxSizePixels,
|
|
115
|
-
minSizePercentage,
|
|
116
|
-
minSizePixels
|
|
106
|
+
defaultSize,
|
|
107
|
+
maxSize,
|
|
108
|
+
minSize
|
|
117
109
|
},
|
|
118
110
|
id: panelId,
|
|
119
111
|
idIsFromProps: idFromProps !== undefined,
|
|
@@ -127,9 +119,9 @@ function PanelWithForwardedRef({
|
|
|
127
119
|
// but effects don't run on the server, so we can't do it there
|
|
128
120
|
{
|
|
129
121
|
if (!devWarningsRef.current.didLogMissingDefaultSizeWarning) {
|
|
130
|
-
if (
|
|
122
|
+
if (defaultSize == null) {
|
|
131
123
|
devWarningsRef.current.didLogMissingDefaultSizeWarning = true;
|
|
132
|
-
console.warn(`WARNING: Panel
|
|
124
|
+
console.warn(`WARNING: Panel defaultSize prop recommended to avoid layout shift after server rendering`);
|
|
133
125
|
}
|
|
134
126
|
}
|
|
135
127
|
}
|
|
@@ -152,19 +144,19 @@ function PanelWithForwardedRef({
|
|
|
152
144
|
isExpanded() {
|
|
153
145
|
return !isPanelCollapsed(panelDataRef.current);
|
|
154
146
|
},
|
|
155
|
-
resize:
|
|
156
|
-
resizePanel(panelDataRef.current,
|
|
147
|
+
resize: size => {
|
|
148
|
+
resizePanel(panelDataRef.current, size);
|
|
157
149
|
}
|
|
158
150
|
}), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
|
|
159
151
|
const style = getPanelStyle(panelDataRef.current);
|
|
160
152
|
return createElement(Type, {
|
|
153
|
+
...rest,
|
|
161
154
|
children,
|
|
162
155
|
className: classNameFromProps,
|
|
163
156
|
style: {
|
|
164
157
|
...style,
|
|
165
158
|
...styleFromProps
|
|
166
159
|
},
|
|
167
|
-
...dataAttributes,
|
|
168
160
|
// CSS selectors
|
|
169
161
|
"data-panel": "",
|
|
170
162
|
"data-panel-id": panelId,
|
|
@@ -181,81 +173,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
181
173
|
PanelWithForwardedRef.displayName = "Panel";
|
|
182
174
|
Panel.displayName = "forwardRef(Panel)";
|
|
183
175
|
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
|
|
189
|
-
let {
|
|
190
|
-
collapsedSizePercentage = 0,
|
|
191
|
-
collapsedSizePixels,
|
|
192
|
-
defaultSizePercentage,
|
|
193
|
-
defaultSizePixels,
|
|
194
|
-
maxSizePercentage = 100,
|
|
195
|
-
maxSizePixels,
|
|
196
|
-
minSizePercentage = 0,
|
|
197
|
-
minSizePixels
|
|
198
|
-
} = panelConstraints;
|
|
199
|
-
const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
|
|
200
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
201
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
202
|
-
return {
|
|
203
|
-
collapsedSizePercentage: 0,
|
|
204
|
-
defaultSizePercentage,
|
|
205
|
-
maxSizePercentage: 0,
|
|
206
|
-
minSizePercentage: 0
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
if (collapsedSizePixels != null) {
|
|
210
|
-
collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
|
|
211
|
-
}
|
|
212
|
-
if (defaultSizePixels != null) {
|
|
213
|
-
defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
|
|
214
|
-
}
|
|
215
|
-
if (minSizePixels != null) {
|
|
216
|
-
minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
|
|
217
|
-
}
|
|
218
|
-
if (maxSizePixels != null) {
|
|
219
|
-
maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
collapsedSizePercentage,
|
|
223
|
-
defaultSizePercentage,
|
|
224
|
-
maxSizePercentage,
|
|
225
|
-
minSizePercentage
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
|
|
230
|
-
// All panel constraints, excluding the current one
|
|
231
|
-
let totalMinConstraints = 0;
|
|
232
|
-
let totalMaxConstraints = 0;
|
|
233
|
-
for (let index = 0; index < panelConstraintsArray.length; index++) {
|
|
234
|
-
if (index !== panelIndex) {
|
|
235
|
-
const {
|
|
236
|
-
collapsible
|
|
237
|
-
} = panelConstraintsArray[index];
|
|
238
|
-
const {
|
|
239
|
-
collapsedSizePercentage,
|
|
240
|
-
maxSizePercentage,
|
|
241
|
-
minSizePercentage
|
|
242
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
|
|
243
|
-
totalMaxConstraints += maxSizePercentage;
|
|
244
|
-
totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
|
|
245
|
-
}
|
|
176
|
+
function assert(expectedCondition, message = "Assertion failed!") {
|
|
177
|
+
if (!expectedCondition) {
|
|
178
|
+
console.error(message);
|
|
179
|
+
throw Error(message);
|
|
246
180
|
}
|
|
247
|
-
const {
|
|
248
|
-
collapsedSizePercentage,
|
|
249
|
-
defaultSizePercentage,
|
|
250
|
-
maxSizePercentage,
|
|
251
|
-
minSizePercentage
|
|
252
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
|
|
253
|
-
return {
|
|
254
|
-
collapsedSizePercentage,
|
|
255
|
-
defaultSizePercentage,
|
|
256
|
-
maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
|
|
257
|
-
minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
|
|
258
|
-
};
|
|
259
181
|
}
|
|
260
182
|
|
|
261
183
|
const PRECISION = 10;
|
|
@@ -277,56 +199,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
|
|
|
277
199
|
|
|
278
200
|
// Panel size must be in percentages; pixel values should be pre-converted
|
|
279
201
|
function resizePanel({
|
|
280
|
-
|
|
281
|
-
panelConstraints,
|
|
202
|
+
panelConstraints: panelConstraintsArray,
|
|
282
203
|
panelIndex,
|
|
283
204
|
size
|
|
284
205
|
}) {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
defaultSizePixels,
|
|
288
|
-
minSizePixels,
|
|
289
|
-
maxSizePixels
|
|
290
|
-
}) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
|
|
291
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
292
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
293
|
-
return 0;
|
|
294
|
-
}
|
|
206
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
207
|
+
assert(panelConstraints != null);
|
|
295
208
|
let {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
|
|
308
|
-
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
309
|
-
size = collapsedSizePercentage;
|
|
310
|
-
} else {
|
|
311
|
-
size = minSizePercentage;
|
|
312
|
-
}
|
|
209
|
+
collapsedSize = 0,
|
|
210
|
+
collapsible,
|
|
211
|
+
maxSize = 100,
|
|
212
|
+
minSize = 0
|
|
213
|
+
} = panelConstraints;
|
|
214
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
215
|
+
if (collapsible) {
|
|
216
|
+
// Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
|
|
217
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
218
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
219
|
+
size = collapsedSize;
|
|
313
220
|
} else {
|
|
314
|
-
size =
|
|
221
|
+
size = minSize;
|
|
315
222
|
}
|
|
223
|
+
} else {
|
|
224
|
+
size = minSize;
|
|
316
225
|
}
|
|
317
226
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
227
|
+
size = Math.min(maxSize, size);
|
|
228
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
321
229
|
return size;
|
|
322
230
|
}
|
|
323
231
|
|
|
324
232
|
// All units must be in percentages; pixel values should be pre-converted
|
|
325
233
|
function adjustLayoutByDelta({
|
|
326
234
|
delta,
|
|
327
|
-
groupSizePixels,
|
|
328
235
|
layout: prevLayout,
|
|
329
|
-
panelConstraints,
|
|
236
|
+
panelConstraints: panelConstraintsArray,
|
|
330
237
|
pivotIndices,
|
|
331
238
|
trigger
|
|
332
239
|
}) {
|
|
@@ -334,6 +241,9 @@ function adjustLayoutByDelta({
|
|
|
334
241
|
return prevLayout;
|
|
335
242
|
}
|
|
336
243
|
const nextLayout = [...prevLayout];
|
|
244
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
245
|
+
assert(firstPivotIndex != null);
|
|
246
|
+
assert(secondPivotIndex != null);
|
|
337
247
|
let deltaApplied = 0;
|
|
338
248
|
|
|
339
249
|
//const DEBUG = [];
|
|
@@ -357,18 +267,23 @@ function adjustLayoutByDelta({
|
|
|
357
267
|
if (trigger === "keyboard") {
|
|
358
268
|
{
|
|
359
269
|
// Check if we should expand a collapsed panel
|
|
360
|
-
const index = delta < 0 ?
|
|
361
|
-
const
|
|
270
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
271
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
272
|
+
assert(panelConstraints);
|
|
273
|
+
|
|
362
274
|
//DEBUG.push(`edge case check 1: ${index}`);
|
|
363
275
|
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
364
|
-
if (
|
|
276
|
+
if (panelConstraints.collapsible) {
|
|
365
277
|
const prevSize = prevLayout[index];
|
|
278
|
+
assert(prevSize != null);
|
|
279
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
280
|
+
assert(panelConstraints);
|
|
366
281
|
const {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
} =
|
|
370
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
371
|
-
const localDelta =
|
|
282
|
+
collapsedSize = 0,
|
|
283
|
+
minSize = 0
|
|
284
|
+
} = panelConstraints;
|
|
285
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
|
|
286
|
+
const localDelta = minSize - prevSize;
|
|
372
287
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
373
288
|
|
|
374
289
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -381,18 +296,26 @@ function adjustLayoutByDelta({
|
|
|
381
296
|
|
|
382
297
|
{
|
|
383
298
|
// Check if we should collapse a panel at its minimum size
|
|
384
|
-
const index = delta < 0 ?
|
|
385
|
-
const
|
|
299
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
300
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
301
|
+
assert(panelConstraints);
|
|
302
|
+
const {
|
|
303
|
+
collapsible
|
|
304
|
+
} = panelConstraints;
|
|
305
|
+
|
|
386
306
|
//DEBUG.push(`edge case check 2: ${index}`);
|
|
387
|
-
//DEBUG.push(` -> collapsible? ${
|
|
388
|
-
if (
|
|
307
|
+
//DEBUG.push(` -> collapsible? ${collapsible}`);
|
|
308
|
+
if (collapsible) {
|
|
389
309
|
const prevSize = prevLayout[index];
|
|
310
|
+
assert(prevSize != null);
|
|
311
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
312
|
+
assert(panelConstraints);
|
|
390
313
|
const {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
} =
|
|
394
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
395
|
-
const localDelta = prevSize -
|
|
314
|
+
collapsedSize = 0,
|
|
315
|
+
minSize = 0
|
|
316
|
+
} = panelConstraints;
|
|
317
|
+
if (fuzzyNumbersEqual(prevSize, minSize)) {
|
|
318
|
+
const localDelta = prevSize - collapsedSize;
|
|
396
319
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
397
320
|
|
|
398
321
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -414,15 +337,15 @@ function adjustLayoutByDelta({
|
|
|
414
337
|
// as an expanding panel might change from collapsed to min size.
|
|
415
338
|
|
|
416
339
|
const increment = delta < 0 ? 1 : -1;
|
|
417
|
-
let index = delta < 0 ?
|
|
340
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
418
341
|
let maxAvailableDelta = 0;
|
|
419
342
|
|
|
420
343
|
//DEBUG.push("pre calc...");
|
|
421
344
|
while (true) {
|
|
422
345
|
const prevSize = prevLayout[index];
|
|
346
|
+
assert(prevSize != null);
|
|
423
347
|
const maxSafeSize = resizePanel({
|
|
424
|
-
|
|
425
|
-
panelConstraints,
|
|
348
|
+
panelConstraints: panelConstraintsArray,
|
|
426
349
|
panelIndex: index,
|
|
427
350
|
size: 100
|
|
428
351
|
});
|
|
@@ -431,7 +354,7 @@ function adjustLayoutByDelta({
|
|
|
431
354
|
|
|
432
355
|
maxAvailableDelta += delta;
|
|
433
356
|
index += increment;
|
|
434
|
-
if (index < 0 || index >=
|
|
357
|
+
if (index < 0 || index >= panelConstraintsArray.length) {
|
|
435
358
|
break;
|
|
436
359
|
}
|
|
437
360
|
}
|
|
@@ -446,15 +369,15 @@ function adjustLayoutByDelta({
|
|
|
446
369
|
{
|
|
447
370
|
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
448
371
|
|
|
449
|
-
const pivotIndex = delta < 0 ?
|
|
372
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
450
373
|
let index = pivotIndex;
|
|
451
|
-
while (index >= 0 && index <
|
|
374
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
452
375
|
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
453
376
|
const prevSize = prevLayout[index];
|
|
377
|
+
assert(prevSize != null);
|
|
454
378
|
const unsafeSize = prevSize - deltaRemaining;
|
|
455
379
|
const safeSize = resizePanel({
|
|
456
|
-
|
|
457
|
-
panelConstraints,
|
|
380
|
+
panelConstraints: panelConstraintsArray,
|
|
458
381
|
panelIndex: index,
|
|
459
382
|
size: unsafeSize
|
|
460
383
|
});
|
|
@@ -486,11 +409,12 @@ function adjustLayoutByDelta({
|
|
|
486
409
|
}
|
|
487
410
|
{
|
|
488
411
|
// Now distribute the applied delta to the panels in the other direction
|
|
489
|
-
const pivotIndex = delta < 0 ?
|
|
490
|
-
const
|
|
412
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
413
|
+
const prevSize = prevLayout[pivotIndex];
|
|
414
|
+
assert(prevSize != null);
|
|
415
|
+
const unsafeSize = prevSize + deltaApplied;
|
|
491
416
|
const safeSize = resizePanel({
|
|
492
|
-
|
|
493
|
-
panelConstraints,
|
|
417
|
+
panelConstraints: panelConstraintsArray,
|
|
494
418
|
panelIndex: pivotIndex,
|
|
495
419
|
size: unsafeSize
|
|
496
420
|
});
|
|
@@ -501,14 +425,14 @@ function adjustLayoutByDelta({
|
|
|
501
425
|
// Edge case where expanding or contracting one panel caused another one to change collapsed state
|
|
502
426
|
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
503
427
|
let deltaRemaining = unsafeSize - safeSize;
|
|
504
|
-
const pivotIndex = delta < 0 ?
|
|
428
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
505
429
|
let index = pivotIndex;
|
|
506
|
-
while (index >= 0 && index <
|
|
430
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
507
431
|
const prevSize = nextLayout[index];
|
|
432
|
+
assert(prevSize != null);
|
|
508
433
|
const unsafeSize = prevSize + deltaRemaining;
|
|
509
434
|
const safeSize = resizePanel({
|
|
510
|
-
|
|
511
|
-
panelConstraints,
|
|
435
|
+
panelConstraints: panelConstraintsArray,
|
|
512
436
|
panelIndex: index,
|
|
513
437
|
size: unsafeSize
|
|
514
438
|
});
|
|
@@ -532,9 +456,7 @@ function adjustLayoutByDelta({
|
|
|
532
456
|
//DEBUG.push("");
|
|
533
457
|
|
|
534
458
|
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
535
|
-
deltaApplied = 100 - totalSize;
|
|
536
459
|
//DEBUG.push(`total size: ${totalSize}`);
|
|
537
|
-
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
538
460
|
//console.log(DEBUG.join("\n"));
|
|
539
461
|
|
|
540
462
|
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
@@ -543,25 +465,6 @@ function adjustLayoutByDelta({
|
|
|
543
465
|
return nextLayout;
|
|
544
466
|
}
|
|
545
467
|
|
|
546
|
-
function assert(expectedCondition, message = "Assertion failed!") {
|
|
547
|
-
if (!expectedCondition) {
|
|
548
|
-
console.error(message);
|
|
549
|
-
throw Error(message);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
function getPercentageSizeFromMixedSizes({
|
|
554
|
-
sizePercentage,
|
|
555
|
-
sizePixels
|
|
556
|
-
}, groupSizePixels) {
|
|
557
|
-
if (sizePercentage != null) {
|
|
558
|
-
return sizePercentage;
|
|
559
|
-
} else if (sizePixels != null) {
|
|
560
|
-
return convertPixelsToPercentage(sizePixels, groupSizePixels);
|
|
561
|
-
}
|
|
562
|
-
return undefined;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
468
|
function getResizeHandleElementsForGroup(groupId) {
|
|
566
469
|
return Array.from(document.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
|
|
567
470
|
}
|
|
@@ -585,42 +488,6 @@ function getPanelGroupElement(id) {
|
|
|
585
488
|
return null;
|
|
586
489
|
}
|
|
587
490
|
|
|
588
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
589
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
590
|
-
if (panelGroupElement == null) {
|
|
591
|
-
return NaN;
|
|
592
|
-
}
|
|
593
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
594
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
595
|
-
if (direction === "horizontal") {
|
|
596
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
597
|
-
return accumulated + handle.offsetWidth;
|
|
598
|
-
}, 0);
|
|
599
|
-
} else {
|
|
600
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
601
|
-
return accumulated + handle.offsetHeight;
|
|
602
|
-
}, 0);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
607
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
608
|
-
if (panelGroupElement == null) {
|
|
609
|
-
return NaN;
|
|
610
|
-
}
|
|
611
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
612
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
613
|
-
if (direction === "horizontal") {
|
|
614
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
615
|
-
return accumulated + handle.offsetWidth;
|
|
616
|
-
}, 0);
|
|
617
|
-
} else {
|
|
618
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
619
|
-
return accumulated + handle.offsetHeight;
|
|
620
|
-
}, 0);
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
491
|
function getResizeHandleElement(id) {
|
|
625
492
|
const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
626
493
|
if (element) {
|
|
@@ -653,14 +520,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
653
520
|
didWarnAboutMissingResizeHandle: false
|
|
654
521
|
});
|
|
655
522
|
useEffect(() => {
|
|
523
|
+
const eagerValues = eagerValuesRef.current;
|
|
524
|
+
assert(eagerValues);
|
|
656
525
|
const {
|
|
657
526
|
panelDataArray
|
|
658
|
-
} =
|
|
527
|
+
} = eagerValues;
|
|
659
528
|
const groupElement = getPanelGroupElement(groupId);
|
|
660
529
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
661
530
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
531
|
+
assert(handles);
|
|
662
532
|
const cleanupFunctions = handles.map(handle => {
|
|
663
533
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
534
|
+
assert(handleId);
|
|
664
535
|
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
665
536
|
if (idBefore == null || idAfter == null) {
|
|
666
537
|
return () => {};
|
|
@@ -676,21 +547,16 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
676
547
|
const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
|
|
677
548
|
if (index >= 0) {
|
|
678
549
|
const panelData = panelDataArray[index];
|
|
550
|
+
assert(panelData);
|
|
679
551
|
const size = layout[index];
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
687
|
-
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
688
|
-
sizePercentage: panelData.constraints.minSizePercentage,
|
|
689
|
-
sizePixels: panelData.constraints.minSizePixels
|
|
690
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
552
|
+
const {
|
|
553
|
+
collapsedSize = 0,
|
|
554
|
+
collapsible,
|
|
555
|
+
minSize = 0
|
|
556
|
+
} = panelData.constraints;
|
|
557
|
+
if (size != null && collapsible) {
|
|
691
558
|
const nextLayout = adjustLayoutByDelta({
|
|
692
559
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
693
|
-
groupSizePixels,
|
|
694
560
|
layout,
|
|
695
561
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
696
562
|
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
@@ -744,6 +610,7 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
744
610
|
return isHorizontal ? event.clientX : event.clientY;
|
|
745
611
|
} else if (isTouchEvent(event)) {
|
|
746
612
|
const firstTouch = event.touches[0];
|
|
613
|
+
assert(firstTouch);
|
|
747
614
|
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
748
615
|
} else {
|
|
749
616
|
throw Error(`Unsupported event type "${event.type}"`);
|
|
@@ -753,12 +620,15 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
753
620
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
754
621
|
const isHorizontal = direction === "horizontal";
|
|
755
622
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
623
|
+
assert(handleElement);
|
|
756
624
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
625
|
+
assert(groupId);
|
|
757
626
|
let {
|
|
758
627
|
initialCursorPosition
|
|
759
628
|
} = initialDragState;
|
|
760
629
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
761
630
|
const groupElement = getPanelGroupElement(groupId);
|
|
631
|
+
assert(groupElement);
|
|
762
632
|
const groupRect = groupElement.getBoundingClientRect();
|
|
763
633
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
764
634
|
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
@@ -767,19 +637,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
767
637
|
}
|
|
768
638
|
|
|
769
639
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
770
|
-
function calculateDeltaPercentage(event,
|
|
640
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
771
641
|
if (isKeyDown(event)) {
|
|
772
642
|
const isHorizontal = direction === "horizontal";
|
|
773
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
774
|
-
const rect = groupElement.getBoundingClientRect();
|
|
775
|
-
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
776
643
|
let delta = 0;
|
|
777
644
|
if (event.shiftKey) {
|
|
778
645
|
delta = 100;
|
|
779
|
-
} else if (
|
|
780
|
-
delta =
|
|
781
|
-
} else if (keyboardResizeByOptions.pixels != null) {
|
|
782
|
-
delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
|
|
646
|
+
} else if (keyboardResizeBy != null) {
|
|
647
|
+
delta = keyboardResizeBy;
|
|
783
648
|
} else {
|
|
784
649
|
delta = 10;
|
|
785
650
|
}
|
|
@@ -806,37 +671,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
806
671
|
}
|
|
807
672
|
return movement;
|
|
808
673
|
} else {
|
|
674
|
+
if (initialDragState == null) {
|
|
675
|
+
return 0;
|
|
676
|
+
}
|
|
809
677
|
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
810
678
|
}
|
|
811
679
|
}
|
|
812
680
|
|
|
813
681
|
function calculateUnsafeDefaultLayout({
|
|
814
|
-
groupSizePixels,
|
|
815
682
|
panelDataArray
|
|
816
683
|
}) {
|
|
817
684
|
const layout = Array(panelDataArray.length);
|
|
818
|
-
const
|
|
685
|
+
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
819
686
|
let numPanelsWithSizes = 0;
|
|
820
687
|
let remainingSize = 100;
|
|
821
688
|
|
|
822
689
|
// Distribute default sizes first
|
|
823
690
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
691
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
692
|
+
assert(panelConstraints);
|
|
824
693
|
const {
|
|
825
|
-
|
|
826
|
-
} =
|
|
827
|
-
if (
|
|
694
|
+
defaultSize
|
|
695
|
+
} = panelConstraints;
|
|
696
|
+
if (defaultSize != null) {
|
|
828
697
|
numPanelsWithSizes++;
|
|
829
|
-
layout[index] =
|
|
830
|
-
remainingSize -=
|
|
698
|
+
layout[index] = defaultSize;
|
|
699
|
+
remainingSize -= defaultSize;
|
|
831
700
|
}
|
|
832
701
|
}
|
|
833
702
|
|
|
834
703
|
// Remaining size should be distributed evenly between panels without default sizes
|
|
835
704
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
705
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
706
|
+
assert(panelConstraints);
|
|
836
707
|
const {
|
|
837
|
-
|
|
838
|
-
} =
|
|
839
|
-
if (
|
|
708
|
+
defaultSize
|
|
709
|
+
} = panelConstraints;
|
|
710
|
+
if (defaultSize != null) {
|
|
840
711
|
continue;
|
|
841
712
|
}
|
|
842
713
|
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
@@ -848,54 +719,36 @@ function calculateUnsafeDefaultLayout({
|
|
|
848
719
|
return layout;
|
|
849
720
|
}
|
|
850
721
|
|
|
851
|
-
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
852
|
-
return percentage / 100 * groupSizePixels;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
722
|
// Layout should be pre-converted into percentages
|
|
856
|
-
function callPanelCallbacks(
|
|
857
|
-
|
|
858
|
-
layout.forEach((sizePercentage, index) => {
|
|
723
|
+
function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
|
|
724
|
+
layout.forEach((size, index) => {
|
|
859
725
|
const panelData = panelsArray[index];
|
|
860
|
-
|
|
861
|
-
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
862
|
-
// The subsequent render+effects will handle the resize notification
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
726
|
+
assert(panelData);
|
|
865
727
|
const {
|
|
866
728
|
callbacks,
|
|
867
729
|
constraints,
|
|
868
730
|
id: panelId
|
|
869
731
|
} = panelData;
|
|
870
732
|
const {
|
|
733
|
+
collapsedSize = 0,
|
|
871
734
|
collapsible
|
|
872
735
|
} = constraints;
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
};
|
|
877
|
-
const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
|
|
878
|
-
if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
|
|
879
|
-
panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
|
|
736
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
|
|
737
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
738
|
+
panelIdToLastNotifiedSizeMap[panelId] = size;
|
|
880
739
|
const {
|
|
881
740
|
onCollapse,
|
|
882
741
|
onExpand,
|
|
883
742
|
onResize
|
|
884
743
|
} = callbacks;
|
|
885
744
|
if (onResize) {
|
|
886
|
-
onResize(
|
|
745
|
+
onResize(size, lastNotifiedSize);
|
|
887
746
|
}
|
|
888
747
|
if (collapsible && (onCollapse || onExpand)) {
|
|
889
|
-
|
|
890
|
-
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
891
|
-
sizePercentage: constraints.collapsedSizePercentage,
|
|
892
|
-
sizePixels: constraints.collapsedSizePixels
|
|
893
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
894
|
-
const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
|
|
895
|
-
if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
|
|
748
|
+
if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
896
749
|
onExpand();
|
|
897
750
|
}
|
|
898
|
-
if (onCollapse && (
|
|
751
|
+
if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
|
|
899
752
|
onCollapse();
|
|
900
753
|
}
|
|
901
754
|
}
|
|
@@ -1078,74 +931,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1078
931
|
}
|
|
1079
932
|
}
|
|
1080
933
|
|
|
1081
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1082
|
-
return constraints.some(constraints => {
|
|
1083
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
934
|
function validatePanelConstraints({
|
|
1088
|
-
|
|
1089
|
-
panelConstraints,
|
|
935
|
+
panelConstraints: panelConstraintsArray,
|
|
1090
936
|
panelId,
|
|
1091
937
|
panelIndex
|
|
1092
938
|
}) {
|
|
1093
939
|
{
|
|
1094
940
|
const warnings = [];
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
} = panelConstraints[panelIndex];
|
|
1106
|
-
const conflictingUnits = [];
|
|
1107
|
-
if (collapsedSizePercentage != null && collapsedSizePixels != null) {
|
|
1108
|
-
conflictingUnits.push("collapsed size");
|
|
1109
|
-
}
|
|
1110
|
-
if (defaultSizePercentage != null && defaultSizePixels != null) {
|
|
1111
|
-
conflictingUnits.push("default size");
|
|
1112
|
-
}
|
|
1113
|
-
if (maxSizePercentage != null && maxSizePixels != null) {
|
|
1114
|
-
conflictingUnits.push("max size");
|
|
1115
|
-
}
|
|
1116
|
-
if (minSizePercentage != null && minSizePixels != null) {
|
|
1117
|
-
conflictingUnits.push("min size");
|
|
1118
|
-
}
|
|
1119
|
-
if (conflictingUnits.length > 0) {
|
|
1120
|
-
warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
|
|
1121
|
-
}
|
|
941
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
942
|
+
assert(panelConstraints);
|
|
943
|
+
const {
|
|
944
|
+
collapsedSize = 0,
|
|
945
|
+
defaultSize,
|
|
946
|
+
maxSize = 100,
|
|
947
|
+
minSize = 0
|
|
948
|
+
} = panelConstraints;
|
|
949
|
+
if (minSize > maxSize) {
|
|
950
|
+
warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
|
|
1122
951
|
}
|
|
1123
|
-
{
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
minSizePercentage
|
|
1129
|
-
} = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
|
|
1130
|
-
if (minSizePercentage > maxSizePercentage) {
|
|
1131
|
-
warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
|
|
1132
|
-
}
|
|
1133
|
-
if (defaultSizePercentage != null) {
|
|
1134
|
-
if (defaultSizePercentage < 0) {
|
|
1135
|
-
warnings.push("default size should not be less than 0");
|
|
1136
|
-
} else if (defaultSizePercentage < minSizePercentage) {
|
|
1137
|
-
warnings.push("default size should not be less than min size");
|
|
1138
|
-
}
|
|
1139
|
-
if (defaultSizePercentage > 100) {
|
|
1140
|
-
warnings.push("default size should not be greater than 100");
|
|
1141
|
-
} else if (defaultSizePercentage > maxSizePercentage) {
|
|
1142
|
-
warnings.push("default size should not be greater than max size");
|
|
1143
|
-
}
|
|
952
|
+
if (defaultSize != null) {
|
|
953
|
+
if (defaultSize < 0) {
|
|
954
|
+
warnings.push("default size should not be less than 0");
|
|
955
|
+
} else if (defaultSize < minSize) {
|
|
956
|
+
warnings.push("default size should not be less than min size");
|
|
1144
957
|
}
|
|
1145
|
-
if (
|
|
1146
|
-
warnings.push("
|
|
958
|
+
if (defaultSize > 100) {
|
|
959
|
+
warnings.push("default size should not be greater than 100");
|
|
960
|
+
} else if (defaultSize > maxSize) {
|
|
961
|
+
warnings.push("default size should not be greater than max size");
|
|
1147
962
|
}
|
|
1148
963
|
}
|
|
964
|
+
if (collapsedSize > minSize) {
|
|
965
|
+
warnings.push("collapsed size should not be greater than min size");
|
|
966
|
+
}
|
|
1149
967
|
if (warnings.length > 0) {
|
|
1150
968
|
const name = panelId != null ? `Panel "${panelId}"` : "Panel";
|
|
1151
969
|
console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
|
|
@@ -1157,20 +975,26 @@ function validatePanelConstraints({
|
|
|
1157
975
|
|
|
1158
976
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1159
977
|
function validatePanelGroupLayout({
|
|
1160
|
-
groupSizePixels,
|
|
1161
978
|
layout: prevLayout,
|
|
1162
979
|
panelConstraints
|
|
1163
980
|
}) {
|
|
1164
981
|
const nextLayout = [...prevLayout];
|
|
982
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1165
983
|
|
|
1166
984
|
// Validate layout expectations
|
|
1167
985
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1168
986
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1169
|
-
} else if (!fuzzyNumbersEqual(
|
|
987
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1170
988
|
// This is not ideal so we should warn about it, but it may be recoverable in some cases
|
|
1171
989
|
// (especially if the amount is small)
|
|
1172
990
|
{
|
|
1173
|
-
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}
|
|
991
|
+
console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
|
|
992
|
+
}
|
|
993
|
+
for (let index = 0; index < panelConstraints.length; index++) {
|
|
994
|
+
const unsafeSize = nextLayout[index];
|
|
995
|
+
assert(unsafeSize != null);
|
|
996
|
+
const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
|
|
997
|
+
nextLayout[index] = safeSize;
|
|
1174
998
|
}
|
|
1175
999
|
}
|
|
1176
1000
|
let remainingSize = 0;
|
|
@@ -1178,8 +1002,8 @@ function validatePanelGroupLayout({
|
|
|
1178
1002
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1179
1003
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1180
1004
|
const unsafeSize = nextLayout[index];
|
|
1005
|
+
assert(unsafeSize != null);
|
|
1181
1006
|
const safeSize = resizePanel({
|
|
1182
|
-
groupSizePixels,
|
|
1183
1007
|
panelConstraints,
|
|
1184
1008
|
panelIndex: index,
|
|
1185
1009
|
size: unsafeSize
|
|
@@ -1195,9 +1019,9 @@ function validatePanelGroupLayout({
|
|
|
1195
1019
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1196
1020
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1197
1021
|
const prevSize = nextLayout[index];
|
|
1022
|
+
assert(prevSize != null);
|
|
1198
1023
|
const unsafeSize = prevSize + remainingSize;
|
|
1199
1024
|
const safeSize = resizePanel({
|
|
1200
|
-
groupSizePixels,
|
|
1201
1025
|
panelConstraints,
|
|
1202
1026
|
panelIndex: index,
|
|
1203
1027
|
size: unsafeSize
|
|
@@ -1232,21 +1056,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1232
1056
|
autoSaveId = null,
|
|
1233
1057
|
children,
|
|
1234
1058
|
className: classNameFromProps = "",
|
|
1235
|
-
dataAttributes,
|
|
1236
1059
|
direction,
|
|
1237
1060
|
forwardedRef,
|
|
1238
|
-
id: idFromProps,
|
|
1061
|
+
id: idFromProps = null,
|
|
1239
1062
|
onLayout = null,
|
|
1240
|
-
|
|
1241
|
-
keyboardResizeByPixels = null,
|
|
1063
|
+
keyboardResizeBy = null,
|
|
1242
1064
|
storage = defaultStorage,
|
|
1243
1065
|
style: styleFromProps,
|
|
1244
|
-
tagName: Type = "div"
|
|
1066
|
+
tagName: Type = "div",
|
|
1067
|
+
...rest
|
|
1245
1068
|
}) {
|
|
1246
1069
|
const groupId = useUniqueId(idFromProps);
|
|
1247
1070
|
const [dragState, setDragState] = useState(null);
|
|
1248
1071
|
const [layout, setLayout] = useState([]);
|
|
1249
|
-
const
|
|
1072
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1250
1073
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1251
1074
|
const prevDeltaRef = useRef(0);
|
|
1252
1075
|
const committedValuesRef = useRef({
|
|
@@ -1254,8 +1077,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1254
1077
|
direction,
|
|
1255
1078
|
dragState,
|
|
1256
1079
|
id: groupId,
|
|
1257
|
-
|
|
1258
|
-
keyboardResizeByPixels,
|
|
1080
|
+
keyboardResizeBy,
|
|
1259
1081
|
onLayout,
|
|
1260
1082
|
storage
|
|
1261
1083
|
});
|
|
@@ -1271,33 +1093,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1271
1093
|
useImperativeHandle(forwardedRef, () => ({
|
|
1272
1094
|
getId: () => committedValuesRef.current.id,
|
|
1273
1095
|
getLayout: () => {
|
|
1274
|
-
const {
|
|
1275
|
-
id: groupId
|
|
1276
|
-
} = committedValuesRef.current;
|
|
1277
1096
|
const {
|
|
1278
1097
|
layout
|
|
1279
1098
|
} = eagerValuesRef.current;
|
|
1280
|
-
|
|
1281
|
-
return layout.map(sizePercentage => {
|
|
1282
|
-
return {
|
|
1283
|
-
sizePercentage,
|
|
1284
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1285
|
-
};
|
|
1286
|
-
});
|
|
1099
|
+
return layout;
|
|
1287
1100
|
},
|
|
1288
|
-
setLayout:
|
|
1101
|
+
setLayout: unsafeLayout => {
|
|
1289
1102
|
const {
|
|
1290
|
-
id: groupId,
|
|
1291
1103
|
onLayout
|
|
1292
1104
|
} = committedValuesRef.current;
|
|
1293
1105
|
const {
|
|
1294
1106
|
layout: prevLayout,
|
|
1295
1107
|
panelDataArray
|
|
1296
1108
|
} = eagerValuesRef.current;
|
|
1297
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1298
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1299
1109
|
const safeLayout = validatePanelGroupLayout({
|
|
1300
|
-
groupSizePixels,
|
|
1301
1110
|
layout: unsafeLayout,
|
|
1302
1111
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1303
1112
|
});
|
|
@@ -1305,16 +1114,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1305
1114
|
setLayout(safeLayout);
|
|
1306
1115
|
eagerValuesRef.current.layout = safeLayout;
|
|
1307
1116
|
if (onLayout) {
|
|
1308
|
-
onLayout(safeLayout
|
|
1309
|
-
sizePercentage,
|
|
1310
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1311
|
-
})));
|
|
1117
|
+
onLayout(safeLayout);
|
|
1312
1118
|
}
|
|
1313
|
-
callPanelCallbacks(
|
|
1119
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1314
1120
|
}
|
|
1315
1121
|
}
|
|
1316
1122
|
}), []);
|
|
1317
|
-
|
|
1318
1123
|
useWindowSplitterPanelGroupBehavior({
|
|
1319
1124
|
committedValuesRef,
|
|
1320
1125
|
eagerValuesRef,
|
|
@@ -1333,12 +1138,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1333
1138
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1334
1139
|
return;
|
|
1335
1140
|
}
|
|
1141
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1336
1142
|
|
|
1337
1143
|
// Limit the frequency of localStorage updates.
|
|
1338
|
-
if (
|
|
1339
|
-
|
|
1144
|
+
if (debouncedSave == null) {
|
|
1145
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1146
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1340
1147
|
}
|
|
1341
|
-
|
|
1148
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1342
1149
|
}
|
|
1343
1150
|
}, [autoSaveId, layout, storage]);
|
|
1344
1151
|
|
|
@@ -1371,12 +1178,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1371
1178
|
}
|
|
1372
1179
|
if (!didLogPanelConstraintsWarning) {
|
|
1373
1180
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1374
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1375
1181
|
for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
|
|
1182
|
+
const panelData = panelDataArray[panelIndex];
|
|
1183
|
+
assert(panelData);
|
|
1376
1184
|
const isValid = validatePanelConstraints({
|
|
1377
|
-
groupSizePixels,
|
|
1378
1185
|
panelConstraints,
|
|
1379
|
-
panelId:
|
|
1186
|
+
panelId: panelData.id,
|
|
1380
1187
|
panelIndex
|
|
1381
1188
|
});
|
|
1382
1189
|
if (!isValid) {
|
|
@@ -1400,20 +1207,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1400
1207
|
if (panelData.constraints.collapsible) {
|
|
1401
1208
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1402
1209
|
const {
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
pivotIndices
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
if (
|
|
1210
|
+
collapsedSize = 0,
|
|
1211
|
+
panelSize,
|
|
1212
|
+
pivotIndices
|
|
1213
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1214
|
+
assert(panelSize != null);
|
|
1215
|
+
if (panelSize !== collapsedSize) {
|
|
1409
1216
|
// Store size before collapse;
|
|
1410
1217
|
// This is the size that gets restored if the expand() API is used.
|
|
1411
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1218
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1412
1219
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1413
|
-
const delta = isLastPanel ?
|
|
1220
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1414
1221
|
const nextLayout = adjustLayoutByDelta({
|
|
1415
1222
|
delta,
|
|
1416
|
-
groupSizePixels,
|
|
1417
1223
|
layout: prevLayout,
|
|
1418
1224
|
panelConstraints: panelConstraintsArray,
|
|
1419
1225
|
pivotIndices,
|
|
@@ -1423,16 +1229,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1423
1229
|
setLayout(nextLayout);
|
|
1424
1230
|
eagerValuesRef.current.layout = nextLayout;
|
|
1425
1231
|
if (onLayout) {
|
|
1426
|
-
onLayout(nextLayout
|
|
1427
|
-
sizePercentage,
|
|
1428
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1429
|
-
})));
|
|
1232
|
+
onLayout(nextLayout);
|
|
1430
1233
|
}
|
|
1431
|
-
callPanelCallbacks(
|
|
1234
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1432
1235
|
}
|
|
1433
1236
|
}
|
|
1434
1237
|
}
|
|
1435
|
-
}, [
|
|
1238
|
+
}, []);
|
|
1436
1239
|
|
|
1437
1240
|
// External APIs are safe to memoize via committed values ref
|
|
1438
1241
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1446,21 +1249,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1446
1249
|
if (panelData.constraints.collapsible) {
|
|
1447
1250
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1448
1251
|
const {
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
pivotIndices
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1252
|
+
collapsedSize = 0,
|
|
1253
|
+
panelSize,
|
|
1254
|
+
minSize = 0,
|
|
1255
|
+
pivotIndices
|
|
1256
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1257
|
+
if (panelSize === collapsedSize) {
|
|
1456
1258
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1457
|
-
const
|
|
1458
|
-
const
|
|
1259
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1260
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1459
1261
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1460
|
-
const delta = isLastPanel ?
|
|
1262
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1461
1263
|
const nextLayout = adjustLayoutByDelta({
|
|
1462
1264
|
delta,
|
|
1463
|
-
groupSizePixels,
|
|
1464
1265
|
layout: prevLayout,
|
|
1465
1266
|
panelConstraints: panelConstraintsArray,
|
|
1466
1267
|
pivotIndices,
|
|
@@ -1470,16 +1271,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1470
1271
|
setLayout(nextLayout);
|
|
1471
1272
|
eagerValuesRef.current.layout = nextLayout;
|
|
1472
1273
|
if (onLayout) {
|
|
1473
|
-
onLayout(nextLayout
|
|
1474
|
-
sizePercentage,
|
|
1475
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1476
|
-
})));
|
|
1274
|
+
onLayout(nextLayout);
|
|
1477
1275
|
}
|
|
1478
|
-
callPanelCallbacks(
|
|
1276
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1479
1277
|
}
|
|
1480
1278
|
}
|
|
1481
1279
|
}
|
|
1482
|
-
}, [
|
|
1280
|
+
}, []);
|
|
1483
1281
|
|
|
1484
1282
|
// External APIs are safe to memoize via committed values ref
|
|
1485
1283
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1488,14 +1286,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1488
1286
|
panelDataArray
|
|
1489
1287
|
} = eagerValuesRef.current;
|
|
1490
1288
|
const {
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
return
|
|
1495
|
-
|
|
1496
|
-
sizePixels: panelSizePixels
|
|
1497
|
-
};
|
|
1498
|
-
}, [groupId]);
|
|
1289
|
+
panelSize
|
|
1290
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1291
|
+
assert(panelSize != null);
|
|
1292
|
+
return panelSize;
|
|
1293
|
+
}, []);
|
|
1499
1294
|
|
|
1500
1295
|
// This API should never read from committedValuesRef
|
|
1501
1296
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1518,12 +1313,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1518
1313
|
panelDataArray
|
|
1519
1314
|
} = eagerValuesRef.current;
|
|
1520
1315
|
const {
|
|
1521
|
-
|
|
1316
|
+
collapsedSize,
|
|
1522
1317
|
collapsible,
|
|
1523
|
-
|
|
1524
|
-
} = panelDataHelper(
|
|
1525
|
-
return collapsible === true &&
|
|
1526
|
-
}, [
|
|
1318
|
+
panelSize
|
|
1319
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1320
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1321
|
+
}, []);
|
|
1527
1322
|
|
|
1528
1323
|
// External APIs are safe to memoize via committed values ref
|
|
1529
1324
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1532,12 +1327,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1532
1327
|
panelDataArray
|
|
1533
1328
|
} = eagerValuesRef.current;
|
|
1534
1329
|
const {
|
|
1535
|
-
|
|
1330
|
+
collapsedSize = 0,
|
|
1536
1331
|
collapsible,
|
|
1537
|
-
|
|
1538
|
-
} = panelDataHelper(
|
|
1539
|
-
|
|
1540
|
-
|
|
1332
|
+
panelSize
|
|
1333
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1334
|
+
assert(panelSize != null);
|
|
1335
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1336
|
+
}, []);
|
|
1541
1337
|
const registerPanel = useCallback(panelData => {
|
|
1542
1338
|
const {
|
|
1543
1339
|
autoSaveId,
|
|
@@ -1577,18 +1373,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1577
1373
|
if (autoSaveId) {
|
|
1578
1374
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1579
1375
|
}
|
|
1580
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1581
|
-
if (groupSizePixels <= 0) {
|
|
1582
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1583
|
-
constraints
|
|
1584
|
-
}) => constraints))) {
|
|
1585
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1586
|
-
return;
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
1376
|
if (unsafeLayout == null) {
|
|
1590
1377
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1591
|
-
groupSizePixels,
|
|
1592
1378
|
panelDataArray
|
|
1593
1379
|
});
|
|
1594
1380
|
}
|
|
@@ -1596,7 +1382,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1596
1382
|
// Validate even saved layouts in case something has changed since last render
|
|
1597
1383
|
// e.g. for pixel groups, this could be the size of the window
|
|
1598
1384
|
const nextLayout = validatePanelGroupLayout({
|
|
1599
|
-
groupSizePixels,
|
|
1600
1385
|
layout: unsafeLayout,
|
|
1601
1386
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1602
1387
|
});
|
|
@@ -1608,12 +1393,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1608
1393
|
eagerValuesRef.current.layout = nextLayout;
|
|
1609
1394
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1610
1395
|
if (onLayout) {
|
|
1611
|
-
onLayout(nextLayout
|
|
1612
|
-
sizePercentage,
|
|
1613
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1614
|
-
})));
|
|
1396
|
+
onLayout(nextLayout);
|
|
1615
1397
|
}
|
|
1616
|
-
callPanelCallbacks(
|
|
1398
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1617
1399
|
}
|
|
1618
1400
|
}, []);
|
|
1619
1401
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1623,8 +1405,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1623
1405
|
direction,
|
|
1624
1406
|
dragState,
|
|
1625
1407
|
id: groupId,
|
|
1626
|
-
|
|
1627
|
-
keyboardResizeByPixels,
|
|
1408
|
+
keyboardResizeBy,
|
|
1628
1409
|
onLayout
|
|
1629
1410
|
} = committedValuesRef.current;
|
|
1630
1411
|
const {
|
|
@@ -1635,10 +1416,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1635
1416
|
initialLayout
|
|
1636
1417
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1637
1418
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1638
|
-
let delta = calculateDeltaPercentage(event,
|
|
1639
|
-
percentage: keyboardResizeByPercentage,
|
|
1640
|
-
pixels: keyboardResizeByPixels
|
|
1641
|
-
});
|
|
1419
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1642
1420
|
if (delta === 0) {
|
|
1643
1421
|
return;
|
|
1644
1422
|
}
|
|
@@ -1648,11 +1426,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1648
1426
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1649
1427
|
delta = -delta;
|
|
1650
1428
|
}
|
|
1651
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1652
1429
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1653
1430
|
const nextLayout = adjustLayoutByDelta({
|
|
1654
1431
|
delta,
|
|
1655
|
-
groupSizePixels,
|
|
1656
1432
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1657
1433
|
panelConstraints,
|
|
1658
1434
|
pivotIndices,
|
|
@@ -1688,18 +1464,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1688
1464
|
setLayout(nextLayout);
|
|
1689
1465
|
eagerValuesRef.current.layout = nextLayout;
|
|
1690
1466
|
if (onLayout) {
|
|
1691
|
-
onLayout(nextLayout
|
|
1692
|
-
sizePercentage,
|
|
1693
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1694
|
-
})));
|
|
1467
|
+
onLayout(nextLayout);
|
|
1695
1468
|
}
|
|
1696
|
-
callPanelCallbacks(
|
|
1469
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1697
1470
|
}
|
|
1698
1471
|
};
|
|
1699
1472
|
}, []);
|
|
1700
1473
|
|
|
1701
1474
|
// External APIs are safe to memoize via committed values ref
|
|
1702
|
-
const resizePanel = useCallback((panelData,
|
|
1475
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1703
1476
|
const {
|
|
1704
1477
|
onLayout
|
|
1705
1478
|
} = committedValuesRef.current;
|
|
@@ -1709,16 +1482,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1709
1482
|
} = eagerValuesRef.current;
|
|
1710
1483
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1711
1484
|
const {
|
|
1712
|
-
|
|
1713
|
-
panelSizePercentage,
|
|
1485
|
+
panelSize,
|
|
1714
1486
|
pivotIndices
|
|
1715
|
-
} = panelDataHelper(
|
|
1716
|
-
|
|
1487
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1488
|
+
assert(panelSize != null);
|
|
1717
1489
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1718
|
-
const delta = isLastPanel ?
|
|
1490
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1719
1491
|
const nextLayout = adjustLayoutByDelta({
|
|
1720
1492
|
delta,
|
|
1721
|
-
groupSizePixels,
|
|
1722
1493
|
layout: prevLayout,
|
|
1723
1494
|
panelConstraints: panelConstraintsArray,
|
|
1724
1495
|
pivotIndices,
|
|
@@ -1728,14 +1499,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1728
1499
|
setLayout(nextLayout);
|
|
1729
1500
|
eagerValuesRef.current.layout = nextLayout;
|
|
1730
1501
|
if (onLayout) {
|
|
1731
|
-
onLayout(nextLayout
|
|
1732
|
-
sizePercentage,
|
|
1733
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1734
|
-
})));
|
|
1502
|
+
onLayout(nextLayout);
|
|
1735
1503
|
}
|
|
1736
|
-
callPanelCallbacks(
|
|
1504
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1737
1505
|
}
|
|
1738
|
-
}, [
|
|
1506
|
+
}, []);
|
|
1739
1507
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1740
1508
|
const {
|
|
1741
1509
|
direction
|
|
@@ -1744,6 +1512,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1744
1512
|
layout
|
|
1745
1513
|
} = eagerValuesRef.current;
|
|
1746
1514
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1515
|
+
assert(handleElement);
|
|
1747
1516
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1748
1517
|
setDragState({
|
|
1749
1518
|
dragHandleId,
|
|
@@ -1762,7 +1531,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1762
1531
|
});
|
|
1763
1532
|
const unregisterPanel = useCallback(panelData => {
|
|
1764
1533
|
const {
|
|
1765
|
-
id: groupId,
|
|
1766
1534
|
onLayout
|
|
1767
1535
|
} = committedValuesRef.current;
|
|
1768
1536
|
const {
|
|
@@ -1785,7 +1553,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1785
1553
|
const {
|
|
1786
1554
|
pendingPanelIds
|
|
1787
1555
|
} = unregisterPanelRef.current;
|
|
1788
|
-
const map =
|
|
1556
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1789
1557
|
|
|
1790
1558
|
// TRICKY
|
|
1791
1559
|
// Strict effects mode
|
|
@@ -1794,7 +1562,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1794
1562
|
pendingPanelIds.delete(panelId);
|
|
1795
1563
|
if (panelDataArray.find(({
|
|
1796
1564
|
id
|
|
1797
|
-
}) => id === panelId)
|
|
1565
|
+
}) => id === panelId) != null) {
|
|
1798
1566
|
unmountDueToStrictMode = true;
|
|
1799
1567
|
|
|
1800
1568
|
// TRICKY
|
|
@@ -1811,16 +1579,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1811
1579
|
// The group is unmounting; skip layout calculation.
|
|
1812
1580
|
return;
|
|
1813
1581
|
}
|
|
1814
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1815
1582
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1816
|
-
groupSizePixels,
|
|
1817
1583
|
panelDataArray
|
|
1818
1584
|
});
|
|
1819
1585
|
|
|
1820
1586
|
// Validate even saved layouts in case something has changed since last render
|
|
1821
1587
|
// e.g. for pixel groups, this could be the size of the window
|
|
1822
1588
|
const nextLayout = validatePanelGroupLayout({
|
|
1823
|
-
groupSizePixels,
|
|
1824
1589
|
layout: unsafeLayout,
|
|
1825
1590
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1826
1591
|
});
|
|
@@ -1828,12 +1593,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1828
1593
|
setLayout(nextLayout);
|
|
1829
1594
|
eagerValuesRef.current.layout = nextLayout;
|
|
1830
1595
|
if (onLayout) {
|
|
1831
|
-
onLayout(nextLayout
|
|
1832
|
-
sizePercentage,
|
|
1833
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1834
|
-
})));
|
|
1596
|
+
onLayout(nextLayout);
|
|
1835
1597
|
}
|
|
1836
|
-
callPanelCallbacks(
|
|
1598
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1837
1599
|
}
|
|
1838
1600
|
}, 0);
|
|
1839
1601
|
}, []);
|
|
@@ -1864,13 +1626,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1864
1626
|
return createElement(PanelGroupContext.Provider, {
|
|
1865
1627
|
value: context
|
|
1866
1628
|
}, createElement(Type, {
|
|
1629
|
+
...rest,
|
|
1867
1630
|
children,
|
|
1868
1631
|
className: classNameFromProps,
|
|
1869
1632
|
style: {
|
|
1870
1633
|
...style,
|
|
1871
1634
|
...styleFromProps
|
|
1872
1635
|
},
|
|
1873
|
-
...dataAttributes,
|
|
1874
1636
|
// CSS selectors
|
|
1875
1637
|
"data-panel-group": "",
|
|
1876
1638
|
"data-panel-group-direction": direction,
|
|
@@ -1883,22 +1645,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
1883
1645
|
}));
|
|
1884
1646
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
1885
1647
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
1886
|
-
function panelDataHelper(
|
|
1648
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
1887
1649
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1888
1650
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1889
1651
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1890
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1891
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
1892
1652
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
1893
1653
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
1894
|
-
const
|
|
1895
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1654
|
+
const panelSize = layout[panelIndex];
|
|
1896
1655
|
return {
|
|
1897
|
-
...
|
|
1898
|
-
|
|
1899
|
-
panelSizePercentage,
|
|
1900
|
-
panelSizePixels,
|
|
1901
|
-
groupSizePixels,
|
|
1656
|
+
...panelConstraints,
|
|
1657
|
+
panelSize,
|
|
1902
1658
|
pivotIndices
|
|
1903
1659
|
};
|
|
1904
1660
|
}
|
|
@@ -1938,6 +1694,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1938
1694
|
{
|
|
1939
1695
|
event.preventDefault();
|
|
1940
1696
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1697
|
+
assert(groupId);
|
|
1941
1698
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
1942
1699
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
1943
1700
|
assert(index !== null);
|
|
@@ -1958,12 +1715,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1958
1715
|
function PanelResizeHandle({
|
|
1959
1716
|
children = null,
|
|
1960
1717
|
className: classNameFromProps = "",
|
|
1961
|
-
dataAttributes,
|
|
1962
1718
|
disabled = false,
|
|
1963
|
-
id: idFromProps
|
|
1719
|
+
id: idFromProps,
|
|
1964
1720
|
onDragging,
|
|
1965
1721
|
style: styleFromProps = {},
|
|
1966
|
-
|
|
1722
|
+
tabIndex = 0,
|
|
1723
|
+
tagName: Type = "div",
|
|
1724
|
+
...rest
|
|
1967
1725
|
}) {
|
|
1968
1726
|
const divElementRef = useRef(null);
|
|
1969
1727
|
|
|
@@ -1993,8 +1751,9 @@ function PanelResizeHandle({
|
|
|
1993
1751
|
const stopDraggingAndBlur = useCallback(() => {
|
|
1994
1752
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
1995
1753
|
// That would cause the PanelGroup to think it was still active.
|
|
1996
|
-
const
|
|
1997
|
-
|
|
1754
|
+
const divElement = divElementRef.current;
|
|
1755
|
+
assert(divElement);
|
|
1756
|
+
divElement.blur();
|
|
1998
1757
|
stopDragging();
|
|
1999
1758
|
const {
|
|
2000
1759
|
onDragging
|
|
@@ -2022,6 +1781,7 @@ function PanelResizeHandle({
|
|
|
2022
1781
|
resizeHandler(event);
|
|
2023
1782
|
};
|
|
2024
1783
|
const divElement = divElementRef.current;
|
|
1784
|
+
assert(divElement);
|
|
2025
1785
|
const targetDocument = divElement.ownerDocument;
|
|
2026
1786
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2027
1787
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2049,15 +1809,18 @@ function PanelResizeHandle({
|
|
|
2049
1809
|
userSelect: "none"
|
|
2050
1810
|
};
|
|
2051
1811
|
return createElement(Type, {
|
|
1812
|
+
...rest,
|
|
2052
1813
|
children,
|
|
2053
1814
|
className: classNameFromProps,
|
|
2054
1815
|
onBlur: () => setIsFocused(false),
|
|
2055
1816
|
onFocus: () => setIsFocused(true),
|
|
2056
1817
|
onMouseDown: event => {
|
|
2057
1818
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1819
|
+
const callbacks = callbacksRef.current;
|
|
1820
|
+
assert(callbacks);
|
|
2058
1821
|
const {
|
|
2059
1822
|
onDragging
|
|
2060
|
-
} =
|
|
1823
|
+
} = callbacks;
|
|
2061
1824
|
if (onDragging) {
|
|
2062
1825
|
onDragging(true);
|
|
2063
1826
|
}
|
|
@@ -2067,9 +1830,11 @@ function PanelResizeHandle({
|
|
|
2067
1830
|
onTouchEnd: stopDraggingAndBlur,
|
|
2068
1831
|
onTouchStart: event => {
|
|
2069
1832
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1833
|
+
const callbacks = callbacksRef.current;
|
|
1834
|
+
assert(callbacks);
|
|
2070
1835
|
const {
|
|
2071
1836
|
onDragging
|
|
2072
|
-
} =
|
|
1837
|
+
} = callbacks;
|
|
2073
1838
|
if (onDragging) {
|
|
2074
1839
|
onDragging(true);
|
|
2075
1840
|
}
|
|
@@ -2080,8 +1845,7 @@ function PanelResizeHandle({
|
|
|
2080
1845
|
...style,
|
|
2081
1846
|
...styleFromProps
|
|
2082
1847
|
},
|
|
2083
|
-
tabIndex
|
|
2084
|
-
...dataAttributes,
|
|
1848
|
+
tabIndex,
|
|
2085
1849
|
// CSS selectors
|
|
2086
1850
|
"data-panel-group-direction": direction,
|
|
2087
1851
|
"data-panel-group-id": groupId,
|
|
@@ -2096,3 +1860,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
|
2096
1860
|
exports.Panel = Panel;
|
|
2097
1861
|
exports.PanelGroup = PanelGroup;
|
|
2098
1862
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
1863
|
+
exports.assert = assert;
|