mtrl-addons 0.2.2 → 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.
Files changed (128) hide show
  1. package/{src/components/index.ts → dist/components/index.d.ts} +0 -2
  2. package/dist/components/vlist/config.d.ts +86 -0
  3. package/{src/components/vlist/constants.ts → dist/components/vlist/constants.d.ts} +10 -11
  4. package/dist/components/vlist/features/api.d.ts +7 -0
  5. package/{src/components/vlist/features/index.ts → dist/components/vlist/features/index.d.ts} +0 -2
  6. package/dist/components/vlist/features/selection.d.ts +6 -0
  7. package/dist/components/vlist/features/viewport.d.ts +9 -0
  8. package/dist/components/vlist/features.d.ts +31 -0
  9. package/{src/components/vlist/index.ts → dist/components/vlist/index.d.ts} +1 -10
  10. package/dist/components/vlist/types.d.ts +596 -0
  11. package/dist/components/vlist/vlist.d.ts +29 -0
  12. package/dist/core/compose/features/gestures/index.d.ts +86 -0
  13. package/dist/core/compose/features/gestures/longpress.d.ts +85 -0
  14. package/dist/core/compose/features/gestures/pan.d.ts +108 -0
  15. package/dist/core/compose/features/gestures/pinch.d.ts +111 -0
  16. package/dist/core/compose/features/gestures/rotate.d.ts +111 -0
  17. package/dist/core/compose/features/gestures/swipe.d.ts +149 -0
  18. package/dist/core/compose/features/gestures/tap.d.ts +79 -0
  19. package/{src/core/compose/features/index.ts → dist/core/compose/features/index.d.ts} +1 -2
  20. package/{src/core/compose/index.ts → dist/core/compose/index.d.ts} +2 -11
  21. package/{src/core/gestures/index.ts → dist/core/gestures/index.d.ts} +1 -20
  22. package/dist/core/gestures/longpress.d.ts +23 -0
  23. package/dist/core/gestures/manager.d.ts +14 -0
  24. package/dist/core/gestures/pan.d.ts +12 -0
  25. package/dist/core/gestures/pinch.d.ts +14 -0
  26. package/dist/core/gestures/rotate.d.ts +14 -0
  27. package/dist/core/gestures/swipe.d.ts +20 -0
  28. package/dist/core/gestures/tap.d.ts +12 -0
  29. package/dist/core/gestures/types.d.ts +320 -0
  30. package/dist/core/gestures/utils.d.ts +57 -0
  31. package/dist/core/index.d.ts +13 -0
  32. package/dist/core/layout/config.d.ts +33 -0
  33. package/dist/core/layout/index.d.ts +51 -0
  34. package/dist/core/layout/jsx.d.ts +65 -0
  35. package/dist/core/layout/schema.d.ts +112 -0
  36. package/dist/core/layout/types.d.ts +69 -0
  37. package/dist/core/viewport/constants.d.ts +105 -0
  38. package/dist/core/viewport/features/base.d.ts +14 -0
  39. package/dist/core/viewport/features/collection.d.ts +41 -0
  40. package/dist/core/viewport/features/events.d.ts +13 -0
  41. package/{src/core/viewport/features/index.ts → dist/core/viewport/features/index.d.ts} +0 -7
  42. package/dist/core/viewport/features/item-size.d.ts +30 -0
  43. package/dist/core/viewport/features/loading.d.ts +34 -0
  44. package/dist/core/viewport/features/momentum.d.ts +17 -0
  45. package/dist/core/viewport/features/performance.d.ts +53 -0
  46. package/dist/core/viewport/features/placeholders.d.ts +38 -0
  47. package/dist/core/viewport/features/rendering.d.ts +16 -0
  48. package/dist/core/viewport/features/scrollbar.d.ts +26 -0
  49. package/dist/core/viewport/features/scrolling.d.ts +16 -0
  50. package/dist/core/viewport/features/utils.d.ts +43 -0
  51. package/dist/core/viewport/features/virtual.d.ts +18 -0
  52. package/{src/core/viewport/index.ts → dist/core/viewport/index.d.ts} +1 -17
  53. package/dist/core/viewport/types.d.ts +96 -0
  54. package/dist/core/viewport/utils/speed-tracker.d.ts +22 -0
  55. package/dist/core/viewport/viewport.d.ts +11 -0
  56. package/{src/index.ts → dist/index.d.ts} +0 -4
  57. package/dist/index.js +5143 -0
  58. package/dist/index.mjs +5111 -0
  59. package/dist/styles.css +254 -0
  60. package/dist/styles.css.map +1 -0
  61. package/package.json +5 -1
  62. package/.cursorrules +0 -117
  63. package/AI.md +0 -39
  64. package/CLAUDE.md +0 -882
  65. package/build.js +0 -377
  66. package/scripts/analyze-orphaned-functions.ts +0 -387
  67. package/scripts/debug/vlist-selection.ts +0 -121
  68. package/src/components/vlist/config.ts +0 -323
  69. package/src/components/vlist/features/api.ts +0 -626
  70. package/src/components/vlist/features/selection.ts +0 -436
  71. package/src/components/vlist/features/viewport.ts +0 -59
  72. package/src/components/vlist/features.ts +0 -112
  73. package/src/components/vlist/types.ts +0 -723
  74. package/src/components/vlist/vlist.ts +0 -92
  75. package/src/core/compose/features/gestures/index.ts +0 -227
  76. package/src/core/compose/features/gestures/longpress.ts +0 -383
  77. package/src/core/compose/features/gestures/pan.ts +0 -424
  78. package/src/core/compose/features/gestures/pinch.ts +0 -475
  79. package/src/core/compose/features/gestures/rotate.ts +0 -485
  80. package/src/core/compose/features/gestures/swipe.ts +0 -492
  81. package/src/core/compose/features/gestures/tap.ts +0 -334
  82. package/src/core/gestures/longpress.ts +0 -68
  83. package/src/core/gestures/manager.ts +0 -418
  84. package/src/core/gestures/pan.ts +0 -48
  85. package/src/core/gestures/pinch.ts +0 -58
  86. package/src/core/gestures/rotate.ts +0 -58
  87. package/src/core/gestures/swipe.ts +0 -66
  88. package/src/core/gestures/tap.ts +0 -45
  89. package/src/core/gestures/types.ts +0 -387
  90. package/src/core/gestures/utils.ts +0 -128
  91. package/src/core/index.ts +0 -43
  92. package/src/core/layout/config.ts +0 -102
  93. package/src/core/layout/index.ts +0 -168
  94. package/src/core/layout/jsx.ts +0 -174
  95. package/src/core/layout/schema.ts +0 -1044
  96. package/src/core/layout/types.ts +0 -95
  97. package/src/core/viewport/constants.ts +0 -145
  98. package/src/core/viewport/features/base.ts +0 -73
  99. package/src/core/viewport/features/collection.ts +0 -1182
  100. package/src/core/viewport/features/events.ts +0 -130
  101. package/src/core/viewport/features/item-size.ts +0 -271
  102. package/src/core/viewport/features/loading.ts +0 -263
  103. package/src/core/viewport/features/momentum.ts +0 -269
  104. package/src/core/viewport/features/performance.ts +0 -161
  105. package/src/core/viewport/features/placeholders.ts +0 -335
  106. package/src/core/viewport/features/rendering.ts +0 -962
  107. package/src/core/viewport/features/scrollbar.ts +0 -434
  108. package/src/core/viewport/features/scrolling.ts +0 -634
  109. package/src/core/viewport/features/utils.ts +0 -94
  110. package/src/core/viewport/features/virtual.ts +0 -525
  111. package/src/core/viewport/types.ts +0 -133
  112. package/src/core/viewport/utils/speed-tracker.ts +0 -79
  113. package/src/core/viewport/viewport.ts +0 -265
  114. package/test/benchmarks/layout/advanced.test.ts +0 -656
  115. package/test/benchmarks/layout/comparison.test.ts +0 -519
  116. package/test/benchmarks/layout/performance-comparison.test.ts +0 -274
  117. package/test/benchmarks/layout/real-components.test.ts +0 -733
  118. package/test/benchmarks/layout/simple.test.ts +0 -321
  119. package/test/benchmarks/layout/stress.test.ts +0 -990
  120. package/test/collection/basic.test.ts +0 -304
  121. package/test/components/vlist-selection.test.ts +0 -240
  122. package/test/components/vlist.test.ts +0 -63
  123. package/test/core/collection/adapter.test.ts +0 -161
  124. package/test/core/collection/collection.test.ts +0 -394
  125. package/test/core/layout/layout.test.ts +0 -201
  126. package/test/utils/dom-helpers.ts +0 -275
  127. package/test/utils/performance-helpers.ts +0 -392
  128. package/tsconfig.json +0 -20
