react-resizable-panels 0.0.54 → 0.0.56

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 (86) hide show
  1. package/.eslintrc.cjs +26 -0
  2. package/CHANGELOG.md +253 -80
  3. package/README.md +55 -49
  4. package/dist/declarations/src/Panel.d.ts +76 -20
  5. package/dist/declarations/src/PanelGroup.d.ts +29 -21
  6. package/dist/declarations/src/PanelResizeHandle.d.ts +1 -1
  7. package/dist/declarations/src/index.d.ts +5 -5
  8. package/dist/declarations/src/types.d.ts +3 -25
  9. package/dist/declarations/src/vendor/react.d.ts +4 -4
  10. package/dist/react-resizable-panels.browser.cjs.js +1279 -796
  11. package/dist/react-resizable-panels.browser.development.cjs.js +1404 -809
  12. package/dist/react-resizable-panels.browser.development.esm.js +1398 -803
  13. package/dist/react-resizable-panels.browser.esm.js +1279 -796
  14. package/dist/react-resizable-panels.cjs.js +1279 -796
  15. package/dist/react-resizable-panels.cjs.js.map +1 -0
  16. package/dist/react-resizable-panels.development.cjs.js +1399 -804
  17. package/dist/react-resizable-panels.development.esm.js +1400 -805
  18. package/dist/react-resizable-panels.development.node.cjs.js +1172 -755
  19. package/dist/react-resizable-panels.development.node.esm.js +1173 -756
  20. package/dist/react-resizable-panels.esm.js +1279 -796
  21. package/dist/react-resizable-panels.esm.js.map +1 -0
  22. package/dist/react-resizable-panels.node.cjs.js +1064 -749
  23. package/dist/react-resizable-panels.node.esm.js +1065 -750
  24. package/jest.config.js +10 -0
  25. package/package.json +3 -1
  26. package/src/Panel.test.tsx +308 -0
  27. package/src/Panel.ts +179 -127
  28. package/src/PanelGroup.test.tsx +210 -0
  29. package/src/PanelGroup.ts +751 -580
  30. package/src/PanelGroupContext.ts +33 -0
  31. package/src/PanelResizeHandle.ts +13 -8
  32. package/src/hooks/useUniqueId.ts +1 -1
  33. package/src/hooks/useWindowSplitterBehavior.ts +9 -161
  34. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +185 -0
  35. package/src/index.ts +24 -11
  36. package/src/types.ts +3 -29
  37. package/src/utils/adjustLayoutByDelta.test.ts +1808 -0
  38. package/src/utils/adjustLayoutByDelta.ts +211 -0
  39. package/src/utils/calculateAriaValues.test.ts +111 -0
  40. package/src/utils/calculateAriaValues.ts +67 -0
  41. package/src/utils/calculateDeltaPercentage.ts +68 -0
  42. package/src/utils/calculateDragOffsetPercentage.ts +30 -0
  43. package/src/utils/calculateUnsafeDefaultLayout.test.ts +92 -0
  44. package/src/utils/calculateUnsafeDefaultLayout.ts +55 -0
  45. package/src/utils/callPanelCallbacks.ts +81 -0
  46. package/src/utils/compareLayouts.test.ts +9 -0
  47. package/src/utils/compareLayouts.ts +12 -0
  48. package/src/utils/computePanelFlexBoxStyle.ts +44 -0
  49. package/src/utils/computePercentagePanelConstraints.test.ts +71 -0
  50. package/src/utils/computePercentagePanelConstraints.ts +56 -0
  51. package/src/utils/convertPercentageToPixels.test.ts +9 -0
  52. package/src/utils/convertPercentageToPixels.ts +6 -0
  53. package/src/utils/convertPixelConstraintsToPercentages.ts +55 -0
  54. package/src/utils/convertPixelsToPercentage.test.ts +9 -0
  55. package/src/utils/convertPixelsToPercentage.ts +6 -0
  56. package/src/utils/determinePivotIndices.ts +10 -0
  57. package/src/utils/dom/calculateAvailablePanelSizeInPixels.ts +29 -0
  58. package/src/utils/dom/getAvailableGroupSizePixels.ts +29 -0
  59. package/src/utils/dom/getPanelElement.ts +7 -0
  60. package/src/utils/dom/getPanelGroupElement.ts +7 -0
  61. package/src/utils/dom/getResizeHandleElement.ts +9 -0
  62. package/src/utils/dom/getResizeHandleElementIndex.ts +12 -0
  63. package/src/utils/dom/getResizeHandleElementsForGroup.ts +9 -0
  64. package/src/utils/dom/getResizeHandlePanelIds.ts +18 -0
  65. package/src/utils/events.ts +13 -0
  66. package/src/utils/getPercentageSizeFromMixedSizes.test.ts +47 -0
  67. package/src/utils/getPercentageSizeFromMixedSizes.ts +15 -0
  68. package/src/utils/getResizeEventCursorPosition.ts +19 -0
  69. package/src/utils/initializeDefaultStorage.ts +26 -0
  70. package/src/utils/numbers/fuzzyCompareNumbers.test.ts +16 -0
  71. package/src/utils/numbers/fuzzyCompareNumbers.ts +17 -0
  72. package/src/utils/numbers/fuzzyNumbersEqual.ts +9 -0
  73. package/src/utils/resizePanel.ts +41 -0
  74. package/src/utils/serialization.ts +9 -4
  75. package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +23 -0
  76. package/src/utils/shouldMonitorPixelBasedConstraints.ts +13 -0
  77. package/src/utils/test-utils.ts +136 -0
  78. package/src/utils/validatePanelConstraints.test.ts +151 -0
  79. package/src/utils/validatePanelConstraints.ts +103 -0
  80. package/src/utils/validatePanelGroupLayout.test.ts +233 -0
  81. package/src/utils/validatePanelGroupLayout.ts +88 -0
  82. package/src/vendor/react.ts +4 -0
  83. package/.eslintrc.json +0 -22
  84. package/src/PanelContexts.ts +0 -20
  85. package/src/utils/coordinates.ts +0 -149
  86. package/src/utils/group.ts +0 -315
