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
package/src/PanelGroup.ts
CHANGED
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
PanelGroupOnLayout,
|
|
26
26
|
PanelGroupStorage,
|
|
27
27
|
ResizeEvent,
|
|
28
|
+
Units,
|
|
28
29
|
} from "./types";
|
|
29
30
|
import { areEqual } from "./utils/arrays";
|
|
30
|
-
import { assert } from "./utils/assert";
|
|
31
31
|
import {
|
|
32
32
|
getDragOffset,
|
|
33
33
|
getMovement,
|
|
@@ -38,13 +38,17 @@ import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
|
|
|
38
38
|
import debounce from "./utils/debounce";
|
|
39
39
|
import {
|
|
40
40
|
adjustByDelta,
|
|
41
|
+
calculateDefaultLayout,
|
|
41
42
|
callPanelCallbacks,
|
|
43
|
+
getAvailableGroupSizePixels,
|
|
42
44
|
getBeforeAndAfterIds,
|
|
43
45
|
getFlexGrow,
|
|
44
46
|
getPanelGroup,
|
|
45
47
|
getResizeHandle,
|
|
46
48
|
getResizeHandlePanelIds,
|
|
47
49
|
panelsMapToSortedArray,
|
|
50
|
+
validatePanelGroupLayout,
|
|
51
|
+
validatePanelProps,
|
|
48
52
|
} from "./utils/group";
|
|
49
53
|
import { loadPanelLayout, savePanelGroupLayout } from "./utils/serialization";
|
|
50
54
|
|
|
@@ -95,8 +99,10 @@ const defaultStorage: PanelGroupStorage = {
|
|
|
95
99
|
|
|
96
100
|
export type CommittedValues = {
|
|
97
101
|
direction: Direction;
|
|
102
|
+
id: string;
|
|
98
103
|
panels: Map<string, PanelData>;
|
|
99
104
|
sizes: number[];
|
|
105
|
+
units: Units;
|
|
100
106
|
};
|
|
101
107
|
|
|
102
108
|
export type PanelDataMap = Map<string, PanelData>;
|
|
@@ -114,10 +120,6 @@ export type InitialDragState = {
|
|
|
114
120
|
sizes: number[];
|
|
115
121
|
};
|
|
116
122
|
|
|
117
|
-
// TODO
|
|
118
|
-
// Within an active drag, remember original positions to refine more easily on expand.
|
|
119
|
-
// Look at what the Chrome devtools Sources does.
|
|
120
|
-
|
|
121
123
|
export type PanelGroupProps = {
|
|
122
124
|
autoSaveId?: string;
|
|
123
125
|
children?: ReactNode;
|
|
@@ -129,11 +131,13 @@ export type PanelGroupProps = {
|
|
|
129
131
|
storage?: PanelGroupStorage;
|
|
130
132
|
style?: CSSProperties;
|
|
131
133
|
tagName?: ElementType;
|
|
134
|
+
units?: Units;
|
|
132
135
|
};
|
|
133
136
|
|
|
134
137
|
export type ImperativePanelGroupHandle = {
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
getId: () => string;
|
|
139
|
+
getLayout: (units?: Units) => number[];
|
|
140
|
+
setLayout: (panelSizes: number[], units?: Units) => void;
|
|
137
141
|
};
|
|
138
142
|
|
|
139
143
|
function PanelGroupWithForwardedRef({
|
|
@@ -148,6 +152,7 @@ function PanelGroupWithForwardedRef({
|
|
|
148
152
|
storage = defaultStorage,
|
|
149
153
|
style: styleFromProps = {},
|
|
150
154
|
tagName: Type = "div",
|
|
155
|
+
units = "percentages",
|
|
151
156
|
}: PanelGroupProps & {
|
|
152
157
|
forwardedRef: ForwardedRef<ImperativePanelGroupHandle>;
|
|
153
158
|
}) {
|
|
@@ -164,10 +169,12 @@ function PanelGroupWithForwardedRef({
|
|
|
164
169
|
const devWarningsRef = useRef<{
|
|
165
170
|
didLogDefaultSizeWarning: boolean;
|
|
166
171
|
didLogIdAndOrderWarning: boolean;
|
|
172
|
+
didLogInvalidLayoutWarning: boolean;
|
|
167
173
|
prevPanelIds: string[];
|
|
168
174
|
}>({
|
|
169
175
|
didLogDefaultSizeWarning: false,
|
|
170
176
|
didLogIdAndOrderWarning: false,
|
|
177
|
+
didLogInvalidLayoutWarning: false,
|
|
171
178
|
prevPanelIds: [],
|
|
172
179
|
});
|
|
173
180
|
|
|
@@ -192,42 +199,71 @@ function PanelGroupWithForwardedRef({
|
|
|
192
199
|
// Store committed values to avoid unnecessarily re-running memoization/effects functions.
|
|
193
200
|
const committedValuesRef = useRef<CommittedValues>({
|
|
194
201
|
direction,
|
|
202
|
+
id: groupId,
|
|
195
203
|
panels,
|
|
196
204
|
sizes,
|
|
205
|
+
units,
|
|
197
206
|
});
|
|
198
207
|
|
|
199
208
|
useImperativeHandle(
|
|
200
209
|
forwardedRef,
|
|
201
210
|
() => ({
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
211
|
+
getId: () => groupId,
|
|
212
|
+
getLayout: (unitsFromParams?: Units) => {
|
|
213
|
+
const { sizes, units: unitsFromProps } = committedValuesRef.current;
|
|
214
|
+
|
|
215
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
216
|
+
if (units === "pixels") {
|
|
217
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
218
|
+
return sizes.map((size) => (size / 100) * groupSizePixels);
|
|
219
|
+
} else {
|
|
220
|
+
return sizes;
|
|
221
|
+
}
|
|
205
222
|
},
|
|
206
|
-
setLayout: (sizes: number[]) => {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
223
|
+
setLayout: (sizes: number[], unitsFromParams?: Units) => {
|
|
224
|
+
const {
|
|
225
|
+
id: groupId,
|
|
226
|
+
panels,
|
|
227
|
+
sizes: prevSizes,
|
|
228
|
+
units,
|
|
229
|
+
} = committedValuesRef.current;
|
|
211
230
|
|
|
212
|
-
|
|
231
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
232
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
233
|
+
sizes = sizes.map((size) => (size / groupSizePixels) * 100);
|
|
234
|
+
}
|
|
213
235
|
|
|
214
|
-
const { panels } = committedValuesRef.current;
|
|
215
236
|
const panelIdToLastNotifiedSizeMap =
|
|
216
237
|
panelIdToLastNotifiedSizeMapRef.current;
|
|
217
238
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
218
239
|
|
|
219
|
-
|
|
240
|
+
const nextSizes = validatePanelGroupLayout({
|
|
241
|
+
groupId,
|
|
242
|
+
panels,
|
|
243
|
+
nextSizes: sizes,
|
|
244
|
+
prevSizes,
|
|
245
|
+
units,
|
|
246
|
+
});
|
|
247
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
248
|
+
setSizes(nextSizes);
|
|
220
249
|
|
|
221
|
-
|
|
250
|
+
callPanelCallbacks(
|
|
251
|
+
panelsArray,
|
|
252
|
+
nextSizes,
|
|
253
|
+
panelIdToLastNotifiedSizeMap
|
|
254
|
+
);
|
|
255
|
+
}
|
|
222
256
|
},
|
|
223
257
|
}),
|
|
224
|
-
[]
|
|
258
|
+
[groupId]
|
|
225
259
|
);
|
|
226
260
|
|
|
227
261
|
useIsomorphicLayoutEffect(() => {
|
|
228
262
|
committedValuesRef.current.direction = direction;
|
|
263
|
+
committedValuesRef.current.id = groupId;
|
|
229
264
|
committedValuesRef.current.panels = panels;
|
|
230
265
|
committedValuesRef.current.sizes = sizes;
|
|
266
|
+
committedValuesRef.current.units = units;
|
|
231
267
|
});
|
|
232
268
|
|
|
233
269
|
useWindowSplitterPanelGroupBehavior({
|
|
@@ -267,7 +303,7 @@ function PanelGroupWithForwardedRef({
|
|
|
267
303
|
// Compute the initial sizes based on default weights.
|
|
268
304
|
// This assumes that panels register during initial mount (no conditional rendering)!
|
|
269
305
|
useIsomorphicLayoutEffect(() => {
|
|
270
|
-
const sizes = committedValuesRef.current
|
|
306
|
+
const { id: groupId, sizes, units } = committedValuesRef.current;
|
|
271
307
|
if (sizes.length === panels.size) {
|
|
272
308
|
// Only compute (or restore) default sizes once per panel configuration.
|
|
273
309
|
return;
|
|
@@ -282,50 +318,25 @@ function PanelGroupWithForwardedRef({
|
|
|
282
318
|
}
|
|
283
319
|
|
|
284
320
|
if (defaultSizes != null) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// TODO
|
|
294
|
-
// Implicit default size calculations below do not account for inferred min/max size values.
|
|
295
|
-
// 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.
|
|
296
|
-
// For now, these logic edge cases are left to the user to handle via props.
|
|
297
|
-
|
|
298
|
-
panelsArray.forEach((panel) => {
|
|
299
|
-
totalMinSize += panel.current.minSize;
|
|
300
|
-
|
|
301
|
-
if (panel.current.defaultSize === null) {
|
|
302
|
-
panelsWithNullDefaultSize++;
|
|
303
|
-
} else {
|
|
304
|
-
totalDefaultSize += panel.current.defaultSize;
|
|
305
|
-
}
|
|
321
|
+
// Validate saved sizes in case something has changed since last render
|
|
322
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
323
|
+
const validatedSizes = validatePanelGroupLayout({
|
|
324
|
+
groupId,
|
|
325
|
+
panels,
|
|
326
|
+
nextSizes: defaultSizes,
|
|
327
|
+
prevSizes: defaultSizes,
|
|
328
|
+
units,
|
|
306
329
|
});
|
|
307
330
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
)
|
|
315
|
-
throw new Error(`Invalid default sizes specified for panels`);
|
|
316
|
-
} else if (totalMinSize > 100) {
|
|
317
|
-
throw new Error(`Minimum panel sizes cannot exceed 100%`);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
setSizes(
|
|
321
|
-
panelsArray.map((panel) => {
|
|
322
|
-
if (panel.current.defaultSize === null) {
|
|
323
|
-
return (100 - totalDefaultSize) / panelsWithNullDefaultSize;
|
|
324
|
-
}
|
|
331
|
+
setSizes(validatedSizes);
|
|
332
|
+
} else {
|
|
333
|
+
const sizes = calculateDefaultLayout({
|
|
334
|
+
groupId,
|
|
335
|
+
panels,
|
|
336
|
+
units,
|
|
337
|
+
});
|
|
325
338
|
|
|
326
|
-
|
|
327
|
-
})
|
|
328
|
-
);
|
|
339
|
+
setSizes(sizes);
|
|
329
340
|
}
|
|
330
341
|
}, [autoSaveId, panels, storage]);
|
|
331
342
|
|
|
@@ -374,6 +385,53 @@ function PanelGroupWithForwardedRef({
|
|
|
374
385
|
}
|
|
375
386
|
}, [autoSaveId, panels, sizes, storage]);
|
|
376
387
|
|
|
388
|
+
useIsomorphicLayoutEffect(() => {
|
|
389
|
+
// Pixel panel constraints need to be reassessed after a group resize
|
|
390
|
+
// We can avoid the ResizeObserver overhead for relative layouts
|
|
391
|
+
if (units === "pixels") {
|
|
392
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
393
|
+
const { panels, sizes: prevSizes } = committedValuesRef.current;
|
|
394
|
+
|
|
395
|
+
const nextSizes = validatePanelGroupLayout({
|
|
396
|
+
groupId,
|
|
397
|
+
panels,
|
|
398
|
+
nextSizes: prevSizes,
|
|
399
|
+
prevSizes,
|
|
400
|
+
units,
|
|
401
|
+
});
|
|
402
|
+
if (!areEqual(prevSizes, nextSizes)) {
|
|
403
|
+
setSizes(nextSizes);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
resizeObserver.observe(getPanelGroup(groupId)!);
|
|
408
|
+
|
|
409
|
+
return () => {
|
|
410
|
+
resizeObserver.disconnect();
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
}, [groupId, units]);
|
|
414
|
+
|
|
415
|
+
const getPanelSize = useCallback(
|
|
416
|
+
(id: string, unitsFromParams?: Units) => {
|
|
417
|
+
const { panels, units: unitsFromProps } = committedValuesRef.current;
|
|
418
|
+
|
|
419
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
420
|
+
|
|
421
|
+
const index = panelsArray.findIndex((panel) => panel.current.id === id);
|
|
422
|
+
const size = sizes[index];
|
|
423
|
+
|
|
424
|
+
const units = unitsFromParams ?? unitsFromProps;
|
|
425
|
+
if (units === "pixels") {
|
|
426
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
427
|
+
return (size / 100) * groupSizePixels;
|
|
428
|
+
} else {
|
|
429
|
+
return size;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
[groupId, sizes]
|
|
433
|
+
);
|
|
434
|
+
|
|
377
435
|
const getPanelStyle = useCallback(
|
|
378
436
|
(id: string, defaultSize: number | null): CSSProperties => {
|
|
379
437
|
const { panels } = committedValuesRef.current;
|
|
@@ -425,6 +483,10 @@ function PanelGroupWithForwardedRef({
|
|
|
425
483
|
);
|
|
426
484
|
|
|
427
485
|
const registerPanel = useCallback((id: string, panelRef: PanelData) => {
|
|
486
|
+
const { units } = committedValuesRef.current;
|
|
487
|
+
|
|
488
|
+
validatePanelProps(units, panelRef);
|
|
489
|
+
|
|
428
490
|
setPanels((prevPanels) => {
|
|
429
491
|
if (prevPanels.has(id)) {
|
|
430
492
|
return prevPanels;
|
|
@@ -484,9 +546,11 @@ function PanelGroupWithForwardedRef({
|
|
|
484
546
|
const size = isHorizontal ? rect.width : rect.height;
|
|
485
547
|
const delta = (movement / size) * 100;
|
|
486
548
|
|
|
549
|
+
// If a validateLayout method has been provided
|
|
550
|
+
// it's important to use it before updating the mouse cursor
|
|
487
551
|
const nextSizes = adjustByDelta(
|
|
488
552
|
event,
|
|
489
|
-
|
|
553
|
+
committedValuesRef.current,
|
|
490
554
|
idBefore,
|
|
491
555
|
idAfter,
|
|
492
556
|
delta,
|
|
@@ -528,6 +592,7 @@ function PanelGroupWithForwardedRef({
|
|
|
528
592
|
const panelIdToLastNotifiedSizeMap =
|
|
529
593
|
panelIdToLastNotifiedSizeMapRef.current;
|
|
530
594
|
|
|
595
|
+
// It's okay to bypass in this case because we already validated above
|
|
531
596
|
setSizes(nextSizes);
|
|
532
597
|
|
|
533
598
|
// If resize change handlers have been declared, this is the time to call them.
|
|
@@ -598,7 +663,7 @@ function PanelGroupWithForwardedRef({
|
|
|
598
663
|
|
|
599
664
|
const nextSizes = adjustByDelta(
|
|
600
665
|
null,
|
|
601
|
-
|
|
666
|
+
committedValuesRef.current,
|
|
602
667
|
idBefore,
|
|
603
668
|
idAfter,
|
|
604
669
|
delta,
|
|
@@ -659,7 +724,7 @@ function PanelGroupWithForwardedRef({
|
|
|
659
724
|
|
|
660
725
|
const nextSizes = adjustByDelta(
|
|
661
726
|
null,
|
|
662
|
-
|
|
727
|
+
committedValuesRef.current,
|
|
663
728
|
idBefore,
|
|
664
729
|
idAfter,
|
|
665
730
|
delta,
|
|
@@ -679,63 +744,103 @@ function PanelGroupWithForwardedRef({
|
|
|
679
744
|
}
|
|
680
745
|
}, []);
|
|
681
746
|
|
|
682
|
-
const resizePanel = useCallback(
|
|
683
|
-
|
|
747
|
+
const resizePanel = useCallback(
|
|
748
|
+
(id: string, nextSize: number, unitsFromParams?: Units) => {
|
|
749
|
+
const {
|
|
750
|
+
id: groupId,
|
|
751
|
+
panels,
|
|
752
|
+
sizes: prevSizes,
|
|
753
|
+
units,
|
|
754
|
+
} = committedValuesRef.current;
|
|
755
|
+
|
|
756
|
+
if ((unitsFromParams || units) === "pixels") {
|
|
757
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
758
|
+
nextSize = (nextSize / groupSizePixels) * 100;
|
|
759
|
+
}
|
|
684
760
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
761
|
+
const panel = panels.get(id);
|
|
762
|
+
if (panel == null) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
689
765
|
|
|
690
|
-
|
|
766
|
+
let { collapsedSize, collapsible, maxSize, minSize } = panel.current;
|
|
691
767
|
|
|
692
|
-
|
|
768
|
+
if (units === "pixels") {
|
|
769
|
+
const groupSizePixels = getAvailableGroupSizePixels(groupId);
|
|
770
|
+
minSize = (minSize / groupSizePixels) * 100;
|
|
771
|
+
if (maxSize != null) {
|
|
772
|
+
maxSize = (maxSize / groupSizePixels) * 100;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
693
775
|
|
|
694
|
-
|
|
695
|
-
if (index < 0) {
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
776
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
698
777
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
778
|
+
const index = panelsArray.indexOf(panel);
|
|
779
|
+
if (index < 0) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
703
782
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
783
|
+
const currentSize = prevSizes[index];
|
|
784
|
+
if (currentSize === nextSize) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
709
787
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
788
|
+
if (collapsible && nextSize === collapsedSize) {
|
|
789
|
+
// This is a valid resize state.
|
|
790
|
+
} else {
|
|
791
|
+
const unsafeNextSize = nextSize;
|
|
714
792
|
|
|
715
|
-
|
|
716
|
-
|
|
793
|
+
nextSize = Math.min(
|
|
794
|
+
maxSize != null ? maxSize : 100,
|
|
795
|
+
Math.max(minSize, nextSize)
|
|
796
|
+
);
|
|
717
797
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
null
|
|
727
|
-
);
|
|
728
|
-
if (prevSizes !== nextSizes) {
|
|
729
|
-
const panelIdToLastNotifiedSizeMap =
|
|
730
|
-
panelIdToLastNotifiedSizeMapRef.current;
|
|
798
|
+
if (isDevelopment) {
|
|
799
|
+
if (unsafeNextSize !== nextSize) {
|
|
800
|
+
console.error(
|
|
801
|
+
`Invalid size (${unsafeNextSize}) specified for Panel "${panel.current.id}" given the panel's min/max size constraints`
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
731
806
|
|
|
732
|
-
|
|
807
|
+
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
808
|
+
if (idBefore == null || idAfter == null) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
733
811
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
812
|
+
const isLastPanel = index === panelsArray.length - 1;
|
|
813
|
+
const delta = isLastPanel
|
|
814
|
+
? currentSize - nextSize
|
|
815
|
+
: nextSize - currentSize;
|
|
816
|
+
|
|
817
|
+
const nextSizes = adjustByDelta(
|
|
818
|
+
null,
|
|
819
|
+
committedValuesRef.current,
|
|
820
|
+
idBefore,
|
|
821
|
+
idAfter,
|
|
822
|
+
delta,
|
|
823
|
+
prevSizes,
|
|
824
|
+
panelSizeBeforeCollapse.current,
|
|
825
|
+
null
|
|
826
|
+
);
|
|
827
|
+
if (prevSizes !== nextSizes) {
|
|
828
|
+
const panelIdToLastNotifiedSizeMap =
|
|
829
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
830
|
+
|
|
831
|
+
setSizes(nextSizes);
|
|
832
|
+
|
|
833
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
834
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
835
|
+
callPanelCallbacks(
|
|
836
|
+
panelsArray,
|
|
837
|
+
nextSizes,
|
|
838
|
+
panelIdToLastNotifiedSizeMap
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
},
|
|
842
|
+
[]
|
|
843
|
+
);
|
|
739
844
|
|
|
740
845
|
const context = useMemo(
|
|
741
846
|
() => ({
|
|
@@ -743,6 +848,7 @@ function PanelGroupWithForwardedRef({
|
|
|
743
848
|
collapsePanel,
|
|
744
849
|
direction,
|
|
745
850
|
expandPanel,
|
|
851
|
+
getPanelSize,
|
|
746
852
|
getPanelStyle,
|
|
747
853
|
groupId,
|
|
748
854
|
registerPanel,
|
|
@@ -767,6 +873,7 @@ function PanelGroupWithForwardedRef({
|
|
|
767
873
|
|
|
768
874
|
initialDragStateRef.current = null;
|
|
769
875
|
},
|
|
876
|
+
units,
|
|
770
877
|
unregisterPanel,
|
|
771
878
|
}),
|
|
772
879
|
[
|
|
@@ -774,11 +881,13 @@ function PanelGroupWithForwardedRef({
|
|
|
774
881
|
collapsePanel,
|
|
775
882
|
direction,
|
|
776
883
|
expandPanel,
|
|
884
|
+
getPanelSize,
|
|
777
885
|
getPanelStyle,
|
|
778
886
|
groupId,
|
|
779
887
|
registerPanel,
|
|
780
888
|
registerResizeHandle,
|
|
781
889
|
resizePanel,
|
|
890
|
+
units,
|
|
782
891
|
unregisterPanel,
|
|
783
892
|
]
|
|
784
893
|
);
|
|
@@ -798,6 +907,7 @@ function PanelGroupWithForwardedRef({
|
|
|
798
907
|
"data-panel-group": "",
|
|
799
908
|
"data-panel-group-direction": direction,
|
|
800
909
|
"data-panel-group-id": groupId,
|
|
910
|
+
"data-panel-group-units": units,
|
|
801
911
|
style: { ...style, ...styleFromProps },
|
|
802
912
|
}),
|
|
803
913
|
value: context,
|
|
@@ -37,7 +37,9 @@ export function useWindowSplitterPanelGroupBehavior({
|
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
const { direction, panels } = committedValuesRef.current!;
|
|
39
39
|
|
|
40
|
-
const groupElement = getPanelGroup(groupId)
|
|
40
|
+
const groupElement = getPanelGroup(groupId);
|
|
41
|
+
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
42
|
+
|
|
41
43
|
const { height, width } = groupElement.getBoundingClientRect();
|
|
42
44
|
|
|
43
45
|
const handles = getResizeHandlesForGroup(groupId);
|
|
@@ -54,25 +56,26 @@ export function useWindowSplitterPanelGroupBehavior({
|
|
|
54
56
|
return () => {};
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
let
|
|
58
|
-
let
|
|
59
|
+
let currentMinSize = 0;
|
|
60
|
+
let currentMaxSize = 100;
|
|
59
61
|
let totalMinSize = 0;
|
|
60
62
|
let totalMaxSize = 0;
|
|
61
63
|
|
|
62
64
|
// A panel's effective min/max sizes also need to account for other panel's sizes.
|
|
63
65
|
panelsArray.forEach((panelData) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
const { id, maxSize, minSize } = panelData.current;
|
|
67
|
+
if (id === idBefore) {
|
|
68
|
+
currentMinSize = minSize;
|
|
69
|
+
currentMaxSize = maxSize != null ? maxSize : 100;
|
|
67
70
|
} else {
|
|
68
|
-
totalMinSize +=
|
|
69
|
-
totalMaxSize +=
|
|
71
|
+
totalMinSize += minSize;
|
|
72
|
+
totalMaxSize += maxSize != null ? maxSize : 100;
|
|
70
73
|
}
|
|
71
74
|
});
|
|
72
75
|
|
|
73
|
-
const ariaValueMax = Math.min(
|
|
76
|
+
const ariaValueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
74
77
|
const ariaValueMin = Math.max(
|
|
75
|
-
|
|
78
|
+
currentMinSize,
|
|
76
79
|
(panelsArray.length - 1) * 100 - totalMaxSize
|
|
77
80
|
);
|
|
78
81
|
|
|
@@ -110,7 +113,7 @@ export function useWindowSplitterPanelGroupBehavior({
|
|
|
110
113
|
|
|
111
114
|
const nextSizes = adjustByDelta(
|
|
112
115
|
event,
|
|
113
|
-
|
|
116
|
+
committedValuesRef.current!,
|
|
114
117
|
idBefore,
|
|
115
118
|
idAfter,
|
|
116
119
|
delta,
|
package/src/index.ts
CHANGED
|
@@ -5,27 +5,35 @@ import { PanelResizeHandle } from "./PanelResizeHandle";
|
|
|
5
5
|
import type { ImperativePanelHandle, PanelProps } from "./Panel";
|
|
6
6
|
import type { ImperativePanelGroupHandle, PanelGroupProps } from "./PanelGroup";
|
|
7
7
|
import type { PanelResizeHandleProps } from "./PanelResizeHandle";
|
|
8
|
+
import { getAvailableGroupSizePixels } from "./utils/group";
|
|
8
9
|
import type {
|
|
9
10
|
PanelGroupOnLayout,
|
|
10
11
|
PanelGroupStorage,
|
|
11
12
|
PanelOnCollapse,
|
|
12
13
|
PanelOnResize,
|
|
13
14
|
PanelResizeHandleOnDragging,
|
|
15
|
+
Units,
|
|
14
16
|
} from "./types";
|
|
15
17
|
|
|
16
18
|
export {
|
|
17
19
|
// TypeScript types
|
|
18
20
|
ImperativePanelGroupHandle,
|
|
19
21
|
ImperativePanelHandle,
|
|
20
|
-
Panel,
|
|
21
22
|
PanelOnCollapse,
|
|
22
23
|
PanelOnResize,
|
|
23
|
-
PanelGroup,
|
|
24
24
|
PanelGroupOnLayout,
|
|
25
25
|
PanelGroupProps,
|
|
26
26
|
PanelGroupStorage,
|
|
27
27
|
PanelProps,
|
|
28
|
-
PanelResizeHandle,
|
|
29
28
|
PanelResizeHandleOnDragging,
|
|
30
29
|
PanelResizeHandleProps,
|
|
30
|
+
Units,
|
|
31
|
+
|
|
32
|
+
// React components
|
|
33
|
+
Panel,
|
|
34
|
+
PanelGroup,
|
|
35
|
+
PanelResizeHandle,
|
|
36
|
+
|
|
37
|
+
// Utility methods
|
|
38
|
+
getAvailableGroupSizePixels,
|
|
31
39
|
};
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RefObject } from "./vendor/react";
|
|
2
2
|
|
|
3
3
|
export type Direction = "horizontal" | "vertical";
|
|
4
|
+
export type Units = "percentages" | "pixels";
|
|
4
5
|
|
|
5
6
|
export type PanelGroupStorage = {
|
|
6
7
|
getItem(name: string): string | null;
|
|
@@ -25,7 +26,7 @@ export type PanelData = {
|
|
|
25
26
|
defaultSize: number | null;
|
|
26
27
|
id: string;
|
|
27
28
|
idWasAutoGenerated: boolean;
|
|
28
|
-
maxSize: number;
|
|
29
|
+
maxSize: number | null;
|
|
29
30
|
minSize: number;
|
|
30
31
|
order: number | null;
|
|
31
32
|
};
|