@@ -1,92 +0,0 @@
1
- // src/components/vlist/vlist.ts
2
-
3
- /**
4
- * VList Component - Virtual List with direct viewport integration
5
- *
6
- * A simplified virtual list that uses the viewport feature directly
7
- * without the list-manager abstraction layer.
8
- */
9
-
10
- import type { VListConfig, VListComponent, VListItem } from "./types";
11
-
12
- // Import mtrl compose system
13
- import { pipe } from "mtrl";
14
- import { createBase, withElement } from "mtrl";
15
- import { withEvents, withLifecycle } from "mtrl";
16
-
17
- // Import viewport feature
18
- import { withViewport } from "./features/viewport";
19
- import { withAPI } from "./features/api";
20
- import { withSelection } from "./features/selection";
21
-
22
- /**
23
- * Creates a new VList component using direct viewport integration
24
- *
25
- * @param {VListConfig} config - List configuration options
26
- * @returns {VListComponent} A fully configured virtual list component
27
- *
28
- * @example
29
- * ```typescript
30
- * const vlist = createVList({
31
- * container: '#my-list',
32
- * collection: myAdapter,
33
- * rangeSize: 20,
34
- * paginationStrategy: 'page',
35
- * template: (item, index) => [
36
- * { class: 'viewport-item', attributes: { 'data-id': item.id }},
37
- * [{ class: 'viewport-item__name', text: item.name }],
38
- * [{ class: 'viewport-item__value', text: item.value }]
39
- * ]
40
- * });
41
- * ```
42
- */
43
- export const createVList = <T extends VListItem = VListItem>(
44
- config: VListConfig<T> = {}
45
- ): VListComponent<T> => {
46
- try {
47
- // console.log(`📋 Creating VList component with direct viewport integration`);
48
-
49
- // Note: Transform should be applied by the collection feature in viewport
50
- // VList should not intercept collection reads as it bypasses the loading manager
51
-
52
- // Create the component through functional composition
53
- const enhancers = [
54
- // 1. Foundation layer
55
- createBase,
56
- withEvents(),
57
- withElement({
58
- tag: "div",
59
- className: config.className || "mtrl-vlist",
60
- attributes: {
61
- role: "list",
62
- "aria-label": config.ariaLabel || "Virtual List",
63
- },
64
- }),
65
-
66
- // 2. Viewport integration
67
- withViewport(config),
68
-
69
- // 3. Component lifecycle
70
- withLifecycle(),
71
-
72
- // 4. Public API layer
73
- withAPI(config),
74
- ];
75
-
76
- // 4.5. Selection capabilities (if enabled) - must be after API
77
- if (config.selection?.enabled) {
78
- enhancers.push(withSelection(config));
79
- }
80
-
81
- const component = pipe(...enhancers)({
82
- ...config,
83
- componentName: "vlist",
84
- prefix: config.prefix || "mtrl",
85
- });
86
-
87
- return component as VListComponent<T>;
88
- } catch (error) {
89
- console.error("❌ [VLIST] Failed to create VList component:", error);
90
- throw error;
91
- }
92
- };
@@ -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
- };