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.
Files changed (129) 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 +16 -2
  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/index.ts +0 -7
  67. package/scripts/analyze-orphaned-functions.ts +0 -387
  68. package/scripts/debug/vlist-selection.ts +0 -121
  69. package/src/components/vlist/config.ts +0 -323
  70. package/src/components/vlist/features/api.ts +0 -626
  71. package/src/components/vlist/features/selection.ts +0 -436
  72. package/src/components/vlist/features/viewport.ts +0 -59
  73. package/src/components/vlist/features.ts +0 -112
  74. package/src/components/vlist/types.ts +0 -723
  75. package/src/components/vlist/vlist.ts +0 -92
  76. package/src/core/compose/features/gestures/index.ts +0 -227
  77. package/src/core/compose/features/gestures/longpress.ts +0 -383
  78. package/src/core/compose/features/gestures/pan.ts +0 -424
  79. package/src/core/compose/features/gestures/pinch.ts +0 -475
  80. package/src/core/compose/features/gestures/rotate.ts +0 -485
  81. package/src/core/compose/features/gestures/swipe.ts +0 -492
  82. package/src/core/compose/features/gestures/tap.ts +0 -334
  83. package/src/core/gestures/longpress.ts +0 -68
  84. package/src/core/gestures/manager.ts +0 -418
  85. package/src/core/gestures/pan.ts +0 -48
  86. package/src/core/gestures/pinch.ts +0 -58
  87. package/src/core/gestures/rotate.ts +0 -58
  88. package/src/core/gestures/swipe.ts +0 -66
  89. package/src/core/gestures/tap.ts +0 -45
  90. package/src/core/gestures/types.ts +0 -387
  91. package/src/core/gestures/utils.ts +0 -128
  92. package/src/core/index.ts +0 -43
  93. package/src/core/layout/config.ts +0 -102
  94. package/src/core/layout/index.ts +0 -168
  95. package/src/core/layout/jsx.ts +0 -174
  96. package/src/core/layout/schema.ts +0 -1044
  97. package/src/core/layout/types.ts +0 -95
  98. package/src/core/viewport/constants.ts +0 -145
  99. package/src/core/viewport/features/base.ts +0 -73
  100. package/src/core/viewport/features/collection.ts +0 -1182
  101. package/src/core/viewport/features/events.ts +0 -130
  102. package/src/core/viewport/features/item-size.ts +0 -271
  103. package/src/core/viewport/features/loading.ts +0 -263
  104. package/src/core/viewport/features/momentum.ts +0 -269
  105. package/src/core/viewport/features/performance.ts +0 -161
  106. package/src/core/viewport/features/placeholders.ts +0 -335
  107. package/src/core/viewport/features/rendering.ts +0 -962
  108. package/src/core/viewport/features/scrollbar.ts +0 -434
  109. package/src/core/viewport/features/scrolling.ts +0 -634
  110. package/src/core/viewport/features/utils.ts +0 -94
  111. package/src/core/viewport/features/virtual.ts +0 -525
  112. package/src/core/viewport/types.ts +0 -133
  113. package/src/core/viewport/utils/speed-tracker.ts +0 -79
  114. package/src/core/viewport/viewport.ts +0 -265
  115. package/test/benchmarks/layout/advanced.test.ts +0 -656
  116. package/test/benchmarks/layout/comparison.test.ts +0 -519
  117. package/test/benchmarks/layout/performance-comparison.test.ts +0 -274
  118. package/test/benchmarks/layout/real-components.test.ts +0 -733
  119. package/test/benchmarks/layout/simple.test.ts +0 -321
  120. package/test/benchmarks/layout/stress.test.ts +0 -990
  121. package/test/collection/basic.test.ts +0 -304
  122. package/test/components/vlist-selection.test.ts +0 -240
  123. package/test/components/vlist.test.ts +0 -63
  124. package/test/core/collection/adapter.test.ts +0 -161
  125. package/test/core/collection/collection.test.ts +0 -394
  126. package/test/core/layout/layout.test.ts +0 -201
  127. package/test/utils/dom-helpers.ts +0 -275
  128. package/test/utils/performance-helpers.ts +0 -392
  129. 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
- };