mtrl-addons 0.2.1 → 0.2.3
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 -9
- 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 +6 -1
- package/src/styles/components/_vlist.scss +234 -213
- package/.cursorrules +0 -117
- package/AI.md +0 -241
- package/build.js +0 -201
- 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 -322
- package/src/components/vlist/features/selection.ts +0 -444
- package/src/components/vlist/features/viewport.ts +0 -65
- package/src/components/vlist/features.ts +0 -112
- package/src/components/vlist/types.ts +0 -591
- 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 -1001
- package/src/core/layout/types.ts +0 -95
- package/src/core/viewport/constants.ts +0 -140
- package/src/core/viewport/features/base.ts +0 -73
- package/src/core/viewport/features/collection.ts +0 -882
- 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 -260
- 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 -568
- package/src/core/viewport/features/scrollbar.ts +0 -434
- package/src/core/viewport/features/scrolling.ts +0 -618
- package/src/core/viewport/features/utils.ts +0 -88
- package/src/core/viewport/features/virtual.ts +0 -384
- 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 -246
- 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,227 +0,0 @@
|
|
|
1
|
-
// src/core/compose/features/gestures.ts
|
|
2
|
-
/**
|
|
3
|
-
* @module core/compose/features
|
|
4
|
-
* @description Adds gesture recognition capabilities to components
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { BaseComponent, ElementComponent } from "mtrl";
|
|
8
|
-
import {
|
|
9
|
-
createGestureManager,
|
|
10
|
-
GestureManager,
|
|
11
|
-
GestureConfig,
|
|
12
|
-
GestureHandler,
|
|
13
|
-
AnyGestureEvent,
|
|
14
|
-
} from "../../../gestures";
|
|
15
|
-
import { hasLifecycle, hasEmit } from "mtrl";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Configuration for gestures feature
|
|
19
|
-
*/
|
|
20
|
-
export interface GesturesFeatureConfig extends GestureConfig {
|
|
21
|
-
/**
|
|
22
|
-
* Whether to enable gesture recognition immediately
|
|
23
|
-
* @default true
|
|
24
|
-
*/
|
|
25
|
-
enableGestures?: boolean;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Initial gesture event handlers
|
|
29
|
-
*/
|
|
30
|
-
gestureHandlers?: Record<string, GestureHandler>;
|
|
31
|
-
|
|
32
|
-
[key: string]: any;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Component with gesture recognition capabilities
|
|
37
|
-
*/
|
|
38
|
-
export interface GesturesComponent extends BaseComponent {
|
|
39
|
-
/**
|
|
40
|
-
* Gesture manager instance
|
|
41
|
-
*/
|
|
42
|
-
gestures: GestureManager;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Add a gesture event handler
|
|
46
|
-
* @param eventType - Type of gesture event
|
|
47
|
-
* @param handler - Event handler function
|
|
48
|
-
* @returns GesturesComponent for chaining
|
|
49
|
-
*/
|
|
50
|
-
onGesture: (eventType: string, handler: GestureHandler) => GesturesComponent;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Remove a gesture event handler
|
|
54
|
-
* @param eventType - Type of gesture event
|
|
55
|
-
* @param handler - Event handler function
|
|
56
|
-
* @returns GesturesComponent for chaining
|
|
57
|
-
*/
|
|
58
|
-
offGesture: (eventType: string, handler: GestureHandler) => GesturesComponent;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Check if a gesture type is supported on the current device
|
|
62
|
-
* @param gestureType - Type of gesture to check
|
|
63
|
-
* @returns Whether the gesture is supported
|
|
64
|
-
*/
|
|
65
|
-
isGestureSupported: (gestureType: string) => boolean;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Enable gesture recognition
|
|
69
|
-
* @returns GesturesComponent for chaining
|
|
70
|
-
*/
|
|
71
|
-
enableGestures: () => GesturesComponent;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Disable gesture recognition
|
|
75
|
-
* @returns GesturesComponent for chaining
|
|
76
|
-
*/
|
|
77
|
-
disableGestures: () => GesturesComponent;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Adds gesture recognition capabilities to a component.
|
|
82
|
-
* This is a comprehensive gesture feature that adds support for all gesture types.
|
|
83
|
-
* For more lightweight, specific gestures, use the individual gesture features.
|
|
84
|
-
*
|
|
85
|
-
* @param config - Configuration object containing gesture settings
|
|
86
|
-
* @returns Function that enhances a component with gesture capabilities
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```ts
|
|
90
|
-
* // Add gesture recognition to a component
|
|
91
|
-
* const component = pipe(
|
|
92
|
-
* createBase,
|
|
93
|
-
* withElement(...),
|
|
94
|
-
* withGestures({
|
|
95
|
-
* swipeThreshold: 50,
|
|
96
|
-
* gestureHandlers: {
|
|
97
|
-
* 'tap': (e) => handleTap(e),
|
|
98
|
-
* 'swipeleft': (e) => navigateForward(e),
|
|
99
|
-
* 'swiperight': (e) => navigateBack(e)
|
|
100
|
-
* }
|
|
101
|
-
* })
|
|
102
|
-
* )(config);
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
export const withGestures =
|
|
106
|
-
(config: GesturesFeatureConfig = {}) =>
|
|
107
|
-
<C extends ElementComponent>(component: C): C & GesturesComponent => {
|
|
108
|
-
if (!component.element) {
|
|
109
|
-
console.warn("Cannot add gesture recognition: missing element");
|
|
110
|
-
return component as C & GesturesComponent;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Default configuration
|
|
114
|
-
const {
|
|
115
|
-
enableGestures = true,
|
|
116
|
-
gestureHandlers = {},
|
|
117
|
-
...gestureConfig
|
|
118
|
-
} = config;
|
|
119
|
-
|
|
120
|
-
// Create gesture manager
|
|
121
|
-
const gestureManager = createGestureManager(
|
|
122
|
-
component.element,
|
|
123
|
-
gestureConfig
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
// Add initial gesture handlers
|
|
127
|
-
Object.entries(gestureHandlers).forEach(([eventType, handler]) => {
|
|
128
|
-
gestureManager.on(eventType, handler);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Enable/disable based on config
|
|
132
|
-
if (!enableGestures) {
|
|
133
|
-
gestureManager.disable();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Connect with existing event system if available
|
|
137
|
-
if (hasEmit(component)) {
|
|
138
|
-
// Forward gesture events to the component's event system
|
|
139
|
-
const forwardGestureEvents = (event: AnyGestureEvent) => {
|
|
140
|
-
component.emit(event.type, event);
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// Register forwarder for common gesture types
|
|
144
|
-
[
|
|
145
|
-
"tap",
|
|
146
|
-
"swipe",
|
|
147
|
-
"swipeleft",
|
|
148
|
-
"swiperight",
|
|
149
|
-
"swipeup",
|
|
150
|
-
"swipedown",
|
|
151
|
-
"longpress",
|
|
152
|
-
"pinch",
|
|
153
|
-
"rotate",
|
|
154
|
-
"pan",
|
|
155
|
-
].forEach((type) => {
|
|
156
|
-
gestureManager.on(type, forwardGestureEvents);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Handle lifecycle integration
|
|
161
|
-
if (hasLifecycle(component)) {
|
|
162
|
-
const originalDestroy = component.lifecycle.destroy;
|
|
163
|
-
|
|
164
|
-
component.lifecycle.destroy = () => {
|
|
165
|
-
// Clean up gesture manager
|
|
166
|
-
gestureManager.destroy();
|
|
167
|
-
|
|
168
|
-
// Call original destroy method
|
|
169
|
-
originalDestroy.call(component.lifecycle);
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Create enhanced component
|
|
174
|
-
return {
|
|
175
|
-
...component,
|
|
176
|
-
gestures: gestureManager,
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Add a gesture event handler
|
|
180
|
-
* @param eventType - Type of gesture event
|
|
181
|
-
* @param handler - Event handler function
|
|
182
|
-
* @returns GesturesComponent for chaining
|
|
183
|
-
*/
|
|
184
|
-
onGesture(eventType: string, handler: GestureHandler) {
|
|
185
|
-
gestureManager.on(eventType, handler);
|
|
186
|
-
return this;
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Remove a gesture event handler
|
|
191
|
-
* @param eventType - Type of gesture event
|
|
192
|
-
* @param handler - Event handler function
|
|
193
|
-
* @returns GesturesComponent for chaining
|
|
194
|
-
*/
|
|
195
|
-
offGesture(eventType: string, handler: GestureHandler) {
|
|
196
|
-
gestureManager.off(eventType, handler);
|
|
197
|
-
return this;
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Check if a gesture type is supported on the current device
|
|
202
|
-
* @param gestureType - Type of gesture to check
|
|
203
|
-
* @returns Whether the gesture is supported
|
|
204
|
-
*/
|
|
205
|
-
isGestureSupported(gestureType: string) {
|
|
206
|
-
return gestureManager.isSupported(gestureType);
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Enable gesture recognition
|
|
211
|
-
* @returns GesturesComponent for chaining
|
|
212
|
-
*/
|
|
213
|
-
enableGestures() {
|
|
214
|
-
gestureManager.enable();
|
|
215
|
-
return this;
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Disable gesture recognition
|
|
220
|
-
* @returns GesturesComponent for chaining
|
|
221
|
-
*/
|
|
222
|
-
disableGestures() {
|
|
223
|
-
gestureManager.disable();
|
|
224
|
-
return this;
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
};
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
// src/core/compose/features/gestures/longpress.ts
|
|
2
|
-
/**
|
|
3
|
-
* @module core/compose/features/gestures
|
|
4
|
-
* @description Adds long press gesture recognition to components
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { BaseComponent, ElementComponent } from "mtrl";
|
|
8
|
-
import { LongPressEvent, GestureHandler } from "../../../gestures";
|
|
9
|
-
import { hasLifecycle, hasEmit } from "mtrl";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Configuration for long press gesture feature
|
|
13
|
-
*/
|
|
14
|
-
export interface LongPressGestureConfig {
|
|
15
|
-
/**
|
|
16
|
-
* Time (in ms) to recognize a long press
|
|
17
|
-
* @default 500
|
|
18
|
-
*/
|
|
19
|
-
longPressTime?: number;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Distance threshold (in pixels) for movement that cancels long press
|
|
23
|
-
* @default 10
|
|
24
|
-
*/
|
|
25
|
-
moveThreshold?: number;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Whether to prevent default behaviors on touch events
|
|
29
|
-
* @default true
|
|
30
|
-
*/
|
|
31
|
-
preventDefault?: boolean;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Handler for long press gesture
|
|
35
|
-
*/
|
|
36
|
-
onLongPress?: GestureHandler;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Whether to enable long press recognition immediately
|
|
40
|
-
* @default true
|
|
41
|
-
*/
|
|
42
|
-
enabled?: boolean;
|
|
43
|
-
|
|
44
|
-
[key: string]: any;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Component with long press gesture recognition capabilities
|
|
49
|
-
*/
|
|
50
|
-
export interface LongPressGestureComponent extends BaseComponent {
|
|
51
|
-
/**
|
|
52
|
-
* Add a long press event handler
|
|
53
|
-
* @param handler - Event handler function
|
|
54
|
-
* @returns Component for chaining
|
|
55
|
-
*/
|
|
56
|
-
onLongPress: (
|
|
57
|
-
handler: (event: LongPressEvent) => void
|
|
58
|
-
) => LongPressGestureComponent;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Remove a long press event handler
|
|
62
|
-
* @param handler - Event handler function
|
|
63
|
-
* @returns Component for chaining
|
|
64
|
-
*/
|
|
65
|
-
offLongPress: (
|
|
66
|
-
handler: (event: LongPressEvent) => void
|
|
67
|
-
) => LongPressGestureComponent;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Enable long press recognition
|
|
71
|
-
* @returns Component for chaining
|
|
72
|
-
*/
|
|
73
|
-
enableLongPress: () => LongPressGestureComponent;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Disable long press recognition
|
|
77
|
-
* @returns Component for chaining
|
|
78
|
-
*/
|
|
79
|
-
disableLongPress: () => LongPressGestureComponent;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Adds long press gesture recognition to a component.
|
|
84
|
-
* This is a lightweight alternative to the full gesture system,
|
|
85
|
-
* focused only on long press detection.
|
|
86
|
-
*
|
|
87
|
-
* @param config - Configuration object containing long press settings
|
|
88
|
-
* @returns Function that enhances a component with long press capabilities
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* // Add long press gesture recognition to a component
|
|
93
|
-
* const component = pipe(
|
|
94
|
-
* createBase,
|
|
95
|
-
* withElement(...),
|
|
96
|
-
* withLongPressGesture({
|
|
97
|
-
* longPressTime: 800,
|
|
98
|
-
* onLongPress: (e) => showContextMenu(e.x, e.y)
|
|
99
|
-
* })
|
|
100
|
-
* )(config);
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export const withLongPressGesture =
|
|
104
|
-
(config: LongPressGestureConfig = {}) =>
|
|
105
|
-
<C extends ElementComponent>(component: C): C & LongPressGestureComponent => {
|
|
106
|
-
if (!component.element) {
|
|
107
|
-
console.warn(
|
|
108
|
-
"Cannot add long press gesture recognition: missing element"
|
|
109
|
-
);
|
|
110
|
-
return component as C & LongPressGestureComponent;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Default configuration
|
|
114
|
-
const {
|
|
115
|
-
longPressTime = 500,
|
|
116
|
-
moveThreshold = 10,
|
|
117
|
-
preventDefault = true,
|
|
118
|
-
onLongPress,
|
|
119
|
-
enabled = true,
|
|
120
|
-
} = config;
|
|
121
|
-
|
|
122
|
-
// Event handlers storage
|
|
123
|
-
const handlers: Set<(event: LongPressEvent) => void> = new Set();
|
|
124
|
-
|
|
125
|
-
// If initial handler provided, add it
|
|
126
|
-
if (onLongPress) {
|
|
127
|
-
handlers.add(onLongPress as (event: LongPressEvent) => void);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Gesture state for tracking
|
|
131
|
-
let startX = 0;
|
|
132
|
-
let startY = 0;
|
|
133
|
-
let currentX = 0;
|
|
134
|
-
let currentY = 0;
|
|
135
|
-
let active = false;
|
|
136
|
-
let startTime = 0;
|
|
137
|
-
let longPressTimer: number | null = null;
|
|
138
|
-
let isEnabled = enabled;
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Dispatch a long press event to all handlers
|
|
142
|
-
*/
|
|
143
|
-
const dispatchLongPress = (e: MouseEvent | TouchEvent): void => {
|
|
144
|
-
// Create the long press event
|
|
145
|
-
const longPressEvent: LongPressEvent = {
|
|
146
|
-
type: "longpress",
|
|
147
|
-
originalEvent: e,
|
|
148
|
-
target: e.target!,
|
|
149
|
-
startTime,
|
|
150
|
-
endTime: Date.now(),
|
|
151
|
-
duration: Date.now() - startTime,
|
|
152
|
-
defaultPrevented: false,
|
|
153
|
-
preventDefault: () => {
|
|
154
|
-
longPressEvent.defaultPrevented = true;
|
|
155
|
-
if (e.cancelable) {
|
|
156
|
-
e.preventDefault();
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
stopPropagation: () => {
|
|
160
|
-
e.stopPropagation();
|
|
161
|
-
},
|
|
162
|
-
x: currentX,
|
|
163
|
-
y: currentY,
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// Call each handler
|
|
167
|
-
handlers.forEach((handler) => {
|
|
168
|
-
try {
|
|
169
|
-
handler(longPressEvent);
|
|
170
|
-
} catch (error) {
|
|
171
|
-
console.error("Error in long press handler:", error);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// Forward to component's event system if available
|
|
176
|
-
if (hasEmit(component)) {
|
|
177
|
-
component.emit("longpress", longPressEvent);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Apply preventDefault if configured
|
|
181
|
-
if (preventDefault && !longPressEvent.defaultPrevented) {
|
|
182
|
-
longPressEvent.preventDefault();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Handle touch/mouse start
|
|
188
|
-
*/
|
|
189
|
-
const handleStart = (e: MouseEvent | TouchEvent): void => {
|
|
190
|
-
if (!isEnabled) return;
|
|
191
|
-
|
|
192
|
-
const touch = "touches" in e ? e.touches[0] : e;
|
|
193
|
-
|
|
194
|
-
startX = currentX = touch.clientX;
|
|
195
|
-
startY = currentY = touch.clientY;
|
|
196
|
-
startTime = Date.now();
|
|
197
|
-
active = true;
|
|
198
|
-
|
|
199
|
-
// Cancel any existing timer
|
|
200
|
-
if (longPressTimer !== null) {
|
|
201
|
-
window.clearTimeout(longPressTimer);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Set up long press timer
|
|
205
|
-
longPressTimer = window.setTimeout(() => {
|
|
206
|
-
if (active) {
|
|
207
|
-
// Check if movement was within threshold
|
|
208
|
-
const deltaX = currentX - startX;
|
|
209
|
-
const deltaY = currentY - startY;
|
|
210
|
-
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
211
|
-
|
|
212
|
-
if (distance < moveThreshold) {
|
|
213
|
-
dispatchLongPress(e);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
longPressTimer = null;
|
|
218
|
-
}, longPressTime);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Handle touch/mouse move
|
|
223
|
-
*/
|
|
224
|
-
const handleMove = (e: MouseEvent | TouchEvent): void => {
|
|
225
|
-
if (!active || !isEnabled) return;
|
|
226
|
-
|
|
227
|
-
const touch = "touches" in e ? e.touches[0] : e;
|
|
228
|
-
|
|
229
|
-
currentX = touch.clientX;
|
|
230
|
-
currentY = touch.clientY;
|
|
231
|
-
|
|
232
|
-
// Check if movement exceeds threshold
|
|
233
|
-
const deltaX = currentX - startX;
|
|
234
|
-
const deltaY = currentY - startY;
|
|
235
|
-
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
236
|
-
|
|
237
|
-
if (distance > moveThreshold) {
|
|
238
|
-
// Cancel long press if moved too much
|
|
239
|
-
if (longPressTimer !== null) {
|
|
240
|
-
window.clearTimeout(longPressTimer);
|
|
241
|
-
longPressTimer = null;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Handle touch/mouse end
|
|
248
|
-
*/
|
|
249
|
-
const handleEnd = (): void => {
|
|
250
|
-
if (longPressTimer !== null) {
|
|
251
|
-
window.clearTimeout(longPressTimer);
|
|
252
|
-
longPressTimer = null;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
active = false;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Handle touch/mouse cancel
|
|
260
|
-
*/
|
|
261
|
-
const handleCancel = (): void => {
|
|
262
|
-
if (longPressTimer !== null) {
|
|
263
|
-
window.clearTimeout(longPressTimer);
|
|
264
|
-
longPressTimer = null;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
active = false;
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// Event listeners dictionary
|
|
271
|
-
const eventListeners: Record<string, EventListener> = {
|
|
272
|
-
mousedown: handleStart as EventListener,
|
|
273
|
-
mousemove: handleMove as EventListener,
|
|
274
|
-
mouseup: handleEnd as EventListener,
|
|
275
|
-
mouseleave: handleCancel as EventListener,
|
|
276
|
-
touchstart: handleStart as EventListener,
|
|
277
|
-
touchmove: handleMove as EventListener,
|
|
278
|
-
touchend: handleEnd as EventListener,
|
|
279
|
-
touchcancel: handleCancel as EventListener,
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Add event listeners to element
|
|
284
|
-
*/
|
|
285
|
-
const setupEventListeners = (): void => {
|
|
286
|
-
Object.entries(eventListeners).forEach(([event, listener]) => {
|
|
287
|
-
component.element.addEventListener(event, listener, {
|
|
288
|
-
passive: !preventDefault,
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Remove event listeners from element
|
|
295
|
-
*/
|
|
296
|
-
const removeEventListeners = (): void => {
|
|
297
|
-
Object.entries(eventListeners).forEach(([event, listener]) => {
|
|
298
|
-
component.element.removeEventListener(event, listener);
|
|
299
|
-
});
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
// Setup listeners if initially enabled
|
|
303
|
-
if (isEnabled) {
|
|
304
|
-
setupEventListeners();
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Handle lifecycle integration
|
|
308
|
-
if (hasLifecycle(component)) {
|
|
309
|
-
const originalDestroy = component.lifecycle.destroy;
|
|
310
|
-
|
|
311
|
-
component.lifecycle.destroy = () => {
|
|
312
|
-
// Clean up event listeners
|
|
313
|
-
removeEventListeners();
|
|
314
|
-
|
|
315
|
-
// Clear any timers
|
|
316
|
-
if (longPressTimer !== null) {
|
|
317
|
-
window.clearTimeout(longPressTimer);
|
|
318
|
-
longPressTimer = null;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Clear handlers
|
|
322
|
-
handlers.clear();
|
|
323
|
-
|
|
324
|
-
// Call original destroy method
|
|
325
|
-
originalDestroy.call(component.lifecycle);
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Create enhanced component
|
|
330
|
-
return {
|
|
331
|
-
...component,
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Add a long press event handler
|
|
335
|
-
* @param handler - Event handler function
|
|
336
|
-
* @returns Component for chaining
|
|
337
|
-
*/
|
|
338
|
-
onLongPress(handler: (event: LongPressEvent) => void) {
|
|
339
|
-
handlers.add(handler);
|
|
340
|
-
return this;
|
|
341
|
-
},
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Remove a long press event handler
|
|
345
|
-
* @param handler - Event handler function
|
|
346
|
-
* @returns Component for chaining
|
|
347
|
-
*/
|
|
348
|
-
offLongPress(handler: (event: LongPressEvent) => void) {
|
|
349
|
-
handlers.delete(handler);
|
|
350
|
-
return this;
|
|
351
|
-
},
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Enable long press recognition
|
|
355
|
-
* @returns Component for chaining
|
|
356
|
-
*/
|
|
357
|
-
enableLongPress() {
|
|
358
|
-
if (!isEnabled) {
|
|
359
|
-
isEnabled = true;
|
|
360
|
-
setupEventListeners();
|
|
361
|
-
}
|
|
362
|
-
return this;
|
|
363
|
-
},
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Disable long press recognition
|
|
367
|
-
* @returns Component for chaining
|
|
368
|
-
*/
|
|
369
|
-
disableLongPress() {
|
|
370
|
-
if (isEnabled) {
|
|
371
|
-
isEnabled = false;
|
|
372
|
-
removeEventListeners();
|
|
373
|
-
|
|
374
|
-
// Clear any timers
|
|
375
|
-
if (longPressTimer !== null) {
|
|
376
|
-
window.clearTimeout(longPressTimer);
|
|
377
|
-
longPressTimer = null;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
return this;
|
|
381
|
-
},
|
|
382
|
-
};
|
|
383
|
-
};
|