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