react-resizable-panels 2.1.5 → 2.1.7

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.
Files changed (89) hide show
  1. package/dist/declarations/src/PanelGroup.d.ts +2 -0
  2. package/dist/react-resizable-panels.browser.cjs.js +16 -10
  3. package/dist/react-resizable-panels.browser.development.cjs.js +16 -10
  4. package/dist/react-resizable-panels.browser.development.esm.js +16 -10
  5. package/dist/react-resizable-panels.browser.esm.js +16 -10
  6. package/dist/react-resizable-panels.cjs.js +16 -10
  7. package/dist/react-resizable-panels.development.cjs.js +16 -10
  8. package/dist/react-resizable-panels.development.esm.js +16 -10
  9. package/dist/react-resizable-panels.development.node.cjs.js +16 -10
  10. package/dist/react-resizable-panels.development.node.esm.js +16 -10
  11. package/dist/react-resizable-panels.esm.js +16 -10
  12. package/dist/react-resizable-panels.node.cjs.js +16 -10
  13. package/dist/react-resizable-panels.node.esm.js +16 -10
  14. package/package.json +7 -1
  15. package/.eslintrc.cjs +0 -27
  16. package/CHANGELOG.md +0 -569
  17. package/jest.config.js +0 -10
  18. package/react-resizable-panels-2.1.5.tgz +0 -0
  19. package/src/Panel.test.tsx +0 -1084
  20. package/src/Panel.ts +0 -259
  21. package/src/PanelGroup.test.tsx +0 -443
  22. package/src/PanelGroup.ts +0 -985
  23. package/src/PanelGroupContext.ts +0 -42
  24. package/src/PanelResizeHandle.test.tsx +0 -367
  25. package/src/PanelResizeHandle.ts +0 -246
  26. package/src/PanelResizeHandleRegistry.ts +0 -336
  27. package/src/constants.ts +0 -1
  28. package/src/env-conditions/browser.ts +0 -1
  29. package/src/env-conditions/development.ts +0 -1
  30. package/src/env-conditions/node.ts +0 -1
  31. package/src/env-conditions/production.ts +0 -1
  32. package/src/env-conditions/unknown.ts +0 -1
  33. package/src/hooks/useForceUpdate.ts +0 -7
  34. package/src/hooks/useIsomorphicEffect.ts +0 -8
  35. package/src/hooks/useUniqueId.ts +0 -19
  36. package/src/hooks/useWindowSplitterBehavior.ts +0 -90
  37. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +0 -201
  38. package/src/index.ts +0 -77
  39. package/src/types.ts +0 -5
  40. package/src/utils/adjustLayoutByDelta.test.ts +0 -2061
  41. package/src/utils/adjustLayoutByDelta.ts +0 -308
  42. package/src/utils/arrays.ts +0 -13
  43. package/src/utils/assert.ts +0 -10
  44. package/src/utils/calculateAriaValues.test.ts +0 -106
  45. package/src/utils/calculateAriaValues.ts +0 -45
  46. package/src/utils/calculateDeltaPercentage.ts +0 -63
  47. package/src/utils/calculateDragOffsetPercentage.ts +0 -40
  48. package/src/utils/calculateUnsafeDefaultLayout.test.ts +0 -87
  49. package/src/utils/calculateUnsafeDefaultLayout.ts +0 -50
  50. package/src/utils/callPanelCallbacks.ts +0 -49
  51. package/src/utils/compareLayouts.test.ts +0 -9
  52. package/src/utils/compareLayouts.ts +0 -12
  53. package/src/utils/computePanelFlexBoxStyle.test.ts +0 -123
  54. package/src/utils/computePanelFlexBoxStyle.ts +0 -50
  55. package/src/utils/csp.ts +0 -9
  56. package/src/utils/cursor.ts +0 -103
  57. package/src/utils/debounce.ts +0 -18
  58. package/src/utils/determinePivotIndices.ts +0 -15
  59. package/src/utils/dom/getPanelElement.ts +0 -10
  60. package/src/utils/dom/getPanelElementsForGroup.ts +0 -8
  61. package/src/utils/dom/getPanelGroupElement.ts +0 -21
  62. package/src/utils/dom/getResizeHandleElement.ts +0 -10
  63. package/src/utils/dom/getResizeHandleElementIndex.ts +0 -13
  64. package/src/utils/dom/getResizeHandleElementsForGroup.ts +0 -10
  65. package/src/utils/dom/getResizeHandlePanelIds.ts +0 -19
  66. package/src/utils/events/getResizeEventCoordinates.ts +0 -23
  67. package/src/utils/events/getResizeEventCursorPosition.ts +0 -14
  68. package/src/utils/events/index.ts +0 -13
  69. package/src/utils/getInputType.ts +0 -5
  70. package/src/utils/initializeDefaultStorage.ts +0 -26
  71. package/src/utils/numbers/fuzzyCompareNumbers.test.ts +0 -16
  72. package/src/utils/numbers/fuzzyCompareNumbers.ts +0 -21
  73. package/src/utils/numbers/fuzzyLayoutsEqual.ts +0 -22
  74. package/src/utils/numbers/fuzzyNumbersEqual.ts +0 -9
  75. package/src/utils/rects/getIntersectingRectangle.test.ts +0 -198
  76. package/src/utils/rects/getIntersectingRectangle.ts +0 -28
  77. package/src/utils/rects/intersects.test.ts +0 -197
  78. package/src/utils/rects/intersects.ts +0 -23
  79. package/src/utils/rects/types.ts +0 -6
  80. package/src/utils/resizePanel.test.ts +0 -59
  81. package/src/utils/resizePanel.ts +0 -47
  82. package/src/utils/serialization.ts +0 -87
  83. package/src/utils/test-utils.ts +0 -205
  84. package/src/utils/validatePanelConstraints.test.ts +0 -143
  85. package/src/utils/validatePanelConstraints.ts +0 -69
  86. package/src/utils/validatePanelGroupLayout.test.ts +0 -148
  87. package/src/utils/validatePanelGroupLayout.ts +0 -95
  88. package/src/vendor/react.ts +0 -73
  89. package/src/vendor/stacking-order.ts +0 -139
