react-resizable-panels 0.0.54 → 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 +29 -0
- package/dist/declarations/src/Panel.d.ts +5 -4
- package/dist/declarations/src/PanelGroup.d.ts +7 -3
- package/dist/declarations/src/index.d.ts +3 -2
- package/dist/declarations/src/types.d.ts +2 -1
- package/dist/declarations/src/utils/group.d.ts +29 -0
- package/dist/react-resizable-panels.browser.cjs.js +385 -108
- package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +417 -108
- package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.browser.development.esm.js +417 -109
- package/dist/react-resizable-panels.browser.esm.js +385 -109
- package/dist/react-resizable-panels.cjs.js +385 -108
- 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 +417 -108
- package/dist/react-resizable-panels.development.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.esm.js +417 -109
- package/dist/react-resizable-panels.development.node.cjs.js +282 -76
- package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.development.node.esm.js +282 -77
- package/dist/react-resizable-panels.esm.js +385 -109
- package/dist/react-resizable-panels.esm.js.map +1 -0
- package/dist/react-resizable-panels.node.cjs.js +254 -76
- package/dist/react-resizable-panels.node.cjs.mjs +2 -1
- package/dist/react-resizable-panels.node.esm.js +254 -77
- package/package.json +1 -1
- package/src/Panel.ts +32 -32
- package/src/PanelContexts.ts +4 -2
- package/src/PanelGroup.ts +221 -111
- package/src/hooks/useWindowSplitterBehavior.ts +14 -11
- package/src/index.ts +11 -3
- package/src/types.ts +2 -1
- package/src/utils/group.ts +327 -28
|
@@ -45,8 +45,8 @@ function PanelWithForwardedRef({
|
|
|
45
45
|
defaultSize = null,
|
|
46
46
|
forwardedRef,
|
|
47
47
|
id: idFromProps = null,
|
|
48
|
-
maxSize =
|
|
49
|
-
minSize
|
|
48
|
+
maxSize = null,
|
|
49
|
+
minSize,
|
|
50
50
|
onCollapse = null,
|
|
51
51
|
onResize = null,
|
|
52
52
|
order = null,
|
|
@@ -61,11 +61,22 @@ function PanelWithForwardedRef({
|
|
|
61
61
|
const {
|
|
62
62
|
collapsePanel,
|
|
63
63
|
expandPanel,
|
|
64
|
+
getPanelSize,
|
|
64
65
|
getPanelStyle,
|
|
65
66
|
registerPanel,
|
|
66
67
|
resizePanel,
|
|
68
|
+
units,
|
|
67
69
|
unregisterPanel
|
|
68
70
|
} = context;
|
|
71
|
+
if (minSize == null) {
|
|
72
|
+
if (units === "percentages") {
|
|
73
|
+
// Mimics legacy default value for percentage based panel groups
|
|
74
|
+
minSize = 10;
|
|
75
|
+
} else {
|
|
76
|
+
// There is no meaningful minimum pixel default we can provide
|
|
77
|
+
minSize = 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
69
80
|
|
|
70
81
|
// Use a ref to guard against users passing inline props
|
|
71
82
|
const callbacksRef = useRef({
|
|
@@ -76,22 +87,6 @@ function PanelWithForwardedRef({
|
|
|
76
87
|
callbacksRef.current.onCollapse = onCollapse;
|
|
77
88
|
callbacksRef.current.onResize = onResize;
|
|
78
89
|
});
|
|
79
|
-
|
|
80
|
-
// Basic props validation
|
|
81
|
-
if (minSize < 0 || minSize > 100) {
|
|
82
|
-
throw Error(`Panel minSize must be between 0 and 100, but was ${minSize}`);
|
|
83
|
-
} else if (maxSize < 0 || maxSize > 100) {
|
|
84
|
-
throw Error(`Panel maxSize must be between 0 and 100, but was ${maxSize}`);
|
|
85
|
-
} else {
|
|
86
|
-
if (defaultSize !== null) {
|
|
87
|
-
if (defaultSize < 0 || defaultSize > 100) {
|
|
88
|
-
throw Error(`Panel defaultSize must be between 0 and 100, but was ${defaultSize}`);
|
|
89
|
-
} else if (minSize > defaultSize && !collapsible) {
|
|
90
|
-
console.error(`Panel minSize ${minSize} cannot be greater than defaultSize ${defaultSize}`);
|
|
91
|
-
defaultSize = minSize;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
90
|
const style = getPanelStyle(panelId, defaultSize);
|
|
96
91
|
const committedValuesRef = useRef({
|
|
97
92
|
size: parseSizeFromStyle(style)
|
|
@@ -131,11 +126,14 @@ function PanelWithForwardedRef({
|
|
|
131
126
|
getCollapsed() {
|
|
132
127
|
return committedValuesRef.current.size === 0;
|
|
133
128
|
},
|
|
134
|
-
|
|
135
|
-
return
|
|
129
|
+
getId() {
|
|
130
|
+
return panelId;
|
|
136
131
|
},
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
getSize(units) {
|
|
133
|
+
return getPanelSize(panelId, units);
|
|
134
|
+
},
|
|
135
|
+
resize: (percentage, units) => resizePanel(panelId, percentage, units)
|
|
136
|
+
}), [collapsePanel, expandPanel, getPanelSize, panelId, resizePanel]);
|
|
139
137
|
return createElement(Type, {
|
|
140
138
|
children,
|
|
141
139
|
className: classNameFromProps,
|
|
@@ -171,7 +169,13 @@ function parseSizeFromStyle(style) {
|
|
|
171
169
|
|
|
172
170
|
const PRECISION = 10;
|
|
173
171
|
|
|
174
|
-
function adjustByDelta(event,
|
|
172
|
+
function adjustByDelta(event, committedValues, idBefore, idAfter, deltaPixels, prevSizes, panelSizeBeforeCollapse, initialDragState) {
|
|
173
|
+
const {
|
|
174
|
+
id: groupId,
|
|
175
|
+
panels,
|
|
176
|
+
units
|
|
177
|
+
} = committedValues;
|
|
178
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
175
179
|
const {
|
|
176
180
|
sizes: initialSizes
|
|
177
181
|
} = initialDragState || {};
|
|
@@ -179,9 +183,6 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
179
183
|
// If we're resizing by mouse or touch, use the initial sizes as a base.
|
|
180
184
|
// This has the benefit of causing force-collapsed panels to spring back open if drag is reversed.
|
|
181
185
|
const baseSizes = initialSizes || prevSizes;
|
|
182
|
-
if (delta === 0) {
|
|
183
|
-
return baseSizes;
|
|
184
|
-
}
|
|
185
186
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
186
187
|
const nextSizes = baseSizes.concat();
|
|
187
188
|
let deltaApplied = 0;
|
|
@@ -196,11 +197,11 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
196
197
|
|
|
197
198
|
// Max-bounds check the panel being expanded first.
|
|
198
199
|
{
|
|
199
|
-
const pivotId =
|
|
200
|
+
const pivotId = deltaPixels < 0 ? idAfter : idBefore;
|
|
200
201
|
const index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
201
202
|
const panel = panelsArray[index];
|
|
202
203
|
const baseSize = baseSizes[index];
|
|
203
|
-
const nextSize = safeResizePanel(panel, Math.abs(
|
|
204
|
+
const nextSize = safeResizePanel(units, groupSizePixels, panel, baseSize, baseSize + Math.abs(deltaPixels), event);
|
|
204
205
|
if (baseSize === nextSize) {
|
|
205
206
|
// If there's no room for the pivot panel to grow, we can ignore this drag update.
|
|
206
207
|
return baseSizes;
|
|
@@ -208,29 +209,29 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
208
209
|
if (nextSize === 0 && baseSize > 0) {
|
|
209
210
|
panelSizeBeforeCollapse.set(pivotId, baseSize);
|
|
210
211
|
}
|
|
211
|
-
|
|
212
|
+
deltaPixels = deltaPixels < 0 ? baseSize - nextSize : nextSize - baseSize;
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
|
-
let pivotId =
|
|
215
|
+
let pivotId = deltaPixels < 0 ? idBefore : idAfter;
|
|
215
216
|
let index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
216
217
|
while (true) {
|
|
217
218
|
const panel = panelsArray[index];
|
|
218
219
|
const baseSize = baseSizes[index];
|
|
219
|
-
const deltaRemaining = Math.abs(
|
|
220
|
-
const nextSize = safeResizePanel(panel,
|
|
220
|
+
const deltaRemaining = Math.abs(deltaPixels) - Math.abs(deltaApplied);
|
|
221
|
+
const nextSize = safeResizePanel(units, groupSizePixels, panel, baseSize, baseSize - deltaRemaining, event);
|
|
221
222
|
if (baseSize !== nextSize) {
|
|
222
223
|
if (nextSize === 0 && baseSize > 0) {
|
|
223
224
|
panelSizeBeforeCollapse.set(panel.current.id, baseSize);
|
|
224
225
|
}
|
|
225
226
|
deltaApplied += baseSize - nextSize;
|
|
226
227
|
nextSizes[index] = nextSize;
|
|
227
|
-
if (deltaApplied.toPrecision(PRECISION).localeCompare(Math.abs(
|
|
228
|
+
if (deltaApplied.toPrecision(PRECISION).localeCompare(Math.abs(deltaPixels).toPrecision(PRECISION), undefined, {
|
|
228
229
|
numeric: true
|
|
229
230
|
}) >= 0) {
|
|
230
231
|
break;
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
|
-
if (
|
|
234
|
+
if (deltaPixels < 0) {
|
|
234
235
|
if (--index < 0) {
|
|
235
236
|
break;
|
|
236
237
|
}
|
|
@@ -248,7 +249,7 @@ function adjustByDelta(event, panels, idBefore, idAfter, delta, prevSizes, panel
|
|
|
248
249
|
}
|
|
249
250
|
|
|
250
251
|
// Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.
|
|
251
|
-
pivotId =
|
|
252
|
+
pivotId = deltaPixels < 0 ? idAfter : idBefore;
|
|
252
253
|
index = panelsArray.findIndex(panel => panel.current.id === pivotId);
|
|
253
254
|
nextSizes[index] = baseSizes[index] + deltaApplied;
|
|
254
255
|
return nextSizes;
|
|
@@ -287,6 +288,89 @@ function callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap) {
|
|
|
287
288
|
}
|
|
288
289
|
});
|
|
289
290
|
}
|
|
291
|
+
function calculateDefaultLayout({
|
|
292
|
+
groupId,
|
|
293
|
+
panels,
|
|
294
|
+
units
|
|
295
|
+
}) {
|
|
296
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
297
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
298
|
+
const sizes = Array(panelsArray.length);
|
|
299
|
+
let numPanelsWithSizes = 0;
|
|
300
|
+
let remainingSize = 100;
|
|
301
|
+
|
|
302
|
+
// Assigning default sizes requires a couple of passes:
|
|
303
|
+
// First, all panels with defaultSize should be set as-is
|
|
304
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
305
|
+
const panel = panelsArray[index];
|
|
306
|
+
const {
|
|
307
|
+
defaultSize
|
|
308
|
+
} = panel.current;
|
|
309
|
+
if (defaultSize != null) {
|
|
310
|
+
numPanelsWithSizes++;
|
|
311
|
+
sizes[index] = units === "pixels" ? defaultSize / groupSizePixels * 100 : defaultSize;
|
|
312
|
+
remainingSize -= sizes[index];
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Remaining total size should be distributed evenly between panels
|
|
317
|
+
// This may require two passes, depending on min/max constraints
|
|
318
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
319
|
+
const panel = panelsArray[index];
|
|
320
|
+
let {
|
|
321
|
+
defaultSize,
|
|
322
|
+
id,
|
|
323
|
+
maxSize,
|
|
324
|
+
minSize
|
|
325
|
+
} = panel.current;
|
|
326
|
+
if (defaultSize != null) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (units === "pixels") {
|
|
330
|
+
minSize = minSize / groupSizePixels * 100;
|
|
331
|
+
if (maxSize != null) {
|
|
332
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const remainingPanels = panelsArray.length - numPanelsWithSizes;
|
|
336
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, remainingSize / remainingPanels));
|
|
337
|
+
sizes[index] = size;
|
|
338
|
+
numPanelsWithSizes++;
|
|
339
|
+
remainingSize -= size;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// If there is additional, left over space, assign it to any panel(s) that permits it
|
|
343
|
+
// (It's not worth taking multiple additional passes to evenly distribute)
|
|
344
|
+
if (remainingSize !== 0) {
|
|
345
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
346
|
+
const panel = panelsArray[index];
|
|
347
|
+
let {
|
|
348
|
+
maxSize,
|
|
349
|
+
minSize
|
|
350
|
+
} = panel.current;
|
|
351
|
+
if (units === "pixels") {
|
|
352
|
+
minSize = minSize / groupSizePixels * 100;
|
|
353
|
+
if (maxSize != null) {
|
|
354
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, sizes[index] + remainingSize));
|
|
358
|
+
if (size !== sizes[index]) {
|
|
359
|
+
remainingSize -= size - sizes[index];
|
|
360
|
+
sizes[index] = size;
|
|
361
|
+
|
|
362
|
+
// Fuzzy comparison to account for imprecise floating point math
|
|
363
|
+
if (Math.abs(remainingSize).toFixed(3) === "0.000") {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Finally, if there is still left-over size, log an error
|
|
371
|
+
if (Math.abs(remainingSize).toFixed(3) !== "0.000") ;
|
|
372
|
+
return sizes;
|
|
373
|
+
}
|
|
290
374
|
function getBeforeAndAfterIds(id, panelsArray) {
|
|
291
375
|
if (panelsArray.length < 2) {
|
|
292
376
|
return [null, null];
|
|
@@ -300,6 +384,23 @@ function getBeforeAndAfterIds(id, panelsArray) {
|
|
|
300
384
|
const idAfter = isLastPanel ? id : panelsArray[index + 1].current.id;
|
|
301
385
|
return [idBefore, idAfter];
|
|
302
386
|
}
|
|
387
|
+
function getAvailableGroupSizePixels(groupId) {
|
|
388
|
+
const panelGroupElement = getPanelGroup(groupId);
|
|
389
|
+
if (panelGroupElement == null) {
|
|
390
|
+
return NaN;
|
|
391
|
+
}
|
|
392
|
+
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
393
|
+
const resizeHandles = getResizeHandlesForGroup(groupId);
|
|
394
|
+
if (direction === "horizontal") {
|
|
395
|
+
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
396
|
+
return accumulated + handle.offsetWidth;
|
|
397
|
+
}, 0);
|
|
398
|
+
} else {
|
|
399
|
+
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
400
|
+
return accumulated + handle.offsetHeight;
|
|
401
|
+
}, 0);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
303
404
|
|
|
304
405
|
// This method returns a number between 1 and 100 representing
|
|
305
406
|
// the % of the group's overall space this panel should occupy.
|
|
@@ -370,18 +471,24 @@ function panelsMapToSortedArray(panels) {
|
|
|
370
471
|
}
|
|
371
472
|
});
|
|
372
473
|
}
|
|
373
|
-
function safeResizePanel(
|
|
374
|
-
|
|
375
|
-
const {
|
|
474
|
+
function safeResizePanel(units, groupSizePixels, panel, prevSize, nextSize, event = null) {
|
|
475
|
+
let {
|
|
376
476
|
collapsedSize,
|
|
377
477
|
collapsible,
|
|
378
478
|
maxSize,
|
|
379
479
|
minSize
|
|
380
480
|
} = panel.current;
|
|
481
|
+
if (units === "pixels") {
|
|
482
|
+
collapsedSize = collapsedSize / groupSizePixels * 100;
|
|
483
|
+
if (maxSize != null) {
|
|
484
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
485
|
+
}
|
|
486
|
+
minSize = minSize / groupSizePixels * 100;
|
|
487
|
+
}
|
|
381
488
|
if (collapsible) {
|
|
382
489
|
if (prevSize > collapsedSize) {
|
|
383
490
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
384
|
-
if (
|
|
491
|
+
if (nextSize <= minSize / 2 + collapsedSize) {
|
|
385
492
|
return collapsedSize;
|
|
386
493
|
}
|
|
387
494
|
} else {
|
|
@@ -390,14 +497,97 @@ function safeResizePanel(panel, delta, prevSize, event) {
|
|
|
390
497
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
391
498
|
// but mouse events should wait until the panel has reached its min size
|
|
392
499
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
393
|
-
if (
|
|
500
|
+
if (nextSize < minSize) {
|
|
394
501
|
return collapsedSize;
|
|
395
502
|
}
|
|
396
503
|
}
|
|
397
504
|
}
|
|
398
505
|
}
|
|
399
|
-
|
|
400
|
-
|
|
506
|
+
return Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSize));
|
|
507
|
+
}
|
|
508
|
+
function validatePanelProps(units, panelData) {
|
|
509
|
+
const {
|
|
510
|
+
collapsible,
|
|
511
|
+
defaultSize,
|
|
512
|
+
maxSize,
|
|
513
|
+
minSize
|
|
514
|
+
} = panelData.current;
|
|
515
|
+
|
|
516
|
+
// Basic props validation
|
|
517
|
+
if (minSize < 0 || units === "percentages" && minSize > 100) {
|
|
518
|
+
panelData.current.minSize = 0;
|
|
519
|
+
}
|
|
520
|
+
if (maxSize != null) {
|
|
521
|
+
if (maxSize < 0 || units === "percentages" && maxSize > 100) {
|
|
522
|
+
panelData.current.maxSize = null;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (defaultSize !== null) {
|
|
526
|
+
if (defaultSize < 0 || units === "percentages" && defaultSize > 100) {
|
|
527
|
+
panelData.current.defaultSize = null;
|
|
528
|
+
} else if (defaultSize < minSize && !collapsible) {
|
|
529
|
+
panelData.current.defaultSize = minSize;
|
|
530
|
+
} else if (maxSize != null && defaultSize > maxSize) {
|
|
531
|
+
panelData.current.defaultSize = maxSize;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function validatePanelGroupLayout({
|
|
536
|
+
groupId,
|
|
537
|
+
panels,
|
|
538
|
+
nextSizes,
|
|
539
|
+
prevSizes,
|
|
540
|
+
units
|
|
541
|
+
}) {
|
|
542
|
+
// Clone because this method modifies
|
|
543
|
+
nextSizes = [...nextSizes];
|
|
544
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
545
|
+
const groupSizePixels = units === "pixels" ? getAvailableGroupSizePixels(groupId) : NaN;
|
|
546
|
+
let remainingSize = 0;
|
|
547
|
+
|
|
548
|
+
// First, check all of the proposed sizes against the min/max constraints
|
|
549
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
550
|
+
const panel = panelsArray[index];
|
|
551
|
+
const prevSize = prevSizes[index];
|
|
552
|
+
const nextSize = nextSizes[index];
|
|
553
|
+
const safeNextSize = safeResizePanel(units, groupSizePixels, panel, prevSize, nextSize);
|
|
554
|
+
if (nextSize != safeNextSize) {
|
|
555
|
+
remainingSize += nextSize - safeNextSize;
|
|
556
|
+
nextSizes[index] = safeNextSize;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// If there is additional, left over space, assign it to any panel(s) that permits it
|
|
561
|
+
// (It's not worth taking multiple additional passes to evenly distribute)
|
|
562
|
+
if (remainingSize.toFixed(3) !== "0.000") {
|
|
563
|
+
for (let index = 0; index < panelsArray.length; index++) {
|
|
564
|
+
const panel = panelsArray[index];
|
|
565
|
+
let {
|
|
566
|
+
maxSize,
|
|
567
|
+
minSize
|
|
568
|
+
} = panel.current;
|
|
569
|
+
if (units === "pixels") {
|
|
570
|
+
minSize = minSize / groupSizePixels * 100;
|
|
571
|
+
if (maxSize != null) {
|
|
572
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
const size = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSizes[index] + remainingSize));
|
|
576
|
+
if (size !== nextSizes[index]) {
|
|
577
|
+
remainingSize -= size - nextSizes[index];
|
|
578
|
+
nextSizes[index] = size;
|
|
579
|
+
|
|
580
|
+
// Fuzzy comparison to account for imprecise floating point math
|
|
581
|
+
if (Math.abs(remainingSize).toFixed(3) === "0.000") {
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// If we still have remainder, the requested layout wasn't valid and we should warn about it
|
|
589
|
+
if (remainingSize.toFixed(3) !== "0.000") ;
|
|
590
|
+
return nextSizes;
|
|
401
591
|
}
|
|
402
592
|
|
|
403
593
|
function assert(expectedCondition, message = "Assertion failed!") {
|
|
@@ -423,6 +613,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
423
613
|
panels
|
|
424
614
|
} = committedValuesRef.current;
|
|
425
615
|
const groupElement = getPanelGroup(groupId);
|
|
616
|
+
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
426
617
|
const {
|
|
427
618
|
height,
|
|
428
619
|
width
|
|
@@ -435,23 +626,28 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
435
626
|
if (idBefore == null || idAfter == null) {
|
|
436
627
|
return () => {};
|
|
437
628
|
}
|
|
438
|
-
let
|
|
439
|
-
let
|
|
629
|
+
let currentMinSize = 0;
|
|
630
|
+
let currentMaxSize = 100;
|
|
440
631
|
let totalMinSize = 0;
|
|
441
632
|
let totalMaxSize = 0;
|
|
442
633
|
|
|
443
634
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
444
635
|
panelsArray.forEach(panelData => {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
636
|
+
const {
|
|
637
|
+
id,
|
|
638
|
+
maxSize,
|
|
639
|
+
minSize
|
|
640
|
+
} = panelData.current;
|
|
641
|
+
if (id === idBefore) {
|
|
642
|
+
currentMinSize = minSize;
|
|
643
|
+
currentMaxSize = maxSize != null ? maxSize : 100;
|
|
448
644
|
} else {
|
|
449
|
-
totalMinSize +=
|
|
450
|
-
totalMaxSize +=
|
|
645
|
+
totalMinSize += minSize;
|
|
646
|
+
totalMaxSize += maxSize != null ? maxSize : 100;
|
|
451
647
|
}
|
|
452
648
|
});
|
|
453
|
-
const ariaValueMax = Math.min(
|
|
454
|
-
const ariaValueMin = Math.max(
|
|
649
|
+
const ariaValueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
650
|
+
const ariaValueMin = Math.max(currentMinSize, (panelsArray.length - 1) * 100 - totalMaxSize);
|
|
455
651
|
const flexGrow = getFlexGrow(panels, idBefore, sizes);
|
|
456
652
|
handle.setAttribute("aria-valuemax", "" + Math.round(ariaValueMax));
|
|
457
653
|
handle.setAttribute("aria-valuemin", "" + Math.round(ariaValueMin));
|
|
@@ -475,7 +671,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
475
671
|
} else {
|
|
476
672
|
delta = -(direction === "horizontal" ? width : height);
|
|
477
673
|
}
|
|
478
|
-
const nextSizes = adjustByDelta(event,
|
|
674
|
+
const nextSizes = adjustByDelta(event, committedValuesRef.current, idBefore, idAfter, delta, sizes, panelSizeBeforeCollapse.current, null);
|
|
479
675
|
if (sizes !== nextSizes) {
|
|
480
676
|
setSizes(nextSizes);
|
|
481
677
|
}
|
|
@@ -790,9 +986,6 @@ const defaultStorage = {
|
|
|
790
986
|
// * dragHandleRect, sizes:
|
|
791
987
|
// When resizing is done via mouse/touch event– some initial state is stored
|
|
792
988
|
// so that any panels that contract will also expand if drag direction is reversed.
|
|
793
|
-
// TODO
|
|
794
|
-
// Within an active drag, remember original positions to refine more easily on expand.
|
|
795
|
-
// Look at what the Chrome devtools Sources does.
|
|
796
989
|
function PanelGroupWithForwardedRef({
|
|
797
990
|
autoSaveId,
|
|
798
991
|
children = null,
|
|
@@ -804,7 +997,8 @@ function PanelGroupWithForwardedRef({
|
|
|
804
997
|
onLayout,
|
|
805
998
|
storage = defaultStorage,
|
|
806
999
|
style: styleFromProps = {},
|
|
807
|
-
tagName: Type = "div"
|
|
1000
|
+
tagName: Type = "div",
|
|
1001
|
+
units = "percentages"
|
|
808
1002
|
}) {
|
|
809
1003
|
const groupId = useUniqueId(idFromProps);
|
|
810
1004
|
const [activeHandleId, setActiveHandleId] = useState(null);
|
|
@@ -817,6 +1011,7 @@ function PanelGroupWithForwardedRef({
|
|
|
817
1011
|
useRef({
|
|
818
1012
|
didLogDefaultSizeWarning: false,
|
|
819
1013
|
didLogIdAndOrderWarning: false,
|
|
1014
|
+
didLogInvalidLayoutWarning: false,
|
|
820
1015
|
prevPanelIds: []
|
|
821
1016
|
});
|
|
822
1017
|
|
|
@@ -839,32 +1034,58 @@ function PanelGroupWithForwardedRef({
|
|
|
839
1034
|
// Store committed values to avoid unnecessarily re-running memoization/effects functions.
|
|
840
1035
|
const committedValuesRef = useRef({
|
|
841
1036
|
direction,
|
|
1037
|
+
id: groupId,
|
|
842
1038
|
panels,
|
|
843
|
-
sizes
|
|
1039
|
+
sizes,
|
|
1040
|
+
units
|
|
844
1041
|
});
|
|
845
1042
|
useImperativeHandle(forwardedRef, () => ({
|
|
846
|
-
|
|
1043
|
+
getId: () => groupId,
|
|
1044
|
+
getLayout: unitsFromParams => {
|
|
847
1045
|
const {
|
|
848
|
-
sizes
|
|
1046
|
+
sizes,
|
|
1047
|
+
units: unitsFromProps
|
|
849
1048
|
} = committedValuesRef.current;
|
|
850
|
-
|
|
1049
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
1050
|
+
if (units === "pixels") {
|
|
1051
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1052
|
+
return sizes.map(size => size / 100 * groupSizePixels);
|
|
1053
|
+
} else {
|
|
1054
|
+
return sizes;
|
|
1055
|
+
}
|
|
851
1056
|
},
|
|
852
|
-
setLayout: sizes => {
|
|
853
|
-
const total = sizes.reduce((accumulated, current) => accumulated + current, 0);
|
|
854
|
-
assert(total === 100, "Panel sizes must add up to 100%");
|
|
1057
|
+
setLayout: (sizes, unitsFromParams) => {
|
|
855
1058
|
const {
|
|
856
|
-
|
|
1059
|
+
id: groupId,
|
|
1060
|
+
panels,
|
|
1061
|
+
sizes: prevSizes,
|
|
1062
|
+
units
|
|
857
1063
|
} = committedValuesRef.current;
|
|
1064
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
1065
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1066
|
+
sizes = sizes.map(size => size / groupSizePixels * 100);
|
|
1067
|
+
}
|
|
858
1068
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
859
1069
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
860
|
-
|
|
861
|
-
|
|
1070
|
+
const nextSizes = validatePanelGroupLayout({
|
|
1071
|
+
groupId,
|
|
1072
|
+
panels,
|
|
1073
|
+
nextSizes: sizes,
|
|
1074
|
+
prevSizes,
|
|
1075
|
+
units
|
|
1076
|
+
});
|
|
1077
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
1078
|
+
setSizes(nextSizes);
|
|
1079
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1080
|
+
}
|
|
862
1081
|
}
|
|
863
|
-
}), []);
|
|
1082
|
+
}), [groupId]);
|
|
864
1083
|
useIsomorphicLayoutEffect(() => {
|
|
865
1084
|
committedValuesRef.current.direction = direction;
|
|
1085
|
+
committedValuesRef.current.id = groupId;
|
|
866
1086
|
committedValuesRef.current.panels = panels;
|
|
867
1087
|
committedValuesRef.current.sizes = sizes;
|
|
1088
|
+
committedValuesRef.current.units = units;
|
|
868
1089
|
});
|
|
869
1090
|
useWindowSplitterPanelGroupBehavior({
|
|
870
1091
|
committedValuesRef,
|
|
@@ -906,7 +1127,11 @@ function PanelGroupWithForwardedRef({
|
|
|
906
1127
|
// Compute the initial sizes based on default weights.
|
|
907
1128
|
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
908
1129
|
useIsomorphicLayoutEffect(() => {
|
|
909
|
-
const
|
|
1130
|
+
const {
|
|
1131
|
+
id: groupId,
|
|
1132
|
+
sizes,
|
|
1133
|
+
units
|
|
1134
|
+
} = committedValuesRef.current;
|
|
910
1135
|
if (sizes.length === panels.size) {
|
|
911
1136
|
// Only compute (or restore) default sizes once per panel configuration.
|
|
912
1137
|
return;
|
|
@@ -920,39 +1145,23 @@ function PanelGroupWithForwardedRef({
|
|
|
920
1145
|
defaultSizes = loadPanelLayout(autoSaveId, panelsArray, storage);
|
|
921
1146
|
}
|
|
922
1147
|
if (defaultSizes != null) {
|
|
923
|
-
|
|
1148
|
+
// Validate saved sizes in case something has changed since last render
|
|
1149
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
1150
|
+
const validatedSizes = validatePanelGroupLayout({
|
|
1151
|
+
groupId,
|
|
1152
|
+
panels,
|
|
1153
|
+
nextSizes: defaultSizes,
|
|
1154
|
+
prevSizes: defaultSizes,
|
|
1155
|
+
units
|
|
1156
|
+
});
|
|
1157
|
+
setSizes(validatedSizes);
|
|
924
1158
|
} else {
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
// TODO
|
|
931
|
-
// Implicit default size calculations below do not account for inferred min/max size values.
|
|
932
|
-
// 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.
|
|
933
|
-
// For now, these logic edge cases are left to the user to handle via props.
|
|
934
|
-
|
|
935
|
-
panelsArray.forEach(panel => {
|
|
936
|
-
totalMinSize += panel.current.minSize;
|
|
937
|
-
if (panel.current.defaultSize === null) {
|
|
938
|
-
panelsWithNullDefaultSize++;
|
|
939
|
-
} else {
|
|
940
|
-
totalDefaultSize += panel.current.defaultSize;
|
|
941
|
-
}
|
|
1159
|
+
const sizes = calculateDefaultLayout({
|
|
1160
|
+
groupId,
|
|
1161
|
+
panels,
|
|
1162
|
+
units
|
|
942
1163
|
});
|
|
943
|
-
|
|
944
|
-
throw new Error(`Default panel sizes cannot exceed 100%`);
|
|
945
|
-
} else if (panelsArray.length > 1 && panelsWithNullDefaultSize === 0 && totalDefaultSize !== 100) {
|
|
946
|
-
throw new Error(`Invalid default sizes specified for panels`);
|
|
947
|
-
} else if (totalMinSize > 100) {
|
|
948
|
-
throw new Error(`Minimum panel sizes cannot exceed 100%`);
|
|
949
|
-
}
|
|
950
|
-
setSizes(panelsArray.map(panel => {
|
|
951
|
-
if (panel.current.defaultSize === null) {
|
|
952
|
-
return (100 - totalDefaultSize) / panelsWithNullDefaultSize;
|
|
953
|
-
}
|
|
954
|
-
return panel.current.defaultSize;
|
|
955
|
-
}));
|
|
1164
|
+
setSizes(sizes);
|
|
956
1165
|
}
|
|
957
1166
|
}, [autoSaveId, panels, storage]);
|
|
958
1167
|
useEffect(() => {
|
|
@@ -970,6 +1179,48 @@ function PanelGroupWithForwardedRef({
|
|
|
970
1179
|
debounceMap[autoSaveId](autoSaveId, panelsArray, sizes, storage);
|
|
971
1180
|
}
|
|
972
1181
|
}, [autoSaveId, panels, sizes, storage]);
|
|
1182
|
+
useIsomorphicLayoutEffect(() => {
|
|
1183
|
+
// Pixel panel constraints need to be reassessed after a group resize
|
|
1184
|
+
// We can avoid the ResizeObserver overhead for relative layouts
|
|
1185
|
+
if (units === "pixels") {
|
|
1186
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1187
|
+
const {
|
|
1188
|
+
panels,
|
|
1189
|
+
sizes: prevSizes
|
|
1190
|
+
} = committedValuesRef.current;
|
|
1191
|
+
const nextSizes = validatePanelGroupLayout({
|
|
1192
|
+
groupId,
|
|
1193
|
+
panels,
|
|
1194
|
+
nextSizes: prevSizes,
|
|
1195
|
+
prevSizes,
|
|
1196
|
+
units
|
|
1197
|
+
});
|
|
1198
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
1199
|
+
setSizes(nextSizes);
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
resizeObserver.observe(getPanelGroup(groupId));
|
|
1203
|
+
return () => {
|
|
1204
|
+
resizeObserver.disconnect();
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
}, [groupId, units]);
|
|
1208
|
+
const getPanelSize = useCallback((id, unitsFromParams) => {
|
|
1209
|
+
const {
|
|
1210
|
+
panels,
|
|
1211
|
+
units: unitsFromProps
|
|
1212
|
+
} = committedValuesRef.current;
|
|
1213
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
1214
|
+
const index = panelsArray.findIndex(panel => panel.current.id === id);
|
|
1215
|
+
const size = sizes[index];
|
|
1216
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
1217
|
+
if (units === "pixels") {
|
|
1218
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1219
|
+
return size / 100 * groupSizePixels;
|
|
1220
|
+
} else {
|
|
1221
|
+
return size;
|
|
1222
|
+
}
|
|
1223
|
+
}, [groupId, sizes]);
|
|
973
1224
|
const getPanelStyle = useCallback((id, defaultSize) => {
|
|
974
1225
|
const {
|
|
975
1226
|
panels
|
|
@@ -1000,6 +1251,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1000
1251
|
};
|
|
1001
1252
|
}, [activeHandleId, disablePointerEventsDuringResize, sizes]);
|
|
1002
1253
|
const registerPanel = useCallback((id, panelRef) => {
|
|
1254
|
+
const {
|
|
1255
|
+
units
|
|
1256
|
+
} = committedValuesRef.current;
|
|
1257
|
+
validatePanelProps(units, panelRef);
|
|
1003
1258
|
setPanels(prevPanels => {
|
|
1004
1259
|
if (prevPanels.has(id)) {
|
|
1005
1260
|
return prevPanels;
|
|
@@ -1036,7 +1291,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1036
1291
|
}
|
|
1037
1292
|
const size = isHorizontal ? rect.width : rect.height;
|
|
1038
1293
|
const delta = movement / size * 100;
|
|
1039
|
-
|
|
1294
|
+
|
|
1295
|
+
// If a validateLayout method has been provided
|
|
1296
|
+
// it's important to use it before updating the mouse cursor
|
|
1297
|
+
const nextSizes = adjustByDelta(event, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, initialDragStateRef.current);
|
|
1040
1298
|
const sizesChanged = !areEqual(prevSizes, nextSizes);
|
|
1041
1299
|
|
|
1042
1300
|
// Don't update cursor for resizes triggered by keyboard interactions.
|
|
@@ -1063,6 +1321,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1063
1321
|
}
|
|
1064
1322
|
if (sizesChanged) {
|
|
1065
1323
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1324
|
+
|
|
1325
|
+
// It's okay to bypass in this case because we already validated above
|
|
1066
1326
|
setSizes(nextSizes);
|
|
1067
1327
|
|
|
1068
1328
|
// If resize change handlers have been declared, this is the time to call them.
|
|
@@ -1116,7 +1376,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1116
1376
|
}
|
|
1117
1377
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1118
1378
|
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
1119
|
-
const nextSizes = adjustByDelta(null,
|
|
1379
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1120
1380
|
if (prevSizes !== nextSizes) {
|
|
1121
1381
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1122
1382
|
setSizes(nextSizes);
|
|
@@ -1159,7 +1419,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1159
1419
|
}
|
|
1160
1420
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1161
1421
|
const delta = isLastPanel ? collapsedSize - sizeBeforeCollapse : sizeBeforeCollapse;
|
|
1162
|
-
const nextSizes = adjustByDelta(null,
|
|
1422
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1163
1423
|
if (prevSizes !== nextSizes) {
|
|
1164
1424
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1165
1425
|
setSizes(nextSizes);
|
|
@@ -1169,21 +1429,34 @@ function PanelGroupWithForwardedRef({
|
|
|
1169
1429
|
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
1170
1430
|
}
|
|
1171
1431
|
}, []);
|
|
1172
|
-
const resizePanel = useCallback((id, nextSize) => {
|
|
1432
|
+
const resizePanel = useCallback((id, nextSize, unitsFromParams) => {
|
|
1173
1433
|
const {
|
|
1434
|
+
id: groupId,
|
|
1174
1435
|
panels,
|
|
1175
|
-
sizes: prevSizes
|
|
1436
|
+
sizes: prevSizes,
|
|
1437
|
+
units
|
|
1176
1438
|
} = committedValuesRef.current;
|
|
1439
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
1440
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1441
|
+
nextSize = nextSize / groupSizePixels * 100;
|
|
1442
|
+
}
|
|
1177
1443
|
const panel = panels.get(id);
|
|
1178
1444
|
if (panel == null) {
|
|
1179
1445
|
return;
|
|
1180
1446
|
}
|
|
1181
|
-
|
|
1447
|
+
let {
|
|
1182
1448
|
collapsedSize,
|
|
1183
1449
|
collapsible,
|
|
1184
1450
|
maxSize,
|
|
1185
1451
|
minSize
|
|
1186
1452
|
} = panel.current;
|
|
1453
|
+
if (units === "pixels") {
|
|
1454
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
1455
|
+
minSize = minSize / groupSizePixels * 100;
|
|
1456
|
+
if (maxSize != null) {
|
|
1457
|
+
maxSize = maxSize / groupSizePixels * 100;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1187
1460
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
1188
1461
|
const index = panelsArray.indexOf(panel);
|
|
1189
1462
|
if (index < 0) {
|
|
@@ -1194,7 +1467,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1194
1467
|
return;
|
|
1195
1468
|
}
|
|
1196
1469
|
if (collapsible && nextSize === collapsedSize) ; else {
|
|
1197
|
-
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
1470
|
+
nextSize = Math.min(maxSize != null ? maxSize : 100, Math.max(minSize, nextSize));
|
|
1198
1471
|
}
|
|
1199
1472
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
1200
1473
|
if (idBefore == null || idAfter == null) {
|
|
@@ -1202,7 +1475,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1202
1475
|
}
|
|
1203
1476
|
const isLastPanel = index === panelsArray.length - 1;
|
|
1204
1477
|
const delta = isLastPanel ? currentSize - nextSize : nextSize - currentSize;
|
|
1205
|
-
const nextSizes = adjustByDelta(null,
|
|
1478
|
+
const nextSizes = adjustByDelta(null, committedValuesRef.current, idBefore, idAfter, delta, prevSizes, panelSizeBeforeCollapse.current, null);
|
|
1206
1479
|
if (prevSizes !== nextSizes) {
|
|
1207
1480
|
const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
|
|
1208
1481
|
setSizes(nextSizes);
|
|
@@ -1217,6 +1490,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1217
1490
|
collapsePanel,
|
|
1218
1491
|
direction,
|
|
1219
1492
|
expandPanel,
|
|
1493
|
+
getPanelSize,
|
|
1220
1494
|
getPanelStyle,
|
|
1221
1495
|
groupId,
|
|
1222
1496
|
registerPanel,
|
|
@@ -1238,8 +1512,9 @@ function PanelGroupWithForwardedRef({
|
|
|
1238
1512
|
setActiveHandleId(null);
|
|
1239
1513
|
initialDragStateRef.current = null;
|
|
1240
1514
|
},
|
|
1515
|
+
units,
|
|
1241
1516
|
unregisterPanel
|
|
1242
|
-
}), [activeHandleId, collapsePanel, direction, expandPanel, getPanelStyle, groupId, registerPanel, registerResizeHandle, resizePanel, unregisterPanel]);
|
|
1517
|
+
}), [activeHandleId, collapsePanel, direction, expandPanel, getPanelSize, getPanelStyle, groupId, registerPanel, registerResizeHandle, resizePanel, units, unregisterPanel]);
|
|
1243
1518
|
const style = {
|
|
1244
1519
|
display: "flex",
|
|
1245
1520
|
flexDirection: direction === "horizontal" ? "row" : "column",
|
|
@@ -1254,6 +1529,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1254
1529
|
"data-panel-group": "",
|
|
1255
1530
|
"data-panel-group-direction": direction,
|
|
1256
1531
|
"data-panel-group-id": groupId,
|
|
1532
|
+
"data-panel-group-units": units,
|
|
1257
1533
|
style: {
|
|
1258
1534
|
...style,
|
|
1259
1535
|
...styleFromProps
|
|
@@ -1403,4 +1679,4 @@ function PanelResizeHandle({
|
|
|
1403
1679
|
}
|
|
1404
1680
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
1405
1681
|
|
|
1406
|
-
export { Panel, PanelGroup, PanelResizeHandle };
|
|
1682
|
+
export { Panel, PanelGroup, PanelResizeHandle, getAvailableGroupSizePixels };
|