react-resizable-panels 0.0.53 → 0.0.55
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/CHANGELOG.md +33 -0
- package/dist/declarations/src/Panel.d.ts +6 -5
- package/dist/declarations/src/PanelGroup.d.ts +8 -4
- package/dist/declarations/src/PanelResizeHandle.d.ts +5 -2
- package/dist/declarations/src/index.d.ts +9 -8
- package/dist/declarations/src/types.d.ts +4 -2
- package/dist/declarations/src/utils/group.d.ts +29 -0
- package/dist/react-resizable-panels.browser.cjs.js +1709 -0
- package/dist/react-resizable-panels.browser.cjs.mjs +6 -0
- package/dist/react-resizable-panels.browser.development.cjs.js +1764 -0
- package/dist/react-resizable-panels.browser.development.cjs.mjs +6 -0
- package/dist/react-resizable-panels.browser.development.esm.js +1737 -0
- package/dist/react-resizable-panels.browser.esm.js +1682 -0
- package/dist/react-resizable-panels.cjs.js +395 -126
- package/dist/react-resizable-panels.cjs.js.map +1 -0
- package/dist/react-resizable-panels.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.cjs.js +452 -135
- package/dist/react-resizable-panels.development.cjs.mjs +6 -0
- package/dist/react-resizable-panels.development.esm.js +452 -136
- package/dist/react-resizable-panels.development.node.cjs.js +1579 -0
- package/dist/react-resizable-panels.development.node.cjs.mjs +6 -0
- package/dist/react-resizable-panels.development.node.esm.js +1552 -0
- package/dist/react-resizable-panels.esm.js +395 -127
- package/dist/react-resizable-panels.esm.js.map +1 -0
- package/dist/react-resizable-panels.node.cjs.js +1523 -0
- package/dist/react-resizable-panels.node.cjs.mjs +6 -0
- package/dist/react-resizable-panels.node.esm.js +1496 -0
- package/package.json +26 -1
- package/src/Panel.ts +37 -37
- package/src/PanelContexts.ts +5 -6
- package/src/PanelGroup.ts +269 -121
- package/src/PanelResizeHandle.ts +1 -4
- package/src/env-conditions/browser.ts +1 -0
- package/src/env-conditions/node.ts +1 -0
- package/src/env-conditions/unknown.ts +1 -0
- package/src/hooks/useIsomorphicEffect.ts +2 -9
- package/src/hooks/useWindowSplitterBehavior.ts +14 -11
- package/src/index.ts +11 -3
- package/src/types.ts +3 -1
- package/src/utils/group.ts +327 -28
- package/src/utils/ssr.ts +0 -7
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
const isBrowser = typeof window !== "undefined";
|
|
4
|
+
|
|
3
5
|
// This module exists to work around Webpack issue https://github.com/webpack/webpack/issues/14814
|
|
4
6
|
|
|
5
7
|
// eslint-disable-next-line no-restricted-imports
|
|
@@ -21,8 +23,7 @@ const {
|
|
|
21
23
|
// `toString()` prevents bundlers from trying to `import { useId } from 'react'`
|
|
22
24
|
const useId = React["useId".toString()];
|
|
23
25
|
|
|
24
|
-
const
|
|
25
|
-
const useIsomorphicLayoutEffect = canUseEffectHooks ? useLayoutEffect : () => {};
|
|
26
|
+
const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : () => {};
|
|
26
27
|
|
|
27
28
|
const wrappedUseId = typeof useId === "function" ? useId : () => null;
|
|
28
29
|
let counter = 0;
|
|
@@ -36,10 +37,6 @@ function useUniqueId(idFromParams = null) {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
const PanelGroupContext = createContext(null);
|
|
39
|
-
|
|
40
|
-
// Workaround for Parcel scope hoisting (which renames objects/functions).
|
|
41
|
-
// Casting to :any is required to avoid corrupting the generated TypeScript types.
|
|
42
|
-
// See github.com/parcel-bundler/parcel/issues/8724
|
|
43
40
|
PanelGroupContext.displayName = "PanelGroupContext";
|
|
44
41
|
|
|
45
42
|
function PanelWithForwardedRef({
|
|
@@ -50,8 +47,8 @@ function PanelWithForwardedRef({
|
|
|
50
47
|
defaultSize = null,
|
|
51
48
|
forwardedRef,
|
|
52
49
|
id: idFromProps = null,
|
|
53
|
-
maxSize =
|
|
54
|
-
minSize
|
|
50
|
+
maxSize = null,
|
|
51
|
+
minSize,
|
|
55
52
|
onCollapse = null,
|
|
56
53
|
onResize = null,
|
|
57
54
|
order = null,
|
|
@@ -66,11 +63,22 @@ function PanelWithForwardedRef({
|
|
|
66
63
|
const {
|
|
67
64
|
collapsePanel,
|
|
68
65
|
expandPanel,
|
|
66
|
+
getPanelSize,
|
|
69
67
|
getPanelStyle,
|
|
70
68
|
registerPanel,
|
|
71
69
|
resizePanel,
|
|
70
|
+
units,
|
|
72
71
|
unregisterPanel
|
|
73
72
|
} = context;
|
|
73
|
+
if (minSize == null) {
|
|
74
|
+
if (units === "percentages") {
|
|
75
|
+
// Mimics legacy default value for percentage based panel groups
|
|
76
|
+
minSize = 10;
|
|
77
|
+
} else {
|
|
78
|
+
// There is no meaningful minimum pixel default we can provide
|
|
79
|
+
minSize = 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
74
82
|
|
|
75
83
|
// Use a ref to guard against users passing inline props
|
|
76
84
|
const callbacksRef = useRef({
|
|
@@ -81,22 +89,6 @@ function PanelWithForwardedRef({
|
|
|
81
89
|
callbacksRef.current.onCollapse = onCollapse;
|
|
82
90
|
callbacksRef.current.onResize = onResize;
|
|
83
91
|
});
|
|
84
|
-
|
|
85
|
-
// Basic props validation
|
|
86
|
-
if (minSize < 0 || minSize > 100) {
|
|
87
|
-
throw Error(`Panel minSize must be between 0 and 100, but was ${minSize}`);
|
|
88
|
-
} else if (maxSize < 0 || maxSize > 100) {
|
|
89
|
-
throw Error(`Panel maxSize must be between 0 and 100, but was ${maxSize}`);
|
|
90
|
-
} else {
|
|
91
|
-
if (defaultSize !== null) {
|
|
92
|
-
if (defaultSize < 0 || defaultSize > 100) {
|
|
93
|
-
throw Error(`Panel defaultSize must be between 0 and 100, but was ${defaultSize}`);
|
|
94
|
-
} else if (minSize > defaultSize && !collapsible) {
|
|
95
|
-
console.error(`Panel minSize ${minSize} cannot be greater than defaultSize ${defaultSize}`);
|
|
96
|
-
defaultSize = minSize;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
92
|
const style = getPanelStyle(panelId, defaultSize);
|
|
101
93
|
const committedValuesRef = useRef({
|
|
102
94
|
size: parseSizeFromStyle(style)
|
|
@@ -107,6 +99,7 @@ function PanelWithForwardedRef({
|
|
|
107
99
|
collapsible,
|
|
108
100
|
defaultSize,
|
|
109
101
|
id: panelId,
|
|
102
|
+
idWasAutoGenerated: idFromProps == null,
|
|
110
103
|
maxSize,
|
|
111
104
|
minSize,
|
|
112
105
|
order
|
|
@@ -118,6 +111,7 @@ function PanelWithForwardedRef({
|
|
|
118
111
|
panelDataRef.current.collapsible = collapsible;
|
|
119
112
|
panelDataRef.current.defaultSize = defaultSize;
|
|
120
113
|
panelDataRef.current.id = panelId;
|
|
114
|
+
panelDataRef.current.idWasAutoGenerated = idFromProps == null;
|
|
121
115
|
panelDataRef.current.maxSize = maxSize;
|
|
122
116
|
panelDataRef.current.minSize = minSize;
|
|
123
117
|
panelDataRef.current.order = order;
|
|
@@ -134,11 +128,14 @@ function PanelWithForwardedRef({
|
|
|
134
128
|
getCollapsed() {
|
|
135
129
|
return committedValuesRef.current.size === 0;
|
|
136
130
|
},
|
|
137
|
-
|
|
138
|
-
return
|
|
131
|
+
getId() {
|
|
132
|
+
return panelId;
|
|
139
133
|
},
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
getSize(units) {
|
|
135
|
+
return getPanelSize(panelId, units);
|
|
136
|
+
},
|
|
137
|
+
resize: (percentage, units) => resizePanel(panelId, percentage, units)
|
|
138
|
+
}), [collapsePanel, expandPanel, getPanelSize, panelId, resizePanel]);
|
|
142
139
|
return createElement(Type, {
|
|
143
140
|
children,
|
|
144
141
|
className: classNameFromProps,
|
|
@@ -157,10 +154,6 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
157
154
|
...props,
|
|
158
155
|
forwardedRef: ref
|
|
159
156
|
}));
|
|
160
|
-
|
|
161
|
-
// Workaround for Parcel scope hoisting (which renames objects/functions).
|
|
162
|
-
// Casting to :any is required to avoid corrupting the generated TypeScript types.
|
|
163
|
-
// See github.com/parcel-bundler/parcel/issues/8724
|
|
164
157
|
PanelWithForwardedRef.displayName = "Panel";
|
|
165
158
|
Panel.displayName = "forwardRef(Panel)";
|
|
166
159
|
|
|
@@ -178,7 +171,13 @@ function parseSizeFromStyle(style) {
|
|
|
178
171
|
|
|
179
172
|
const PRECISION = 10;
|
|
180
173
|
|
|
181
|
-
function adjustByDelta(event,
|
|
174
|
+
function adjustByDelta(event, committedValues, idBefore, idAfter, deltaPixels, prevSizes, panelSizeBeforeCollapse, initialDragState) {
|
|
175
|
+
const {
|
|
176
|
+
id: groupId,
|
|
177
|
+
panels,
|
|
178
|
+
units
|
|
179
|
+
} = committedValues;
|
|
180
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
182
181
|
const {
|
|
183
182
|
sizes: initialSizes
|
|
184
183
|
} = initialDragState || {};
|
|
@@ -186,9 +185,6 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
186
185
|
// If we're resizing by mouse or touch, use the initial sizes as a base.
|
|
187
186
|
// This has the benefit of causing force-collapsed panels to spring back open if drag is reversed.
|
|
188
187
|
const baseSizes = initialSizes || prevSizes;
|
|
189
|
-
if (delta === 0) {
|
|
190
|
-
return baseSizes;
|
|
191
|
-
}
|
|
192
188
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
193
189
|
const nextSizes = baseSizes.concat();
|
|
194
190
|
let deltaApplied = 0;
|
|
@@ -203,11 +199,11 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
203
199
|
|
|
204
200
|
// Max-bounds check the panel being expanded first.
|
|
205
201
|
{
|
|
206
|
-
const pivotId =
|
|
202
|
+
const pivotId = deltaPixels < 0 ? idAfter : idBefore;
|
|
207
203
|
const index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
208
204
|
const panel = panelsArray[index];
|
|
209
205
|
const baseSize = baseSizes[index];
|
|
210
|
-
const nextSize = safeResizePanel(panel, Math.abs(
|
|
206
|
+
const nextSize = safeResizePanel(units, groupSizePixels, panel, baseSize, baseSize + Math.abs(deltaPixels), event);
|
|
211
207
|
if (baseSize === nextSize) {
|
|
212
208
|
// If there's no room for the pivot panel to grow, we can ignore this drag update.
|
|
213
209
|
return baseSizes;
|
|
@@ -215,29 +211,29 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
215
211
|
if (nextSize === 0 && baseSize > 0) {
|
|
216
212
|
panelSizeBeforeCollapse.set(pivotId, baseSize);
|
|
217
213
|
}
|
|
218
|
-
|
|
214
|
+
deltaPixels = deltaPixels < 0 ? baseSize - nextSize : nextSize - baseSize;
|
|
219
215
|
}
|
|
220
216
|
}
|
|
221
|
-
let pivotId =
|
|
217
|
+
let pivotId = deltaPixels < 0 ? idBefore : idAfter;
|
|
222
218
|
let index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
223
219
|
while (true) {
|
|
224
220
|
const panel = panelsArray[index];
|
|
225
221
|
const baseSize = baseSizes[index];
|
|
226
|
-
const deltaRemaining = Math.abs(
|
|
227
|
-
const nextSize = safeResizePanel(panel,
|
|
222
|
+
const deltaRemaining = Math.abs(deltaPixels) - Math.abs(deltaApplied);
|
|
223
|
+
const nextSize = safeResizePanel(units, groupSizePixels, panel, baseSize, baseSize - deltaRemaining, event);
|
|
228
224
|
if (baseSize !== nextSize) {
|
|
229
225
|
if (nextSize === 0 && baseSize > 0) {
|
|
230
226
|
panelSizeBeforeCollapse.set(panel.current.id, baseSize);
|
|
231
227
|
}
|
|
232
228
|
deltaApplied += baseSize - nextSize;
|
|
233
229
|
nextSizes[index] = nextSize;
|
|
234
|
-
if (deltaApplied.toPrecision(PRECISION).localeCompare(Math.abs(
|
|
230
|
+
if (deltaApplied.toPrecision(PRECISION).localeCompare(Math.abs(deltaPixels).toPrecision(PRECISION), undefined, {
|
|
235
231
|
numeric: true
|
|
236
232
|
}) >= 0) {
|
|
237
233
|
break;
|
|
238
234
|
}
|
|
239
235
|
}
|
|
240
|
-
if (
|
|
236
|
+
if (deltaPixels < 0) {
|
|
241
237
|
if (--index < 0) {
|
|
242
238
|
break;
|
|
243
239
|
}
|
|
@@ -255,7 +251,7 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
255
251
|
}
|
|
256
252
|
|
|
257
253
|
// Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.
|
|
258
|
-
pivotId =
|
|
254
|
+
pivotId = deltaPixels < 0 ? idAfter : idBefore;
|
|
259
255
|
index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
260
256
|
nextSizes[index] = baseSizes[index] + deltaApplied;
|
|
261
257
|
return nextSizes;
|
|
@@ -294,6 +290,89 @@ function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
|
294
290
|
}
|
|
295
291
|
});
|
|
296
292
|
}
|
|
293
|
+
function calculateDefaultLayout({
|
|
294
|
+
groupId,
|
|
295
|
+
panels,
|
|
296
|
+
units
|
|
297
|
+
}) {
|
|
298
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
299
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
300
|
+
const sizes = Array(panelsArray.length);
|
|
301
|
+
let numPanelsWithSizes = 0;
|
|
302
|
+
let remainingSize = 100;
|
|
303
|
+
|
|
304
|
+
// Assigning default sizes requires a couple of passes:
|
|
305
|
+
// First, all panels with defaultSize should be set as-is
|
|
306
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
307
|
+
const panel = panelsArray[index];
|
|
308
|
+
const {
|
|
309
|
+
defaultSize
|
|
310
|
+
} = panel.current;
|
|
311
|
+
if (defaultSize != null) {
|
|
312
|
+
numPanelsWithSizes++;
|
|
313
|
+
sizes[index] = units === "pixels" ? defaultSize / groupSizePixels * 100 : defaultSize;
|
|
314
|
+
remainingSize -= sizes[index];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Remaining total size should be distributed evenly between panels
|
|
319
|
+
// This may require two passes, depending on min/max constraints
|
|
320
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
321
|
+
const panel = panelsArray[index];
|
|
322
|
+
let {
|
|
323
|
+
defaultSize,
|
|
324
|
+
id,
|
|
325
|
+
maxSize,
|
|
326
|
+
minSize
|
|
327
|
+
} = panel.current;
|
|
328
|
+
if (defaultSize != null) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (units === "pixels") {
|
|
332
|
+
minSize = minSize / groupSizePixels * 100;
|
|
333
|
+
if (maxSize != null) {
|
|
334
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const remainingPanels = panelsArray.length - numPanelsWithSizes;
|
|
338
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, remainingSize / remainingPanels));
|
|
339
|
+
sizes[index] = size;
|
|
340
|
+
numPanelsWithSizes++;
|
|
341
|
+
remainingSize -= size;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// If there is additional, left over space, assign it to any panel(s) that permits it
|
|
345
|
+
// (It's not worth taking multiple additional passes to evenly distribute)
|
|
346
|
+
if (remainingSize !== 0) {
|
|
347
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
348
|
+
const panel = panelsArray[index];
|
|
349
|
+
let {
|
|
350
|
+
maxSize,
|
|
351
|
+
minSize
|
|
352
|
+
} = panel.current;
|
|
353
|
+
if (units === "pixels") {
|
|
354
|
+
minSize = minSize / groupSizePixels * 100;
|
|
355
|
+
if (maxSize != null) {
|
|
356
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, sizes[index] + remainingSize));
|
|
360
|
+
if (size !== sizes[index]) {
|
|
361
|
+
remainingSize -= size - sizes[index];
|
|
362
|
+
sizes[index] = size;
|
|
363
|
+
|
|
364
|
+
// Fuzzy comparison to account for imprecise floating point math
|
|
365
|
+
if (Math.abs(remainingSize).toFixed(3) === "0.000") {
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Finally, if there is still left-over size, log an error
|
|
373
|
+
if (Math.abs(remainingSize).toFixed(3) !== "0.000") ;
|
|
374
|
+
return sizes;
|
|
375
|
+
}
|
|
297
376
|
function getBeforeAndAfterIds(id, panelsArray) {
|
|
298
377
|
if (panelsArray.length < 2) {
|
|
299
378
|
return [null, null];
|
|
@@ -307,6 +386,23 @@ function getBeforeAndAfterIds(id, panelsArray) {
|
|
|
307
386
|
const idAfter = isLastPanel ? id : panelsArray[index + 1].current.id;
|
|
308
387
|
return [idBefore, idAfter];
|
|
309
388
|
}
|
|
389
|
+
function getAvailableGroupSizePixels(groupId) {
|
|
390
|
+
const panelGroupElement = getPanelGroup(groupId);
|
|
391
|
+
if (panelGroupElement == null) {
|
|
392
|
+
return NaN;
|
|
393
|
+
}
|
|
394
|
+
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
395
|
+
const resizeHandles = getResizeHandlesForGroup(groupId);
|
|
396
|
+
if (direction === "horizontal") {
|
|
397
|
+
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
398
|
+
return accumulated + handle.offsetWidth;
|
|
399
|
+
}, 0);
|
|
400
|
+
} else {
|
|
401
|
+
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
402
|
+
return accumulated + handle.offsetHeight;
|
|
403
|
+
}, 0);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
310
406
|
|
|
311
407
|
// This method returns a number between 1 and 100 representing
|
|
312
408
|
// the % of the group's overall space this panel should occupy.
|
|
@@ -377,18 +473,24 @@ function panelsMapToSortedArray(panels) {
|
|
|
377
473
|
}
|
|
378
474
|
});
|
|
379
475
|
}
|
|
380
|
-
function safeResizePanel(
|
|
381
|
-
|
|
382
|
-
const {
|
|
476
|
+
function safeResizePanel(units, groupSizePixels, panel, prevSize, nextSize, event = null) {
|
|
477
|
+
let {
|
|
383
478
|
collapsedSize,
|
|
384
479
|
collapsible,
|
|
385
480
|
maxSize,
|
|
386
481
|
minSize
|
|
387
482
|
} = panel.current;
|
|
483
|
+
if (units === "pixels") {
|
|
484
|
+
collapsedSize = collapsedSize / groupSizePixels * 100;
|
|
485
|
+
if (maxSize != null) {
|
|
486
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
487
|
+
}
|
|
488
|
+
minSize = minSize / groupSizePixels * 100;
|
|
489
|
+
}
|
|
388
490
|
if (collapsible) {
|
|
389
491
|
if (prevSize > collapsedSize) {
|
|
390
492
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
391
|
-
if (
|
|
493
|
+
if (nextSize <= minSize / 2 + collapsedSize) {
|
|
392
494
|
return collapsedSize;
|
|
393
495
|
}
|
|
394
496
|
} else {
|
|
@@ -397,14 +499,97 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
397
499
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
398
500
|
// but mouse events should wait until the panel has reached its min size
|
|
399
501
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
400
|
-
if (
|
|
502
|
+
if (nextSize < minSize) {
|
|
401
503
|
return collapsedSize;
|
|
402
504
|
}
|
|
403
505
|
}
|
|
404
506
|
}
|
|
405
507
|
}
|
|
406
|
-
|
|
407
|
-
|
|
508
|
+
return Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSize));
|
|
509
|
+
}
|
|
510
|
+
function validatePanelProps(units, panelData) {
|
|
511
|
+
const {
|
|
512
|
+
collapsible,
|
|
513
|
+
defaultSize,
|
|
514
|
+
maxSize,
|
|
515
|
+
minSize
|
|
516
|
+
} = panelData.current;
|
|
517
|
+
|
|
518
|
+
// Basic props validation
|
|
519
|
+
if (minSize < 0 || units === "percentages" && minSize > 100) {
|
|
520
|
+
panelData.current.minSize = 0;
|
|
521
|
+
}
|
|
522
|
+
if (maxSize != null) {
|
|
523
|
+
if (maxSize < 0 || units === "percentages" && maxSize > 100) {
|
|
524
|
+
panelData.current.maxSize = null;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (defaultSize !== null) {
|
|
528
|
+
if (defaultSize < 0 || units === "percentages" && defaultSize > 100) {
|
|
529
|
+
panelData.current.defaultSize = null;
|
|
530
|
+
} else if (defaultSize < minSize && !collapsible) {
|
|
531
|
+
panelData.current.defaultSize = minSize;
|
|
532
|
+
} else if (maxSize != null && defaultSize > maxSize) {
|
|
533
|
+
panelData.current.defaultSize = maxSize;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function validatePanelGroupLayout({
|
|
538
|
+
groupId,
|
|
539
|
+
panels,
|
|
540
|
+
nextSizes,
|
|
541
|
+
prevSizes,
|
|
542
|
+
units
|
|
543
|
+
}) {
|
|
544
|
+
// Clone because this method modifies
|
|
545
|
+
nextSizes = [...nextSizes];
|
|
546
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
547
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
548
|
+
let remainingSize = 0;
|
|
549
|
+
|
|
550
|
+
// First, check all of the proposed sizes against the min/max constraints
|
|
551
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
552
|
+
const panel = panelsArray[index];
|
|
553
|
+
const prevSize = prevSizes[index];
|
|
554
|
+
const nextSize = nextSizes[index];
|
|
555
|
+
const safeNextSize = safeResizePanel(units, groupSizePixels, panel, prevSize, nextSize);
|
|
556
|
+
if (nextSize != safeNextSize) {
|
|
557
|
+
remainingSize += nextSize - safeNextSize;
|
|
558
|
+
nextSizes[index] = safeNextSize;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// If there is additional, left over space, assign it to any panel(s) that permits it
|
|
563
|
+
// (It's not worth taking multiple additional passes to evenly distribute)
|
|
564
|
+
if (remainingSize.toFixed(3) !== "0.000") {
|
|
565
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
566
|
+
const panel = panelsArray[index];
|
|
567
|
+
let {
|
|
568
|
+
maxSize,
|
|
569
|
+
minSize
|
|
570
|
+
} = panel.current;
|
|
571
|
+
if (units === "pixels") {
|
|
572
|
+
minSize = minSize / groupSizePixels * 100;
|
|
573
|
+
if (maxSize != null) {
|
|
574
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSizes[index] + remainingSize));
|
|
578
|
+
if (size !== nextSizes[index]) {
|
|
579
|
+
remainingSize -= size - nextSizes[index];
|
|
580
|
+
nextSizes[index] = size;
|
|
581
|
+
|
|
582
|
+
// Fuzzy comparison to account for imprecise floating point math
|
|
583
|
+
if (Math.abs(remainingSize).toFixed(3) === "0.000") {
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// If we still have remainder, the requested layout wasn't valid and we should warn about it
|
|
591
|
+
if (remainingSize.toFixed(3) !== "0.000") ;
|
|
592
|
+
return nextSizes;
|
|
408
593
|
}
|
|
409
594
|
|
|
410
595
|
function assert(expectedCondition, message = "Assertion failed!") {
|
|
@@ -430,6 +615,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
430
615
|
panels
|
|
431
616
|
} = committedValuesRef.current;
|
|
432
617
|
const groupElement = getPanelGroup(groupId);
|
|
618
|
+
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
433
619
|
const {
|
|
434
620
|
height,
|
|
435
621
|
width
|
|
@@ -442,23 +628,28 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
442
628
|
if (idBefore == null || idAfter == null) {
|
|
443
629
|
return () => {};
|
|
444
630
|
}
|
|
445
|
-
let
|
|
446
|
-
let
|
|
631
|
+
let currentMinSize = 0;
|
|
632
|
+
let currentMaxSize = 100;
|
|
447
633
|
let totalMinSize = 0;
|
|
448
634
|
let totalMaxSize = 0;
|
|
449
635
|
|
|
450
636
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
451
637
|
panelsArray.forEach(panelData => {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
638
|
+
const {
|
|
639
|
+
id,
|
|
640
|
+
maxSize,
|
|
641
|
+
minSize
|
|
642
|
+
} = panelData.current;
|
|
643
|
+
if (id === idBefore) {
|
|
644
|
+
currentMinSize = minSize;
|
|
645
|
+
currentMaxSize = maxSize != null ? maxSize : 100;
|
|
455
646
|
} else {
|
|
456
|
-
totalMinSize +=
|
|
457
|
-
totalMaxSize +=
|
|
647
|
+
totalMinSize += minSize;
|
|
648
|
+
totalMaxSize += maxSize != null ? maxSize : 100;
|
|
458
649
|
}
|
|
459
650
|
});
|
|
460
|
-
const ariaValueMax = Math.min(
|
|
461
|
-
const ariaValueMin = Math.max(
|
|
651
|
+
const ariaValueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
652
|
+
const ariaValueMin = Math.max(currentMinSize, (panelsArray.length - 1) * 100 - totalMaxSize);
|
|
462
653
|
const flexGrow = getFlexGrow(panels, idBefore, sizes);
|
|
463
654
|
handle.setAttribute("aria-valuemax", "" + Math.round(ariaValueMax));
|
|
464
655
|
handle.setAttribute("aria-valuemin", "" + Math.round(ariaValueMin));
|
|
@@ -482,7 +673,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
482
673
|
} else {
|
|
483
674
|
delta = -(direction === "horizontal" ? width : height);
|
|
484
675
|
}
|
|
485
|
-
const nextSizes = adjustByDelta(event,
|
|
676
|
+
const nextSizes = adjustByDelta(event, committedValuesRef.current, idBefore, idAfter, delta, sizes, panelSizeBeforeCollapse.current, null);
|
|
486
677
|
if (sizes !== nextSizes) {
|
|
487
678
|
setSizes(nextSizes);
|
|
488
679
|
}
|
|
@@ -797,9 +988,6 @@ const defaultStorage = {
|
|
|
797
988
|
// * dragHandleRect, sizes:
|
|
798
989
|
// When resizing is done via mouse/touch event– some initial state is stored
|
|
799
990
|
// so that any panels that contract will also expand if drag direction is reversed.
|
|
800
|
-
// TODO
|
|
801
|
-
// Within an active drag, remember original positions to refine more easily on expand.
|
|
802
|
-
// Look at what the Chrome devtools Sources does.
|
|
803
991
|
function PanelGroupWithForwardedRef({
|
|
804
992
|
autoSaveId,
|
|
805
993
|
children = null,
|
|
@@ -811,7 +999,8 @@ function PanelGroupWithForwardedRef({
|
|
|
811
999
|
onLayout,
|
|
812
1000
|
storage = defaultStorage,
|
|
813
1001
|
style: styleFromProps = {},
|
|
814
|
-
tagName: Type = "div"
|
|
1002
|
+
tagName: Type = "div",
|
|
1003
|
+
units = "percentages"
|
|
815
1004
|
}) {
|
|
816
1005
|
const groupId = useUniqueId(idFromProps);
|
|
817
1006
|
const [activeHandleId, setActiveHandleId] = useState(null);
|
|
@@ -821,6 +1010,12 @@ function PanelGroupWithForwardedRef({
|
|
|
821
1010
|
// We store the initial Panel sizes in this ref, and apply move deltas to them instead of to the current sizes.
|
|
822
1011
|
// This has the benefit of causing force-collapsed panels to spring back open if drag is reversed.
|
|
823
1012
|
const initialDragStateRef = useRef(null);
|
|
1013
|
+
useRef({
|
|
1014
|
+
didLogDefaultSizeWarning: false,
|
|
1015
|
+
didLogIdAndOrderWarning: false,
|
|
1016
|
+
didLogInvalidLayoutWarning: false,
|
|
1017
|
+
prevPanelIds: []
|
|
1018
|
+
});
|
|
824
1019
|
|
|
825
1020
|
// Use a ref to guard against users passing inline props
|
|
826
1021
|
const callbacksRef = useRef({
|
|
@@ -841,32 +1036,58 @@ function PanelGroupWithForwardedRef({
|
|
|
841
1036
|
// Store committed values to avoid unnecessarily re-running memoization/effects functions.
|
|
842
1037
|
const committedValuesRef = useRef({
|
|
843
1038
|
direction,
|
|
1039
|
+
id: groupId,
|
|
844
1040
|
panels,
|
|
845
|
-
sizes
|
|
1041
|
+
sizes,
|
|
1042
|
+
units
|
|
846
1043
|
});
|
|
847
1044
|
useImperativeHandle(forwardedRef, () => ({
|
|
848
|
-
|
|
1045
|
+
getId: () => groupId,
|
|
1046
|
+
getLayout: unitsFromParams => {
|
|
849
1047
|
const {
|
|
850
|
-
sizes
|
|
1048
|
+
sizes,
|
|
1049
|
+
units: unitsFromProps
|
|
851
1050
|
} = committedValuesRef.current;
|
|
852
|
-
|
|
1051
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
1052
|
+
if (units === "pixels") {
|
|
1053
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1054
|
+
return sizes.map(size => size / 100 * groupSizePixels);
|
|
1055
|
+
} else {
|
|
1056
|
+
return sizes;
|
|
1057
|
+
}
|
|
853
1058
|
},
|
|
854
|
-
setLayout: sizes => {
|
|
855
|
-
const total = sizes.reduce((accumulated, current) => accumulated + current, 0);
|
|
856
|
-
assert(total === 100, "Panel sizes must add up to 100%");
|
|
1059
|
+
setLayout: (sizes, unitsFromParams) => {
|
|
857
1060
|
const {
|
|
858
|
-
|
|
1061
|
+
id: groupId,
|
|
1062
|
+
panels,
|
|
1063
|
+
sizes: prevSizes,
|
|
1064
|
+
units
|
|
859
1065
|
} = committedValuesRef.current;
|
|
1066
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
1067
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1068
|
+
sizes = sizes.map(size => size / groupSizePixels * 100);
|
|
1069
|
+
}
|
|
860
1070
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
861
1071
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
862
|
-
|
|
863
|
-
|
|
1072
|
+
const nextSizes = validatePanelGroupLayout({
|
|
1073
|
+
groupId,
|
|
1074
|
+
panels,
|
|
1075
|
+
nextSizes: sizes,
|
|
1076
|
+
prevSizes,
|
|
1077
|
+
units
|
|
1078
|
+
});
|
|
1079
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
1080
|
+
setSizes(nextSizes);
|
|
1081
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1082
|
+
}
|
|
864
1083
|
}
|
|
865
|
-
}), []);
|
|
1084
|
+
}), [groupId]);
|
|
866
1085
|
useIsomorphicLayoutEffect(() => {
|
|
867
1086
|
committedValuesRef.current.direction = direction;
|
|
1087
|
+
committedValuesRef.current.id = groupId;
|
|
868
1088
|
committedValuesRef.current.panels = panels;
|
|
869
1089
|
committedValuesRef.current.sizes = sizes;
|
|
1090
|
+
committedValuesRef.current.units = units;
|
|
870
1091
|
});
|
|
871
1092
|
useWindowSplitterPanelGroupBehavior({
|
|
872
1093
|
committedValuesRef,
|
|
@@ -908,7 +1129,11 @@ function PanelGroupWithForwardedRef({
|
|
|
908
1129
|
// Compute the initial sizes based on default weights.
|
|
909
1130
|
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
910
1131
|
useIsomorphicLayoutEffect(() => {
|
|
911
|
-
const
|
|
1132
|
+
const {
|
|
1133
|
+
id: groupId,
|
|
1134
|
+
sizes,
|
|
1135
|
+
units
|
|
1136
|
+
} = committedValuesRef.current;
|
|
912
1137
|
if (sizes.length === panels.size) {
|
|
913
1138
|
// Only compute (or restore) default sizes once per panel configuration.
|
|
914
1139
|
return;
|
|
@@ -922,39 +1147,23 @@ function PanelGroupWithForwardedRef({
|
|
|
922
1147
|
defaultSizes = loadPanelLayout(autoSaveId, panelsArray, storage);
|
|
923
1148
|
}
|
|
924
1149
|
if (defaultSizes != null) {
|
|
925
|
-
|
|
1150
|
+
// Validate saved sizes in case something has changed since last render
|
|
1151
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1152
|
+
const validatedSizes = validatePanelGroupLayout({
|
|
1153
|
+
groupId,
|
|
1154
|
+
panels,
|
|
1155
|
+
nextSizes: defaultSizes,
|
|
1156
|
+
prevSizes: defaultSizes,
|
|
1157
|
+
units
|
|
1158
|
+
});
|
|
1159
|
+
setSizes(validatedSizes);
|
|
926
1160
|
} else {
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
// TODO
|
|
933
|
-
// Implicit default size calculations below do not account for inferred min/max size values.
|
|
934
|
-
// e.g. if Panel A has a maxSize of 40 then Panels A and B can't both have an implicit default size of 50.
|
|
935
|
-
// For now, these logic edge cases are left to the user to handle via props.
|
|
936
|
-
|
|
937
|
-
panelsArray.forEach(panel => {
|
|
938
|
-
totalMinSize += panel.current.minSize;
|
|
939
|
-
if (panel.current.defaultSize === null) {
|
|
940
|
-
panelsWithNullDefaultSize++;
|
|
941
|
-
} else {
|
|
942
|
-
totalDefaultSize += panel.current.defaultSize;
|
|
943
|
-
}
|
|
1161
|
+
const sizes = calculateDefaultLayout({
|
|
1162
|
+
groupId,
|
|
1163
|
+
panels,
|
|
1164
|
+
units
|
|
944
1165
|
});
|
|
945
|
-
|
|
946
|
-
throw new Error(`Default panel sizes cannot exceed 100%`);
|
|
947
|
-
} else if (panelsArray.length > 1 && panelsWithNullDefaultSize === 0 && totalDefaultSize !== 100) {
|
|
948
|
-
throw new Error(`Invalid default sizes specified for panels`);
|
|
949
|
-
} else if (totalMinSize > 100) {
|
|
950
|
-
throw new Error(`Minimum panel sizes cannot exceed 100%`);
|
|
951
|
-
}
|
|
952
|
-
setSizes(panelsArray.map(panel => {
|
|
953
|
-
if (panel.current.defaultSize === null) {
|
|
954
|
-
return (100 - totalDefaultSize) / panelsWithNullDefaultSize;
|
|
955
|
-
}
|
|
956
|
-
return panel.current.defaultSize;
|
|
957
|
-
}));
|
|
1166
|
+
setSizes(sizes);
|
|
958
1167
|
}
|
|
959
1168
|
}, [autoSaveId, panels, storage]);
|
|
960
1169
|
useEffect(() => {
|
|
@@ -972,6 +1181,48 @@ function PanelGroupWithForwardedRef({
|
|
|
972
1181
|
debounceMap[autoSaveId](autoSaveId, panelsArray, sizes, storage);
|
|
973
1182
|
}
|
|
974
1183
|
}, [autoSaveId, panels, sizes, storage]);
|
|
1184
|
+
useIsomorphicLayoutEffect(() => {
|
|
1185
|
+
// Pixel panel constraints need to be reassessed after a group resize
|
|
1186
|
+
// We can avoid the ResizeObserver overhead for relative layouts
|
|
1187
|
+
if (units === "pixels") {
|
|
1188
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1189
|
+
const {
|
|
1190
|
+
panels,
|
|
1191
|
+
sizes: prevSizes
|
|
1192
|
+
} = committedValuesRef.current;
|
|
1193
|
+
const nextSizes = validatePanelGroupLayout({
|
|
1194
|
+
groupId,
|
|
1195
|
+
panels,
|
|
1196
|
+
nextSizes: prevSizes,
|
|
1197
|
+
prevSizes,
|
|
1198
|
+
units
|
|
1199
|
+
});
|
|
1200
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
1201
|
+
setSizes(nextSizes);
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
resizeObserver.observe(getPanelGroup(groupId));
|
|
1205
|
+
return () => {
|
|
1206
|
+
resizeObserver.disconnect();
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
}, [groupId, units]);
|
|
1210
|
+
const getPanelSize = useCallback((id, unitsFromParams) => {
|
|
1211
|
+
const {
|
|
1212
|
+
panels,
|
|
1213
|
+
units: unitsFromProps
|
|
1214
|
+
} = committedValuesRef.current;
|
|
1215
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
1216
|
+
const index = panelsArray.findIndex(panel => panel.current.id === id);
|
|
1217
|
+
const size = sizes[index];
|
|
1218
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
1219
|
+
if (units === "pixels") {
|
|
1220
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1221
|
+
return size / 100 * groupSizePixels;
|
|
1222
|
+
} else {
|
|
1223
|
+
return size;
|
|
1224
|
+
}
|
|
1225
|
+
}, [groupId, sizes]);
|
|
975
1226
|
const getPanelStyle = useCallback((id, defaultSize) => {
|
|
976
1227
|
const {
|
|
977
1228
|
panels
|
|
@@ -1002,6 +1253,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1002
1253
|
};
|
|
1003
1254
|
}, [activeHandleId, disablePointerEventsDuringResize, sizes]);
|
|
1004
1255
|
const registerPanel = useCallback((id, panelRef) => {
|
|
1256
|
+
const {
|
|
1257
|
+
units
|
|
1258
|
+
} = committedValuesRef.current;
|
|
1259
|
+
validatePanelProps(units, panelRef);
|
|
1005
1260
|
setPanels(prevPanels => {
|
|
1006
1261
|
if (prevPanels.has(id)) {
|
|
1007
1262
|
return prevPanels;
|
|
@@ -1038,7 +1293,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1038
1293
|
}
|
|
1039
1294
|
const size = isHorizontal ? rect.width : rect.height;
|
|
1040
1295
|
const delta = movement / size * 100;
|
|
1041
|
-
|
|
1296
|
+
|
|
1297
|
+
// If a validateLayout method has been provided
|
|
1298
|
+
// it's important to use it before updating the mouse cursor
|
|
1299
|
+
const nextSizes = adjustByDelta(event, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, initialDragStateRef.current);
|
|
1042
1300
|
const sizesChanged = !areEqual(prevSizes, nextSizes);
|
|
1043
1301
|
|
|
1044
1302
|
// Don't update cursor for resizes triggered by keyboard interactions.
|
|
@@ -1065,6 +1323,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1065
1323
|
}
|
|
1066
1324
|
if (sizesChanged) {
|
|
1067
1325
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1326
|
+
|
|
1327
|
+
// It's okay to bypass in this case because we already validated above
|
|
1068
1328
|
setSizes(nextSizes);
|
|
1069
1329
|
|
|
1070
1330
|
// If resize change handlers have been declared, this is the time to call them.
|
|
@@ -1118,7 +1378,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1118
1378
|
}
|
|
1119
1379
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1120
1380
|
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1121
|
-
const nextSizes = adjustByDelta(null,
|
|
1381
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1122
1382
|
if (prevSizes !== nextSizes) {
|
|
1123
1383
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1124
1384
|
setSizes(nextSizes);
|
|
@@ -1161,7 +1421,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1161
1421
|
}
|
|
1162
1422
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1163
1423
|
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1164
|
-
const nextSizes = adjustByDelta(null,
|
|
1424
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1165
1425
|
if (prevSizes !== nextSizes) {
|
|
1166
1426
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1167
1427
|
setSizes(nextSizes);
|
|
@@ -1171,21 +1431,34 @@ function PanelGroupWithForwardedRef({
|
|
|
1171
1431
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1172
1432
|
}
|
|
1173
1433
|
}, []);
|
|
1174
|
-
const resizePanel = useCallback((id, nextSize) => {
|
|
1434
|
+
const resizePanel = useCallback((id, nextSize, unitsFromParams) => {
|
|
1175
1435
|
const {
|
|
1436
|
+
id: groupId,
|
|
1176
1437
|
panels,
|
|
1177
|
-
sizes: prevSizes
|
|
1438
|
+
sizes: prevSizes,
|
|
1439
|
+
units
|
|
1178
1440
|
} = committedValuesRef.current;
|
|
1441
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
1442
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1443
|
+
nextSize = nextSize / groupSizePixels * 100;
|
|
1444
|
+
}
|
|
1179
1445
|
const panel = panels.get(id);
|
|
1180
1446
|
if (panel == null) {
|
|
1181
1447
|
return;
|
|
1182
1448
|
}
|
|
1183
|
-
|
|
1449
|
+
let {
|
|
1184
1450
|
collapsedSize,
|
|
1185
1451
|
collapsible,
|
|
1186
1452
|
maxSize,
|
|
1187
1453
|
minSize
|
|
1188
1454
|
} = panel.current;
|
|
1455
|
+
if (units === "pixels") {
|
|
1456
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1457
|
+
minSize = minSize / groupSizePixels * 100;
|
|
1458
|
+
if (maxSize != null) {
|
|
1459
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1189
1462
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1190
1463
|
const index = panelsArray.indexOf(panel);
|
|
1191
1464
|
if (index < 0) {
|
|
@@ -1196,7 +1469,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1196
1469
|
return;
|
|
1197
1470
|
}
|
|
1198
1471
|
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1199
|
-
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1472
|
+
nextSize = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSize));
|
|
1200
1473
|
}
|
|
1201
1474
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1202
1475
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1204,7 +1477,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1204
1477
|
}
|
|
1205
1478
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1206
1479
|
const delta = isLastPanel ? currentSize - nextSize : nextSize - currentSize;
|
|
1207
|
-
const nextSizes = adjustByDelta(null,
|
|
1480
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1208
1481
|
if (prevSizes !== nextSizes) {
|
|
1209
1482
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1210
1483
|
setSizes(nextSizes);
|
|
@@ -1219,6 +1492,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1219
1492
|
collapsePanel,
|
|
1220
1493
|
direction,
|
|
1221
1494
|
expandPanel,
|
|
1495
|
+
getPanelSize,
|
|
1222
1496
|
getPanelStyle,
|
|
1223
1497
|
groupId,
|
|
1224
1498
|
registerPanel,
|
|
@@ -1240,8 +1514,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1240
1514
|
setActiveHandleId(null);
|
|
1241
1515
|
initialDragStateRef.current = null;
|
|
1242
1516
|
},
|
|
1517
|
+
units,
|
|
1243
1518
|
unregisterPanel
|
|
1244
|
-
}), [activeHandleId, collapsePanel, direction, expandPanel, getPanelStyle, groupId, registerPanel, registerResizeHandle, resizePanel, unregisterPanel]);
|
|
1519
|
+
}), [activeHandleId, collapsePanel, direction, expandPanel, getPanelSize, getPanelStyle, groupId, registerPanel, registerResizeHandle, resizePanel, units, unregisterPanel]);
|
|
1245
1520
|
const style = {
|
|
1246
1521
|
display: "flex",
|
|
1247
1522
|
flexDirection: direction === "horizontal" ? "row" : "column",
|
|
@@ -1256,6 +1531,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1256
1531
|
"data-panel-group": "",
|
|
1257
1532
|
"data-panel-group-direction": direction,
|
|
1258
1533
|
"data-panel-group-id": groupId,
|
|
1534
|
+
"data-panel-group-units": units,
|
|
1259
1535
|
style: {
|
|
1260
1536
|
...style,
|
|
1261
1537
|
...styleFromProps
|
|
@@ -1268,10 +1544,6 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
|
|
|
1268
1544
|
...props,
|
|
1269
1545
|
forwardedRef: ref
|
|
1270
1546
|
}));
|
|
1271
|
-
|
|
1272
|
-
// Workaround for Parcel scope hoisting (which renames objects/functions).
|
|
1273
|
-
// Casting to :any is required to avoid corrupting the generated TypeScript types.
|
|
1274
|
-
// See github.com/parcel-bundler/parcel/issues/8724
|
|
1275
1547
|
PanelGroupWithForwardedRef.displayName = "PanelGroup";
|
|
1276
1548
|
PanelGroup.displayName = "forwardRef(PanelGroup)";
|
|
1277
1549
|
|
|
@@ -1407,10 +1679,6 @@ function PanelResizeHandle({
|
|
|
1407
1679
|
tabIndex: 0
|
|
1408
1680
|
});
|
|
1409
1681
|
}
|
|
1410
|
-
|
|
1411
|
-
// Workaround for Parcel scope hoisting (which renames objects/functions).
|
|
1412
|
-
// Casting to :any is required to avoid corrupting the generated TypeScript types.
|
|
1413
|
-
// See github.com/parcel-bundler/parcel/issues/8724
|
|
1414
1682
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
1415
1683
|
|
|
1416
|
-
export { Panel, PanelGroup, PanelResizeHandle };
|
|
1684
|
+
export { Panel, PanelGroup, PanelResizeHandle, getAvailableGroupSizePixels };
|