react-resizable-panels 2.1.6 → 2.1.8

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 (92) hide show
  1. package/README.md +4 -0
  2. package/dist/declarations/src/Panel.d.ts +1 -1
  3. package/dist/declarations/src/PanelGroup.d.ts +1 -1
  4. package/dist/declarations/src/PanelResizeHandle.d.ts +6 -3
  5. package/dist/react-resizable-panels.browser.cjs.js +90 -94
  6. package/dist/react-resizable-panels.browser.development.cjs.js +90 -94
  7. package/dist/react-resizable-panels.browser.development.esm.js +38 -41
  8. package/dist/react-resizable-panels.browser.esm.js +38 -41
  9. package/dist/react-resizable-panels.cjs.js +90 -94
  10. package/dist/react-resizable-panels.development.cjs.js +90 -94
  11. package/dist/react-resizable-panels.development.esm.js +38 -41
  12. package/dist/react-resizable-panels.development.node.cjs.js +89 -92
  13. package/dist/react-resizable-panels.development.node.esm.js +37 -39
  14. package/dist/react-resizable-panels.esm.js +38 -41
  15. package/dist/react-resizable-panels.node.cjs.js +89 -92
  16. package/dist/react-resizable-panels.node.esm.js +37 -39
  17. package/package.json +7 -2
  18. package/.eslintrc.cjs +0 -27
  19. package/CHANGELOG.md +0 -574
  20. package/dist/declarations/src/vendor/react.d.ts +0 -7
  21. package/jest.config.js +0 -10
  22. package/src/Panel.test.tsx +0 -1084
  23. package/src/Panel.ts +0 -259
  24. package/src/PanelGroup.test.tsx +0 -443
  25. package/src/PanelGroup.ts +0 -999
  26. package/src/PanelGroupContext.ts +0 -42
  27. package/src/PanelResizeHandle.test.tsx +0 -367
  28. package/src/PanelResizeHandle.ts +0 -246
  29. package/src/PanelResizeHandleRegistry.ts +0 -336
  30. package/src/constants.ts +0 -1
  31. package/src/env-conditions/browser.ts +0 -1
  32. package/src/env-conditions/development.ts +0 -1
  33. package/src/env-conditions/node.ts +0 -1
  34. package/src/env-conditions/production.ts +0 -1
  35. package/src/env-conditions/unknown.ts +0 -1
  36. package/src/hooks/useForceUpdate.ts +0 -7
  37. package/src/hooks/useIsomorphicEffect.ts +0 -8
  38. package/src/hooks/useUniqueId.ts +0 -19
  39. package/src/hooks/useWindowSplitterBehavior.ts +0 -90
  40. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +0 -201
  41. package/src/index.ts +0 -77
  42. package/src/types.ts +0 -5
  43. package/src/utils/adjustLayoutByDelta.test.ts +0 -2061
  44. package/src/utils/adjustLayoutByDelta.ts +0 -308
  45. package/src/utils/arrays.ts +0 -13
  46. package/src/utils/assert.ts +0 -10
  47. package/src/utils/calculateAriaValues.test.ts +0 -106
  48. package/src/utils/calculateAriaValues.ts +0 -45
  49. package/src/utils/calculateDeltaPercentage.ts +0 -63
  50. package/src/utils/calculateDragOffsetPercentage.ts +0 -40
  51. package/src/utils/calculateUnsafeDefaultLayout.test.ts +0 -87
  52. package/src/utils/calculateUnsafeDefaultLayout.ts +0 -50
  53. package/src/utils/callPanelCallbacks.ts +0 -49
  54. package/src/utils/compareLayouts.test.ts +0 -9
  55. package/src/utils/compareLayouts.ts +0 -12
  56. package/src/utils/computePanelFlexBoxStyle.test.ts +0 -123
  57. package/src/utils/computePanelFlexBoxStyle.ts +0 -50
  58. package/src/utils/csp.ts +0 -9
  59. package/src/utils/cursor.ts +0 -103
  60. package/src/utils/debounce.ts +0 -18
  61. package/src/utils/determinePivotIndices.ts +0 -15
  62. package/src/utils/dom/getPanelElement.ts +0 -10
  63. package/src/utils/dom/getPanelElementsForGroup.ts +0 -8
  64. package/src/utils/dom/getPanelGroupElement.ts +0 -21
  65. package/src/utils/dom/getResizeHandleElement.ts +0 -10
  66. package/src/utils/dom/getResizeHandleElementIndex.ts +0 -13
  67. package/src/utils/dom/getResizeHandleElementsForGroup.ts +0 -10
  68. package/src/utils/dom/getResizeHandlePanelIds.ts +0 -19
  69. package/src/utils/events/getResizeEventCoordinates.ts +0 -23
  70. package/src/utils/events/getResizeEventCursorPosition.ts +0 -14
  71. package/src/utils/events/index.ts +0 -13
  72. package/src/utils/getInputType.ts +0 -5
  73. package/src/utils/initializeDefaultStorage.ts +0 -26
  74. package/src/utils/numbers/fuzzyCompareNumbers.test.ts +0 -16
  75. package/src/utils/numbers/fuzzyCompareNumbers.ts +0 -21
  76. package/src/utils/numbers/fuzzyLayoutsEqual.ts +0 -22
  77. package/src/utils/numbers/fuzzyNumbersEqual.ts +0 -9
  78. package/src/utils/rects/getIntersectingRectangle.test.ts +0 -198
  79. package/src/utils/rects/getIntersectingRectangle.ts +0 -28
  80. package/src/utils/rects/intersects.test.ts +0 -197
  81. package/src/utils/rects/intersects.ts +0 -23
  82. package/src/utils/rects/types.ts +0 -6
  83. package/src/utils/resizePanel.test.ts +0 -59
  84. package/src/utils/resizePanel.ts +0 -47
  85. package/src/utils/serialization.ts +0 -87
  86. package/src/utils/test-utils.ts +0 -205
  87. package/src/utils/validatePanelConstraints.test.ts +0 -143
  88. package/src/utils/validatePanelConstraints.ts +0 -69
  89. package/src/utils/validatePanelGroupLayout.test.ts +0 -148
  90. package/src/utils/validatePanelGroupLayout.ts +0 -95
  91. package/src/vendor/react.ts +0 -73
  92. 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
- }