@@ -0,0 +1,233 @@
1
+ import { verifyExpectedWarnings } from "./test-utils";
2
+ import { validatePanelGroupLayout } from "./validatePanelGroupLayout";
3
+
4
+ describe("validatePanelGroupLayout", () => {
5
+ it("should accept requested layout if there are no constraints provided", () => {
6
+ expect(
7
+ validatePanelGroupLayout({
8
+ groupSizePixels: NaN,
9
+ layout: [10, 60, 30],
10
+ panelConstraints: [{}, {}, {}],
11
+ })
12
+ ).toEqual([10, 60, 30]);
13
+ });
14
+
15
+ it("should reject layouts that do not total 100%", () => {
16
+ verifyExpectedWarnings(
17
+ () =>
18
+ validatePanelGroupLayout({
19
+ groupSizePixels: NaN,
20
+ layout: [10, 20, 30],
21
+ panelConstraints: [{}, {}, {}],
22
+ }),
23
+ "Invalid layout total size"
24
+ );
25
+
26
+ verifyExpectedWarnings(
27
+ () =>
28
+ validatePanelGroupLayout({
29
+ groupSizePixels: NaN,
30
+ layout: [50, 100, 150],
31
+ panelConstraints: [{}, {}, {}],
32
+ }),
33
+ "Invalid layout total size"
34
+ );
35
+ });
36
+
37
+ it("should reject layouts that do not match the number of panels", () => {
38
+ expect(() =>
39
+ validatePanelGroupLayout({
40
+ groupSizePixels: NaN,
41
+ layout: [10, 20, 30],
42
+ panelConstraints: [{}, {}],
43
+ })
44
+ ).toThrow("Invalid 2 panel layout");
45
+
46
+ expect(() =>
47
+ validatePanelGroupLayout({
48
+ groupSizePixels: NaN,
49
+ layout: [50, 50],
50
+ panelConstraints: [{}, {}, {}],
51
+ })
52
+ ).toThrow("Invalid 3 panel layout");
53
+ });
54
+
55
+ describe("minimum size constraints", () => {
56
+ it("should adjust the layout to account for minimum percentage sizes", () => {
57
+ expect(
58
+ validatePanelGroupLayout({
59
+ groupSizePixels: NaN,
60
+ layout: [25, 75],
61
+ panelConstraints: [
62
+ {
63
+ minSizePercentage: 35,
64
+ },
65
+ {},
66
+ ],
67
+ })
68
+ ).toEqual([35, 65]);
69
+ });
70
+
71
+ it("should adjust the layout to account for minimum pixel sizes", () => {
72
+ expect(
73
+ validatePanelGroupLayout({
74
+ groupSizePixels: 400,
75
+ layout: [20, 80],
76
+ panelConstraints: [
77
+ {
78
+ minSizePixels: 100,
79
+ },
80
+ {},
81
+ ],
82
+ })
83
+ ).toEqual([25, 75]);
84
+ });
85
+
86
+ it("should account for multiple panels with minimum size constraints", () => {
87
+ expect(
88
+ validatePanelGroupLayout({
89
+ groupSizePixels: NaN,
90
+ layout: [20, 60, 20],
91
+ panelConstraints: [
92
+ {
93
+ minSizePercentage: 25,
94
+ },
95
+ {},
96
+ {
97
+ minSizePercentage: 25,
98
+ },
99
+ ],
100
+ })
101
+ ).toEqual([25, 50, 25]);
102
+ });
103
+ });
104
+
105
+ describe("maximum size constraints", () => {
106
+ it("should adjust the layout to account for maximum percentage sizes", () => {
107
+ expect(
108
+ validatePanelGroupLayout({
109
+ groupSizePixels: NaN,
110
+ layout: [25, 75],
111
+ panelConstraints: [{}, { maxSizePercentage: 65 }],
112
+ })
113
+ ).toEqual([35, 65]);
114
+ });
115
+
116
+ it("should adjust the layout to account for maximum pixel sizes", () => {
117
+ expect(
118
+ validatePanelGroupLayout({
119
+ groupSizePixels: 400,
120
+ layout: [20, 80],
121
+ panelConstraints: [
122
+ {},
123
+ {
124
+ maxSizePixels: 100,
125
+ },
126
+ ],
127
+ })
128
+ ).toEqual([75, 25]);
129
+ });
130
+
131
+ it("should account for multiple panels with maximum size constraints", () => {
132
+ expect(
133
+ validatePanelGroupLayout({
134
+ groupSizePixels: NaN,
135
+ layout: [20, 60, 20],
136
+ panelConstraints: [
137
+ {
138
+ maxSizePercentage: 15,
139
+ },
140
+ { maxSizePercentage: 50 },
141
+ {},
142
+ ],
143
+ })
144
+ ).toEqual([15, 50, 35]);
145
+ });
146
+ });
147
+
148
+ describe("collapsible panels", () => {
149
+ it("should not collapse a panel that's at or above the minimum size", () => {
150
+ expect(
151
+ validatePanelGroupLayout({
152
+ groupSizePixels: NaN,
153
+ layout: [25, 75],
154
+ panelConstraints: [{ collapsible: true, minSizePercentage: 25 }, {}],
155
+ })
156
+ ).toEqual([25, 75]);
157
+ });
158
+
159
+ it("should collapse a panel that's below the minimum percentage size", () => {
160
+ expect(
161
+ validatePanelGroupLayout({
162
+ groupSizePixels: NaN,
163
+ layout: [20, 80],
164
+ panelConstraints: [
165
+ {
166
+ collapsible: true,
167
+ collapsedSizePercentage: 10,
168
+ minSizePercentage: 25,
169
+ },
170
+ {},
171
+ ],
172
+ })
173
+ ).toEqual([10, 90]);
174
+ });
175
+
176
+ it("should collapse a panel that's below the minimum pixel size", () => {
177
+ expect(
178
+ validatePanelGroupLayout({
179
+ groupSizePixels: 400,
180
+ layout: [20, 80],
181
+ panelConstraints: [
182
+ {
183
+ collapsible: true,
184
+ collapsedSizePixels: 40,
185
+ minSizePixels: 100,
186
+ },
187
+ {},
188
+ ],
189
+ })
190
+ ).toEqual([10, 90]);
191
+ });
192
+ });
193
+
194
+ describe("combination of minimum and maximum size constraints", () => {
195
+ it("three panel min/max configuration", () => {
196
+ expect(
197
+ validatePanelGroupLayout({
198
+ groupSizePixels: NaN,
199
+ layout: [25, 50, 25],
200
+ panelConstraints: [
201
+ { minSizePercentage: 10, maxSizePercentage: 25 },
202
+ { maxSizePercentage: 75 },
203
+ { minSizePercentage: 10, maxSizePercentage: 50 },
204
+ ],
205
+ })
206
+ ).toEqual([25, 50, 25]);
207
+
208
+ expect(
209
+ validatePanelGroupLayout({
210
+ groupSizePixels: NaN,
211
+ layout: [5, 80, 15],
212
+ panelConstraints: [
213
+ { minSizePercentage: 10, maxSizePercentage: 25 },
214
+ { maxSizePercentage: 75 },
215
+ { minSizePercentage: 10, maxSizePercentage: 50 },
216
+ ],
217
+ })
218
+ ).toEqual([10, 75, 15]);
219
+
220
+ expect(
221
+ validatePanelGroupLayout({
222
+ groupSizePixels: NaN,
223
+ layout: [30, 10, 60],
224
+ panelConstraints: [
225
+ { minSizePercentage: 10, maxSizePercentage: 25 },
226
+ { maxSizePercentage: 75 },
227
+ { minSizePercentage: 10, maxSizePercentage: 50 },
228
+ ],
229
+ })
230
+ ).toEqual([25, 25, 50]);
231
+ });
232
+ });
233
+ });
@@ -0,0 +1,88 @@
1
+ import { isDevelopment } from "#is-development";
2
+ import { PanelConstraints } from "../Panel";
3
+ import { fuzzyNumbersEqual } from "./numbers/fuzzyNumbersEqual";
4
+ import { resizePanel } from "./resizePanel";
5
+
6
+ // All units must be in percentages; pixel values should be pre-converted
7
+ export function validatePanelGroupLayout({
8
+ groupSizePixels,
9
+ layout: prevLayout,
10
+ panelConstraints,
11
+ }: {
12
+ groupSizePixels: number;
13
+ layout: number[];
14
+ panelConstraints: PanelConstraints[];
15
+ }): number[] {
16
+ const nextLayout = [...prevLayout];
17
+
18
+ // Validate layout expectations
19
+ if (nextLayout.length !== panelConstraints.length) {
20
+ throw Error(
21
+ `Invalid ${panelConstraints.length} panel layout: ${nextLayout
22
+ .map((size) => `${size}%`)
23
+ .join(", ")}`
24
+ );
25
+ } else if (
26
+ !fuzzyNumbersEqual(
27
+ nextLayout.reduce((accumulated, current) => accumulated + current, 0),
28
+ 100
29
+ )
30
+ ) {
31
+ // This is not ideal so we should warn about it, but it may be recoverable in some cases
32
+ // (especially if the amount is small)
33
+ if (isDevelopment) {
34
+ console.warn(
35
+ `WARNING: Invalid layout total size: ${nextLayout
36
+ .map((size) => `${size}%`)
37
+ .join(", ")}`
38
+ );
39
+ }
40
+ }
41
+
42
+ let remainingSize = 0;
43
+
44
+ // First pass: Validate the proposed layout given each panel's constraints
45
+ for (let index = 0; index < panelConstraints.length; index++) {
46
+ const unsafeSize = nextLayout[index]!;
47
+
48
+ const safeSize = resizePanel({
49
+ groupSizePixels,
50
+ panelConstraints,
51
+ panelIndex: index,
52
+ size: unsafeSize,
53
+ });
54
+
55
+ if (unsafeSize != safeSize) {
56
+ remainingSize += unsafeSize - safeSize;
57
+
58
+ nextLayout[index] = safeSize;
59
+ }
60
+ }
61
+
62
+ // If there is additional, left over space, assign it to any panel(s) that permits it
63
+ // (It's not worth taking multiple additional passes to evenly distribute)
64
+ if (!fuzzyNumbersEqual(remainingSize, 0)) {
65
+ for (let index = 0; index < panelConstraints.length; index++) {
66
+ const prevSize = nextLayout[index]!;
67
+ const unsafeSize = prevSize + remainingSize;
68
+ const safeSize = resizePanel({
69
+ groupSizePixels,
70
+ panelConstraints,
71
+ panelIndex: index,
72
+ size: unsafeSize,
73
+ });
74
+
75
+ if (prevSize !== safeSize) {
76
+ remainingSize -= safeSize - prevSize;
77
+ nextLayout[index] = safeSize;
78
+
79
+ // Once we've used up the remainder, bail
80
+ if (fuzzyNumbersEqual(remainingSize, 0)) {
81
+ break;
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ return nextLayout;
88
+ }
@@ -13,6 +13,7 @@ import type {
13
13
  ElementType,
14
14
  ForwardedRef,
15
15
  MouseEvent,
16
+ PropsWithChildren,
16
17
  ReactNode,
17
18
  RefObject,
18
19
  TouchEvent,
@@ -21,6 +22,7 @@ import type {
21
22
  const {
22
23
  createElement,
23
24
  createContext,
25
+ createRef,
24
26
  forwardRef,
25
27
  useCallback,
26
28
  useContext,
@@ -38,6 +40,7 @@ const useId = (React as any)["useId".toString()] as () => string;
38
40
  export {
39
41
  createElement,
40
42
  createContext,
43
+ createRef,
41
44
  forwardRef,
42
45
  useCallback,
43
46
  useContext,
@@ -55,6 +58,7 @@ export type {
55
58
  ElementType,
56
59
  ForwardedRef,
57
60
  MouseEvent,
61
+ PropsWithChildren,
58
62
  ReactNode,
59
63
  RefObject,
60
64
  TouchEvent,
package/.eslintrc.json DELETED
@@ -1,22 +0,0 @@
1
- {
2
- "ignorePatterns": [".parcel-cache", "dist", "node_modules"],
3
- "parser": "@typescript-eslint/parser",
4
- "parserOptions": { "project": ["../../tsconfig.json"] },
5
- "plugins": ["@typescript-eslint", "no-restricted-imports", "react-hooks"],
6
- "root": true,
7
- "rules": {
8
- "no-restricted-imports": [
9
- "error",
10
- {
11
- "paths": ["react"]
12
- }
13
- ],
14
- "react-hooks/rules-of-hooks": "error",
15
- "react-hooks/exhaustive-deps": [
16
- "warn",
17
- {
18
- "additionalHooks": "(useIsomorphicLayoutEffect)"
19
- }
20
- ]
21
- }
22
- }
@@ -1,20 +0,0 @@
1
- import { CSSProperties, createContext } from "./vendor/react";
2
-
3
- import { PanelData, ResizeEvent, ResizeHandler } from "./types";
4
-
5
- export const PanelGroupContext = createContext<{
6
- activeHandleId: string | null;
7
- collapsePanel: (id: string) => void;
8
- direction: "horizontal" | "vertical";
9
- expandPanel: (id: string) => void;
10
- getPanelStyle: (id: string, defaultSize: number | null) => CSSProperties;
11
- groupId: string;
12
- registerPanel: (id: string, panel: PanelData) => void;
13
- registerResizeHandle: (id: string) => ResizeHandler;
14
- resizePanel: (id: string, percentage: number) => void;
15
- startDragging: (id: string, event: ResizeEvent) => void;
16
- stopDragging: () => void;
17
- unregisterPanel: (id: string) => void;
18
- } | null>(null);
19
-
20
- PanelGroupContext.displayName = "PanelGroupContext";
@@ -1,149 +0,0 @@
1
- import { PRECISION } from "../constants";
2
- import { InitialDragState } from "../PanelGroup";
3
- import { Direction, PanelData, ResizeEvent } from "../types";
4
- import {
5
- getPanelGroup,
6
- getResizeHandle,
7
- getResizeHandlePanelIds,
8
- } from "./group";
9
-
10
- export type Coordinates = {
11
- movement: number;
12
- offset: number;
13
- };
14
-
15
- export type Size = {
16
- height: number;
17
- width: number;
18
- };
19
-
20
- export function getDragOffset(
21
- event: ResizeEvent,
22
- handleId: string,
23
- direction: Direction,
24
- initialOffset: number = 0,
25
- initialHandleElementRect: DOMRect | null = null
26
- ): number {
27
- const isHorizontal = direction === "horizontal";
28
-
29
- let pointerOffset = 0;
30
- if (isMouseEvent(event)) {
31
- pointerOffset = isHorizontal ? event.clientX : event.clientY;
32
- } else if (isTouchEvent(event)) {
33
- const firstTouch = event.touches[0];
34
- pointerOffset = isHorizontal ? firstTouch.screenX : firstTouch.screenY;
35
- } else {
36
- return 0;
37
- }
38
-
39
- const handleElement = getResizeHandle(handleId)!;
40
- const rect =
41
- initialHandleElementRect || handleElement.getBoundingClientRect();
42
- const elementOffset = isHorizontal ? rect.left : rect.top;
43
-
44
- return pointerOffset - elementOffset - initialOffset;
45
- }
46
-
47
- // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
48
- export function getMovement(
49
- event: ResizeEvent,
50
- groupId: string,
51
- handleId: string,
52
- panelsArray: PanelData[],
53
- direction: Direction,
54
- prevSizes: number[],
55
- initialDragState: InitialDragState | null
56
- ): number {
57
- const {
58
- dragOffset = 0,
59
- dragHandleRect,
60
- sizes: initialSizes,
61
- } = initialDragState || {};
62
-
63
- // If we're resizing by mouse or touch, use the initial sizes as a base.
64
- // This has the benefit of causing force-collapsed panels to spring back open if drag is reversed.
65
- const baseSizes = initialSizes || prevSizes;
66
-
67
- if (isKeyDown(event)) {
68
- const isHorizontal = direction === "horizontal";
69
-
70
- const groupElement = getPanelGroup(groupId)!;
71
- const rect = groupElement.getBoundingClientRect();
72
- const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
73
-
74
- const denominator = event.shiftKey ? 10 : 100;
75
- const delta = groupSizeInPixels / denominator;
76
-
77
- let movement = 0;
78
- switch (event.key) {
79
- case "ArrowDown":
80
- movement = isHorizontal ? 0 : delta;
81
- break;
82
- case "ArrowLeft":
83
- movement = isHorizontal ? -delta : 0;
84
- break;
85
- case "ArrowRight":
86
- movement = isHorizontal ? delta : 0;
87
- break;
88
- case "ArrowUp":
89
- movement = isHorizontal ? 0 : -delta;
90
- break;
91
- case "End":
92
- movement = groupSizeInPixels;
93
- break;
94
- case "Home":
95
- movement = -groupSizeInPixels;
96
- break;
97
- }
98
-
99
- // If the Panel being resized is collapsible,
100
- // we need to special case resizing around the minSize boundary.
101
- // If contracting, Panels should shrink to their minSize and then snap to fully collapsed.
102
- // If expanding from collapsed, they should snap back to their minSize.
103
- const [idBefore, idAfter] = getResizeHandlePanelIds(
104
- groupId,
105
- handleId,
106
- panelsArray
107
- );
108
- const targetPanelId = movement < 0 ? idBefore : idAfter;
109
- const targetPanelIndex = panelsArray.findIndex(
110
- (panel) => panel.current.id === targetPanelId
111
- );
112
- const targetPanel = panelsArray[targetPanelIndex];
113
- if (targetPanel.current.collapsible) {
114
- const baseSize = baseSizes[targetPanelIndex];
115
- if (
116
- baseSize === 0 ||
117
- baseSize.toPrecision(PRECISION) ===
118
- targetPanel.current.minSize.toPrecision(PRECISION)
119
- ) {
120
- movement =
121
- movement < 0
122
- ? -targetPanel.current.minSize * groupSizeInPixels
123
- : targetPanel.current.minSize * groupSizeInPixels;
124
- }
125
- }
126
-
127
- return movement;
128
- } else {
129
- return getDragOffset(
130
- event,
131
- handleId,
132
- direction,
133
- dragOffset,
134
- dragHandleRect
135
- );
136
- }
137
- }
138
-
139
- export function isKeyDown(event: ResizeEvent): event is KeyboardEvent {
140
- return event.type === "keydown";
141
- }
142
-
143
- export function isMouseEvent(event: ResizeEvent): event is MouseEvent {
144
- return event.type.startsWith("mouse");
145
- }
146
-
147
- export function isTouchEvent(event: ResizeEvent): event is TouchEvent {
148
- return event.type.startsWith("touch");
149
- }