@@ -1,336 +0,0 @@
1
- import { Direction, ResizeEvent } from "./types";
2
- import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
3
- import { getResizeEventCoordinates } from "./utils/events/getResizeEventCoordinates";
4
- import { getInputType } from "./utils/getInputType";
5
- import { intersects } from "./utils/rects/intersects";
6
- import { compare } from "./vendor/stacking-order";
7
-
8
- export type ResizeHandlerAction = "down" | "move" | "up";
9
- export type SetResizeHandlerState = (
10
- action: ResizeHandlerAction,
11
- isActive: boolean,
12
- event: ResizeEvent | null
13
- ) => void;
14
-
15
- export type PointerHitAreaMargins = {
16
- coarse: number;
17
- fine: number;
18
- };
19
-
20
- export type ResizeHandlerData = {
21
- direction: Direction;
22
- element: HTMLElement;
23
- hitAreaMargins: PointerHitAreaMargins;
24
- setResizeHandlerState: SetResizeHandlerState;
25
- };
26
-
27
- export const EXCEEDED_HORIZONTAL_MIN = 0b0001;
28
- export const EXCEEDED_HORIZONTAL_MAX = 0b0010;
29
- export const EXCEEDED_VERTICAL_MIN = 0b0100;
30
- export const EXCEEDED_VERTICAL_MAX = 0b1000;
31
-
32
- const isCoarsePointer = getInputType() === "coarse";
33
-
34
- let intersectingHandles: ResizeHandlerData[] = [];
35
- let isPointerDown = false;
36
- let ownerDocumentCounts: Map<Document, number> = new Map();
37
- let panelConstraintFlags: Map<string, number> = new Map();
38
-
39
- const registeredResizeHandlers = new Set<ResizeHandlerData>();
40
-
41
- export function registerResizeHandle(
42
- resizeHandleId: string,
43
- element: HTMLElement,
44
- direction: Direction,
45
- hitAreaMargins: PointerHitAreaMargins,
46
- setResizeHandlerState: SetResizeHandlerState
47
- ) {
48
- const { ownerDocument } = element;
49
-
50
- const data: ResizeHandlerData = {
51
- direction,
52
- element,
53
- hitAreaMargins,
54
- setResizeHandlerState,
55
- };
56
-
57
- const count = ownerDocumentCounts.get(ownerDocument) ?? 0;
58
- ownerDocumentCounts.set(ownerDocument, count + 1);
59
-
60
- registeredResizeHandlers.add(data);
61
-
62
- updateListeners();
63
-
64
- return function unregisterResizeHandle() {
65
- panelConstraintFlags.delete(resizeHandleId);
66
- registeredResizeHandlers.delete(data);
67
-
68
- const count = ownerDocumentCounts.get(ownerDocument) ?? 1;
69
- ownerDocumentCounts.set(ownerDocument, count - 1);
70
-
71
- updateListeners();
72
-
73
- if (count === 1) {
74
- ownerDocumentCounts.delete(ownerDocument);
75
- }
76
-
77
- // If the resize handle that is currently unmounting is intersecting with the pointer,
78
- // update the global pointer to account for the change
79
- if (intersectingHandles.includes(data)) {
80
- const index = intersectingHandles.indexOf(data);
81
- if (index >= 0) {
82
- intersectingHandles.splice(index, 1);
83
- }
84
-
85
- updateCursor();
86
-
87
- // Also instruct the handle to stop dragging; this prevents the parent group from being left in an inconsistent state
88
- // See github.com/bvaughn/react-resizable-panels/issues/402
89
- setResizeHandlerState("up", true, null);
90
- }
91
- };
92
- }
93
-
94
- function handlePointerDown(event: PointerEvent) {
95
- const { target } = event;
96
- const { x, y } = getResizeEventCoordinates(event);
97
-
98
- isPointerDown = true;
99
-
100
- recalculateIntersectingHandles({ target, x, y });
101
- updateListeners();
102
-
103
- if (intersectingHandles.length > 0) {
104
- updateResizeHandlerStates("down", event);
105
-
106
- event.preventDefault();
107
- event.stopPropagation();
108
- }
109
- }
110
-
111
- function handlePointerMove(event: PointerEvent) {
112
- const { x, y } = getResizeEventCoordinates(event);
113
-
114
- // Edge case (see #340)
115
- // Detect when the pointer has been released outside an iframe on a different domain
116
- if (isPointerDown && event.buttons === 0) {
117
- isPointerDown = false;
118
-
119
- updateResizeHandlerStates("up", event);
120
- }
121
-
122
- if (!isPointerDown) {
123
- const { target } = event;
124
-
125
- // Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
126
- // at that point, the handles may not move with the pointer (depending on constraints)
127
- // but the same set of active handles should be locked until the pointer is released
128
- recalculateIntersectingHandles({ target, x, y });
129
- }
130
-
131
- updateResizeHandlerStates("move", event);
132
-
133
- // Update cursor based on return value(s) from active handles
134
- updateCursor();
135
-
136
- if (intersectingHandles.length > 0) {
137
- event.preventDefault();
138
- }
139
- }
140
-
141
- function handlePointerUp(event: ResizeEvent) {
142
- const { target } = event;
143
- const { x, y } = getResizeEventCoordinates(event);
144
-
145
- panelConstraintFlags.clear();
146
- isPointerDown = false;
147
-
148
- if (intersectingHandles.length > 0) {
149
- event.preventDefault();
150
- }
151
-
152
- updateResizeHandlerStates("up", event);
153
- recalculateIntersectingHandles({ target, x, y });
154
- updateCursor();
155
-
156
- updateListeners();
157
- }
158
-
159
- function recalculateIntersectingHandles({
160
- target,
161
- x,
162
- y,
163
- }: {
164
- target: EventTarget | null;
165
- x: number;
166
- y: number;
167
- }) {
168
- intersectingHandles.splice(0);
169
-
170
- let targetElement: HTMLElement | null = null;
171
- if (target instanceof HTMLElement) {
172
- targetElement = target;
173
- }
174
-
175
- registeredResizeHandlers.forEach((data) => {
176
- const { element: dragHandleElement, hitAreaMargins } = data;
177
-
178
- const dragHandleRect = dragHandleElement.getBoundingClientRect();
179
- const { bottom, left, right, top } = dragHandleRect;
180
-
181
- const margin = isCoarsePointer
182
- ? hitAreaMargins.coarse
183
- : hitAreaMargins.fine;
184
-
185
- const eventIntersects =
186
- x >= left - margin &&
187
- x <= right + margin &&
188
- y >= top - margin &&
189
- y <= bottom + margin;
190
-
191
- if (eventIntersects) {
192
- // TRICKY
193
- // We listen for pointers events at the root in order to support hit area margins
194
- // (determining when the pointer is close enough to an element to be considered a "hit")
195
- // Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
196
- // so at this point we need to compare stacking order of a potentially intersecting drag handle,
197
- // and the element that was actually clicked/touched
198
- if (
199
- targetElement !== null &&
200
- document.contains(targetElement) &&
201
- dragHandleElement !== targetElement &&
202
- !dragHandleElement.contains(targetElement) &&
203
- !targetElement.contains(dragHandleElement) &&
204
- // Calculating stacking order has a cost, so we should avoid it if possible
205
- // That is why we only check potentially intersecting handles,
206
- // and why we skip if the event target is within the handle's DOM
207
- compare(targetElement, dragHandleElement) > 0
208
- ) {
209
- // If the target is above the drag handle, then we also need to confirm they overlap
210
- // If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
211
- //
212
- // It's not enough to compare only the target
213
- // The target might be a small element inside of a larger container
214
- // (For example, a SPAN or a DIV inside of a larger modal dialog)
215
- let currentElement: HTMLElement | null = targetElement;
216
- let didIntersect = false;
217
- while (currentElement) {
218
- if (currentElement.contains(dragHandleElement)) {
219
- break;
220
- } else if (
221
- intersects(
222
- currentElement.getBoundingClientRect(),
223
- dragHandleRect,
224
- true
225
- )
226
- ) {
227
- didIntersect = true;
228
- break;
229
- }
230
-
231
- currentElement = currentElement.parentElement;
232
- }
233
-
234
- if (didIntersect) {
235
- return;
236
- }
237
- }
238
-
239
- intersectingHandles.push(data);
240
- }
241
- });
242
- }
243
-
244
- export function reportConstraintsViolation(
245
- resizeHandleId: string,
246
- flag: number
247
- ) {
248
- panelConstraintFlags.set(resizeHandleId, flag);
249
- }
250
-
251
- function updateCursor() {
252
- let intersectsHorizontal = false;
253
- let intersectsVertical = false;
254
-
255
- intersectingHandles.forEach((data) => {
256
- const { direction } = data;
257
-
258
- if (direction === "horizontal") {
259
- intersectsHorizontal = true;
260
- } else {
261
- intersectsVertical = true;
262
- }
263
- });
264
-
265
- let constraintFlags = 0;
266
- panelConstraintFlags.forEach((flag) => {
267
- constraintFlags |= flag;
268
- });
269
-
270
- if (intersectsHorizontal && intersectsVertical) {
271
- setGlobalCursorStyle("intersection", constraintFlags);
272
- } else if (intersectsHorizontal) {
273
- setGlobalCursorStyle("horizontal", constraintFlags);
274
- } else if (intersectsVertical) {
275
- setGlobalCursorStyle("vertical", constraintFlags);
276
- } else {
277
- resetGlobalCursorStyle();
278
- }
279
- }
280
-
281
- function updateListeners() {
282
- ownerDocumentCounts.forEach((_, ownerDocument) => {
283
- const { body } = ownerDocument;
284
-
285
- body.removeEventListener("contextmenu", handlePointerUp);
286
- body.removeEventListener("pointerdown", handlePointerDown);
287
- body.removeEventListener("pointerleave", handlePointerMove);
288
- body.removeEventListener("pointermove", handlePointerMove);
289
- });
290
-
291
- window.removeEventListener("pointerup", handlePointerUp);
292
- window.removeEventListener("pointercancel", handlePointerUp);
293
-
294
- if (registeredResizeHandlers.size > 0) {
295
- if (isPointerDown) {
296
- if (intersectingHandles.length > 0) {
297
- ownerDocumentCounts.forEach((count, ownerDocument) => {
298
- const { body } = ownerDocument;
299
-
300
- if (count > 0) {
301
- body.addEventListener("contextmenu", handlePointerUp);
302
- body.addEventListener("pointerleave", handlePointerMove);
303
- body.addEventListener("pointermove", handlePointerMove);
304
- }
305
- });
306
- }
307
-
308
- window.addEventListener("pointerup", handlePointerUp);
309
- window.addEventListener("pointercancel", handlePointerUp);
310
- } else {
311
- ownerDocumentCounts.forEach((count, ownerDocument) => {
312
- const { body } = ownerDocument;
313
-
314
- if (count > 0) {
315
- body.addEventListener("pointerdown", handlePointerDown, {
316
- capture: true,
317
- });
318
- body.addEventListener("pointermove", handlePointerMove);
319
- }
320
- });
321
- }
322
- }
323
- }
324
-
325
- function updateResizeHandlerStates(
326
- action: ResizeHandlerAction,
327
- event: ResizeEvent
328
- ) {
329
- registeredResizeHandlers.forEach((data) => {
330
- const { setResizeHandlerState } = data;
331
-
332
- const isActive = intersectingHandles.includes(data);
333
-
334
- setResizeHandlerState(action, isActive, event);
335
- });
336
- }
package/src/constants.ts DELETED
@@ -1 +0,0 @@
1
- export const PRECISION = 10;
@@ -1 +0,0 @@
1
- export const isBrowser = true;
@@ -1 +0,0 @@
1
- export const isDevelopment = true;
@@ -1 +0,0 @@
1
- export const isBrowser = false;
@@ -1 +0,0 @@
1
- export const isDevelopment = false;
@@ -1 +0,0 @@
1
- export const isBrowser = typeof window !== "undefined";
@@ -1,7 +0,0 @@
1
- import { useCallback, useState } from "../vendor/react";
2
-
3
- export function useForceUpdate() {
4
- const [_, setCount] = useState(0);
5
-
6
- return useCallback(() => setCount((prevCount) => prevCount + 1), []);
7
- }
@@ -1,8 +0,0 @@
1
- import { isBrowser } from "#is-browser";
2
- import { useLayoutEffect_do_not_use_directly } from "../vendor/react";
3
-
4
- const useIsomorphicLayoutEffect = isBrowser
5
- ? useLayoutEffect_do_not_use_directly
6
- : () => {};
7
-
8
- export default useIsomorphicLayoutEffect;
@@ -1,19 +0,0 @@
1
- import { useId, useRef } from "../vendor/react";
2
-
3
- const wrappedUseId: () => string | null =
4
- typeof useId === "function" ? useId : (): null => null;
5
-
6
- let counter = 0;
7
-
8
- export default function useUniqueId(
9
- idFromParams: string | null = null
10
- ): string {
11
- const idFromUseId = wrappedUseId();
12
-
13
- const idRef = useRef<string | null>(idFromParams || idFromUseId || null);
14
- if (idRef.current === null) {
15
- idRef.current = "" + counter++;
16
- }
17
-
18
- return idFromParams ?? idRef.current;
19
- }
@@ -1,90 +0,0 @@
1
- import { ResizeHandler } from "../types";
2
- import { assert } from "../utils/assert";
3
- import { getResizeHandleElement } from "../utils/dom/getResizeHandleElement";
4
- import { getResizeHandleElementIndex } from "../utils/dom/getResizeHandleElementIndex";
5
- import { getResizeHandleElementsForGroup } from "../utils/dom/getResizeHandleElementsForGroup";
6
- import { useEffect } from "../vendor/react";
7
-
8
- // https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/
9
-
10
- export function useWindowSplitterResizeHandlerBehavior({
11
- disabled,
12
- handleId,
13
- resizeHandler,
14
- panelGroupElement,
15
- }: {
16
- disabled: boolean;
17
- handleId: string;
18
- resizeHandler: ResizeHandler | null;
19
- panelGroupElement: ParentNode | null;
20
- }): void {
21
- useEffect(() => {
22
- if (disabled || resizeHandler == null || panelGroupElement == null) {
23
- return;
24
- }
25
-
26
- const handleElement = getResizeHandleElement(handleId, panelGroupElement);
27
- if (handleElement == null) {
28
- return;
29
- }
30
-
31
- const onKeyDown = (event: KeyboardEvent) => {
32
- if (event.defaultPrevented) {
33
- return;
34
- }
35
-
36
- switch (event.key) {
37
- case "ArrowDown":
38
- case "ArrowLeft":
39
- case "ArrowRight":
40
- case "ArrowUp":
41
- case "End":
42
- case "Home": {
43
- event.preventDefault();
44
-
45
- resizeHandler(event);
46
- break;
47
- }
48
- case "F6": {
49
- event.preventDefault();
50
-
51
- const groupId = handleElement.getAttribute("data-panel-group-id");
52
- assert(groupId, `No group element found for id "${groupId}"`);
53
-
54
- const handles = getResizeHandleElementsForGroup(
55
- groupId,
56
- panelGroupElement
57
- );
58
- const index = getResizeHandleElementIndex(
59
- groupId,
60
- handleId,
61
- panelGroupElement
62
- );
63
-
64
- assert(
65
- index !== null,
66
- `No resize element found for id "${handleId}"`
67
- );
68
-
69
- const nextIndex = event.shiftKey
70
- ? index > 0
71
- ? index - 1
72
- : handles.length - 1
73
- : index + 1 < handles.length
74
- ? index + 1
75
- : 0;
76
-
77
- const nextHandle = handles[nextIndex] as HTMLElement;
78
- nextHandle.focus();
79
-
80
- break;
81
- }
82
- }
83
- };
84
-
85
- handleElement.addEventListener("keydown", onKeyDown);
86
- return () => {
87
- handleElement.removeEventListener("keydown", onKeyDown);
88
- };
89
- }, [panelGroupElement, disabled, handleId, resizeHandler]);
90
- }
@@ -1,201 +0,0 @@
1
- import { isDevelopment } from "#is-development";
2
- import { PanelData } from "../Panel";
3
- import { Direction } from "../types";
4
- import { adjustLayoutByDelta } from "../utils/adjustLayoutByDelta";
5
- import { assert } from "../utils/assert";
6
- import { calculateAriaValues } from "../utils/calculateAriaValues";
7
- import { determinePivotIndices } from "../utils/determinePivotIndices";
8
- import { getPanelGroupElement } from "../utils/dom/getPanelGroupElement";
9
- import { getResizeHandleElementsForGroup } from "../utils/dom/getResizeHandleElementsForGroup";
10
- import { getResizeHandlePanelIds } from "../utils/dom/getResizeHandlePanelIds";
11
- import { fuzzyNumbersEqual } from "../utils/numbers/fuzzyNumbersEqual";
12
- import { RefObject, useEffect, useRef } from "../vendor/react";
13
- import useIsomorphicLayoutEffect from "./useIsomorphicEffect";
14
-
15
- // https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/
16
-
17
- export function useWindowSplitterPanelGroupBehavior({
18
- committedValuesRef,
19
- eagerValuesRef,
20
- groupId,
21
- layout,
22
- panelDataArray,
23
- panelGroupElement,
24
- setLayout,
25
- }: {
26
- committedValuesRef: RefObject<{
27
- direction: Direction;
28
- }>;
29
- eagerValuesRef: RefObject<{
30
- panelDataArray: PanelData[];
31
- }>;
32
- groupId: string;
33
- layout: number[];
34
- panelDataArray: PanelData[];
35
- panelGroupElement: ParentNode | null;
36
- setLayout: (sizes: number[]) => void;
37
- }): void {
38
- const devWarningsRef = useRef<{
39
- didWarnAboutMissingResizeHandle: boolean;
40
- }>({
41
- didWarnAboutMissingResizeHandle: false,
42
- });
43
-
44
- useIsomorphicLayoutEffect(() => {
45
- if (!panelGroupElement) {
46
- return;
47
- }
48
- const resizeHandleElements = getResizeHandleElementsForGroup(
49
- groupId,
50
- panelGroupElement
51
- );
52
-
53
- for (let index = 0; index < panelDataArray.length - 1; index++) {
54
- const { valueMax, valueMin, valueNow } = calculateAriaValues({
55
- layout,
56
- panelsArray: panelDataArray,
57
- pivotIndices: [index, index + 1],
58
- });
59
-
60
- const resizeHandleElement = resizeHandleElements[index];
61
- if (resizeHandleElement == null) {
62
- if (isDevelopment) {
63
- const { didWarnAboutMissingResizeHandle } = devWarningsRef.current;
64
-
65
- if (!didWarnAboutMissingResizeHandle) {
66
- devWarningsRef.current.didWarnAboutMissingResizeHandle = true;
67
-
68
- console.warn(
69
- `WARNING: Missing resize handle for PanelGroup "${groupId}"`
70
- );
71
- }
72
- }
73
- } else {
74
- const panelData = panelDataArray[index];
75
- assert(panelData, `No panel data found for index "${index}"`);
76
-
77
- resizeHandleElement.setAttribute("aria-controls", panelData.id);
78
- resizeHandleElement.setAttribute(
79
- "aria-valuemax",
80
- "" + Math.round(valueMax)
81
- );
82
- resizeHandleElement.setAttribute(
83
- "aria-valuemin",
84
- "" + Math.round(valueMin)
85
- );
86
- resizeHandleElement.setAttribute(
87
- "aria-valuenow",
88
- valueNow != null ? "" + Math.round(valueNow) : ""
89
- );
90
- }
91
- }
92
-
93
- return () => {
94
- resizeHandleElements.forEach((resizeHandleElement, index) => {
95
- resizeHandleElement.removeAttribute("aria-controls");
96
- resizeHandleElement.removeAttribute("aria-valuemax");
97
- resizeHandleElement.removeAttribute("aria-valuemin");
98
- resizeHandleElement.removeAttribute("aria-valuenow");
99
- });
100
- };
101
- }, [groupId, layout, panelDataArray, panelGroupElement]);
102
-
103
- useEffect(() => {
104
- if (!panelGroupElement) {
105
- return;
106
- }
107
- const eagerValues = eagerValuesRef.current;
108
- assert(eagerValues, `Eager values not found`);
109
-
110
- const { panelDataArray } = eagerValues;
111
- const groupElement = getPanelGroupElement(groupId, panelGroupElement);
112
- assert(groupElement != null, `No group found for id "${groupId}"`);
113
-
114
- const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
115
- assert(handles, `No resize handles found for group id "${groupId}"`);
116
-
117
- const cleanupFunctions = handles.map((handle) => {
118
- const handleId = handle.getAttribute("data-panel-resize-handle-id");
119
- assert(handleId, `Resize handle element has no handle id attribute`);
120
-
121
- const [idBefore, idAfter] = getResizeHandlePanelIds(
122
- groupId,
123
- handleId,
124
- panelDataArray,
125
- panelGroupElement
126
- );
127
- if (idBefore == null || idAfter == null) {
128
- return () => {};
129
- }
130
-
131
- const onKeyDown = (event: KeyboardEvent) => {
132
- if (event.defaultPrevented) {
133
- return;
134
- }
135
-
136
- switch (event.key) {
137
- case "Enter": {
138
- event.preventDefault();
139
-
140
- const index = panelDataArray.findIndex(
141
- (panelData) => panelData.id === idBefore
142
- );
143
- if (index >= 0) {
144
- const panelData = panelDataArray[index];
145
- assert(panelData, `No panel data found for index ${index}`);
146
-
147
- const size = layout[index];
148
-
149
- const {
150
- collapsedSize = 0,
151
- collapsible,
152
- minSize = 0,
153
- } = panelData.constraints;
154
-
155
- if (size != null && collapsible) {
156
- const nextLayout = adjustLayoutByDelta({
157
- delta: fuzzyNumbersEqual(size, collapsedSize)
158
- ? minSize - collapsedSize
159
- : collapsedSize - size,
160
- initialLayout: layout,
161
- panelConstraints: panelDataArray.map(
162
- (panelData) => panelData.constraints
163
- ),
164
- pivotIndices: determinePivotIndices(
165
- groupId,
166
- handleId,
167
- panelGroupElement
168
- ),
169
- prevLayout: layout,
170
- trigger: "keyboard",
171
- });
172
- if (layout !== nextLayout) {
173
- setLayout(nextLayout);
174
- }
175
- }
176
- }
177
- break;
178
- }
179
- }
180
- };
181
-
182
- handle.addEventListener("keydown", onKeyDown);
183
-
184
- return () => {
185
- handle.removeEventListener("keydown", onKeyDown);
186
- };
187
- });
188
-
189
- return () => {
190
- cleanupFunctions.forEach((cleanupFunction) => cleanupFunction());
191
- };
192
- }, [
193
- panelGroupElement,
194
- committedValuesRef,
195
- eagerValuesRef,
196
- groupId,
197
- layout,
198
- panelDataArray,
199
- setLayout,
200
- ]);
201
- }