@flowgram-vue/core 0.2.0

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 (133) hide show
  1. package/LICENSE +22 -0
  2. package/dist/index.cjs +0 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +0 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +63 -0
  8. package/src/common/config-entity.ts +80 -0
  9. package/src/common/entity-data.ts +171 -0
  10. package/src/common/entity-manager-contribution.ts +12 -0
  11. package/src/common/entity-manager.ts +475 -0
  12. package/src/common/entity.ts +482 -0
  13. package/src/common/index.ts +22 -0
  14. package/src/common/playground-context.ts +35 -0
  15. package/src/common/playground-decorator-helper.ts +113 -0
  16. package/src/common/playground-decorators.ts +85 -0
  17. package/src/common/playground-schedule.ts +30 -0
  18. package/src/common/protect-wheel-area.ts +11 -0
  19. package/src/common/schema/index.ts +14 -0
  20. package/src/common/schema/node.ts +15 -0
  21. package/src/common/schema/opacity-schema.ts +19 -0
  22. package/src/common/schema/origin-schema.ts +35 -0
  23. package/src/common/schema/position-schema.ts +35 -0
  24. package/src/common/schema/rotation-schema.ts +19 -0
  25. package/src/common/schema/scale-schema.ts +35 -0
  26. package/src/common/schema/size-schema.ts +42 -0
  27. package/src/common/schema/skew-schema.ts +35 -0
  28. package/src/common/schema/transform-schema.ts +613 -0
  29. package/src/common/utils/bounds.spec.ts +229 -0
  30. package/src/common/utils/bounds.ts +176 -0
  31. package/src/common/utils/index.ts +6 -0
  32. package/src/composables/index.ts +16 -0
  33. package/src/composables/use-config-entity.ts +31 -0
  34. package/src/composables/use-entities.ts +26 -0
  35. package/src/composables/use-entity-data-from-context.ts +34 -0
  36. package/src/composables/use-entity-from-context.ts +31 -0
  37. package/src/composables/use-listen-events.ts +22 -0
  38. package/src/composables/use-playground-container.ts +16 -0
  39. package/src/composables/use-playground-context.ts +15 -0
  40. package/src/composables/use-playground-drag.ts +31 -0
  41. package/src/composables/use-playground.ts +16 -0
  42. package/src/composables/use-refresh.ts +6 -0
  43. package/src/composables/use-service.ts +17 -0
  44. package/src/core/index.ts +8 -0
  45. package/src/core/layer/config/editor-state-config-entity.ts +180 -0
  46. package/src/core/layer/config/index.ts +7 -0
  47. package/src/core/layer/config/playground-config-entity.ts +604 -0
  48. package/src/core/layer/index.ts +8 -0
  49. package/src/core/layer/layer.ts +248 -0
  50. package/src/core/layer/playground-layer.ts +547 -0
  51. package/src/core/pipeline/index.ts +10 -0
  52. package/src/core/pipeline/pipeline-entities-selector.ts +200 -0
  53. package/src/core/pipeline/pipeline-entities.ts +230 -0
  54. package/src/core/pipeline/pipeline-registry.ts +344 -0
  55. package/src/core/pipeline/pipeline-renderer.ts +248 -0
  56. package/src/core/pipeline/pipeline-vue-utils.ts +96 -0
  57. package/src/core/pipeline/pipeline.ts +28 -0
  58. package/src/core/utils/index.ts +12 -0
  59. package/src/core/utils/inject-provider-decorators.ts +27 -0
  60. package/src/core/utils/lazy-inject-decorators.ts +38 -0
  61. package/src/core/utils/mouse-touch-event.ts +120 -0
  62. package/src/core/utils/playground-drag.ts +511 -0
  63. package/src/core/utils/playground-gesture.spec.ts +135 -0
  64. package/src/core/utils/playground-gesture.ts +118 -0
  65. package/src/core/utils/tween.ts +156 -0
  66. package/src/core/utils/use-gesture/core/Controller.ts +212 -0
  67. package/src/core/utils/use-gesture/core/EventStore.ts +46 -0
  68. package/src/core/utils/use-gesture/core/TimeoutStore.ts +28 -0
  69. package/src/core/utils/use-gesture/core/actions.ts +63 -0
  70. package/src/core/utils/use-gesture/core/config/commonConfigResolver.ts +86 -0
  71. package/src/core/utils/use-gesture/core/config/coordinatesConfigResolver.ts +48 -0
  72. package/src/core/utils/use-gesture/core/config/dragConfigResolver.ts +140 -0
  73. package/src/core/utils/use-gesture/core/config/hoverConfigResolver.ts +11 -0
  74. package/src/core/utils/use-gesture/core/config/moveConfigResolver.ts +11 -0
  75. package/src/core/utils/use-gesture/core/config/pinchConfigResolver.ts +59 -0
  76. package/src/core/utils/use-gesture/core/config/resolver.ts +70 -0
  77. package/src/core/utils/use-gesture/core/config/scrollConfigResolver.ts +8 -0
  78. package/src/core/utils/use-gesture/core/config/sharedConfigResolver.ts +28 -0
  79. package/src/core/utils/use-gesture/core/config/support.ts +52 -0
  80. package/src/core/utils/use-gesture/core/config/wheelConfigResolver.ts +8 -0
  81. package/src/core/utils/use-gesture/core/engines/CoordinatesEngine.ts +78 -0
  82. package/src/core/utils/use-gesture/core/engines/DragEngine.ts +403 -0
  83. package/src/core/utils/use-gesture/core/engines/Engine.ts +406 -0
  84. package/src/core/utils/use-gesture/core/engines/HoverEngine.ts +43 -0
  85. package/src/core/utils/use-gesture/core/engines/MoveEngine.ts +52 -0
  86. package/src/core/utils/use-gesture/core/engines/PinchEngine.ts +345 -0
  87. package/src/core/utils/use-gesture/core/engines/ScrollEngine.ts +42 -0
  88. package/src/core/utils/use-gesture/core/engines/WheelEngine.ts +48 -0
  89. package/src/core/utils/use-gesture/core/index.ts +7 -0
  90. package/src/core/utils/use-gesture/core/parser.ts +92 -0
  91. package/src/core/utils/use-gesture/core/types/action.ts +19 -0
  92. package/src/core/utils/use-gesture/core/types/config.ts +255 -0
  93. package/src/core/utils/use-gesture/core/types/handlers.ts +73 -0
  94. package/src/core/utils/use-gesture/core/types/index.ts +11 -0
  95. package/src/core/utils/use-gesture/core/types/internalConfig.ts +80 -0
  96. package/src/core/utils/use-gesture/core/types/state.ts +275 -0
  97. package/src/core/utils/use-gesture/core/types/utils.ts +204 -0
  98. package/src/core/utils/use-gesture/core/types.ts +8 -0
  99. package/src/core/utils/use-gesture/core/utils/events.ts +158 -0
  100. package/src/core/utils/use-gesture/core/utils/fn.ts +32 -0
  101. package/src/core/utils/use-gesture/core/utils/maths.ts +63 -0
  102. package/src/core/utils/use-gesture/core/utils/state.ts +24 -0
  103. package/src/core/utils/use-gesture/core/utils.ts +8 -0
  104. package/src/core/utils/use-gesture/index.ts +6 -0
  105. package/src/core/utils/use-gesture/vanilla/DragGesture.ts +27 -0
  106. package/src/core/utils/use-gesture/vanilla/Gesture.ts +45 -0
  107. package/src/core/utils/use-gesture/vanilla/HoverGesture.ts +27 -0
  108. package/src/core/utils/use-gesture/vanilla/MoveGesture.ts +27 -0
  109. package/src/core/utils/use-gesture/vanilla/PinchGesture.ts +27 -0
  110. package/src/core/utils/use-gesture/vanilla/Recognizer.ts +43 -0
  111. package/src/core/utils/use-gesture/vanilla/ScrollGesture.ts +27 -0
  112. package/src/core/utils/use-gesture/vanilla/WheelGesture.ts +27 -0
  113. package/src/core/utils/use-gesture/vanilla/createGesture.ts +18 -0
  114. package/src/core/utils/use-gesture/vanilla/index.ts +18 -0
  115. package/src/env.d.ts +10 -0
  116. package/src/index.ts +17 -0
  117. package/src/playground-config.ts +70 -0
  118. package/src/playground-container.ts +129 -0
  119. package/src/playground-contribution.ts +81 -0
  120. package/src/playground-mock-tools.ts +143 -0
  121. package/src/playground.ts +401 -0
  122. package/src/plugin/index.ts +6 -0
  123. package/src/plugin/plugin.ts +226 -0
  124. package/src/services/clipboard-service.ts +40 -0
  125. package/src/services/context-menu-service.ts +25 -0
  126. package/src/services/index.ts +10 -0
  127. package/src/services/logger-service.ts +49 -0
  128. package/src/services/selection-service.ts +54 -0
  129. package/src/services/storage-service.ts +65 -0
  130. package/src/vue/index.ts +8 -0
  131. package/src/vue/playground-vue-context.ts +22 -0
  132. package/src/vue/playground-vue-provider.ts +115 -0
  133. package/src/vue/playground-vue-renderer.vue +44 -0
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { clampStateInternalMovementToBounds } from '../utils/state';
7
+ import { V } from '../utils/maths';
8
+ import { touchDistanceAngle, distanceAngle, wheelValues } from '../utils/events';
9
+ import { Vector2, WebKitGestureEvent } from '../types';
10
+ import { Engine } from './Engine';
11
+
12
+ const SCALE_ANGLE_RATIO_INTENT_DEG = 30;
13
+ const PINCH_WHEEL_RATIO = 100;
14
+
15
+ export class PinchEngine extends Engine<'pinch'> {
16
+ ingKey = 'pinching' as const;
17
+
18
+ aliasKey = 'da';
19
+
20
+ init() {
21
+ this.state.offset = [1, 0];
22
+ this.state.lastOffset = [1, 0];
23
+ this.state._pointerEvents = new Map();
24
+ }
25
+
26
+ // superseeds generic Engine reset call
27
+ reset() {
28
+ super.reset();
29
+ const state = this.state;
30
+ state._touchIds = [];
31
+ state.canceled = false;
32
+ state.cancel = this.cancel.bind(this);
33
+ state.turns = 0;
34
+ }
35
+
36
+ computeOffset() {
37
+ const { type, movement, lastOffset } = this.state;
38
+ if (type === 'wheel') {
39
+ this.state.offset = V.add(movement, lastOffset);
40
+ } else {
41
+ this.state.offset = [(1 + movement[0]) * lastOffset[0], movement[1] + lastOffset[1]];
42
+ }
43
+ }
44
+
45
+ computeMovement() {
46
+ const { offset, lastOffset } = this.state;
47
+ this.state.movement = [offset[0] / lastOffset[0], offset[1] - lastOffset[1]];
48
+ }
49
+
50
+ axisIntent() {
51
+ const state = this.state;
52
+ const [_m0, _m1] = state._movement;
53
+ if (!state.axis) {
54
+ const axisMovementDifference = Math.abs(_m0) * SCALE_ANGLE_RATIO_INTENT_DEG - Math.abs(_m1);
55
+ if (axisMovementDifference < 0) state.axis = 'angle';
56
+ else if (axisMovementDifference > 0) state.axis = 'scale';
57
+ }
58
+ }
59
+
60
+ restrictToAxis(v: Vector2) {
61
+ if (this.config.lockDirection) {
62
+ if (this.state.axis === 'scale') v[1] = 0;
63
+ else if (this.state.axis === 'angle') v[0] = 0;
64
+ }
65
+ }
66
+
67
+ cancel() {
68
+ const state = this.state;
69
+ if (state.canceled) return;
70
+ setTimeout(() => {
71
+ state.canceled = true;
72
+ state._active = false;
73
+ // we run compute with no event so that kinematics won't be computed
74
+ this.compute();
75
+ this.emit();
76
+ }, 0);
77
+ }
78
+
79
+ touchStart(event: TouchEvent) {
80
+ this.ctrl.setEventIds(event);
81
+ const state = this.state;
82
+ const ctrlTouchIds = this.ctrl.touchIds;
83
+
84
+ if (state._active) {
85
+ // check that the touchIds that initiated the gesture are still enabled
86
+ // This is useful for when the page loses track of the pointers (minifying
87
+ // gesture on iPad).
88
+ if (state._touchIds.every(id => ctrlTouchIds.has(id))) return;
89
+ // The gesture is still active, but probably didn't have the opportunity to
90
+ // end properly, so we restart the pinch.
91
+ }
92
+
93
+ if (ctrlTouchIds.size < 2) return;
94
+
95
+ this.start(event);
96
+ state._touchIds = Array.from(ctrlTouchIds).slice(0, 2) as [number, number];
97
+
98
+ const payload = touchDistanceAngle(event, state._touchIds);
99
+
100
+ if (!payload) return;
101
+ this.pinchStart(event, payload);
102
+ }
103
+
104
+ pointerStart(event: PointerEvent) {
105
+ if (event.buttons != null && event.buttons % 2 !== 1) return;
106
+ this.ctrl.setEventIds(event);
107
+ (event.target as HTMLElement).setPointerCapture(event.pointerId);
108
+ const state = this.state;
109
+ const _pointerEvents = state._pointerEvents;
110
+ const ctrlPointerIds = this.ctrl.pointerIds;
111
+
112
+ if (state._active) {
113
+ // see touchStart comment
114
+ if (Array.from(_pointerEvents.keys()).every(id => ctrlPointerIds.has(id))) return;
115
+ }
116
+
117
+ if (_pointerEvents.size < 2) {
118
+ _pointerEvents.set(event.pointerId, event);
119
+ }
120
+
121
+ if (state._pointerEvents.size < 2) return;
122
+
123
+ this.start(event);
124
+
125
+ // @ts-ignore
126
+ const payload = distanceAngle(...Array.from(_pointerEvents.values()));
127
+
128
+ if (!payload) return;
129
+ this.pinchStart(event, payload);
130
+ }
131
+
132
+ pinchStart(
133
+ event: PointerEvent | TouchEvent,
134
+ payload: { distance: number; angle: number; origin: Vector2 },
135
+ ) {
136
+ const state = this.state;
137
+ state.origin = payload.origin;
138
+ this.computeValues([payload.distance, payload.angle]);
139
+ this.computeInitial();
140
+
141
+ this.compute(event);
142
+ this.emit();
143
+ }
144
+
145
+ touchMove(event: TouchEvent) {
146
+ if (!this.state._active) return;
147
+ const payload = touchDistanceAngle(event, this.state._touchIds);
148
+
149
+ if (!payload) return;
150
+ this.pinchMove(event, payload);
151
+ }
152
+
153
+ pointerMove(event: PointerEvent) {
154
+ const _pointerEvents = this.state._pointerEvents;
155
+ if (_pointerEvents.has(event.pointerId)) {
156
+ _pointerEvents.set(event.pointerId, event);
157
+ }
158
+ if (!this.state._active) return;
159
+ // @ts-ignore
160
+ const payload = distanceAngle(...Array.from(_pointerEvents.values()));
161
+
162
+ if (!payload) return;
163
+ this.pinchMove(event, payload);
164
+ }
165
+
166
+ pinchMove(
167
+ event: PointerEvent | TouchEvent,
168
+ payload: { distance: number; angle: number; origin: Vector2 },
169
+ ) {
170
+ const state = this.state;
171
+ const prev_a = state._values[1];
172
+ const delta_a = payload.angle - prev_a;
173
+
174
+ let delta_turns = 0;
175
+ if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a);
176
+
177
+ this.computeValues([payload.distance, payload.angle - 360 * delta_turns]);
178
+
179
+ state.origin = payload.origin;
180
+ state.turns = delta_turns;
181
+ state._movement = [
182
+ state._values[0] / state._initial[0] - 1,
183
+ state._values[1] - state._initial[1],
184
+ ];
185
+
186
+ this.compute(event);
187
+ this.emit();
188
+ }
189
+
190
+ touchEnd(event: TouchEvent) {
191
+ this.ctrl.setEventIds(event);
192
+ if (!this.state._active) return;
193
+
194
+ if (this.state._touchIds.some(id => !this.ctrl.touchIds.has(id))) {
195
+ this.state._active = false;
196
+
197
+ this.compute(event);
198
+ this.emit();
199
+ }
200
+ }
201
+
202
+ pointerEnd(event: PointerEvent) {
203
+ const state = this.state;
204
+ this.ctrl.setEventIds(event);
205
+ try {
206
+ // @ts-ignore r3f
207
+ event.target.releasePointerCapture(event.pointerId);
208
+ } catch {}
209
+
210
+ if (state._pointerEvents.has(event.pointerId)) {
211
+ state._pointerEvents.delete(event.pointerId);
212
+ }
213
+
214
+ if (!state._active) return;
215
+
216
+ if (state._pointerEvents.size < 2) {
217
+ state._active = false;
218
+ this.compute(event);
219
+ this.emit();
220
+ }
221
+ }
222
+
223
+ gestureStart(event: WebKitGestureEvent) {
224
+ if (event.cancelable) event.preventDefault();
225
+ const state = this.state;
226
+
227
+ if (state._active) return;
228
+
229
+ this.start(event);
230
+ this.computeValues([event.scale, event.rotation]);
231
+ state.origin = [event.clientX, event.clientY];
232
+ this.compute(event);
233
+
234
+ this.emit();
235
+ }
236
+
237
+ gestureMove(event: WebKitGestureEvent) {
238
+ if (event.cancelable) event.preventDefault();
239
+
240
+ if (!this.state._active) return;
241
+
242
+ const state = this.state;
243
+
244
+ this.computeValues([event.scale, event.rotation]);
245
+ state.origin = [event.clientX, event.clientY];
246
+ const _previousMovement = state._movement;
247
+ state._movement = [event.scale - 1, event.rotation];
248
+ state._delta = V.sub(state._movement, _previousMovement);
249
+ this.compute(event);
250
+ this.emit();
251
+ }
252
+
253
+ gestureEnd(event: WebKitGestureEvent) {
254
+ if (!this.state._active) return;
255
+
256
+ this.state._active = false;
257
+
258
+ this.compute(event);
259
+ this.emit();
260
+ }
261
+
262
+ wheel(event: WheelEvent) {
263
+ const modifierKey = this.config.modifierKey;
264
+ if (
265
+ modifierKey &&
266
+ (Array.isArray(modifierKey) ? !modifierKey.find(k => event[k]) : !event[modifierKey])
267
+ )
268
+ return;
269
+ if (!this.state._active) this.wheelStart(event);
270
+ else this.wheelChange(event);
271
+ this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this));
272
+ }
273
+
274
+ wheelStart(event: WheelEvent) {
275
+ this.start(event);
276
+ this.wheelChange(event);
277
+ }
278
+
279
+ wheelChange(event: WheelEvent) {
280
+ const isR3f = 'uv' in event;
281
+ if (!isR3f) {
282
+ if (event.cancelable) {
283
+ event.preventDefault();
284
+ }
285
+ if (process.env.NODE_ENV === 'development' && !event.defaultPrevented) {
286
+ // eslint-disable-next-line no-console
287
+ console.warn(
288
+ `[@use-gesture]: To properly support zoom on trackpads, try using the \`target\` option.\n\nThis message will only appear in development mode.`,
289
+ );
290
+ }
291
+ }
292
+ const state = this.state;
293
+ /**
294
+ * 原版的计算对鼠标滚轮不友好
295
+ * 1. 基数问题。鼠标滚轮的 delta 像素级在 0 - 300+ 浮动不等。相对的触摸板在 0 - 10+ 左右,所以相对会觉得触摸板缩放比较稳定
296
+ * 2. 步进问题。一次缩放的增量 = 基数 * 上一次缩放。本身是为了营造平滑加速的感觉,但对于基数较大的滚轮加速曲线会特别快
297
+ * 3. 所以最终步进值限制在 0.1(触摸板在 0.01 - 0.08 左右,无影响),用来约束太快的滚轮连续滚动。该值先写死(受限于 maxOffset)
298
+ * 4. 计算公式 offset = lastOffset + movement - delta * offset
299
+ */
300
+ // state._delta = [(-wheelValues(event)[1] / PINCH_WHEEL_RATIO) * state.offset[0], 0]
301
+ let stepValue = (-wheelValues(event)[1] / PINCH_WHEEL_RATIO) * state.offset[0];
302
+ if (Math.abs(stepValue) > 0.1) {
303
+ stepValue = 0.1 * Math.sign(stepValue);
304
+ }
305
+
306
+ state._delta = [stepValue, 0];
307
+ V.addTo(state._movement, state._delta);
308
+
309
+ // _movement rolls back to when it passed the bounds.
310
+ clampStateInternalMovementToBounds(state);
311
+
312
+ this.state.origin = [event.clientX, event.clientY];
313
+
314
+ this.compute(event);
315
+ this.emit();
316
+ }
317
+
318
+ wheelEnd() {
319
+ if (!this.state._active) return;
320
+ this.state._active = false;
321
+ this.compute();
322
+ this.emit();
323
+ }
324
+
325
+ bind(bindFunction: any) {
326
+ const device = this.config.device;
327
+ if (!!device) {
328
+ // @ts-ignore
329
+ bindFunction(device, 'start', this[device + 'Start'].bind(this));
330
+ // @ts-ignore
331
+ bindFunction(device, 'change', this[device + 'Move'].bind(this));
332
+ // @ts-ignore
333
+ bindFunction(device, 'end', this[device + 'End'].bind(this));
334
+ // @ts-ignore
335
+ bindFunction(device, 'cancel', this[device + 'End'].bind(this));
336
+ // @ts-ignore
337
+ bindFunction('lostPointerCapture', '', this[device + 'End'].bind(this));
338
+ }
339
+ // we try to set a passive listener, knowing that in any case React will
340
+ // ignore it.
341
+ if (this.config.pinchOnWheel) {
342
+ bindFunction('wheel', '', this.wheel.bind(this), { passive: false });
343
+ }
344
+ }
345
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { V } from '../utils/maths';
7
+ import { scrollValues } from '../utils/events';
8
+ import { CoordinatesEngine } from './CoordinatesEngine';
9
+
10
+ export class ScrollEngine extends CoordinatesEngine<'scroll'> {
11
+ ingKey = 'scrolling' as const;
12
+
13
+ scroll(event: UIEvent) {
14
+ if (!this.state._active) this.start(event);
15
+ this.scrollChange(event);
16
+ this.timeoutStore.add('scrollEnd', this.scrollEnd.bind(this));
17
+ }
18
+
19
+ scrollChange(event: UIEvent) {
20
+ if (event.cancelable) event.preventDefault();
21
+ const state = this.state;
22
+ const values = scrollValues(event);
23
+ state._delta = V.sub(values, state._values);
24
+ V.addTo(state._movement, state._delta);
25
+
26
+ this.computeValues(values);
27
+ this.compute(event);
28
+
29
+ this.emit();
30
+ }
31
+
32
+ scrollEnd() {
33
+ if (!this.state._active) return;
34
+ this.state._active = false;
35
+ this.compute();
36
+ this.emit();
37
+ }
38
+
39
+ bind(bindFunction: any) {
40
+ bindFunction('scroll', '', this.scroll.bind(this));
41
+ }
42
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { clampStateInternalMovementToBounds } from '../utils/state';
7
+ import { V } from '../utils/maths';
8
+ import { wheelValues } from '../utils/events';
9
+ import { CoordinatesEngine } from './CoordinatesEngine';
10
+
11
+ export interface WheelEngine extends CoordinatesEngine<'wheel'> {
12
+ wheel(this: WheelEngine, event: WheelEvent): void;
13
+ wheelChange(this: WheelEngine, event: WheelEvent): void;
14
+ wheelEnd(this: WheelEngine): void;
15
+ }
16
+
17
+ export class WheelEngine extends CoordinatesEngine<'wheel'> {
18
+ ingKey = 'wheeling' as const;
19
+
20
+ wheel(event: WheelEvent) {
21
+ if (!this.state._active) this.start(event);
22
+ this.wheelChange(event);
23
+ this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this));
24
+ }
25
+
26
+ wheelChange(event: WheelEvent) {
27
+ const state = this.state;
28
+ state._delta = wheelValues(event);
29
+ V.addTo(state._movement, state._delta);
30
+
31
+ // _movement rolls back to when it passed the bounds.
32
+ clampStateInternalMovementToBounds(state);
33
+
34
+ this.compute(event);
35
+ this.emit();
36
+ }
37
+
38
+ wheelEnd() {
39
+ if (!this.state._active) return;
40
+ this.state._active = false;
41
+ this.compute();
42
+ this.emit();
43
+ }
44
+
45
+ bind(bindFunction: any) {
46
+ bindFunction('wheel', '', this.wheel.bind(this));
47
+ }
48
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export { Controller } from './Controller';
7
+ export { parseMergedHandlers } from './parser';
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import {
7
+ FullGestureState,
8
+ GestureHandlers,
9
+ GestureKey,
10
+ InternalHandlers,
11
+ UserGestureConfig,
12
+ } from './types';
13
+ import { EngineMap } from './actions';
14
+
15
+ const RE_NOT_NATIVE = /^on(Drag|Wheel|Scroll|Move|Pinch|Hover)/;
16
+
17
+ function sortHandlers(_handlers: GestureHandlers) {
18
+ const native: any = {};
19
+ const handlers: InternalHandlers = {};
20
+ const actions = new Set();
21
+
22
+ for (let key in _handlers) {
23
+ if (RE_NOT_NATIVE.test(key)) {
24
+ actions.add(RegExp.lastMatch);
25
+ // @ts-ignore
26
+ handlers[key] = _handlers[key];
27
+ } else {
28
+ // @ts-ignore
29
+ native[key] = _handlers[key];
30
+ }
31
+ }
32
+
33
+ return [handlers, native, actions];
34
+ }
35
+
36
+ type HandlerKey = 'onDrag' | 'onPinch' | 'onWheel' | 'onMove' | 'onScroll' | 'onHover';
37
+
38
+ function registerGesture(
39
+ actions: Set<unknown>,
40
+ handlers: GestureHandlers,
41
+ handlerKey: HandlerKey,
42
+ key: GestureKey,
43
+ internalHandlers: any,
44
+ config: any,
45
+ ) {
46
+ if (!actions.has(handlerKey)) return;
47
+
48
+ if (!EngineMap.has(key)) {
49
+ if (process.env.NODE_ENV === 'development') {
50
+ // eslint-disable-next-line no-console
51
+ console.warn(
52
+ `[@use-gesture]: You've created a custom handler that that uses the \`${key}\` gesture but isn't properly configured.\n\nPlease add \`${key}Action\` when creating your handler.`,
53
+ );
54
+ }
55
+ return;
56
+ }
57
+
58
+ const startKey = handlerKey + 'Start';
59
+ const endKey = handlerKey + 'End';
60
+
61
+ const fn = (state: FullGestureState<GestureKey>) => {
62
+ let memo = undefined;
63
+ // @ts-ignore
64
+ if (state.first && startKey in handlers) handlers[startKey](state);
65
+ // @ts-ignore
66
+ if (handlerKey in handlers) memo = handlers[handlerKey](state);
67
+ // @ts-ignore
68
+ if (state.last && endKey in handlers) handlers[endKey](state);
69
+ return memo;
70
+ };
71
+
72
+ internalHandlers[key] = fn;
73
+ config[key] = config[key] || {};
74
+ }
75
+
76
+ export function parseMergedHandlers(
77
+ mergedHandlers: GestureHandlers,
78
+ mergedConfig: UserGestureConfig,
79
+ ) {
80
+ const [handlers, nativeHandlers, actions] = sortHandlers(mergedHandlers);
81
+
82
+ const internalHandlers = {};
83
+
84
+ registerGesture(actions, handlers, 'onDrag', 'drag', internalHandlers, mergedConfig);
85
+ registerGesture(actions, handlers, 'onWheel', 'wheel', internalHandlers, mergedConfig);
86
+ registerGesture(actions, handlers, 'onScroll', 'scroll', internalHandlers, mergedConfig);
87
+ registerGesture(actions, handlers, 'onPinch', 'pinch', internalHandlers, mergedConfig);
88
+ registerGesture(actions, handlers, 'onMove', 'move', internalHandlers, mergedConfig);
89
+ registerGesture(actions, handlers, 'onHover', 'hover', internalHandlers, mergedConfig);
90
+
91
+ return { handlers: internalHandlers, config: mergedConfig, nativeHandlers };
92
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import type { Engine } from '../engines/Engine';
7
+ import type { Controller } from '../Controller';
8
+ import type { ResolverMap } from '../config/resolver';
9
+ import { GestureKey } from './config';
10
+
11
+ export type EngineClass<Key extends GestureKey> = {
12
+ new (controller: Controller, args: any[], key: Key): Engine<Key>;
13
+ };
14
+
15
+ export type Action = {
16
+ key: GestureKey;
17
+ engine: EngineClass<GestureKey>;
18
+ resolver: ResolverMap;
19
+ };