react-resizable-panels 0.0.50 → 0.0.52
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 +8 -0
- package/README.md +15 -14
- package/dist/declarations/src/Panel.d.ts +1 -0
- package/dist/declarations/src/types.d.ts +2 -1
- package/dist/react-resizable-panels.cjs.js +95 -57
- package/dist/react-resizable-panels.cjs.js.map +1 -0
- package/dist/react-resizable-panels.development.cjs.js +95 -57
- package/dist/react-resizable-panels.development.esm.js +95 -57
- package/dist/react-resizable-panels.esm.js +95 -57
- package/dist/react-resizable-panels.esm.js.map +1 -0
- package/package.json +1 -1
- package/src/Panel.ts +5 -0
- package/src/PanelGroup.ts +68 -37
- package/src/types.ts +2 -1
- package/src/utils/group.ts +28 -21
package/src/PanelGroup.ts
CHANGED
|
@@ -169,6 +169,8 @@ function PanelGroupWithForwardedRef({
|
|
|
169
169
|
callbacksRef.current.onLayout = onLayout;
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
+
const panelIdToLastNotifiedSizeMapRef = useRef<Record<string, number>>({});
|
|
173
|
+
|
|
172
174
|
// 0-1 values representing the relative size of each panel.
|
|
173
175
|
const [sizes, setSizes] = useState<number[]>([]);
|
|
174
176
|
|
|
@@ -199,7 +201,14 @@ function PanelGroupWithForwardedRef({
|
|
|
199
201
|
|
|
200
202
|
assert(total === 100, "Panel sizes must add up to 100%");
|
|
201
203
|
|
|
204
|
+
const { panels } = committedValuesRef.current;
|
|
205
|
+
const panelIdToLastNotifiedSizeMap =
|
|
206
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
207
|
+
const panelsArray = panelsMapToSortedArray(panels);
|
|
208
|
+
|
|
202
209
|
setSizes(sizes);
|
|
210
|
+
|
|
211
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
203
212
|
},
|
|
204
213
|
}),
|
|
205
214
|
[]
|
|
@@ -223,30 +232,24 @@ function PanelGroupWithForwardedRef({
|
|
|
223
232
|
// Notify external code when sizes have changed.
|
|
224
233
|
useEffect(() => {
|
|
225
234
|
const { onLayout } = callbacksRef.current!;
|
|
226
|
-
|
|
227
|
-
const { sizes } = committedValuesRef.current;
|
|
235
|
+
const { panels, sizes } = committedValuesRef.current;
|
|
228
236
|
|
|
229
|
-
|
|
230
|
-
|
|
237
|
+
// Don't commit layout until all panels have registered and re-rendered with their actual sizes.
|
|
238
|
+
if (sizes.length > 0) {
|
|
239
|
+
if (onLayout) {
|
|
231
240
|
onLayout(sizes);
|
|
232
241
|
}
|
|
233
|
-
}
|
|
234
|
-
}, [sizes]);
|
|
235
242
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const didNotifyCallbacksAfterMountRef = useRef(false);
|
|
239
|
-
useIsomorphicLayoutEffect(() => {
|
|
240
|
-
if (didNotifyCallbacksAfterMountRef.current) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const { panels, sizes } = committedValuesRef.current;
|
|
245
|
-
if (sizes.length > 0) {
|
|
246
|
-
didNotifyCallbacksAfterMountRef.current = true;
|
|
243
|
+
const panelIdToLastNotifiedSizeMap =
|
|
244
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
247
245
|
|
|
246
|
+
// When possible, we notify before the next render so that rendering work can be batched together.
|
|
247
|
+
// Some cases are difficult to detect though,
|
|
248
|
+
// for example– panels that are conditionally rendered can affect the size of neighboring panels.
|
|
249
|
+
// In this case, the best we can do is notify on commit.
|
|
250
|
+
// The callPanelCallbacks() uses its own memoization to avoid notifying panels twice in these cases.
|
|
248
251
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
249
|
-
callPanelCallbacks(panelsArray,
|
|
252
|
+
callPanelCallbacks(panelsArray, sizes, panelIdToLastNotifiedSizeMap);
|
|
250
253
|
}
|
|
251
254
|
}, [sizes]);
|
|
252
255
|
|
|
@@ -481,10 +484,18 @@ function PanelGroupWithForwardedRef({
|
|
|
481
484
|
}
|
|
482
485
|
|
|
483
486
|
if (sizesChanged) {
|
|
484
|
-
|
|
485
|
-
|
|
487
|
+
const panelIdToLastNotifiedSizeMap =
|
|
488
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
486
489
|
|
|
487
490
|
setSizes(nextSizes);
|
|
491
|
+
|
|
492
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
493
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
494
|
+
callPanelCallbacks(
|
|
495
|
+
panelsArray,
|
|
496
|
+
nextSizes,
|
|
497
|
+
panelIdToLastNotifiedSizeMap
|
|
498
|
+
);
|
|
488
499
|
}
|
|
489
500
|
|
|
490
501
|
prevDeltaRef.current = delta;
|
|
@@ -512,7 +523,12 @@ function PanelGroupWithForwardedRef({
|
|
|
512
523
|
const { panels, sizes: prevSizes } = committedValuesRef.current;
|
|
513
524
|
|
|
514
525
|
const panel = panels.get(id);
|
|
515
|
-
if (panel == null
|
|
526
|
+
if (panel == null) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const { collapsedSize, collapsible } = panel.current;
|
|
531
|
+
if (!collapsible) {
|
|
516
532
|
return;
|
|
517
533
|
}
|
|
518
534
|
|
|
@@ -524,7 +540,7 @@ function PanelGroupWithForwardedRef({
|
|
|
524
540
|
}
|
|
525
541
|
|
|
526
542
|
const currentSize = prevSizes[index];
|
|
527
|
-
if (currentSize ===
|
|
543
|
+
if (currentSize === collapsedSize) {
|
|
528
544
|
// Panel is already collapsed.
|
|
529
545
|
return;
|
|
530
546
|
}
|
|
@@ -537,7 +553,7 @@ function PanelGroupWithForwardedRef({
|
|
|
537
553
|
}
|
|
538
554
|
|
|
539
555
|
const isLastPanel = index === panelsArray.length - 1;
|
|
540
|
-
const delta = isLastPanel ? currentSize :
|
|
556
|
+
const delta = isLastPanel ? currentSize : collapsedSize - currentSize;
|
|
541
557
|
|
|
542
558
|
const nextSizes = adjustByDelta(
|
|
543
559
|
null,
|
|
@@ -550,10 +566,14 @@ function PanelGroupWithForwardedRef({
|
|
|
550
566
|
null
|
|
551
567
|
);
|
|
552
568
|
if (prevSizes !== nextSizes) {
|
|
553
|
-
|
|
554
|
-
|
|
569
|
+
const panelIdToLastNotifiedSizeMap =
|
|
570
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
555
571
|
|
|
556
572
|
setSizes(nextSizes);
|
|
573
|
+
|
|
574
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
575
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
576
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
557
577
|
}
|
|
558
578
|
}, []);
|
|
559
579
|
|
|
@@ -565,8 +585,10 @@ function PanelGroupWithForwardedRef({
|
|
|
565
585
|
return;
|
|
566
586
|
}
|
|
567
587
|
|
|
588
|
+
const { collapsedSize, minSize } = panel.current;
|
|
589
|
+
|
|
568
590
|
const sizeBeforeCollapse =
|
|
569
|
-
panelSizeBeforeCollapse.current.get(id) ||
|
|
591
|
+
panelSizeBeforeCollapse.current.get(id) || minSize;
|
|
570
592
|
if (!sizeBeforeCollapse) {
|
|
571
593
|
return;
|
|
572
594
|
}
|
|
@@ -579,7 +601,7 @@ function PanelGroupWithForwardedRef({
|
|
|
579
601
|
}
|
|
580
602
|
|
|
581
603
|
const currentSize = prevSizes[index];
|
|
582
|
-
if (currentSize !==
|
|
604
|
+
if (currentSize !== collapsedSize) {
|
|
583
605
|
// Panel is already expanded.
|
|
584
606
|
return;
|
|
585
607
|
}
|
|
@@ -590,7 +612,9 @@ function PanelGroupWithForwardedRef({
|
|
|
590
612
|
}
|
|
591
613
|
|
|
592
614
|
const isLastPanel = index === panelsArray.length - 1;
|
|
593
|
-
const delta = isLastPanel
|
|
615
|
+
const delta = isLastPanel
|
|
616
|
+
? collapsedSize - sizeBeforeCollapse
|
|
617
|
+
: sizeBeforeCollapse;
|
|
594
618
|
|
|
595
619
|
const nextSizes = adjustByDelta(
|
|
596
620
|
null,
|
|
@@ -603,10 +627,14 @@ function PanelGroupWithForwardedRef({
|
|
|
603
627
|
null
|
|
604
628
|
);
|
|
605
629
|
if (prevSizes !== nextSizes) {
|
|
606
|
-
|
|
607
|
-
|
|
630
|
+
const panelIdToLastNotifiedSizeMap =
|
|
631
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
608
632
|
|
|
609
633
|
setSizes(nextSizes);
|
|
634
|
+
|
|
635
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
636
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
637
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
610
638
|
}
|
|
611
639
|
}, []);
|
|
612
640
|
|
|
@@ -618,6 +646,8 @@ function PanelGroupWithForwardedRef({
|
|
|
618
646
|
return;
|
|
619
647
|
}
|
|
620
648
|
|
|
649
|
+
const { collapsedSize, collapsible, maxSize, minSize } = panel.current;
|
|
650
|
+
|
|
621
651
|
const panelsArray = panelsMapToSortedArray(panels);
|
|
622
652
|
|
|
623
653
|
const index = panelsArray.indexOf(panel);
|
|
@@ -630,13 +660,10 @@ function PanelGroupWithForwardedRef({
|
|
|
630
660
|
return;
|
|
631
661
|
}
|
|
632
662
|
|
|
633
|
-
if (
|
|
663
|
+
if (collapsible && nextSize === collapsedSize) {
|
|
634
664
|
// This is a valid resize state.
|
|
635
665
|
} else {
|
|
636
|
-
nextSize = Math.min(
|
|
637
|
-
panel.current.maxSize,
|
|
638
|
-
Math.max(panel.current.minSize, nextSize)
|
|
639
|
-
);
|
|
666
|
+
nextSize = Math.min(maxSize, Math.max(minSize, nextSize));
|
|
640
667
|
}
|
|
641
668
|
|
|
642
669
|
const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
|
|
@@ -658,10 +685,14 @@ function PanelGroupWithForwardedRef({
|
|
|
658
685
|
null
|
|
659
686
|
);
|
|
660
687
|
if (prevSizes !== nextSizes) {
|
|
661
|
-
|
|
662
|
-
|
|
688
|
+
const panelIdToLastNotifiedSizeMap =
|
|
689
|
+
panelIdToLastNotifiedSizeMapRef.current;
|
|
663
690
|
|
|
664
691
|
setSizes(nextSizes);
|
|
692
|
+
|
|
693
|
+
// If resize change handlers have been declared, this is the time to call them.
|
|
694
|
+
// Trigger user callbacks after updating state, so that user code can override the sizes.
|
|
695
|
+
callPanelCallbacks(panelsArray, nextSizes, panelIdToLastNotifiedSizeMap);
|
|
665
696
|
}
|
|
666
697
|
}, []);
|
|
667
698
|
|
package/src/types.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type PanelGroupStorage = {
|
|
|
9
9
|
|
|
10
10
|
export type PanelGroupOnLayout = (sizes: number[]) => void;
|
|
11
11
|
export type PanelOnCollapse = (collapsed: boolean) => void;
|
|
12
|
-
export type PanelOnResize = (size: number) => void;
|
|
12
|
+
export type PanelOnResize = (size: number, prevSize: number) => void;
|
|
13
13
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
14
14
|
|
|
15
15
|
export type PanelCallbackRef = RefObject<{
|
|
@@ -20,6 +20,7 @@ export type PanelCallbackRef = RefObject<{
|
|
|
20
20
|
export type PanelData = {
|
|
21
21
|
current: {
|
|
22
22
|
callbacksRef: PanelCallbackRef;
|
|
23
|
+
collapsedSize: number;
|
|
23
24
|
collapsible: boolean;
|
|
24
25
|
defaultSize: number | null;
|
|
25
26
|
id: string;
|
package/src/utils/group.ts
CHANGED
|
@@ -119,25 +119,33 @@ export function adjustByDelta(
|
|
|
119
119
|
|
|
120
120
|
export function callPanelCallbacks(
|
|
121
121
|
panelsArray: PanelData[],
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
sizes: number[],
|
|
123
|
+
panelIdToLastNotifiedSizeMap: Record<string, number>
|
|
124
124
|
) {
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
sizes.forEach((size, index) => {
|
|
126
|
+
const { callbacksRef, collapsedSize, collapsible, id } =
|
|
127
|
+
panelsArray[index].current;
|
|
128
|
+
|
|
129
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap[id];
|
|
130
|
+
if (lastNotifiedSize !== size) {
|
|
131
|
+
panelIdToLastNotifiedSizeMap[id] = size;
|
|
132
|
+
|
|
129
133
|
const { onCollapse, onResize } = callbacksRef.current!;
|
|
130
134
|
|
|
131
135
|
if (onResize) {
|
|
132
|
-
onResize(
|
|
136
|
+
onResize(size, lastNotifiedSize);
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
if (collapsible && onCollapse) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
if (
|
|
141
|
+
(lastNotifiedSize == null || lastNotifiedSize === collapsedSize) &&
|
|
142
|
+
size !== collapsedSize
|
|
143
|
+
) {
|
|
139
144
|
onCollapse(false);
|
|
140
|
-
} else if (
|
|
145
|
+
} else if (
|
|
146
|
+
lastNotifiedSize !== collapsedSize &&
|
|
147
|
+
size === collapsedSize
|
|
148
|
+
) {
|
|
141
149
|
onCollapse(true);
|
|
142
150
|
}
|
|
143
151
|
}
|
|
@@ -274,11 +282,13 @@ function safeResizePanel(
|
|
|
274
282
|
): number {
|
|
275
283
|
const nextSizeUnsafe = prevSize + delta;
|
|
276
284
|
|
|
277
|
-
|
|
278
|
-
|
|
285
|
+
const { collapsedSize, collapsible, maxSize, minSize } = panel.current;
|
|
286
|
+
|
|
287
|
+
if (collapsible) {
|
|
288
|
+
if (prevSize > collapsedSize) {
|
|
279
289
|
// Mimic VS COde behavior; collapse a panel if it's smaller than half of its min-size
|
|
280
|
-
if (nextSizeUnsafe <=
|
|
281
|
-
return
|
|
290
|
+
if (nextSizeUnsafe <= minSize / 2 + collapsedSize) {
|
|
291
|
+
return collapsedSize;
|
|
282
292
|
}
|
|
283
293
|
} else {
|
|
284
294
|
const isKeyboardEvent = event?.type?.startsWith("key");
|
|
@@ -286,17 +296,14 @@ function safeResizePanel(
|
|
|
286
296
|
// Keyboard events should expand a collapsed panel to the min size,
|
|
287
297
|
// but mouse events should wait until the panel has reached its min size
|
|
288
298
|
// to avoid a visual flickering when dragging between collapsed and min size.
|
|
289
|
-
if (nextSizeUnsafe <
|
|
290
|
-
return
|
|
299
|
+
if (nextSizeUnsafe < minSize) {
|
|
300
|
+
return collapsedSize;
|
|
291
301
|
}
|
|
292
302
|
}
|
|
293
303
|
}
|
|
294
304
|
}
|
|
295
305
|
|
|
296
|
-
const nextSize = Math.min(
|
|
297
|
-
panel.current.maxSize,
|
|
298
|
-
Math.max(panel.current.minSize, nextSizeUnsafe)
|
|
299
|
-
);
|
|
306
|
+
const nextSize = Math.min(maxSize, Math.max(minSize, nextSizeUnsafe));
|
|
300
307
|
|
|
301
308
|
return nextSize;
|
|
302
309
|
}
|