react-resizable-panels 0.0.43 → 0.0.45

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/src/PanelGroup.ts CHANGED
@@ -45,6 +45,7 @@ import {
45
45
  panelsMapToSortedArray,
46
46
  } from "./utils/group";
47
47
  import { loadPanelLayout, savePanelGroupLayout } from "./utils/serialization";
48
+ import { isServerRendering } from "./utils/ssr";
48
49
 
49
50
  const debounceMap: {
50
51
  [key: string]: (
@@ -260,12 +261,12 @@ function PanelGroupWithForwardedRef({
260
261
  // For now, these logic edge cases are left to the user to handle via props.
261
262
 
262
263
  panelsArray.forEach((panel) => {
263
- totalMinSize += panel.minSize;
264
+ totalMinSize += panel.current.minSize;
264
265
 
265
- if (panel.defaultSize === null) {
266
+ if (panel.current.defaultSize === null) {
266
267
  panelsWithNullDefaultSize++;
267
268
  } else {
268
- totalDefaultSize += panel.defaultSize;
269
+ totalDefaultSize += panel.current.defaultSize;
269
270
  }
270
271
  });
271
272
 
@@ -281,11 +282,11 @@ function PanelGroupWithForwardedRef({
281
282
 
282
283
  setSizes(
283
284
  panelsArray.map((panel) => {
284
- if (panel.defaultSize === null) {
285
+ if (panel.current.defaultSize === null) {
285
286
  return (100 - totalDefaultSize) / panelsWithNullDefaultSize;
286
287
  }
287
288
 
288
- return panel.defaultSize;
289
+ return panel.current.defaultSize;
289
290
  })
290
291
  );
291
292
  }
@@ -309,16 +310,22 @@ function PanelGroupWithForwardedRef({
309
310
  }, [autoSaveId, panels, sizes, storage]);
310
311
 
311
312
  const getPanelStyle = useCallback(
312
- (id: string): CSSProperties => {
313
+ (id: string, defaultSize: number | null): CSSProperties => {
313
314
  const { panels } = committedValuesRef.current;
314
315
 
315
316
  // Before mounting, Panels will not yet have registered themselves.
316
317
  // This includes server rendering.
317
318
  // At this point the best we can do is render everything with the same size.
318
319
  if (panels.size === 0) {
320
+ if (isServerRendering() && defaultSize == null) {
321
+ console.warn(
322
+ `WARNING: Panel defaultSize prop recommended to avoid layout shift after server rendering`
323
+ );
324
+ }
325
+
319
326
  return {
320
- flexBasis: "auto",
321
- flexGrow: 1,
327
+ flexBasis: 0,
328
+ flexGrow: defaultSize != null ? defaultSize : undefined,
322
329
  flexShrink: 1,
323
330
 
324
331
  // Without this, Panel sizes may be unintentionally overridden by their content.
@@ -347,14 +354,14 @@ function PanelGroupWithForwardedRef({
347
354
  [activeHandleId, disablePointerEventsDuringResize, sizes]
348
355
  );
349
356
 
350
- const registerPanel = useCallback((id: string, panel: PanelData) => {
357
+ const registerPanel = useCallback((id: string, panelRef: PanelData) => {
351
358
  setPanels((prevPanels) => {
352
359
  if (prevPanels.has(id)) {
353
360
  return prevPanels;
354
361
  }
355
362
 
356
363
  const nextPanels = new Map(prevPanels);
357
- nextPanels.set(id, panel);
364
+ nextPanels.set(id, panelRef);
358
365
 
359
366
  return nextPanels;
360
367
  });
@@ -382,7 +389,7 @@ function PanelGroupWithForwardedRef({
382
389
  return;
383
390
  }
384
391
 
385
- const movement = getMovement(
392
+ let movement = getMovement(
386
393
  event,
387
394
  groupId,
388
395
  handleId,
@@ -398,6 +405,12 @@ function PanelGroupWithForwardedRef({
398
405
  const groupElement = getPanelGroup(groupId)!;
399
406
  const rect = groupElement.getBoundingClientRect();
400
407
  const isHorizontal = direction === "horizontal";
408
+
409
+ // Support RTL layouts
410
+ if (document.dir === "rtl" && isHorizontal) {
411
+ movement = -movement;
412
+ }
413
+
401
414
  const size = isHorizontal ? rect.width : rect.height;
402
415
  const delta = (movement / size) * 100;
403
416
 
@@ -473,7 +486,7 @@ function PanelGroupWithForwardedRef({
473
486
  const { panels, sizes: prevSizes } = committedValuesRef.current;
474
487
 
475
488
  const panel = panels.get(id);
476
- if (panel == null || !panel.collapsible) {
489
+ if (panel == null || !panel.current.collapsible) {
477
490
  return;
478
491
  }
479
492
 
@@ -527,7 +540,7 @@ function PanelGroupWithForwardedRef({
527
540
  }
528
541
 
529
542
  const sizeBeforeCollapse =
530
- panelSizeBeforeCollapse.current.get(id) || panel.minSize;
543
+ panelSizeBeforeCollapse.current.get(id) || panel.current.minSize;
531
544
  if (!sizeBeforeCollapse) {
532
545
  return;
533
546
  }
@@ -591,10 +604,13 @@ function PanelGroupWithForwardedRef({
591
604
  return;
592
605
  }
593
606
 
594
- if (panel.collapsible && nextSize === 0) {
607
+ if (panel.current.collapsible && nextSize === 0) {
595
608
  // This is a valid resize state.
596
609
  } else {
597
- nextSize = Math.min(panel.maxSize, Math.max(panel.minSize, nextSize));
610
+ nextSize = Math.min(
611
+ panel.current.maxSize,
612
+ Math.max(panel.current.minSize, nextSize)
613
+ );
598
614
  }
599
615
 
600
616
  const [idBefore, idAfter] = getBeforeAndAfterIds(id, panelsArray);
@@ -61,12 +61,12 @@ export function useWindowSplitterPanelGroupBehavior({
61
61
 
62
62
  // A panel's effective min/max sizes also need to account for other panel's sizes.
63
63
  panelsArray.forEach((panelData) => {
64
- if (panelData.id === idBefore) {
65
- maxSize = panelData.maxSize;
66
- minSize = panelData.minSize;
64
+ if (panelData.current.id === idBefore) {
65
+ maxSize = panelData.current.maxSize;
66
+ minSize = panelData.current.minSize;
67
67
  } else {
68
- totalMinSize += panelData.minSize;
69
- totalMaxSize += panelData.maxSize;
68
+ totalMinSize += panelData.current.minSize;
69
+ totalMaxSize += panelData.current.maxSize;
70
70
  }
71
71
  });
72
72
 
@@ -92,7 +92,7 @@ export function useWindowSplitterPanelGroupBehavior({
92
92
  event.preventDefault();
93
93
 
94
94
  const index = panelsArray.findIndex(
95
- (panel) => panel.id === idBefore
95
+ (panel) => panel.current.id === idBefore
96
96
  );
97
97
  if (index >= 0) {
98
98
  const panelData = panelsArray[index];
@@ -101,7 +101,7 @@ export function useWindowSplitterPanelGroupBehavior({
101
101
  let delta = 0;
102
102
  if (
103
103
  size.toPrecision(PRECISION) <=
104
- panelData.minSize.toPrecision(PRECISION)
104
+ panelData.current.minSize.toPrecision(PRECISION)
105
105
  ) {
106
106
  delta = direction === "horizontal" ? width : height;
107
107
  } else {
package/src/types.ts CHANGED
@@ -12,17 +12,21 @@ export type PanelOnCollapse = (collapsed: boolean) => void;
12
12
  export type PanelOnResize = (size: number) => void;
13
13
  export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
14
14
 
15
+ export type PanelCallbackRef = RefObject<{
16
+ onCollapse: PanelOnCollapse | null;
17
+ onResize: PanelOnResize | null;
18
+ }>;
19
+
15
20
  export type PanelData = {
16
- callbacksRef: RefObject<{
17
- onCollapse: PanelOnCollapse | null;
18
- onResize: PanelOnResize | null;
19
- }>;
20
- collapsible: boolean;
21
- defaultSize: number | null;
22
- id: string;
23
- maxSize: number;
24
- minSize: number;
25
- order: number | null;
21
+ current: {
22
+ callbacksRef: PanelCallbackRef;
23
+ collapsible: boolean;
24
+ defaultSize: number | null;
25
+ id: string;
26
+ maxSize: number;
27
+ minSize: number;
28
+ order: number | null;
29
+ };
26
30
  };
27
31
 
28
32
  export type ResizeEvent = KeyboardEvent | MouseEvent | TouchEvent;
@@ -107,20 +107,20 @@ export function getMovement(
107
107
  );
108
108
  const targetPanelId = movement < 0 ? idBefore : idAfter;
109
109
  const targetPanelIndex = panelsArray.findIndex(
110
- (panel) => panel.id === targetPanelId
110
+ (panel) => panel.current.id === targetPanelId
111
111
  );
112
112
  const targetPanel = panelsArray[targetPanelIndex];
113
- if (targetPanel.collapsible) {
113
+ if (targetPanel.current.collapsible) {
114
114
  const baseSize = baseSizes[targetPanelIndex];
115
115
  if (
116
116
  baseSize === 0 ||
117
117
  baseSize.toPrecision(PRECISION) ===
118
- targetPanel.minSize.toPrecision(PRECISION)
118
+ targetPanel.current.minSize.toPrecision(PRECISION)
119
119
  ) {
120
120
  movement =
121
121
  movement < 0
122
- ? -targetPanel.minSize * groupSizeInPixels
123
- : targetPanel.minSize * groupSizeInPixels;
122
+ ? -targetPanel.current.minSize * groupSizeInPixels
123
+ : targetPanel.current.minSize * groupSizeInPixels;
124
124
  }
125
125
  }
126
126
 
@@ -1,5 +1,5 @@
1
- import { PRECISION } from "../constants";
2
1
  import { InitialDragState } from "../PanelGroup";
2
+ import { PRECISION } from "../constants";
3
3
  import { PanelData, ResizeEvent } from "../types";
4
4
 
5
5
  export function adjustByDelta(
@@ -39,7 +39,9 @@ export function adjustByDelta(
39
39
  // Max-bounds check the panel being expanded first.
40
40
  {
41
41
  const pivotId = delta < 0 ? idAfter : idBefore;
42
- const index = panelsArray.findIndex((panel) => panel.id === pivotId);
42
+ const index = panelsArray.findIndex(
43
+ (panel) => panel.current.id === pivotId
44
+ );
43
45
  const panel = panelsArray[index];
44
46
  const baseSize = baseSizes[index];
45
47
 
@@ -57,7 +59,7 @@ export function adjustByDelta(
57
59
  }
58
60
 
59
61
  let pivotId = delta < 0 ? idBefore : idAfter;
60
- let index = panelsArray.findIndex((panel) => panel.id === pivotId);
62
+ let index = panelsArray.findIndex((panel) => panel.current.id === pivotId);
61
63
  while (true) {
62
64
  const panel = panelsArray[index];
63
65
  const baseSize = baseSizes[index];
@@ -72,7 +74,7 @@ export function adjustByDelta(
72
74
  );
73
75
  if (baseSize !== nextSize) {
74
76
  if (nextSize === 0 && baseSize > 0) {
75
- panelSizeBeforeCollapse.set(panel.id, baseSize);
77
+ panelSizeBeforeCollapse.set(panel.current.id, baseSize);
76
78
  }
77
79
 
78
80
  deltaApplied += baseSize - nextSize;
@@ -109,7 +111,7 @@ export function adjustByDelta(
109
111
 
110
112
  // Adjust the pivot panel before, but only by the amount that surrounding panels were able to shrink/contract.
111
113
  pivotId = delta < 0 ? idAfter : idBefore;
112
- index = panelsArray.findIndex((panel) => panel.id === pivotId);
114
+ index = panelsArray.findIndex((panel) => panel.current.id === pivotId);
113
115
  nextSizes[index] = baseSizes[index] + deltaApplied;
114
116
 
115
117
  return nextSizes;
@@ -123,7 +125,7 @@ export function callPanelCallbacks(
123
125
  nextSizes.forEach((nextSize, index) => {
124
126
  const prevSize = prevSizes[index];
125
127
  if (prevSize !== nextSize) {
126
- const { callbacksRef, collapsible } = panelsArray[index];
128
+ const { callbacksRef, collapsible } = panelsArray[index].current;
127
129
  const { onCollapse, onResize } = callbacksRef.current!;
128
130
 
129
131
  if (onResize) {
@@ -151,14 +153,14 @@ export function getBeforeAndAfterIds(
151
153
  return [null, null];
152
154
  }
153
155
 
154
- const index = panelsArray.findIndex((panel) => panel.id === id);
156
+ const index = panelsArray.findIndex((panel) => panel.current.id === id);
155
157
  if (index < 0) {
156
158
  return [null, null];
157
159
  }
158
160
 
159
161
  const isLastPanel = index === panelsArray.length - 1;
160
- const idBefore = isLastPanel ? panelsArray[index - 1].id : id;
161
- const idAfter = isLastPanel ? id : panelsArray[index + 1].id;
162
+ const idBefore = isLastPanel ? panelsArray[index - 1].current.id : id;
163
+ const idAfter = isLastPanel ? id : panelsArray[index + 1].current.id;
162
164
 
163
165
  return [idBefore, idAfter];
164
166
  }
@@ -176,7 +178,7 @@ export function getFlexGrow(
176
178
 
177
179
  const panelsArray = panelsMapToSortedArray(panels);
178
180
 
179
- const index = panelsArray.findIndex((panel) => panel.id === id);
181
+ const index = panelsArray.findIndex((panel) => panel.current.id === id);
180
182
  const size = sizes[index];
181
183
  if (size == null) {
182
184
  return "0";
@@ -240,8 +242,8 @@ export function getResizeHandlePanelIds(
240
242
  const handles = getResizeHandlesForGroup(groupId);
241
243
  const index = handle ? handles.indexOf(handle) : -1;
242
244
 
243
- const idBefore: string | null = panelsArray[index]?.id ?? null;
244
- const idAfter: string | null = panelsArray[index + 1]?.id ?? null;
245
+ const idBefore: string | null = panelsArray[index]?.current?.id ?? null;
246
+ const idAfter: string | null = panelsArray[index + 1]?.current?.id ?? null;
245
247
 
246
248
  return [idBefore, idAfter];
247
249
  }
@@ -250,8 +252,8 @@ export function panelsMapToSortedArray(
250
252
  panels: Map<string, PanelData>
251
253
  ): PanelData[] {
252
254
  return Array.from(panels.values()).sort((panelA, panelB) => {
253
- const orderA = panelA.order;
254
- const orderB = panelB.order;
255
+ const orderA = panelA.current.order;
256
+ const orderB = panelB.current.order;
255
257
  if (orderA == null && orderB == null) {
256
258
  return 0;
257
259
  } else if (orderA == null) {
@@ -272,7 +274,7 @@ function safeResizePanel(
272
274
  ): number {
273
275
  const nextSizeUnsafe = prevSize + delta;
274
276
 
275
- if (panel.collapsible) {
277
+ if (panel.current.collapsible) {
276
278
  if (prevSize > 0) {
277
279
  if (nextSizeUnsafe <= 0) {
278
280
  return 0;
@@ -283,7 +285,7 @@ function safeResizePanel(
283
285
  // Keyboard events should expand a collapsed panel to the min size,
284
286
  // but mouse events should wait until the panel has reached its min size
285
287
  // to avoid a visual flickering when dragging between collapsed and min size.
286
- if (nextSizeUnsafe < panel.minSize) {
288
+ if (nextSizeUnsafe < panel.current.minSize) {
287
289
  return 0;
288
290
  }
289
291
  }
@@ -291,8 +293,8 @@ function safeResizePanel(
291
293
  }
292
294
 
293
295
  const nextSize = Math.min(
294
- panel.maxSize,
295
- Math.max(panel.minSize, nextSizeUnsafe)
296
+ panel.current.maxSize,
297
+ Math.max(panel.current.minSize, nextSizeUnsafe)
296
298
  );
297
299
 
298
300
  return nextSize;
@@ -9,7 +9,7 @@ type SerializedPanelGroupState = { [panelIds: string]: number[] };
9
9
  function getSerializationKey(panels: PanelData[]): string {
10
10
  return panels
11
11
  .map((panel) => {
12
- const { minSize, order } = panel;
12
+ const { minSize, order } = panel.current;
13
13
  return order ? `${order}:${minSize}` : `${minSize}`;
14
14
  })
15
15
  .sort((a, b) => a.localeCompare(b))
@@ -0,0 +1,7 @@
1
+ export function isServerRendering(): boolean {
2
+ try {
3
+ return typeof window === undefined;
4
+ } catch (error) {}
5
+
6
+ return true;
7
+ }