mtrl-addons 0.2.2 → 0.2.4
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/components/index.ts → dist/components/index.d.ts} +0 -2
- package/dist/components/vlist/config.d.ts +86 -0
- package/{src/components/vlist/constants.ts → dist/components/vlist/constants.d.ts} +10 -11
- package/dist/components/vlist/features/api.d.ts +7 -0
- package/{src/components/vlist/features/index.ts → dist/components/vlist/features/index.d.ts} +0 -2
- package/dist/components/vlist/features/selection.d.ts +6 -0
- package/dist/components/vlist/features/viewport.d.ts +9 -0
- package/dist/components/vlist/features.d.ts +31 -0
- package/{src/components/vlist/index.ts → dist/components/vlist/index.d.ts} +1 -10
- package/dist/components/vlist/types.d.ts +596 -0
- package/dist/components/vlist/vlist.d.ts +29 -0
- package/dist/core/compose/features/gestures/index.d.ts +86 -0
- package/dist/core/compose/features/gestures/longpress.d.ts +85 -0
- package/dist/core/compose/features/gestures/pan.d.ts +108 -0
- package/dist/core/compose/features/gestures/pinch.d.ts +111 -0
- package/dist/core/compose/features/gestures/rotate.d.ts +111 -0
- package/dist/core/compose/features/gestures/swipe.d.ts +149 -0
- package/dist/core/compose/features/gestures/tap.d.ts +79 -0
- package/{src/core/compose/features/index.ts → dist/core/compose/features/index.d.ts} +1 -2
- package/{src/core/compose/index.ts → dist/core/compose/index.d.ts} +2 -11
- package/{src/core/gestures/index.ts → dist/core/gestures/index.d.ts} +1 -20
- package/dist/core/gestures/longpress.d.ts +23 -0
- package/dist/core/gestures/manager.d.ts +14 -0
- package/dist/core/gestures/pan.d.ts +12 -0
- package/dist/core/gestures/pinch.d.ts +14 -0
- package/dist/core/gestures/rotate.d.ts +14 -0
- package/dist/core/gestures/swipe.d.ts +20 -0
- package/dist/core/gestures/tap.d.ts +12 -0
- package/dist/core/gestures/types.d.ts +320 -0
- package/dist/core/gestures/utils.d.ts +57 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/layout/config.d.ts +33 -0
- package/dist/core/layout/index.d.ts +51 -0
- package/dist/core/layout/jsx.d.ts +65 -0
- package/dist/core/layout/schema.d.ts +112 -0
- package/dist/core/layout/types.d.ts +69 -0
- package/dist/core/viewport/constants.d.ts +105 -0
- package/dist/core/viewport/features/base.d.ts +14 -0
- package/dist/core/viewport/features/collection.d.ts +41 -0
- package/dist/core/viewport/features/events.d.ts +13 -0
- package/{src/core/viewport/features/index.ts → dist/core/viewport/features/index.d.ts} +0 -7
- package/dist/core/viewport/features/item-size.d.ts +30 -0
- package/dist/core/viewport/features/loading.d.ts +34 -0
- package/dist/core/viewport/features/momentum.d.ts +17 -0
- package/dist/core/viewport/features/performance.d.ts +53 -0
- package/dist/core/viewport/features/placeholders.d.ts +38 -0
- package/dist/core/viewport/features/rendering.d.ts +16 -0
- package/dist/core/viewport/features/scrollbar.d.ts +26 -0
- package/dist/core/viewport/features/scrolling.d.ts +16 -0
- package/dist/core/viewport/features/utils.d.ts +43 -0
- package/dist/core/viewport/features/virtual.d.ts +18 -0
- package/{src/core/viewport/index.ts → dist/core/viewport/index.d.ts} +1 -17
- package/dist/core/viewport/types.d.ts +96 -0
- package/dist/core/viewport/utils/speed-tracker.d.ts +22 -0
- package/dist/core/viewport/viewport.d.ts +11 -0
- package/{src/index.ts → dist/index.d.ts} +0 -4
- package/dist/index.js +5143 -0
- package/dist/index.mjs +5111 -0
- package/dist/styles.css +254 -0
- package/dist/styles.css.map +1 -0
- package/package.json +16 -2
- package/.cursorrules +0 -117
- package/AI.md +0 -39
- package/CLAUDE.md +0 -882
- package/build.js +0 -377
- package/index.ts +0 -7
- package/scripts/analyze-orphaned-functions.ts +0 -387
- package/scripts/debug/vlist-selection.ts +0 -121
- package/src/components/vlist/config.ts +0 -323
- package/src/components/vlist/features/api.ts +0 -626
- package/src/components/vlist/features/selection.ts +0 -436
- package/src/components/vlist/features/viewport.ts +0 -59
- package/src/components/vlist/features.ts +0 -112
- package/src/components/vlist/types.ts +0 -723
- package/src/components/vlist/vlist.ts +0 -92
- package/src/core/compose/features/gestures/index.ts +0 -227
- package/src/core/compose/features/gestures/longpress.ts +0 -383
- package/src/core/compose/features/gestures/pan.ts +0 -424
- package/src/core/compose/features/gestures/pinch.ts +0 -475
- package/src/core/compose/features/gestures/rotate.ts +0 -485
- package/src/core/compose/features/gestures/swipe.ts +0 -492
- package/src/core/compose/features/gestures/tap.ts +0 -334
- package/src/core/gestures/longpress.ts +0 -68
- package/src/core/gestures/manager.ts +0 -418
- package/src/core/gestures/pan.ts +0 -48
- package/src/core/gestures/pinch.ts +0 -58
- package/src/core/gestures/rotate.ts +0 -58
- package/src/core/gestures/swipe.ts +0 -66
- package/src/core/gestures/tap.ts +0 -45
- package/src/core/gestures/types.ts +0 -387
- package/src/core/gestures/utils.ts +0 -128
- package/src/core/index.ts +0 -43
- package/src/core/layout/config.ts +0 -102
- package/src/core/layout/index.ts +0 -168
- package/src/core/layout/jsx.ts +0 -174
- package/src/core/layout/schema.ts +0 -1044
- package/src/core/layout/types.ts +0 -95
- package/src/core/viewport/constants.ts +0 -145
- package/src/core/viewport/features/base.ts +0 -73
- package/src/core/viewport/features/collection.ts +0 -1182
- package/src/core/viewport/features/events.ts +0 -130
- package/src/core/viewport/features/item-size.ts +0 -271
- package/src/core/viewport/features/loading.ts +0 -263
- package/src/core/viewport/features/momentum.ts +0 -269
- package/src/core/viewport/features/performance.ts +0 -161
- package/src/core/viewport/features/placeholders.ts +0 -335
- package/src/core/viewport/features/rendering.ts +0 -962
- package/src/core/viewport/features/scrollbar.ts +0 -434
- package/src/core/viewport/features/scrolling.ts +0 -634
- package/src/core/viewport/features/utils.ts +0 -94
- package/src/core/viewport/features/virtual.ts +0 -525
- package/src/core/viewport/types.ts +0 -133
- package/src/core/viewport/utils/speed-tracker.ts +0 -79
- package/src/core/viewport/viewport.ts +0 -265
- package/test/benchmarks/layout/advanced.test.ts +0 -656
- package/test/benchmarks/layout/comparison.test.ts +0 -519
- package/test/benchmarks/layout/performance-comparison.test.ts +0 -274
- package/test/benchmarks/layout/real-components.test.ts +0 -733
- package/test/benchmarks/layout/simple.test.ts +0 -321
- package/test/benchmarks/layout/stress.test.ts +0 -990
- package/test/collection/basic.test.ts +0 -304
- package/test/components/vlist-selection.test.ts +0 -240
- package/test/components/vlist.test.ts +0 -63
- package/test/core/collection/adapter.test.ts +0 -161
- package/test/core/collection/collection.test.ts +0 -394
- package/test/core/layout/layout.test.ts +0 -201
- package/test/utils/dom-helpers.ts +0 -275
- package/test/utils/performance-helpers.ts +0 -392
- package/tsconfig.json +0 -20
|
@@ -1,485 +0,0 @@
|
|
|
1
|
-
// src/core/compose/features/gestures/rotate.ts
|
|
2
|
-
/**
|
|
3
|
-
* @module core/compose/features/gestures
|
|
4
|
-
* @description Adds rotate gesture recognition to components
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { BaseComponent, ElementComponent } from "mtrl";
|
|
8
|
-
import { RotateEvent, GestureHandler } from "../../../gestures";
|
|
9
|
-
import { getAngle } from "../../../gestures/utils";
|
|
10
|
-
import { hasLifecycle, hasEmit } from "mtrl";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Extend the RotateEvent interface to support our custom event types
|
|
14
|
-
*/
|
|
15
|
-
interface ExtendedRotateEvent extends Omit<RotateEvent, "type"> {
|
|
16
|
-
type: "rotate" | "rotatestart" | "rotateend";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Configuration for rotate gesture feature
|
|
21
|
-
*/
|
|
22
|
-
export interface RotateGestureConfig {
|
|
23
|
-
/**
|
|
24
|
-
* Whether to prevent default behaviors on touch events
|
|
25
|
-
* @default true
|
|
26
|
-
*/
|
|
27
|
-
preventDefault?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Handler for rotate gesture
|
|
31
|
-
*/
|
|
32
|
-
onRotate?: GestureHandler;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Handler for rotate start
|
|
36
|
-
*/
|
|
37
|
-
onRotateStart?: GestureHandler;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Handler for rotate end
|
|
41
|
-
*/
|
|
42
|
-
onRotateEnd?: GestureHandler;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Whether to enable rotate recognition immediately
|
|
46
|
-
* @default true
|
|
47
|
-
*/
|
|
48
|
-
enabled?: boolean;
|
|
49
|
-
|
|
50
|
-
[key: string]: any;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Component with rotate gesture recognition capabilities
|
|
55
|
-
*/
|
|
56
|
-
export interface RotateGestureComponent extends BaseComponent {
|
|
57
|
-
/**
|
|
58
|
-
* Add a rotate event handler
|
|
59
|
-
* @param handler - Event handler function
|
|
60
|
-
* @returns Component for chaining
|
|
61
|
-
*/
|
|
62
|
-
onRotate: (handler: (event: RotateEvent) => void) => RotateGestureComponent;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Add a rotate start event handler
|
|
66
|
-
* @param handler - Event handler function
|
|
67
|
-
* @returns Component for chaining
|
|
68
|
-
*/
|
|
69
|
-
onRotateStart: (
|
|
70
|
-
handler: (event: RotateEvent) => void
|
|
71
|
-
) => RotateGestureComponent;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Add a rotate end event handler
|
|
75
|
-
* @param handler - Event handler function
|
|
76
|
-
* @returns Component for chaining
|
|
77
|
-
*/
|
|
78
|
-
onRotateEnd: (
|
|
79
|
-
handler: (event: RotateEvent) => void
|
|
80
|
-
) => RotateGestureComponent;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Remove a rotate event handler
|
|
84
|
-
* @param handler - Event handler function
|
|
85
|
-
* @returns Component for chaining
|
|
86
|
-
*/
|
|
87
|
-
offRotate: (handler: (event: RotateEvent) => void) => RotateGestureComponent;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Remove a rotate start event handler
|
|
91
|
-
* @param handler - Event handler function
|
|
92
|
-
* @returns Component for chaining
|
|
93
|
-
*/
|
|
94
|
-
offRotateStart: (
|
|
95
|
-
handler: (event: RotateEvent) => void
|
|
96
|
-
) => RotateGestureComponent;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Remove a rotate end event handler
|
|
100
|
-
* @param handler - Event handler function
|
|
101
|
-
* @returns Component for chaining
|
|
102
|
-
*/
|
|
103
|
-
offRotateEnd: (
|
|
104
|
-
handler: (event: RotateEvent) => void
|
|
105
|
-
) => RotateGestureComponent;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Enable rotate recognition
|
|
109
|
-
* @returns Component for chaining
|
|
110
|
-
*/
|
|
111
|
-
enableRotate: () => RotateGestureComponent;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Disable rotate recognition
|
|
115
|
-
* @returns Component for chaining
|
|
116
|
-
*/
|
|
117
|
-
disableRotate: () => RotateGestureComponent;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Check if rotate gestures are supported on the current device
|
|
121
|
-
* @returns Whether rotate gestures are supported
|
|
122
|
-
*/
|
|
123
|
-
isRotateSupported: () => boolean;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Adds rotate gesture recognition to a component.
|
|
128
|
-
* This is a lightweight alternative to the full gesture system,
|
|
129
|
-
* focused only on rotate detection.
|
|
130
|
-
*
|
|
131
|
-
* @param config - Configuration object containing rotate settings
|
|
132
|
-
* @returns Function that enhances a component with rotate capabilities
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```ts
|
|
136
|
-
* // Add rotate gesture recognition to a component
|
|
137
|
-
* const component = pipe(
|
|
138
|
-
* createBase,
|
|
139
|
-
* withElement(...),
|
|
140
|
-
* withRotateGesture({
|
|
141
|
-
* onRotate: (e) => updateRotation(e.rotation)
|
|
142
|
-
* })
|
|
143
|
-
* )(config);
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
export const withRotateGesture =
|
|
147
|
-
(config: RotateGestureConfig = {}) =>
|
|
148
|
-
<C extends ElementComponent>(component: C): C & RotateGestureComponent => {
|
|
149
|
-
if (!component.element) {
|
|
150
|
-
console.warn("Cannot add rotate gesture recognition: missing element");
|
|
151
|
-
return component as C & RotateGestureComponent;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Default configuration
|
|
155
|
-
const {
|
|
156
|
-
preventDefault = true,
|
|
157
|
-
onRotate,
|
|
158
|
-
onRotateStart,
|
|
159
|
-
onRotateEnd,
|
|
160
|
-
enabled = true,
|
|
161
|
-
} = config;
|
|
162
|
-
|
|
163
|
-
// Event handlers storage
|
|
164
|
-
const handlers = {
|
|
165
|
-
rotate: new Set<(event: RotateEvent) => void>(),
|
|
166
|
-
rotatestart: new Set<(event: RotateEvent) => void>(),
|
|
167
|
-
rotateend: new Set<(event: RotateEvent) => void>(),
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// Add initial handlers if provided
|
|
171
|
-
if (onRotate) handlers.rotate.add(onRotate as (event: RotateEvent) => void);
|
|
172
|
-
if (onRotateStart)
|
|
173
|
-
handlers.rotatestart.add(onRotateStart as (event: RotateEvent) => void);
|
|
174
|
-
if (onRotateEnd)
|
|
175
|
-
handlers.rotateend.add(onRotateEnd as (event: RotateEvent) => void);
|
|
176
|
-
|
|
177
|
-
// Check if device supports touch (required for rotate)
|
|
178
|
-
const isTouchSupported =
|
|
179
|
-
"ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
180
|
-
|
|
181
|
-
// Gesture state for tracking
|
|
182
|
-
let startAngle = 0;
|
|
183
|
-
let lastRotation = 0;
|
|
184
|
-
let isRotating = false;
|
|
185
|
-
let startTime = 0;
|
|
186
|
-
let isEnabled = enabled;
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Create a rotate event
|
|
190
|
-
*/
|
|
191
|
-
const createRotateEvent = (
|
|
192
|
-
e: TouchEvent,
|
|
193
|
-
type: "rotate" | "rotatestart" | "rotateend",
|
|
194
|
-
rotation: number,
|
|
195
|
-
centerX: number,
|
|
196
|
-
centerY: number
|
|
197
|
-
): ExtendedRotateEvent => {
|
|
198
|
-
const event: ExtendedRotateEvent = {
|
|
199
|
-
type,
|
|
200
|
-
originalEvent: e,
|
|
201
|
-
target: e.target!,
|
|
202
|
-
startTime,
|
|
203
|
-
endTime: Date.now(),
|
|
204
|
-
duration: Date.now() - startTime,
|
|
205
|
-
defaultPrevented: false,
|
|
206
|
-
preventDefault: () => {
|
|
207
|
-
event.defaultPrevented = true;
|
|
208
|
-
if (e.cancelable) {
|
|
209
|
-
e.preventDefault();
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
stopPropagation: () => {
|
|
213
|
-
e.stopPropagation();
|
|
214
|
-
},
|
|
215
|
-
rotation,
|
|
216
|
-
centerX,
|
|
217
|
-
centerY,
|
|
218
|
-
};
|
|
219
|
-
return event;
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Dispatch a rotate event to registered handlers
|
|
224
|
-
*/
|
|
225
|
-
const dispatchRotateEvent = (
|
|
226
|
-
e: TouchEvent,
|
|
227
|
-
type: "rotate" | "rotatestart" | "rotateend",
|
|
228
|
-
rotation: number,
|
|
229
|
-
centerX: number,
|
|
230
|
-
centerY: number
|
|
231
|
-
): void => {
|
|
232
|
-
const extendedRotateEvent = createRotateEvent(
|
|
233
|
-
e,
|
|
234
|
-
type,
|
|
235
|
-
rotation,
|
|
236
|
-
centerX,
|
|
237
|
-
centerY
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
// Call each handler for this type
|
|
241
|
-
handlers[type].forEach((handler) => {
|
|
242
|
-
try {
|
|
243
|
-
// Type assertion to handle the extended type
|
|
244
|
-
handler(extendedRotateEvent as unknown as RotateEvent);
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.error(`Error in ${type} handler:`, error);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Forward to component's event system if available
|
|
251
|
-
if (hasEmit(component)) {
|
|
252
|
-
component.emit(type, extendedRotateEvent);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Apply preventDefault if configured
|
|
256
|
-
if (preventDefault && !extendedRotateEvent.defaultPrevented) {
|
|
257
|
-
extendedRotateEvent.preventDefault();
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Handle touch start
|
|
263
|
-
*/
|
|
264
|
-
const handleTouchStart = (e: TouchEvent): void => {
|
|
265
|
-
if (!isEnabled || e.touches.length !== 2) return;
|
|
266
|
-
|
|
267
|
-
// Calculate initial angle between touch points
|
|
268
|
-
const touch1 = e.touches[0];
|
|
269
|
-
const touch2 = e.touches[1];
|
|
270
|
-
|
|
271
|
-
startAngle = getAngle(
|
|
272
|
-
touch1.clientX,
|
|
273
|
-
touch1.clientY,
|
|
274
|
-
touch2.clientX,
|
|
275
|
-
touch2.clientY
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
startTime = Date.now();
|
|
279
|
-
lastRotation = 0;
|
|
280
|
-
isRotating = false;
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Handle touch move
|
|
285
|
-
*/
|
|
286
|
-
const handleTouchMove = (e: TouchEvent): void => {
|
|
287
|
-
if (!isEnabled || e.touches.length !== 2) return;
|
|
288
|
-
|
|
289
|
-
const touch1 = e.touches[0];
|
|
290
|
-
const touch2 = e.touches[1];
|
|
291
|
-
|
|
292
|
-
// Calculate current angle and rotation
|
|
293
|
-
const currentAngle = getAngle(
|
|
294
|
-
touch1.clientX,
|
|
295
|
-
touch1.clientY,
|
|
296
|
-
touch2.clientX,
|
|
297
|
-
touch2.clientY
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
// Calculate rotation in degrees (normalized to -180 to 180)
|
|
301
|
-
let rotation = currentAngle - startAngle;
|
|
302
|
-
|
|
303
|
-
// Normalize rotation to the -180 to 180 range
|
|
304
|
-
if (rotation > 180) rotation -= 360;
|
|
305
|
-
if (rotation < -180) rotation += 360;
|
|
306
|
-
|
|
307
|
-
const centerX = (touch1.clientX + touch2.clientX) / 2;
|
|
308
|
-
const centerY = (touch1.clientY + touch2.clientY) / 2;
|
|
309
|
-
|
|
310
|
-
// Check if rotation change is significant enough
|
|
311
|
-
const rotationDiff = Math.abs(rotation - lastRotation);
|
|
312
|
-
const ROTATION_THRESHOLD = 2; // degrees
|
|
313
|
-
|
|
314
|
-
if (rotationDiff > ROTATION_THRESHOLD) {
|
|
315
|
-
// Start rotate if this is the first significant rotation
|
|
316
|
-
if (!isRotating) {
|
|
317
|
-
isRotating = true;
|
|
318
|
-
dispatchRotateEvent(e, "rotatestart", rotation, centerX, centerY);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Dispatch continuous rotate event
|
|
322
|
-
dispatchRotateEvent(e, "rotate", rotation, centerX, centerY);
|
|
323
|
-
lastRotation = rotation;
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Handle touch end
|
|
329
|
-
*/
|
|
330
|
-
const handleTouchEnd = (e: TouchEvent): void => {
|
|
331
|
-
if (!isEnabled || !isRotating) return;
|
|
332
|
-
|
|
333
|
-
// Calculate final center point if we still have one finger on screen
|
|
334
|
-
let centerX = 0;
|
|
335
|
-
let centerY = 0;
|
|
336
|
-
|
|
337
|
-
if (e.touches.length === 1) {
|
|
338
|
-
centerX = e.touches[0].clientX;
|
|
339
|
-
centerY = e.touches[0].clientY;
|
|
340
|
-
} else if (e.changedTouches.length > 0) {
|
|
341
|
-
centerX = e.changedTouches[0].clientX;
|
|
342
|
-
centerY = e.changedTouches[0].clientY;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Dispatch rotate end event
|
|
346
|
-
dispatchRotateEvent(e, "rotateend", lastRotation, centerX, centerY);
|
|
347
|
-
|
|
348
|
-
// Reset state
|
|
349
|
-
isRotating = false;
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Handle touch cancel
|
|
354
|
-
*/
|
|
355
|
-
const handleTouchCancel = (e: TouchEvent): void => {
|
|
356
|
-
if (!isEnabled || !isRotating) return;
|
|
357
|
-
|
|
358
|
-
// Calculate final center point
|
|
359
|
-
let centerX = 0;
|
|
360
|
-
let centerY = 0;
|
|
361
|
-
|
|
362
|
-
if (e.touches.length > 0) {
|
|
363
|
-
centerX = e.touches[0].clientX;
|
|
364
|
-
centerY = e.touches[0].clientY;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Dispatch rotate end event
|
|
368
|
-
dispatchRotateEvent(e, "rotateend", lastRotation, centerX, centerY);
|
|
369
|
-
|
|
370
|
-
// Reset state
|
|
371
|
-
isRotating = false;
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
// Event listeners dictionary
|
|
375
|
-
const eventListeners: Record<string, EventListener> = {
|
|
376
|
-
touchstart: handleTouchStart as EventListener,
|
|
377
|
-
touchmove: handleTouchMove as EventListener,
|
|
378
|
-
touchend: handleTouchEnd as EventListener,
|
|
379
|
-
touchcancel: handleTouchCancel as EventListener,
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Add event listeners to element
|
|
384
|
-
*/
|
|
385
|
-
const setupEventListeners = (): void => {
|
|
386
|
-
if (!isTouchSupported) return;
|
|
387
|
-
|
|
388
|
-
Object.entries(eventListeners).forEach(([event, listener]) => {
|
|
389
|
-
component.element.addEventListener(event, listener, {
|
|
390
|
-
passive: !preventDefault,
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Remove event listeners from element
|
|
397
|
-
*/
|
|
398
|
-
const removeEventListeners = (): void => {
|
|
399
|
-
if (!isTouchSupported) return;
|
|
400
|
-
|
|
401
|
-
Object.entries(eventListeners).forEach(([event, listener]) => {
|
|
402
|
-
component.element.removeEventListener(event, listener);
|
|
403
|
-
});
|
|
404
|
-
};
|
|
405
|
-
|
|
406
|
-
// Setup listeners if initially enabled
|
|
407
|
-
if (isEnabled && isTouchSupported) {
|
|
408
|
-
setupEventListeners();
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Handle lifecycle integration
|
|
412
|
-
if (hasLifecycle(component)) {
|
|
413
|
-
const originalDestroy = component.lifecycle.destroy;
|
|
414
|
-
|
|
415
|
-
component.lifecycle.destroy = () => {
|
|
416
|
-
// Clean up event listeners
|
|
417
|
-
removeEventListeners();
|
|
418
|
-
|
|
419
|
-
// Clear handlers
|
|
420
|
-
Object.values(handlers).forEach((handlerSet) => handlerSet.clear());
|
|
421
|
-
|
|
422
|
-
// Call original destroy method
|
|
423
|
-
originalDestroy.call(component.lifecycle);
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Create enhanced component
|
|
428
|
-
return {
|
|
429
|
-
...component,
|
|
430
|
-
|
|
431
|
-
// Add handler methods
|
|
432
|
-
onRotate(handler: (event: RotateEvent) => void) {
|
|
433
|
-
handlers.rotate.add(handler);
|
|
434
|
-
return this;
|
|
435
|
-
},
|
|
436
|
-
|
|
437
|
-
onRotateStart(handler: (event: RotateEvent) => void) {
|
|
438
|
-
handlers.rotatestart.add(handler);
|
|
439
|
-
return this;
|
|
440
|
-
},
|
|
441
|
-
|
|
442
|
-
onRotateEnd(handler: (event: RotateEvent) => void) {
|
|
443
|
-
handlers.rotateend.add(handler);
|
|
444
|
-
return this;
|
|
445
|
-
},
|
|
446
|
-
|
|
447
|
-
// Remove handler methods
|
|
448
|
-
offRotate(handler: (event: RotateEvent) => void) {
|
|
449
|
-
handlers.rotate.delete(handler);
|
|
450
|
-
return this;
|
|
451
|
-
},
|
|
452
|
-
|
|
453
|
-
offRotateStart(handler: (event: RotateEvent) => void) {
|
|
454
|
-
handlers.rotatestart.delete(handler);
|
|
455
|
-
return this;
|
|
456
|
-
},
|
|
457
|
-
|
|
458
|
-
offRotateEnd(handler: (event: RotateEvent) => void) {
|
|
459
|
-
handlers.rotateend.delete(handler);
|
|
460
|
-
return this;
|
|
461
|
-
},
|
|
462
|
-
|
|
463
|
-
// Enable/disable methods
|
|
464
|
-
enableRotate() {
|
|
465
|
-
if (!isEnabled) {
|
|
466
|
-
isEnabled = true;
|
|
467
|
-
setupEventListeners();
|
|
468
|
-
}
|
|
469
|
-
return this;
|
|
470
|
-
},
|
|
471
|
-
|
|
472
|
-
disableRotate() {
|
|
473
|
-
if (isEnabled) {
|
|
474
|
-
isEnabled = false;
|
|
475
|
-
removeEventListeners();
|
|
476
|
-
}
|
|
477
|
-
return this;
|
|
478
|
-
},
|
|
479
|
-
|
|
480
|
-
// Support check method
|
|
481
|
-
isRotateSupported() {
|
|
482
|
-
return isTouchSupported;
|
|
483
|
-
},
|
|
484
|
-
};
|
|
485
|
-
};
|