react-resizable-panels 0.0.42 → 0.0.44

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
@@ -13,21 +13,27 @@ import {
13
13
  useState,
14
14
  } from "./vendor/react";
15
15
 
16
+ import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
17
+ import useUniqueId from "./hooks/useUniqueId";
18
+ import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterBehavior";
16
19
  import { PanelGroupContext } from "./PanelContexts";
17
20
  import {
18
21
  Direction,
19
22
  PanelData,
20
23
  PanelGroupOnLayout,
21
- ResizeEvent,
22
24
  PanelGroupStorage,
25
+ ResizeEvent,
23
26
  } from "./types";
24
- import { loadPanelLayout, savePanelGroupLayout } from "./utils/serialization";
27
+ import { areEqual } from "./utils/arrays";
28
+ import { assert } from "./utils/assert";
25
29
  import {
26
30
  getDragOffset,
27
31
  getMovement,
28
32
  isMouseEvent,
29
33
  isTouchEvent,
30
34
  } from "./utils/coordinates";
35
+ import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
36
+ import debounce from "./utils/debounce";
31
37
  import {
32
38
  adjustByDelta,
33
39
  callPanelCallbacks,
@@ -38,16 +44,16 @@ import {
38
44
  getResizeHandlePanelIds,
39
45
  panelsMapToSortedArray,
40
46
  } from "./utils/group";
41
- import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
42
- import useUniqueId from "./hooks/useUniqueId";
43
- import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterBehavior";
44
- import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
45
- import debounce from "./utils/debounce";
46
- import { areEqual } from "./utils/arrays";
47
- import { assert } from "./utils/assert";
47
+ import { loadPanelLayout, savePanelGroupLayout } from "./utils/serialization";
48
48
 
49
- // Limit the frequency of localStorage updates.
50
- const savePanelGroupLayoutDebounced = debounce(savePanelGroupLayout, 100);
49
+ const debounceMap: {
50
+ [key: string]: (
51
+ autoSaveId: string,
52
+ panels: PanelData[],
53
+ sizes: number[],
54
+ storage: PanelGroupStorage
55
+ ) => void;
56
+ } = {};
51
57
 
52
58
  function throwServerError() {
53
59
  throw new Error('PanelGroup "storage" prop required for server rendering.');
@@ -103,6 +109,7 @@ export type PanelGroupProps = {
103
109
  };
104
110
 
105
111
  export type ImperativePanelGroupHandle = {
112
+ getLayout: () => number[];
106
113
  setLayout: (panelSizes: number[]) => void;
107
114
  };
108
115
 
@@ -157,6 +164,10 @@ function PanelGroupWithForwardedRef({
157
164
  useImperativeHandle(
158
165
  forwardedRef,
159
166
  () => ({
167
+ getLayout: () => {
168
+ const { sizes } = committedValuesRef.current;
169
+ return sizes;
170
+ },
160
171
  setLayout: (sizes: number[]) => {
161
172
  const total = sizes.reduce(
162
173
  (accumulated, current) => accumulated + current,
@@ -249,12 +260,12 @@ function PanelGroupWithForwardedRef({
249
260
  // For now, these logic edge cases are left to the user to handle via props.
250
261
 
251
262
  panelsArray.forEach((panel) => {
252
- totalMinSize += panel.minSize;
263
+ totalMinSize += panel.current.minSize;
253
264
 
254
- if (panel.defaultSize === null) {
265
+ if (panel.current.defaultSize === null) {
255
266
  panelsWithNullDefaultSize++;
256
267
  } else {
257
- totalDefaultSize += panel.defaultSize;
268
+ totalDefaultSize += panel.current.defaultSize;
258
269
  }
259
270
  });
260
271
 
@@ -270,11 +281,11 @@ function PanelGroupWithForwardedRef({
270
281
 
271
282
  setSizes(
272
283
  panelsArray.map((panel) => {
273
- if (panel.defaultSize === null) {
284
+ if (panel.current.defaultSize === null) {
274
285
  return (100 - totalDefaultSize) / panelsWithNullDefaultSize;
275
286
  }
276
287
 
277
- return panel.defaultSize;
288
+ return panel.current.defaultSize;
278
289
  })
279
290
  );
280
291
  }
@@ -289,7 +300,11 @@ function PanelGroupWithForwardedRef({
289
300
 
290
301
  const panelsArray = panelsMapToSortedArray(panels);
291
302
 
292
- savePanelGroupLayoutDebounced(autoSaveId, panelsArray, sizes, storage);
303
+ // Limit the frequency of localStorage updates.
304
+ if (!debounceMap[autoSaveId]) {
305
+ debounceMap[autoSaveId] = debounce(savePanelGroupLayout, 100);
306
+ }
307
+ debounceMap[autoSaveId](autoSaveId, panelsArray, sizes, storage);
293
308
  }
294
309
  }, [autoSaveId, panels, sizes, storage]);
295
310
 
@@ -332,14 +347,14 @@ function PanelGroupWithForwardedRef({
332
347
  [activeHandleId, disablePointerEventsDuringResize, sizes]
333
348
  );
334
349
 
335
- const registerPanel = useCallback((id: string, panel: PanelData) => {
350
+ const registerPanel = useCallback((id: string, panelRef: PanelData) => {
336
351
  setPanels((prevPanels) => {
337
352
  if (prevPanels.has(id)) {
338
353
  return prevPanels;
339
354
  }
340
355
 
341
356
  const nextPanels = new Map(prevPanels);
342
- nextPanels.set(id, panel);
357
+ nextPanels.set(id, panelRef);
343
358
 
344
359
  return nextPanels;
345
360
  });
@@ -458,7 +473,7 @@ function PanelGroupWithForwardedRef({
458
473
  const { panels, sizes: prevSizes } = committedValuesRef.current;
459
474
 
460
475
  const panel = panels.get(id);
461
- if (panel == null || !panel.collapsible) {
476
+ if (panel == null || !panel.current.collapsible) {
462
477
  return;
463
478
  }
464
479
 
@@ -512,7 +527,7 @@ function PanelGroupWithForwardedRef({
512
527
  }
513
528
 
514
529
  const sizeBeforeCollapse =
515
- panelSizeBeforeCollapse.current.get(id) || panel.minSize;
530
+ panelSizeBeforeCollapse.current.get(id) || panel.current.minSize;
516
531
  if (!sizeBeforeCollapse) {
517
532
  return;
518
533
  }
@@ -576,10 +591,13 @@ function PanelGroupWithForwardedRef({
576
591
  return;
577
592
  }
578
593
 
579
- if (panel.collapsible && nextSize === 0) {
594
+ if (panel.current.collapsible && nextSize === 0) {
580
595
  // This is a valid resize state.
581
596
  } else {
582
- nextSize = Math.min(panel.maxSize, Math.max(panel.minSize, nextSize));
597
+ nextSize = Math.min(
598
+ panel.current.maxSize,
599
+ Math.max(panel.current.minSize, nextSize)
600
+ );
583
601
  }
584
602
 
585
603
  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/index.ts CHANGED
@@ -8,14 +8,14 @@ import type { PanelResizeHandleProps } from "./PanelResizeHandle";
8
8
  import type { PanelGroupStorage } from "./types";
9
9
 
10
10
  export {
11
- Panel,
12
- PanelGroup,
13
- PanelResizeHandle,
14
-
15
11
  // TypeScript types
12
+ ImperativePanelGroupHandle,
16
13
  ImperativePanelHandle,
14
+ Panel,
15
+ PanelGroup,
17
16
  PanelGroupProps,
18
17
  PanelGroupStorage,
19
18
  PanelProps,
19
+ PanelResizeHandle,
20
20
  PanelResizeHandleProps,
21
21
  };
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))