react-resizable-panels 0.0.63 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +1 -0
- package/CHANGELOG.md +5 -0
- package/dist/declarations/src/Panel.d.ts +19 -34
- package/dist/declarations/src/PanelGroup.d.ts +9 -13
- package/dist/declarations/src/PanelResizeHandle.d.ts +5 -7
- package/dist/declarations/src/index.d.ts +2 -2
- package/dist/declarations/src/types.d.ts +0 -7
- package/dist/declarations/src/utils/assert.d.ts +1 -0
- package/dist/declarations/src/vendor/react.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +252 -517
- package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +278 -573
- package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.esm.js +278 -574
- package/dist/react-resizable-panels.browser.esm.js +252 -518
- package/dist/react-resizable-panels.cjs.js +252 -517
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.cjs.js +280 -575
- package/dist/react-resizable-panels.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.esm.js +280 -576
- package/dist/react-resizable-panels.development.node.cjs.js +266 -501
- package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.node.esm.js +266 -502
- package/dist/react-resizable-panels.esm.js +252 -518
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +238 -443
- package/dist/react-resizable-panels.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.node.esm.js +238 -444
- package/package.json +1 -1
- package/src/Panel.test.tsx +74 -73
- package/src/Panel.ts +44 -68
- package/src/PanelGroup.test.tsx +43 -42
- package/src/PanelGroup.ts +189 -403
- package/src/PanelGroupContext.ts +2 -3
- package/src/PanelResizeHandle.test.tsx +68 -0
- package/src/PanelResizeHandle.ts +31 -22
- package/src/hooks/useWindowSplitterBehavior.ts +2 -1
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +22 -33
- package/src/index.ts +4 -3
- package/src/types.ts +0 -9
- package/src/utils/adjustLayoutByDelta.test.ts +206 -336
- package/src/utils/adjustLayoutByDelta.ts +59 -51
- package/src/utils/assert.ts +1 -1
- package/src/utils/calculateAriaValues.test.ts +6 -11
- package/src/utils/calculateAriaValues.ts +7 -29
- package/src/utils/calculateDeltaPercentage.ts +8 -15
- package/src/utils/calculateDragOffsetPercentage.ts +11 -5
- package/src/utils/calculateUnsafeDefaultLayout.test.ts +4 -9
- package/src/utils/calculateUnsafeDefaultLayout.ts +13 -18
- package/src/utils/callPanelCallbacks.ts +11 -46
- package/src/utils/getResizeEventCursorPosition.ts +2 -0
- package/src/utils/resizePanel.test.ts +6 -52
- package/src/utils/resizePanel.ts +24 -46
- package/src/utils/test-utils.ts +6 -7
- package/src/utils/validatePanelConstraints.test.ts +12 -65
- package/src/utils/validatePanelConstraints.ts +26 -67
- package/src/utils/validatePanelGroupLayout.test.ts +27 -142
- package/src/utils/validatePanelGroupLayout.ts +17 -13
- package/src/vendor/react.ts +2 -0
- package/src/utils/computePercentagePanelConstraints.test.ts +0 -98
- package/src/utils/computePercentagePanelConstraints.ts +0 -56
- package/src/utils/convertPercentageToPixels.test.ts +0 -9
- package/src/utils/convertPercentageToPixels.ts +0 -6
- package/src/utils/convertPixelConstraintsToPercentages.test.ts +0 -47
- package/src/utils/convertPixelConstraintsToPercentages.ts +0 -72
- package/src/utils/convertPixelsToPercentage.test.ts +0 -9
- package/src/utils/convertPixelsToPercentage.ts +0 -6
- package/src/utils/getPercentageSizeFromMixedSizes.test.ts +0 -47
- package/src/utils/getPercentageSizeFromMixedSizes.ts +0 -15
- package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +0 -23
- package/src/utils/shouldMonitorPixelBasedConstraints.ts +0 -13
|
@@ -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,
|
|
@@ -111,15 +103,11 @@ function PanelWithForwardedRef({
|
|
|
111
103
|
callbacks.onCollapse = onCollapse;
|
|
112
104
|
callbacks.onExpand = onExpand;
|
|
113
105
|
callbacks.onResize = onResize;
|
|
114
|
-
constraints.
|
|
115
|
-
constraints.collapsedSizePixels = collapsedSizePixels;
|
|
106
|
+
constraints.collapsedSize = collapsedSize;
|
|
116
107
|
constraints.collapsible = collapsible;
|
|
117
|
-
constraints.
|
|
118
|
-
constraints.
|
|
119
|
-
constraints.
|
|
120
|
-
constraints.maxSizePixels = maxSizePixels;
|
|
121
|
-
constraints.minSizePercentage = minSizePercentage;
|
|
122
|
-
constraints.minSizePixels = minSizePixels;
|
|
108
|
+
constraints.defaultSize = defaultSize;
|
|
109
|
+
constraints.maxSize = maxSize;
|
|
110
|
+
constraints.minSize = minSize;
|
|
123
111
|
});
|
|
124
112
|
useIsomorphicLayoutEffect(() => {
|
|
125
113
|
const panelData = panelDataRef.current;
|
|
@@ -147,19 +135,19 @@ function PanelWithForwardedRef({
|
|
|
147
135
|
isExpanded() {
|
|
148
136
|
return !isPanelCollapsed(panelDataRef.current);
|
|
149
137
|
},
|
|
150
|
-
resize:
|
|
151
|
-
resizePanel(panelDataRef.current,
|
|
138
|
+
resize: size => {
|
|
139
|
+
resizePanel(panelDataRef.current, size);
|
|
152
140
|
}
|
|
153
141
|
}), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
|
|
154
142
|
const style = getPanelStyle(panelDataRef.current);
|
|
155
143
|
return createElement(Type, {
|
|
144
|
+
...rest,
|
|
156
145
|
children,
|
|
157
146
|
className: classNameFromProps,
|
|
158
147
|
style: {
|
|
159
148
|
...style,
|
|
160
149
|
...styleFromProps
|
|
161
150
|
},
|
|
162
|
-
...dataAttributes,
|
|
163
151
|
// CSS selectors
|
|
164
152
|
"data-panel": "",
|
|
165
153
|
"data-panel-id": panelId,
|
|
@@ -176,81 +164,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
176
164
|
PanelWithForwardedRef.displayName = "Panel";
|
|
177
165
|
Panel.displayName = "forwardRef(Panel)";
|
|
178
166
|
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
|
|
184
|
-
let {
|
|
185
|
-
collapsedSizePercentage = 0,
|
|
186
|
-
collapsedSizePixels,
|
|
187
|
-
defaultSizePercentage,
|
|
188
|
-
defaultSizePixels,
|
|
189
|
-
maxSizePercentage = 100,
|
|
190
|
-
maxSizePixels,
|
|
191
|
-
minSizePercentage = 0,
|
|
192
|
-
minSizePixels
|
|
193
|
-
} = panelConstraints;
|
|
194
|
-
const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
|
|
195
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
196
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
197
|
-
return {
|
|
198
|
-
collapsedSizePercentage: 0,
|
|
199
|
-
defaultSizePercentage,
|
|
200
|
-
maxSizePercentage: 0,
|
|
201
|
-
minSizePercentage: 0
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
if (collapsedSizePixels != null) {
|
|
205
|
-
collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
|
|
206
|
-
}
|
|
207
|
-
if (defaultSizePixels != null) {
|
|
208
|
-
defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
|
|
209
|
-
}
|
|
210
|
-
if (minSizePixels != null) {
|
|
211
|
-
minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
|
|
212
|
-
}
|
|
213
|
-
if (maxSizePixels != null) {
|
|
214
|
-
maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
|
|
215
|
-
}
|
|
216
|
-
return {
|
|
217
|
-
collapsedSizePercentage,
|
|
218
|
-
defaultSizePercentage,
|
|
219
|
-
maxSizePercentage,
|
|
220
|
-
minSizePercentage
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
|
|
225
|
-
// All panel constraints, excluding the current one
|
|
226
|
-
let totalMinConstraints = 0;
|
|
227
|
-
let totalMaxConstraints = 0;
|
|
228
|
-
for (let index = 0; index < panelConstraintsArray.length; index++) {
|
|
229
|
-
if (index !== panelIndex) {
|
|
230
|
-
const {
|
|
231
|
-
collapsible
|
|
232
|
-
} = panelConstraintsArray[index];
|
|
233
|
-
const {
|
|
234
|
-
collapsedSizePercentage,
|
|
235
|
-
maxSizePercentage,
|
|
236
|
-
minSizePercentage
|
|
237
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
|
|
238
|
-
totalMaxConstraints += maxSizePercentage;
|
|
239
|
-
totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
|
|
240
|
-
}
|
|
167
|
+
function assert(expectedCondition, message = "Assertion failed!") {
|
|
168
|
+
if (!expectedCondition) {
|
|
169
|
+
console.error(message);
|
|
170
|
+
throw Error(message);
|
|
241
171
|
}
|
|
242
|
-
const {
|
|
243
|
-
collapsedSizePercentage,
|
|
244
|
-
defaultSizePercentage,
|
|
245
|
-
maxSizePercentage,
|
|
246
|
-
minSizePercentage
|
|
247
|
-
} = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
|
|
248
|
-
return {
|
|
249
|
-
collapsedSizePercentage,
|
|
250
|
-
defaultSizePercentage,
|
|
251
|
-
maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
|
|
252
|
-
minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
|
|
253
|
-
};
|
|
254
172
|
}
|
|
255
173
|
|
|
256
174
|
const PRECISION = 10;
|
|
@@ -272,56 +190,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
|
|
|
272
190
|
|
|
273
191
|
// Panel size must be in percentages; pixel values should be pre-converted
|
|
274
192
|
function resizePanel({
|
|
275
|
-
|
|
276
|
-
panelConstraints,
|
|
193
|
+
panelConstraints: panelConstraintsArray,
|
|
277
194
|
panelIndex,
|
|
278
195
|
size
|
|
279
196
|
}) {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
defaultSizePixels,
|
|
283
|
-
minSizePixels,
|
|
284
|
-
maxSizePixels
|
|
285
|
-
}) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
|
|
286
|
-
if (hasPixelConstraints && groupSizePixels <= 0) {
|
|
287
|
-
console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
|
|
288
|
-
return 0;
|
|
289
|
-
}
|
|
197
|
+
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
198
|
+
assert(panelConstraints != null);
|
|
290
199
|
let {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
|
|
303
|
-
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
304
|
-
size = collapsedSizePercentage;
|
|
305
|
-
} else {
|
|
306
|
-
size = minSizePercentage;
|
|
307
|
-
}
|
|
200
|
+
collapsedSize = 0,
|
|
201
|
+
collapsible,
|
|
202
|
+
maxSize = 100,
|
|
203
|
+
minSize = 0
|
|
204
|
+
} = panelConstraints;
|
|
205
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
206
|
+
if (collapsible) {
|
|
207
|
+
// Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
|
|
208
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
209
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
210
|
+
size = collapsedSize;
|
|
308
211
|
} else {
|
|
309
|
-
size =
|
|
212
|
+
size = minSize;
|
|
310
213
|
}
|
|
214
|
+
} else {
|
|
215
|
+
size = minSize;
|
|
311
216
|
}
|
|
312
217
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
218
|
+
size = Math.min(maxSize, size);
|
|
219
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
316
220
|
return size;
|
|
317
221
|
}
|
|
318
222
|
|
|
319
223
|
// All units must be in percentages; pixel values should be pre-converted
|
|
320
224
|
function adjustLayoutByDelta({
|
|
321
225
|
delta,
|
|
322
|
-
groupSizePixels,
|
|
323
226
|
layout: prevLayout,
|
|
324
|
-
panelConstraints,
|
|
227
|
+
panelConstraints: panelConstraintsArray,
|
|
325
228
|
pivotIndices,
|
|
326
229
|
trigger
|
|
327
230
|
}) {
|
|
@@ -329,6 +232,9 @@ function adjustLayoutByDelta({
|
|
|
329
232
|
return prevLayout;
|
|
330
233
|
}
|
|
331
234
|
const nextLayout = [...prevLayout];
|
|
235
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
236
|
+
assert(firstPivotIndex != null);
|
|
237
|
+
assert(secondPivotIndex != null);
|
|
332
238
|
let deltaApplied = 0;
|
|
333
239
|
|
|
334
240
|
//const DEBUG = [];
|
|
@@ -352,18 +258,23 @@ function adjustLayoutByDelta({
|
|
|
352
258
|
if (trigger === "keyboard") {
|
|
353
259
|
{
|
|
354
260
|
// Check if we should expand a collapsed panel
|
|
355
|
-
const index = delta < 0 ?
|
|
356
|
-
const
|
|
261
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
262
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
263
|
+
assert(panelConstraints);
|
|
264
|
+
|
|
357
265
|
//DEBUG.push(`edge case check 1: ${index}`);
|
|
358
266
|
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
359
|
-
if (
|
|
267
|
+
if (panelConstraints.collapsible) {
|
|
360
268
|
const prevSize = prevLayout[index];
|
|
269
|
+
assert(prevSize != null);
|
|
270
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
271
|
+
assert(panelConstraints);
|
|
361
272
|
const {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
} =
|
|
365
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
366
|
-
const localDelta =
|
|
273
|
+
collapsedSize = 0,
|
|
274
|
+
minSize = 0
|
|
275
|
+
} = panelConstraints;
|
|
276
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
|
|
277
|
+
const localDelta = minSize - prevSize;
|
|
367
278
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
368
279
|
|
|
369
280
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -376,18 +287,26 @@ function adjustLayoutByDelta({
|
|
|
376
287
|
|
|
377
288
|
{
|
|
378
289
|
// Check if we should collapse a panel at its minimum size
|
|
379
|
-
const index = delta < 0 ?
|
|
380
|
-
const
|
|
290
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
291
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
292
|
+
assert(panelConstraints);
|
|
293
|
+
const {
|
|
294
|
+
collapsible
|
|
295
|
+
} = panelConstraints;
|
|
296
|
+
|
|
381
297
|
//DEBUG.push(`edge case check 2: ${index}`);
|
|
382
|
-
//DEBUG.push(` -> collapsible? ${
|
|
383
|
-
if (
|
|
298
|
+
//DEBUG.push(` -> collapsible? ${collapsible}`);
|
|
299
|
+
if (collapsible) {
|
|
384
300
|
const prevSize = prevLayout[index];
|
|
301
|
+
assert(prevSize != null);
|
|
302
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
303
|
+
assert(panelConstraints);
|
|
385
304
|
const {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
} =
|
|
389
|
-
if (fuzzyNumbersEqual(prevSize,
|
|
390
|
-
const localDelta = prevSize -
|
|
305
|
+
collapsedSize = 0,
|
|
306
|
+
minSize = 0
|
|
307
|
+
} = panelConstraints;
|
|
308
|
+
if (fuzzyNumbersEqual(prevSize, minSize)) {
|
|
309
|
+
const localDelta = prevSize - collapsedSize;
|
|
391
310
|
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
392
311
|
|
|
393
312
|
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
@@ -409,15 +328,15 @@ function adjustLayoutByDelta({
|
|
|
409
328
|
// as an expanding panel might change from collapsed to min size.
|
|
410
329
|
|
|
411
330
|
const increment = delta < 0 ? 1 : -1;
|
|
412
|
-
let index = delta < 0 ?
|
|
331
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
413
332
|
let maxAvailableDelta = 0;
|
|
414
333
|
|
|
415
334
|
//DEBUG.push("pre calc...");
|
|
416
335
|
while (true) {
|
|
417
336
|
const prevSize = prevLayout[index];
|
|
337
|
+
assert(prevSize != null);
|
|
418
338
|
const maxSafeSize = resizePanel({
|
|
419
|
-
|
|
420
|
-
panelConstraints,
|
|
339
|
+
panelConstraints: panelConstraintsArray,
|
|
421
340
|
panelIndex: index,
|
|
422
341
|
size: 100
|
|
423
342
|
});
|
|
@@ -426,7 +345,7 @@ function adjustLayoutByDelta({
|
|
|
426
345
|
|
|
427
346
|
maxAvailableDelta += delta;
|
|
428
347
|
index += increment;
|
|
429
|
-
if (index < 0 || index >=
|
|
348
|
+
if (index < 0 || index >= panelConstraintsArray.length) {
|
|
430
349
|
break;
|
|
431
350
|
}
|
|
432
351
|
}
|
|
@@ -441,15 +360,15 @@ function adjustLayoutByDelta({
|
|
|
441
360
|
{
|
|
442
361
|
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
443
362
|
|
|
444
|
-
const pivotIndex = delta < 0 ?
|
|
363
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
445
364
|
let index = pivotIndex;
|
|
446
|
-
while (index >= 0 && index <
|
|
365
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
447
366
|
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
448
367
|
const prevSize = prevLayout[index];
|
|
368
|
+
assert(prevSize != null);
|
|
449
369
|
const unsafeSize = prevSize - deltaRemaining;
|
|
450
370
|
const safeSize = resizePanel({
|
|
451
|
-
|
|
452
|
-
panelConstraints,
|
|
371
|
+
panelConstraints: panelConstraintsArray,
|
|
453
372
|
panelIndex: index,
|
|
454
373
|
size: unsafeSize
|
|
455
374
|
});
|
|
@@ -481,11 +400,12 @@ function adjustLayoutByDelta({
|
|
|
481
400
|
}
|
|
482
401
|
{
|
|
483
402
|
// Now distribute the applied delta to the panels in the other direction
|
|
484
|
-
const pivotIndex = delta < 0 ?
|
|
485
|
-
const
|
|
403
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
404
|
+
const prevSize = prevLayout[pivotIndex];
|
|
405
|
+
assert(prevSize != null);
|
|
406
|
+
const unsafeSize = prevSize + deltaApplied;
|
|
486
407
|
const safeSize = resizePanel({
|
|
487
|
-
|
|
488
|
-
panelConstraints,
|
|
408
|
+
panelConstraints: panelConstraintsArray,
|
|
489
409
|
panelIndex: pivotIndex,
|
|
490
410
|
size: unsafeSize
|
|
491
411
|
});
|
|
@@ -496,14 +416,14 @@ function adjustLayoutByDelta({
|
|
|
496
416
|
// Edge case where expanding or contracting one panel caused another one to change collapsed state
|
|
497
417
|
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
498
418
|
let deltaRemaining = unsafeSize - safeSize;
|
|
499
|
-
const pivotIndex = delta < 0 ?
|
|
419
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
500
420
|
let index = pivotIndex;
|
|
501
|
-
while (index >= 0 && index <
|
|
421
|
+
while (index >= 0 && index < panelConstraintsArray.length) {
|
|
502
422
|
const prevSize = nextLayout[index];
|
|
423
|
+
assert(prevSize != null);
|
|
503
424
|
const unsafeSize = prevSize + deltaRemaining;
|
|
504
425
|
const safeSize = resizePanel({
|
|
505
|
-
|
|
506
|
-
panelConstraints,
|
|
426
|
+
panelConstraints: panelConstraintsArray,
|
|
507
427
|
panelIndex: index,
|
|
508
428
|
size: unsafeSize
|
|
509
429
|
});
|
|
@@ -527,9 +447,7 @@ function adjustLayoutByDelta({
|
|
|
527
447
|
//DEBUG.push("");
|
|
528
448
|
|
|
529
449
|
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
530
|
-
deltaApplied = 100 - totalSize;
|
|
531
450
|
//DEBUG.push(`total size: ${totalSize}`);
|
|
532
|
-
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
533
451
|
//console.log(DEBUG.join("\n"));
|
|
534
452
|
|
|
535
453
|
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
@@ -538,27 +456,7 @@ function adjustLayoutByDelta({
|
|
|
538
456
|
return nextLayout;
|
|
539
457
|
}
|
|
540
458
|
|
|
541
|
-
function assert(expectedCondition, message = "Assertion failed!") {
|
|
542
|
-
if (!expectedCondition) {
|
|
543
|
-
console.error(message);
|
|
544
|
-
throw Error(message);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function getPercentageSizeFromMixedSizes({
|
|
549
|
-
sizePercentage,
|
|
550
|
-
sizePixels
|
|
551
|
-
}, groupSizePixels) {
|
|
552
|
-
if (sizePercentage != null) {
|
|
553
|
-
return sizePercentage;
|
|
554
|
-
} else if (sizePixels != null) {
|
|
555
|
-
return convertPixelsToPercentage(sizePixels, groupSizePixels);
|
|
556
|
-
}
|
|
557
|
-
return undefined;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
459
|
function calculateAriaValues({
|
|
561
|
-
groupSizePixels,
|
|
562
460
|
layout,
|
|
563
461
|
panelsArray,
|
|
564
462
|
pivotIndices
|
|
@@ -567,28 +465,19 @@ function calculateAriaValues({
|
|
|
567
465
|
let currentMaxSize = 100;
|
|
568
466
|
let totalMinSize = 0;
|
|
569
467
|
let totalMaxSize = 0;
|
|
468
|
+
const firstIndex = pivotIndices[0];
|
|
469
|
+
assert(firstIndex != null);
|
|
570
470
|
|
|
571
471
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
572
472
|
panelsArray.forEach((panelData, index) => {
|
|
573
|
-
var _getPercentageSizeFro, _getPercentageSizeFro2;
|
|
574
473
|
const {
|
|
575
474
|
constraints
|
|
576
475
|
} = panelData;
|
|
577
476
|
const {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
minSizePercentage,
|
|
581
|
-
minSizePixels
|
|
477
|
+
maxSize = 100,
|
|
478
|
+
minSize = 0
|
|
582
479
|
} = constraints;
|
|
583
|
-
|
|
584
|
-
sizePercentage: minSizePercentage,
|
|
585
|
-
sizePixels: minSizePixels
|
|
586
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
587
|
-
const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
588
|
-
sizePercentage: maxSizePercentage,
|
|
589
|
-
sizePixels: maxSizePixels
|
|
590
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
|
|
591
|
-
if (index === pivotIndices[0]) {
|
|
480
|
+
if (index === firstIndex) {
|
|
592
481
|
currentMinSize = minSize;
|
|
593
482
|
currentMaxSize = maxSize;
|
|
594
483
|
} else {
|
|
@@ -598,7 +487,7 @@ function calculateAriaValues({
|
|
|
598
487
|
});
|
|
599
488
|
const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
600
489
|
const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
|
|
601
|
-
const valueNow = layout[
|
|
490
|
+
const valueNow = layout[firstIndex];
|
|
602
491
|
return {
|
|
603
492
|
valueMax,
|
|
604
493
|
valueMin,
|
|
@@ -629,42 +518,6 @@ function getPanelGroupElement(id) {
|
|
|
629
518
|
return null;
|
|
630
519
|
}
|
|
631
520
|
|
|
632
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
633
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
634
|
-
if (panelGroupElement == null) {
|
|
635
|
-
return NaN;
|
|
636
|
-
}
|
|
637
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
638
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
639
|
-
if (direction === "horizontal") {
|
|
640
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
641
|
-
return accumulated + handle.offsetWidth;
|
|
642
|
-
}, 0);
|
|
643
|
-
} else {
|
|
644
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
645
|
-
return accumulated + handle.offsetHeight;
|
|
646
|
-
}, 0);
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
651
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
652
|
-
if (panelGroupElement == null) {
|
|
653
|
-
return NaN;
|
|
654
|
-
}
|
|
655
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
656
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
657
|
-
if (direction === "horizontal") {
|
|
658
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
659
|
-
return accumulated + handle.offsetWidth;
|
|
660
|
-
}, 0);
|
|
661
|
-
} else {
|
|
662
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
663
|
-
return accumulated + handle.offsetHeight;
|
|
664
|
-
}, 0);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
521
|
function getResizeHandleElement(id) {
|
|
669
522
|
const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
670
523
|
if (element) {
|
|
@@ -697,7 +550,6 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
697
550
|
didWarnAboutMissingResizeHandle: false
|
|
698
551
|
});
|
|
699
552
|
useIsomorphicLayoutEffect(() => {
|
|
700
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
701
553
|
const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
|
|
702
554
|
for (let index = 0; index < panelDataArray.length - 1; index++) {
|
|
703
555
|
const {
|
|
@@ -705,17 +557,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
705
557
|
valueMin,
|
|
706
558
|
valueNow
|
|
707
559
|
} = calculateAriaValues({
|
|
708
|
-
groupSizePixels,
|
|
709
560
|
layout,
|
|
710
561
|
panelsArray: panelDataArray,
|
|
711
562
|
pivotIndices: [index, index + 1]
|
|
712
563
|
});
|
|
713
564
|
const resizeHandleElement = resizeHandleElements[index];
|
|
714
565
|
if (resizeHandleElement == null) ; else {
|
|
715
|
-
|
|
566
|
+
const panelData = panelDataArray[index];
|
|
567
|
+
assert(panelData);
|
|
568
|
+
resizeHandleElement.setAttribute("aria-controls", panelData.id);
|
|
716
569
|
resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
|
|
717
570
|
resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
|
|
718
|
-
resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
|
|
571
|
+
resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
|
|
719
572
|
}
|
|
720
573
|
}
|
|
721
574
|
return () => {
|
|
@@ -728,14 +581,18 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
728
581
|
};
|
|
729
582
|
}, [groupId, layout, panelDataArray]);
|
|
730
583
|
useEffect(() => {
|
|
584
|
+
const eagerValues = eagerValuesRef.current;
|
|
585
|
+
assert(eagerValues);
|
|
731
586
|
const {
|
|
732
587
|
panelDataArray
|
|
733
|
-
} =
|
|
588
|
+
} = eagerValues;
|
|
734
589
|
const groupElement = getPanelGroupElement(groupId);
|
|
735
590
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
736
591
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
592
|
+
assert(handles);
|
|
737
593
|
const cleanupFunctions = handles.map(handle => {
|
|
738
594
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
595
|
+
assert(handleId);
|
|
739
596
|
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
740
597
|
if (idBefore == null || idAfter == null) {
|
|
741
598
|
return () => {};
|
|
@@ -751,21 +608,16 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
751
608
|
const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
|
|
752
609
|
if (index >= 0) {
|
|
753
610
|
const panelData = panelDataArray[index];
|
|
611
|
+
assert(panelData);
|
|
754
612
|
const size = layout[index];
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
762
|
-
const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
|
|
763
|
-
sizePercentage: panelData.constraints.minSizePercentage,
|
|
764
|
-
sizePixels: panelData.constraints.minSizePixels
|
|
765
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
|
|
613
|
+
const {
|
|
614
|
+
collapsedSize = 0,
|
|
615
|
+
collapsible,
|
|
616
|
+
minSize = 0
|
|
617
|
+
} = panelData.constraints;
|
|
618
|
+
if (size != null && collapsible) {
|
|
766
619
|
const nextLayout = adjustLayoutByDelta({
|
|
767
620
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
768
|
-
groupSizePixels,
|
|
769
621
|
layout,
|
|
770
622
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
771
623
|
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
@@ -819,6 +671,7 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
819
671
|
return isHorizontal ? event.clientX : event.clientY;
|
|
820
672
|
} else if (isTouchEvent(event)) {
|
|
821
673
|
const firstTouch = event.touches[0];
|
|
674
|
+
assert(firstTouch);
|
|
822
675
|
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
823
676
|
} else {
|
|
824
677
|
throw Error(`Unsupported event type "${event.type}"`);
|
|
@@ -828,12 +681,15 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
828
681
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
829
682
|
const isHorizontal = direction === "horizontal";
|
|
830
683
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
684
|
+
assert(handleElement);
|
|
831
685
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
686
|
+
assert(groupId);
|
|
832
687
|
let {
|
|
833
688
|
initialCursorPosition
|
|
834
689
|
} = initialDragState;
|
|
835
690
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
836
691
|
const groupElement = getPanelGroupElement(groupId);
|
|
692
|
+
assert(groupElement);
|
|
837
693
|
const groupRect = groupElement.getBoundingClientRect();
|
|
838
694
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
839
695
|
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
@@ -842,19 +698,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
842
698
|
}
|
|
843
699
|
|
|
844
700
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
845
|
-
function calculateDeltaPercentage(event,
|
|
701
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
846
702
|
if (isKeyDown(event)) {
|
|
847
703
|
const isHorizontal = direction === "horizontal";
|
|
848
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
849
|
-
const rect = groupElement.getBoundingClientRect();
|
|
850
|
-
const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
|
|
851
704
|
let delta = 0;
|
|
852
705
|
if (event.shiftKey) {
|
|
853
706
|
delta = 100;
|
|
854
|
-
} else if (
|
|
855
|
-
delta =
|
|
856
|
-
} else if (keyboardResizeByOptions.pixels != null) {
|
|
857
|
-
delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
|
|
707
|
+
} else if (keyboardResizeBy != null) {
|
|
708
|
+
delta = keyboardResizeBy;
|
|
858
709
|
} else {
|
|
859
710
|
delta = 10;
|
|
860
711
|
}
|
|
@@ -881,37 +732,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
|
|
|
881
732
|
}
|
|
882
733
|
return movement;
|
|
883
734
|
} else {
|
|
735
|
+
if (initialDragState == null) {
|
|
736
|
+
return 0;
|
|
737
|
+
}
|
|
884
738
|
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
885
739
|
}
|
|
886
740
|
}
|
|
887
741
|
|
|
888
742
|
function calculateUnsafeDefaultLayout({
|
|
889
|
-
groupSizePixels,
|
|
890
743
|
panelDataArray
|
|
891
744
|
}) {
|
|
892
745
|
const layout = Array(panelDataArray.length);
|
|
893
|
-
const
|
|
746
|
+
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
894
747
|
let numPanelsWithSizes = 0;
|
|
895
748
|
let remainingSize = 100;
|
|
896
749
|
|
|
897
750
|
// Distribute default sizes first
|
|
898
751
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
752
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
753
|
+
assert(panelConstraints);
|
|
899
754
|
const {
|
|
900
|
-
|
|
901
|
-
} =
|
|
902
|
-
if (
|
|
755
|
+
defaultSize
|
|
756
|
+
} = panelConstraints;
|
|
757
|
+
if (defaultSize != null) {
|
|
903
758
|
numPanelsWithSizes++;
|
|
904
|
-
layout[index] =
|
|
905
|
-
remainingSize -=
|
|
759
|
+
layout[index] = defaultSize;
|
|
760
|
+
remainingSize -= defaultSize;
|
|
906
761
|
}
|
|
907
762
|
}
|
|
908
763
|
|
|
909
764
|
// Remaining size should be distributed evenly between panels without default sizes
|
|
910
765
|
for (let index = 0; index < panelDataArray.length; index++) {
|
|
766
|
+
const panelConstraints = panelConstraintsArray[index];
|
|
767
|
+
assert(panelConstraints);
|
|
911
768
|
const {
|
|
912
|
-
|
|
913
|
-
} =
|
|
914
|
-
if (
|
|
769
|
+
defaultSize
|
|
770
|
+
} = panelConstraints;
|
|
771
|
+
if (defaultSize != null) {
|
|
915
772
|
continue;
|
|
916
773
|
}
|
|
917
774
|
const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
|
|
@@ -923,54 +780,36 @@ function calculateUnsafeDefaultLayout({
|
|
|
923
780
|
return layout;
|
|
924
781
|
}
|
|
925
782
|
|
|
926
|
-
function convertPercentageToPixels(percentage, groupSizePixels) {
|
|
927
|
-
return percentage / 100 * groupSizePixels;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
783
|
// Layout should be pre-converted into percentages
|
|
931
|
-
function callPanelCallbacks(
|
|
932
|
-
|
|
933
|
-
layout.forEach((sizePercentage, index) => {
|
|
784
|
+
function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
|
|
785
|
+
layout.forEach((size, index) => {
|
|
934
786
|
const panelData = panelsArray[index];
|
|
935
|
-
|
|
936
|
-
// Handle initial mount (when panels are registered too late to be in the panels array)
|
|
937
|
-
// The subsequent render+effects will handle the resize notification
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
787
|
+
assert(panelData);
|
|
940
788
|
const {
|
|
941
789
|
callbacks,
|
|
942
790
|
constraints,
|
|
943
791
|
id: panelId
|
|
944
792
|
} = panelData;
|
|
945
793
|
const {
|
|
794
|
+
collapsedSize = 0,
|
|
946
795
|
collapsible
|
|
947
796
|
} = constraints;
|
|
948
|
-
const
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
};
|
|
952
|
-
const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
|
|
953
|
-
if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
|
|
954
|
-
panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
|
|
797
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
|
|
798
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
799
|
+
panelIdToLastNotifiedSizeMap[panelId] = size;
|
|
955
800
|
const {
|
|
956
801
|
onCollapse,
|
|
957
802
|
onExpand,
|
|
958
803
|
onResize
|
|
959
804
|
} = callbacks;
|
|
960
805
|
if (onResize) {
|
|
961
|
-
onResize(
|
|
806
|
+
onResize(size, lastNotifiedSize);
|
|
962
807
|
}
|
|
963
808
|
if (collapsible && (onCollapse || onExpand)) {
|
|
964
|
-
|
|
965
|
-
const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
|
|
966
|
-
sizePercentage: constraints.collapsedSizePercentage,
|
|
967
|
-
sizePixels: constraints.collapsedSizePixels
|
|
968
|
-
}, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
|
|
969
|
-
const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
|
|
970
|
-
if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
|
|
809
|
+
if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
|
|
971
810
|
onExpand();
|
|
972
811
|
}
|
|
973
|
-
if (onCollapse && (
|
|
812
|
+
if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
|
|
974
813
|
onCollapse();
|
|
975
814
|
}
|
|
976
815
|
}
|
|
@@ -1153,31 +992,32 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
|
|
|
1153
992
|
}
|
|
1154
993
|
}
|
|
1155
994
|
|
|
1156
|
-
function shouldMonitorPixelBasedConstraints(constraints) {
|
|
1157
|
-
return constraints.some(constraints => {
|
|
1158
|
-
return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
|
|
1159
|
-
});
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
995
|
// All units must be in percentages; pixel values should be pre-converted
|
|
1163
996
|
function validatePanelGroupLayout({
|
|
1164
|
-
groupSizePixels,
|
|
1165
997
|
layout: prevLayout,
|
|
1166
998
|
panelConstraints
|
|
1167
999
|
}) {
|
|
1168
1000
|
const nextLayout = [...prevLayout];
|
|
1001
|
+
const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
|
|
1169
1002
|
|
|
1170
1003
|
// Validate layout expectations
|
|
1171
1004
|
if (nextLayout.length !== panelConstraints.length) {
|
|
1172
1005
|
throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
|
|
1173
|
-
} else if (!fuzzyNumbersEqual(
|
|
1006
|
+
} else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
|
|
1007
|
+
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1008
|
+
const unsafeSize = nextLayout[index];
|
|
1009
|
+
assert(unsafeSize != null);
|
|
1010
|
+
const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
|
|
1011
|
+
nextLayout[index] = safeSize;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1174
1014
|
let remainingSize = 0;
|
|
1175
1015
|
|
|
1176
1016
|
// First pass: Validate the proposed layout given each panel's constraints
|
|
1177
1017
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1178
1018
|
const unsafeSize = nextLayout[index];
|
|
1019
|
+
assert(unsafeSize != null);
|
|
1179
1020
|
const safeSize = resizePanel({
|
|
1180
|
-
groupSizePixels,
|
|
1181
1021
|
panelConstraints,
|
|
1182
1022
|
panelIndex: index,
|
|
1183
1023
|
size: unsafeSize
|
|
@@ -1193,9 +1033,9 @@ function validatePanelGroupLayout({
|
|
|
1193
1033
|
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
1194
1034
|
for (let index = 0; index < panelConstraints.length; index++) {
|
|
1195
1035
|
const prevSize = nextLayout[index];
|
|
1036
|
+
assert(prevSize != null);
|
|
1196
1037
|
const unsafeSize = prevSize + remainingSize;
|
|
1197
1038
|
const safeSize = resizePanel({
|
|
1198
|
-
groupSizePixels,
|
|
1199
1039
|
panelConstraints,
|
|
1200
1040
|
panelIndex: index,
|
|
1201
1041
|
size: unsafeSize
|
|
@@ -1230,21 +1070,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1230
1070
|
autoSaveId = null,
|
|
1231
1071
|
children,
|
|
1232
1072
|
className: classNameFromProps = "",
|
|
1233
|
-
dataAttributes,
|
|
1234
1073
|
direction,
|
|
1235
1074
|
forwardedRef,
|
|
1236
|
-
id: idFromProps,
|
|
1075
|
+
id: idFromProps = null,
|
|
1237
1076
|
onLayout = null,
|
|
1238
|
-
|
|
1239
|
-
keyboardResizeByPixels = null,
|
|
1077
|
+
keyboardResizeBy = null,
|
|
1240
1078
|
storage = defaultStorage,
|
|
1241
1079
|
style: styleFromProps,
|
|
1242
|
-
tagName: Type = "div"
|
|
1080
|
+
tagName: Type = "div",
|
|
1081
|
+
...rest
|
|
1243
1082
|
}) {
|
|
1244
1083
|
const groupId = useUniqueId(idFromProps);
|
|
1245
1084
|
const [dragState, setDragState] = useState(null);
|
|
1246
1085
|
const [layout, setLayout] = useState([]);
|
|
1247
|
-
const
|
|
1086
|
+
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
1248
1087
|
const panelSizeBeforeCollapseRef = useRef(new Map());
|
|
1249
1088
|
const prevDeltaRef = useRef(0);
|
|
1250
1089
|
const committedValuesRef = useRef({
|
|
@@ -1252,8 +1091,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1252
1091
|
direction,
|
|
1253
1092
|
dragState,
|
|
1254
1093
|
id: groupId,
|
|
1255
|
-
|
|
1256
|
-
keyboardResizeByPixels,
|
|
1094
|
+
keyboardResizeBy,
|
|
1257
1095
|
onLayout,
|
|
1258
1096
|
storage
|
|
1259
1097
|
});
|
|
@@ -1269,33 +1107,20 @@ function PanelGroupWithForwardedRef({
|
|
|
1269
1107
|
useImperativeHandle(forwardedRef, () => ({
|
|
1270
1108
|
getId: () => committedValuesRef.current.id,
|
|
1271
1109
|
getLayout: () => {
|
|
1272
|
-
const {
|
|
1273
|
-
id: groupId
|
|
1274
|
-
} = committedValuesRef.current;
|
|
1275
1110
|
const {
|
|
1276
1111
|
layout
|
|
1277
1112
|
} = eagerValuesRef.current;
|
|
1278
|
-
|
|
1279
|
-
return layout.map(sizePercentage => {
|
|
1280
|
-
return {
|
|
1281
|
-
sizePercentage,
|
|
1282
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1283
|
-
};
|
|
1284
|
-
});
|
|
1113
|
+
return layout;
|
|
1285
1114
|
},
|
|
1286
|
-
setLayout:
|
|
1115
|
+
setLayout: unsafeLayout => {
|
|
1287
1116
|
const {
|
|
1288
|
-
id: groupId,
|
|
1289
1117
|
onLayout
|
|
1290
1118
|
} = committedValuesRef.current;
|
|
1291
1119
|
const {
|
|
1292
1120
|
layout: prevLayout,
|
|
1293
1121
|
panelDataArray
|
|
1294
1122
|
} = eagerValuesRef.current;
|
|
1295
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1296
|
-
const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
|
|
1297
1123
|
const safeLayout = validatePanelGroupLayout({
|
|
1298
|
-
groupSizePixels,
|
|
1299
1124
|
layout: unsafeLayout,
|
|
1300
1125
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1301
1126
|
});
|
|
@@ -1303,12 +1128,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1303
1128
|
setLayout(safeLayout);
|
|
1304
1129
|
eagerValuesRef.current.layout = safeLayout;
|
|
1305
1130
|
if (onLayout) {
|
|
1306
|
-
onLayout(safeLayout
|
|
1307
|
-
sizePercentage,
|
|
1308
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1309
|
-
})));
|
|
1131
|
+
onLayout(safeLayout);
|
|
1310
1132
|
}
|
|
1311
|
-
callPanelCallbacks(
|
|
1133
|
+
callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1312
1134
|
}
|
|
1313
1135
|
}
|
|
1314
1136
|
}), []);
|
|
@@ -1319,11 +1141,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1319
1141
|
committedValuesRef.current.id = groupId;
|
|
1320
1142
|
committedValuesRef.current.onLayout = onLayout;
|
|
1321
1143
|
committedValuesRef.current.storage = storage;
|
|
1322
|
-
|
|
1323
|
-
// panelDataArray and layout are updated in-sync with scheduled state updates.
|
|
1324
|
-
// TODO [217] Move these values into a separate ref
|
|
1325
1144
|
});
|
|
1326
|
-
|
|
1327
1145
|
useWindowSplitterPanelGroupBehavior({
|
|
1328
1146
|
committedValuesRef,
|
|
1329
1147
|
eagerValuesRef,
|
|
@@ -1342,57 +1160,16 @@ function PanelGroupWithForwardedRef({
|
|
|
1342
1160
|
if (layout.length === 0 || layout.length !== panelDataArray.length) {
|
|
1343
1161
|
return;
|
|
1344
1162
|
}
|
|
1163
|
+
let debouncedSave = debounceMap[autoSaveId];
|
|
1345
1164
|
|
|
1346
1165
|
// Limit the frequency of localStorage updates.
|
|
1347
|
-
if (
|
|
1348
|
-
|
|
1166
|
+
if (debouncedSave == null) {
|
|
1167
|
+
debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
|
|
1168
|
+
debounceMap[autoSaveId] = debouncedSave;
|
|
1349
1169
|
}
|
|
1350
|
-
|
|
1170
|
+
debouncedSave(autoSaveId, panelDataArray, layout, storage);
|
|
1351
1171
|
}
|
|
1352
1172
|
}, [autoSaveId, layout, storage]);
|
|
1353
|
-
useIsomorphicLayoutEffect(() => {
|
|
1354
|
-
const {
|
|
1355
|
-
layout: prevLayout,
|
|
1356
|
-
panelDataArray
|
|
1357
|
-
} = eagerValuesRef.current;
|
|
1358
|
-
const constraints = panelDataArray.map(({
|
|
1359
|
-
constraints
|
|
1360
|
-
}) => constraints);
|
|
1361
|
-
if (!shouldMonitorPixelBasedConstraints(constraints)) {
|
|
1362
|
-
// Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
|
|
1363
|
-
return;
|
|
1364
|
-
}
|
|
1365
|
-
if (typeof ResizeObserver === "undefined") {
|
|
1366
|
-
console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
|
|
1367
|
-
} else {
|
|
1368
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
1369
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1370
|
-
const {
|
|
1371
|
-
onLayout
|
|
1372
|
-
} = committedValuesRef.current;
|
|
1373
|
-
const nextLayout = validatePanelGroupLayout({
|
|
1374
|
-
groupSizePixels,
|
|
1375
|
-
layout: prevLayout,
|
|
1376
|
-
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1377
|
-
});
|
|
1378
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
1379
|
-
setLayout(nextLayout);
|
|
1380
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
1381
|
-
if (onLayout) {
|
|
1382
|
-
onLayout(nextLayout.map(sizePercentage => ({
|
|
1383
|
-
sizePercentage,
|
|
1384
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1385
|
-
})));
|
|
1386
|
-
}
|
|
1387
|
-
callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
|
|
1388
|
-
}
|
|
1389
|
-
});
|
|
1390
|
-
resizeObserver.observe(getPanelGroupElement(groupId));
|
|
1391
|
-
return () => {
|
|
1392
|
-
resizeObserver.disconnect();
|
|
1393
|
-
};
|
|
1394
|
-
}
|
|
1395
|
-
}, [groupId]);
|
|
1396
1173
|
|
|
1397
1174
|
// DEV warnings
|
|
1398
1175
|
useEffect(() => {
|
|
@@ -1410,20 +1187,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1410
1187
|
if (panelData.constraints.collapsible) {
|
|
1411
1188
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1412
1189
|
const {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
pivotIndices
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
if (
|
|
1190
|
+
collapsedSize = 0,
|
|
1191
|
+
panelSize,
|
|
1192
|
+
pivotIndices
|
|
1193
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1194
|
+
assert(panelSize != null);
|
|
1195
|
+
if (panelSize !== collapsedSize) {
|
|
1419
1196
|
// Store size before collapse;
|
|
1420
1197
|
// This is the size that gets restored if the expand() API is used.
|
|
1421
|
-
panelSizeBeforeCollapseRef.current.set(panelData.id,
|
|
1198
|
+
panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
|
|
1422
1199
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1423
|
-
const delta = isLastPanel ?
|
|
1200
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
1424
1201
|
const nextLayout = adjustLayoutByDelta({
|
|
1425
1202
|
delta,
|
|
1426
|
-
groupSizePixels,
|
|
1427
1203
|
layout: prevLayout,
|
|
1428
1204
|
panelConstraints: panelConstraintsArray,
|
|
1429
1205
|
pivotIndices,
|
|
@@ -1433,16 +1209,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1433
1209
|
setLayout(nextLayout);
|
|
1434
1210
|
eagerValuesRef.current.layout = nextLayout;
|
|
1435
1211
|
if (onLayout) {
|
|
1436
|
-
onLayout(nextLayout
|
|
1437
|
-
sizePercentage,
|
|
1438
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1439
|
-
})));
|
|
1212
|
+
onLayout(nextLayout);
|
|
1440
1213
|
}
|
|
1441
|
-
callPanelCallbacks(
|
|
1214
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1442
1215
|
}
|
|
1443
1216
|
}
|
|
1444
1217
|
}
|
|
1445
|
-
}, [
|
|
1218
|
+
}, []);
|
|
1446
1219
|
|
|
1447
1220
|
// External APIs are safe to memoize via committed values ref
|
|
1448
1221
|
const expandPanel = useCallback(panelData => {
|
|
@@ -1456,21 +1229,19 @@ function PanelGroupWithForwardedRef({
|
|
|
1456
1229
|
if (panelData.constraints.collapsible) {
|
|
1457
1230
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1458
1231
|
const {
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
pivotIndices
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
if (panelSizePercentage === collapsedSizePercentage) {
|
|
1232
|
+
collapsedSize = 0,
|
|
1233
|
+
panelSize,
|
|
1234
|
+
minSize = 0,
|
|
1235
|
+
pivotIndices
|
|
1236
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1237
|
+
if (panelSize === collapsedSize) {
|
|
1466
1238
|
// Restore this panel to the size it was before it was collapsed, if possible.
|
|
1467
|
-
const
|
|
1468
|
-
const
|
|
1239
|
+
const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
|
|
1240
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
1469
1241
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1470
|
-
const delta = isLastPanel ?
|
|
1242
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
1471
1243
|
const nextLayout = adjustLayoutByDelta({
|
|
1472
1244
|
delta,
|
|
1473
|
-
groupSizePixels,
|
|
1474
1245
|
layout: prevLayout,
|
|
1475
1246
|
panelConstraints: panelConstraintsArray,
|
|
1476
1247
|
pivotIndices,
|
|
@@ -1480,16 +1251,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1480
1251
|
setLayout(nextLayout);
|
|
1481
1252
|
eagerValuesRef.current.layout = nextLayout;
|
|
1482
1253
|
if (onLayout) {
|
|
1483
|
-
onLayout(nextLayout
|
|
1484
|
-
sizePercentage,
|
|
1485
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1486
|
-
})));
|
|
1254
|
+
onLayout(nextLayout);
|
|
1487
1255
|
}
|
|
1488
|
-
callPanelCallbacks(
|
|
1256
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1489
1257
|
}
|
|
1490
1258
|
}
|
|
1491
1259
|
}
|
|
1492
|
-
}, [
|
|
1260
|
+
}, []);
|
|
1493
1261
|
|
|
1494
1262
|
// External APIs are safe to memoize via committed values ref
|
|
1495
1263
|
const getPanelSize = useCallback(panelData => {
|
|
@@ -1498,14 +1266,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1498
1266
|
panelDataArray
|
|
1499
1267
|
} = eagerValuesRef.current;
|
|
1500
1268
|
const {
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
return
|
|
1505
|
-
|
|
1506
|
-
sizePixels: panelSizePixels
|
|
1507
|
-
};
|
|
1508
|
-
}, [groupId]);
|
|
1269
|
+
panelSize
|
|
1270
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1271
|
+
assert(panelSize != null);
|
|
1272
|
+
return panelSize;
|
|
1273
|
+
}, []);
|
|
1509
1274
|
|
|
1510
1275
|
// This API should never read from committedValuesRef
|
|
1511
1276
|
const getPanelStyle = useCallback(panelData => {
|
|
@@ -1528,12 +1293,12 @@ function PanelGroupWithForwardedRef({
|
|
|
1528
1293
|
panelDataArray
|
|
1529
1294
|
} = eagerValuesRef.current;
|
|
1530
1295
|
const {
|
|
1531
|
-
|
|
1296
|
+
collapsedSize,
|
|
1532
1297
|
collapsible,
|
|
1533
|
-
|
|
1534
|
-
} = panelDataHelper(
|
|
1535
|
-
return collapsible === true &&
|
|
1536
|
-
}, [
|
|
1298
|
+
panelSize
|
|
1299
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1300
|
+
return collapsible === true && panelSize === collapsedSize;
|
|
1301
|
+
}, []);
|
|
1537
1302
|
|
|
1538
1303
|
// External APIs are safe to memoize via committed values ref
|
|
1539
1304
|
const isPanelExpanded = useCallback(panelData => {
|
|
@@ -1542,12 +1307,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1542
1307
|
panelDataArray
|
|
1543
1308
|
} = eagerValuesRef.current;
|
|
1544
1309
|
const {
|
|
1545
|
-
|
|
1310
|
+
collapsedSize = 0,
|
|
1546
1311
|
collapsible,
|
|
1547
|
-
|
|
1548
|
-
} = panelDataHelper(
|
|
1549
|
-
|
|
1550
|
-
|
|
1312
|
+
panelSize
|
|
1313
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1314
|
+
assert(panelSize != null);
|
|
1315
|
+
return !collapsible || panelSize > collapsedSize;
|
|
1316
|
+
}, []);
|
|
1551
1317
|
const registerPanel = useCallback(panelData => {
|
|
1552
1318
|
const {
|
|
1553
1319
|
autoSaveId,
|
|
@@ -1587,18 +1353,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1587
1353
|
if (autoSaveId) {
|
|
1588
1354
|
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
1589
1355
|
}
|
|
1590
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1591
|
-
if (groupSizePixels <= 0) {
|
|
1592
|
-
if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
|
|
1593
|
-
constraints
|
|
1594
|
-
}) => constraints))) {
|
|
1595
|
-
// Wait until the group has rendered a non-zero size before computing layout.
|
|
1596
|
-
return;
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
1356
|
if (unsafeLayout == null) {
|
|
1600
1357
|
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1601
|
-
groupSizePixels,
|
|
1602
1358
|
panelDataArray
|
|
1603
1359
|
});
|
|
1604
1360
|
}
|
|
@@ -1606,7 +1362,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1606
1362
|
// Validate even saved layouts in case something has changed since last render
|
|
1607
1363
|
// e.g. for pixel groups, this could be the size of the window
|
|
1608
1364
|
const nextLayout = validatePanelGroupLayout({
|
|
1609
|
-
groupSizePixels,
|
|
1610
1365
|
layout: unsafeLayout,
|
|
1611
1366
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1612
1367
|
});
|
|
@@ -1618,12 +1373,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1618
1373
|
eagerValuesRef.current.layout = nextLayout;
|
|
1619
1374
|
if (!areEqual(prevLayout, nextLayout)) {
|
|
1620
1375
|
if (onLayout) {
|
|
1621
|
-
onLayout(nextLayout
|
|
1622
|
-
sizePercentage,
|
|
1623
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1624
|
-
})));
|
|
1376
|
+
onLayout(nextLayout);
|
|
1625
1377
|
}
|
|
1626
|
-
callPanelCallbacks(
|
|
1378
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1627
1379
|
}
|
|
1628
1380
|
}, []);
|
|
1629
1381
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
@@ -1633,8 +1385,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1633
1385
|
direction,
|
|
1634
1386
|
dragState,
|
|
1635
1387
|
id: groupId,
|
|
1636
|
-
|
|
1637
|
-
keyboardResizeByPixels,
|
|
1388
|
+
keyboardResizeBy,
|
|
1638
1389
|
onLayout
|
|
1639
1390
|
} = committedValuesRef.current;
|
|
1640
1391
|
const {
|
|
@@ -1645,10 +1396,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1645
1396
|
initialLayout
|
|
1646
1397
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1647
1398
|
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1648
|
-
let delta = calculateDeltaPercentage(event,
|
|
1649
|
-
percentage: keyboardResizeByPercentage,
|
|
1650
|
-
pixels: keyboardResizeByPixels
|
|
1651
|
-
});
|
|
1399
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1652
1400
|
if (delta === 0) {
|
|
1653
1401
|
return;
|
|
1654
1402
|
}
|
|
@@ -1658,11 +1406,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1658
1406
|
if (document.dir === "rtl" && isHorizontal) {
|
|
1659
1407
|
delta = -delta;
|
|
1660
1408
|
}
|
|
1661
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1662
1409
|
const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
|
|
1663
1410
|
const nextLayout = adjustLayoutByDelta({
|
|
1664
1411
|
delta,
|
|
1665
|
-
groupSizePixels,
|
|
1666
1412
|
layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
|
|
1667
1413
|
panelConstraints,
|
|
1668
1414
|
pivotIndices,
|
|
@@ -1698,18 +1444,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1698
1444
|
setLayout(nextLayout);
|
|
1699
1445
|
eagerValuesRef.current.layout = nextLayout;
|
|
1700
1446
|
if (onLayout) {
|
|
1701
|
-
onLayout(nextLayout
|
|
1702
|
-
sizePercentage,
|
|
1703
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1704
|
-
})));
|
|
1447
|
+
onLayout(nextLayout);
|
|
1705
1448
|
}
|
|
1706
|
-
callPanelCallbacks(
|
|
1449
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1707
1450
|
}
|
|
1708
1451
|
};
|
|
1709
1452
|
}, []);
|
|
1710
1453
|
|
|
1711
1454
|
// External APIs are safe to memoize via committed values ref
|
|
1712
|
-
const resizePanel = useCallback((panelData,
|
|
1455
|
+
const resizePanel = useCallback((panelData, unsafePanelSize) => {
|
|
1713
1456
|
const {
|
|
1714
1457
|
onLayout
|
|
1715
1458
|
} = committedValuesRef.current;
|
|
@@ -1719,16 +1462,14 @@ function PanelGroupWithForwardedRef({
|
|
|
1719
1462
|
} = eagerValuesRef.current;
|
|
1720
1463
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1721
1464
|
const {
|
|
1722
|
-
|
|
1723
|
-
panelSizePercentage,
|
|
1465
|
+
panelSize,
|
|
1724
1466
|
pivotIndices
|
|
1725
|
-
} = panelDataHelper(
|
|
1726
|
-
|
|
1467
|
+
} = panelDataHelper(panelDataArray, panelData, prevLayout);
|
|
1468
|
+
assert(panelSize != null);
|
|
1727
1469
|
const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
|
|
1728
|
-
const delta = isLastPanel ?
|
|
1470
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
1729
1471
|
const nextLayout = adjustLayoutByDelta({
|
|
1730
1472
|
delta,
|
|
1731
|
-
groupSizePixels,
|
|
1732
1473
|
layout: prevLayout,
|
|
1733
1474
|
panelConstraints: panelConstraintsArray,
|
|
1734
1475
|
pivotIndices,
|
|
@@ -1738,14 +1479,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1738
1479
|
setLayout(nextLayout);
|
|
1739
1480
|
eagerValuesRef.current.layout = nextLayout;
|
|
1740
1481
|
if (onLayout) {
|
|
1741
|
-
onLayout(nextLayout
|
|
1742
|
-
sizePercentage,
|
|
1743
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1744
|
-
})));
|
|
1482
|
+
onLayout(nextLayout);
|
|
1745
1483
|
}
|
|
1746
|
-
callPanelCallbacks(
|
|
1484
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1747
1485
|
}
|
|
1748
|
-
}, [
|
|
1486
|
+
}, []);
|
|
1749
1487
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1750
1488
|
const {
|
|
1751
1489
|
direction
|
|
@@ -1754,6 +1492,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1754
1492
|
layout
|
|
1755
1493
|
} = eagerValuesRef.current;
|
|
1756
1494
|
const handleElement = getResizeHandleElement(dragHandleId);
|
|
1495
|
+
assert(handleElement);
|
|
1757
1496
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1758
1497
|
setDragState({
|
|
1759
1498
|
dragHandleId,
|
|
@@ -1772,7 +1511,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1772
1511
|
});
|
|
1773
1512
|
const unregisterPanel = useCallback(panelData => {
|
|
1774
1513
|
const {
|
|
1775
|
-
id: groupId,
|
|
1776
1514
|
onLayout
|
|
1777
1515
|
} = committedValuesRef.current;
|
|
1778
1516
|
const {
|
|
@@ -1795,7 +1533,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1795
1533
|
const {
|
|
1796
1534
|
pendingPanelIds
|
|
1797
1535
|
} = unregisterPanelRef.current;
|
|
1798
|
-
const map =
|
|
1536
|
+
const map = panelIdToLastNotifiedSizeMapRef.current;
|
|
1799
1537
|
|
|
1800
1538
|
// TRICKY
|
|
1801
1539
|
// Strict effects mode
|
|
@@ -1821,16 +1559,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1821
1559
|
// The group is unmounting; skip layout calculation.
|
|
1822
1560
|
return;
|
|
1823
1561
|
}
|
|
1824
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1825
1562
|
let unsafeLayout = calculateUnsafeDefaultLayout({
|
|
1826
|
-
groupSizePixels,
|
|
1827
1563
|
panelDataArray
|
|
1828
1564
|
});
|
|
1829
1565
|
|
|
1830
1566
|
// Validate even saved layouts in case something has changed since last render
|
|
1831
1567
|
// e.g. for pixel groups, this could be the size of the window
|
|
1832
1568
|
const nextLayout = validatePanelGroupLayout({
|
|
1833
|
-
groupSizePixels,
|
|
1834
1569
|
layout: unsafeLayout,
|
|
1835
1570
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints)
|
|
1836
1571
|
});
|
|
@@ -1838,12 +1573,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1838
1573
|
setLayout(nextLayout);
|
|
1839
1574
|
eagerValuesRef.current.layout = nextLayout;
|
|
1840
1575
|
if (onLayout) {
|
|
1841
|
-
onLayout(nextLayout
|
|
1842
|
-
sizePercentage,
|
|
1843
|
-
sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
|
|
1844
|
-
})));
|
|
1576
|
+
onLayout(nextLayout);
|
|
1845
1577
|
}
|
|
1846
|
-
callPanelCallbacks(
|
|
1578
|
+
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1847
1579
|
}
|
|
1848
1580
|
}, 0);
|
|
1849
1581
|
}, []);
|
|
@@ -1874,13 +1606,13 @@ function PanelGroupWithForwardedRef({
|
|
|
1874
1606
|
return createElement(PanelGroupContext.Provider, {
|
|
1875
1607
|
value: context
|
|
1876
1608
|
}, createElement(Type, {
|
|
1609
|
+
...rest,
|
|
1877
1610
|
children,
|
|
1878
1611
|
className: classNameFromProps,
|
|
1879
1612
|
style: {
|
|
1880
1613
|
...style,
|
|
1881
1614
|
...styleFromProps
|
|
1882
1615
|
},
|
|
1883
|
-
...dataAttributes,
|
|
1884
1616
|
// CSS selectors
|
|
1885
1617
|
"data-panel-group": "",
|
|
1886
1618
|
"data-panel-group-direction": direction,
|
|
@@ -1893,22 +1625,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
1893
1625
|
}));
|
|
1894
1626
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
1895
1627
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
1896
|
-
function panelDataHelper(
|
|
1628
|
+
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
1897
1629
|
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1898
1630
|
const panelIndex = panelDataArray.indexOf(panelData);
|
|
1899
1631
|
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1900
|
-
const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
|
|
1901
|
-
const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
|
|
1902
1632
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
1903
1633
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
1904
|
-
const
|
|
1905
|
-
const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
|
|
1634
|
+
const panelSize = layout[panelIndex];
|
|
1906
1635
|
return {
|
|
1907
|
-
...
|
|
1908
|
-
|
|
1909
|
-
panelSizePercentage,
|
|
1910
|
-
panelSizePixels,
|
|
1911
|
-
groupSizePixels,
|
|
1636
|
+
...panelConstraints,
|
|
1637
|
+
panelSize,
|
|
1912
1638
|
pivotIndices
|
|
1913
1639
|
};
|
|
1914
1640
|
}
|
|
@@ -1948,6 +1674,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1948
1674
|
{
|
|
1949
1675
|
event.preventDefault();
|
|
1950
1676
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1677
|
+
assert(groupId);
|
|
1951
1678
|
const handles = getResizeHandleElementsForGroup(groupId);
|
|
1952
1679
|
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
1953
1680
|
assert(index !== null);
|
|
@@ -1968,12 +1695,13 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1968
1695
|
function PanelResizeHandle({
|
|
1969
1696
|
children = null,
|
|
1970
1697
|
className: classNameFromProps = "",
|
|
1971
|
-
dataAttributes,
|
|
1972
1698
|
disabled = false,
|
|
1973
|
-
id: idFromProps
|
|
1699
|
+
id: idFromProps,
|
|
1974
1700
|
onDragging,
|
|
1975
1701
|
style: styleFromProps = {},
|
|
1976
|
-
|
|
1702
|
+
tabIndex = 0,
|
|
1703
|
+
tagName: Type = "div",
|
|
1704
|
+
...rest
|
|
1977
1705
|
}) {
|
|
1978
1706
|
const divElementRef = useRef(null);
|
|
1979
1707
|
|
|
@@ -2003,8 +1731,9 @@ function PanelResizeHandle({
|
|
|
2003
1731
|
const stopDraggingAndBlur = useCallback(() => {
|
|
2004
1732
|
// Clicking on the drag handle shouldn't leave it focused;
|
|
2005
1733
|
// That would cause the PanelGroup to think it was still active.
|
|
2006
|
-
const
|
|
2007
|
-
|
|
1734
|
+
const divElement = divElementRef.current;
|
|
1735
|
+
assert(divElement);
|
|
1736
|
+
divElement.blur();
|
|
2008
1737
|
stopDragging();
|
|
2009
1738
|
const {
|
|
2010
1739
|
onDragging
|
|
@@ -2032,6 +1761,7 @@ function PanelResizeHandle({
|
|
|
2032
1761
|
resizeHandler(event);
|
|
2033
1762
|
};
|
|
2034
1763
|
const divElement = divElementRef.current;
|
|
1764
|
+
assert(divElement);
|
|
2035
1765
|
const targetDocument = divElement.ownerDocument;
|
|
2036
1766
|
targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
|
|
2037
1767
|
targetDocument.body.addEventListener("mousemove", onMove);
|
|
@@ -2059,15 +1789,18 @@ function PanelResizeHandle({
|
|
|
2059
1789
|
userSelect: "none"
|
|
2060
1790
|
};
|
|
2061
1791
|
return createElement(Type, {
|
|
1792
|
+
...rest,
|
|
2062
1793
|
children,
|
|
2063
1794
|
className: classNameFromProps,
|
|
2064
1795
|
onBlur: () => setIsFocused(false),
|
|
2065
1796
|
onFocus: () => setIsFocused(true),
|
|
2066
1797
|
onMouseDown: event => {
|
|
2067
1798
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1799
|
+
const callbacks = callbacksRef.current;
|
|
1800
|
+
assert(callbacks);
|
|
2068
1801
|
const {
|
|
2069
1802
|
onDragging
|
|
2070
|
-
} =
|
|
1803
|
+
} = callbacks;
|
|
2071
1804
|
if (onDragging) {
|
|
2072
1805
|
onDragging(true);
|
|
2073
1806
|
}
|
|
@@ -2077,9 +1810,11 @@ function PanelResizeHandle({
|
|
|
2077
1810
|
onTouchEnd: stopDraggingAndBlur,
|
|
2078
1811
|
onTouchStart: event => {
|
|
2079
1812
|
startDragging(resizeHandleId, event.nativeEvent);
|
|
1813
|
+
const callbacks = callbacksRef.current;
|
|
1814
|
+
assert(callbacks);
|
|
2080
1815
|
const {
|
|
2081
1816
|
onDragging
|
|
2082
|
-
} =
|
|
1817
|
+
} = callbacks;
|
|
2083
1818
|
if (onDragging) {
|
|
2084
1819
|
onDragging(true);
|
|
2085
1820
|
}
|
|
@@ -2090,8 +1825,7 @@ function PanelResizeHandle({
|
|
|
2090
1825
|
...style,
|
|
2091
1826
|
...styleFromProps
|
|
2092
1827
|
},
|
|
2093
|
-
tabIndex
|
|
2094
|
-
...dataAttributes,
|
|
1828
|
+
tabIndex,
|
|
2095
1829
|
// CSS selectors
|
|
2096
1830
|
"data-panel-group-direction": direction,
|
|
2097
1831
|
"data-panel-group-id": groupId,
|
|
@@ -2103,4 +1837,4 @@ function PanelResizeHandle({
|
|
|
2103
1837
|
}
|
|
2104
1838
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
2105
1839
|
|
|
2106
|
-
export { Panel, PanelGroup, PanelResizeHandle };
|
|
1840
|
+
export { Panel, PanelGroup, PanelResizeHandle, assert };
|