@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,63 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { GestureKey, EngineClass, Action } from './types';
7
+ import { WheelEngine } from './engines/WheelEngine';
8
+ import { ScrollEngine } from './engines/ScrollEngine';
9
+ import { PinchEngine } from './engines/PinchEngine';
10
+ import { MoveEngine } from './engines/MoveEngine';
11
+ import { HoverEngine } from './engines/HoverEngine';
12
+ import { DragEngine } from './engines/DragEngine';
13
+ import { wheelConfigResolver } from './config/wheelConfigResolver';
14
+ import { scrollConfigResolver } from './config/scrollConfigResolver';
15
+ import { ResolverMap } from './config/resolver';
16
+ import { pinchConfigResolver } from './config/pinchConfigResolver';
17
+ import { moveConfigResolver } from './config/moveConfigResolver';
18
+ import { hoverConfigResolver } from './config/hoverConfigResolver';
19
+ import { dragConfigResolver } from './config/dragConfigResolver';
20
+
21
+ export const EngineMap = new Map<GestureKey, EngineClass<any>>();
22
+ export const ConfigResolverMap = new Map<GestureKey, ResolverMap>();
23
+
24
+ export function registerAction(action: Action) {
25
+ EngineMap.set(action.key, action.engine);
26
+ ConfigResolverMap.set(action.key, action.resolver);
27
+ }
28
+
29
+ export const dragAction: Action = {
30
+ key: 'drag',
31
+ engine: DragEngine as any,
32
+ resolver: dragConfigResolver,
33
+ };
34
+
35
+ export const hoverAction: Action = {
36
+ key: 'hover',
37
+ engine: HoverEngine as any,
38
+ resolver: hoverConfigResolver,
39
+ };
40
+
41
+ export const moveAction: Action = {
42
+ key: 'move',
43
+ engine: MoveEngine as any,
44
+ resolver: moveConfigResolver,
45
+ };
46
+
47
+ export const pinchAction: Action = {
48
+ key: 'pinch',
49
+ engine: PinchEngine as any,
50
+ resolver: pinchConfigResolver,
51
+ };
52
+
53
+ export const scrollAction: Action = {
54
+ key: 'scroll',
55
+ engine: ScrollEngine as any,
56
+ resolver: scrollConfigResolver,
57
+ };
58
+
59
+ export const wheelAction: Action = {
60
+ key: 'wheel',
61
+ engine: WheelEngine as any,
62
+ resolver: wheelConfigResolver,
63
+ };
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { InternalGestureOptions } from '../types'
7
+ import { Vector2, State, GenericOptions } from '../types'
8
+ import { V } from '../utils/maths'
9
+
10
+ export const identity = (v: Vector2) => v
11
+ export const DEFAULT_RUBBERBAND = 0.15
12
+
13
+ export const commonConfigResolver = {
14
+ enabled(value = true) {
15
+ return value
16
+ },
17
+ eventOptions(value: AddEventListenerOptions | undefined, _k: string, config: { shared: GenericOptions }) {
18
+ return { ...config.shared.eventOptions, ...value }
19
+ },
20
+ preventDefault(value = false) {
21
+ return value
22
+ },
23
+ triggerAllEvents(value = false) {
24
+ return value
25
+ },
26
+ rubberband(value: number | boolean | Vector2 = 0): Vector2 {
27
+ switch (value) {
28
+ case true:
29
+ return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND]
30
+ case false:
31
+ return [0, 0]
32
+ default:
33
+ return V.toVector(value)
34
+ }
35
+ },
36
+ from(value: number | Vector2 | ((s: State) => Vector2)) {
37
+ if (typeof value === 'function') return value
38
+ // eslint-disable-next-line eqeqeq
39
+ if (value != null) return V.toVector(value)
40
+ },
41
+ transform(this: InternalGestureOptions, value: any, _k: string, config: { shared: GenericOptions }) {
42
+ const transform = value || config.shared.transform
43
+ this.hasCustomTransform = !!transform
44
+
45
+ if (process.env.NODE_ENV === 'development') {
46
+ const originalTransform = transform || identity
47
+ return (v: Vector2) => {
48
+ const r = originalTransform(v)
49
+ if (!isFinite(r[0]) || !isFinite(r[1])) {
50
+ // eslint-disable-next-line no-console
51
+ console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r[0]},${[1]}]`)
52
+ }
53
+ return r
54
+ }
55
+ }
56
+ return transform || identity
57
+ },
58
+ threshold(value: any) {
59
+ return V.toVector(value, 0)
60
+ }
61
+ }
62
+
63
+ if (process.env.NODE_ENV === 'development') {
64
+ Object.assign(commonConfigResolver, {
65
+ domTarget(value: any) {
66
+ if (value !== undefined) {
67
+ throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`)
68
+ }
69
+ return NaN
70
+ },
71
+ lockDirection(value: any) {
72
+ if (value !== undefined) {
73
+ throw Error(
74
+ `[@use-gesture]: \`lockDirection\` option has been merged with \`axis\`. Use it as in \`{ axis: 'lock' }\``
75
+ )
76
+ }
77
+ return NaN
78
+ },
79
+ initial(value: any) {
80
+ if (value !== undefined) {
81
+ throw Error(`[@use-gesture]: \`initial\` option has been renamed to \`from\`.`)
82
+ }
83
+ return NaN
84
+ }
85
+ })
86
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { commonConfigResolver } from './commonConfigResolver'
7
+ import { InternalCoordinatesOptions, CoordinatesConfig, Bounds, DragBounds, State, Vector2 } from '../types'
8
+
9
+ const DEFAULT_AXIS_THRESHOLD = 0
10
+
11
+ export const coordinatesConfigResolver = {
12
+ ...commonConfigResolver,
13
+ axis(
14
+ this: InternalCoordinatesOptions,
15
+ _v: any,
16
+ _k: string,
17
+ { axis }: CoordinatesConfig
18
+ ): InternalCoordinatesOptions['axis'] {
19
+ this.lockDirection = axis === 'lock'
20
+ if (!this.lockDirection) return axis as any
21
+ },
22
+ axisThreshold(value = DEFAULT_AXIS_THRESHOLD) {
23
+ return value
24
+ },
25
+ bounds(
26
+ value: DragBounds | ((state: State) => DragBounds) = {}
27
+ ): (() => EventTarget | null) | HTMLElement | [Vector2, Vector2] {
28
+ if (typeof value === 'function') {
29
+ // @ts-ignore
30
+ return (state: State) => coordinatesConfigResolver.bounds(value(state))
31
+ }
32
+
33
+ if ('current' in value) {
34
+ return () => value.current
35
+ }
36
+
37
+ if (typeof HTMLElement === 'function' && value instanceof HTMLElement) {
38
+ return value
39
+ }
40
+
41
+ const { left = -Infinity, right = Infinity, top = -Infinity, bottom = Infinity } = value as Bounds
42
+
43
+ return [
44
+ [left, right],
45
+ [top, bottom]
46
+ ]
47
+ }
48
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { PointerType } from '../types'
7
+ import { DragConfig, InternalDragOptions, Vector2 } from '../types'
8
+ import { V } from '../utils/maths'
9
+ import { coordinatesConfigResolver } from './coordinatesConfigResolver'
10
+ import { SUPPORT } from './support'
11
+
12
+ export const DEFAULT_PREVENT_SCROLL_DELAY = 250
13
+ export const DEFAULT_DRAG_DELAY = 180
14
+ export const DEFAULT_SWIPE_VELOCITY = 0.5
15
+ export const DEFAULT_SWIPE_DISTANCE = 50
16
+ export const DEFAULT_SWIPE_DURATION = 250
17
+ export const DEFAULT_KEYBOARD_DISPLACEMENT = 10
18
+
19
+ const DEFAULT_DRAG_AXIS_THRESHOLD: Record<PointerType, number> = { mouse: 0, touch: 0, pen: 8 }
20
+
21
+ export const dragConfigResolver = {
22
+ ...coordinatesConfigResolver,
23
+ device(
24
+ this: InternalDragOptions,
25
+ _v: any,
26
+ _k: string,
27
+ { pointer: { touch = false, lock = false, mouse = false } = {} }: DragConfig
28
+ ) {
29
+ this.pointerLock = lock && SUPPORT.pointerLock
30
+ if (SUPPORT.touch && touch) return 'touch'
31
+ if (this.pointerLock) return 'mouse'
32
+ if (SUPPORT.pointer && !mouse) return 'pointer'
33
+ if (SUPPORT.touch) return 'touch'
34
+ return 'mouse'
35
+ },
36
+ preventScrollAxis(this: InternalDragOptions, value: 'x' | 'y' | 'xy', _k: string, { preventScroll }: DragConfig) {
37
+ this.preventScrollDelay =
38
+ typeof preventScroll === 'number'
39
+ ? preventScroll
40
+ : preventScroll || (preventScroll === undefined && value)
41
+ ? DEFAULT_PREVENT_SCROLL_DELAY
42
+ : undefined
43
+ if (!SUPPORT.touchscreen || preventScroll === false) return undefined
44
+ return value ? value : preventScroll !== undefined ? 'y' : undefined
45
+ },
46
+ pointerCapture(
47
+ this: InternalDragOptions,
48
+ _v: any,
49
+ _k: string,
50
+ { pointer: { capture = true, buttons = 1, keys = true } = {} }
51
+ ) {
52
+ this.pointerButtons = buttons
53
+ this.keys = keys
54
+ return !this.pointerLock && this.device === 'pointer' && capture
55
+ },
56
+ threshold(
57
+ this: InternalDragOptions,
58
+ value: number | Vector2,
59
+ _k: string,
60
+ { filterTaps = false, tapsThreshold = 3, axis = undefined }
61
+ ) {
62
+ // TODO add warning when value is 0 and filterTaps or axis is set
63
+ const threshold = V.toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0)
64
+ this.filterTaps = filterTaps
65
+ this.tapsThreshold = tapsThreshold
66
+ return threshold
67
+ },
68
+ swipe(
69
+ this: InternalDragOptions,
70
+ { velocity = DEFAULT_SWIPE_VELOCITY, distance = DEFAULT_SWIPE_DISTANCE, duration = DEFAULT_SWIPE_DURATION } = {}
71
+ ) {
72
+ return {
73
+ velocity: this.transform(V.toVector(velocity)),
74
+ distance: this.transform(V.toVector(distance)),
75
+ duration
76
+ }
77
+ },
78
+ delay(value: number | boolean = 0) {
79
+ switch (value) {
80
+ case true:
81
+ return DEFAULT_DRAG_DELAY
82
+ case false:
83
+ return 0
84
+ default:
85
+ return value
86
+ }
87
+ },
88
+ axisThreshold(value: Record<PointerType, number>) {
89
+ if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD
90
+ return { ...DEFAULT_DRAG_AXIS_THRESHOLD, ...value }
91
+ },
92
+ keyboardDisplacement(value: number = DEFAULT_KEYBOARD_DISPLACEMENT) {
93
+ return value
94
+ }
95
+ }
96
+
97
+ if (process.env.NODE_ENV === 'development') {
98
+ Object.assign(dragConfigResolver, {
99
+ useTouch(value: any) {
100
+ if (value !== undefined) {
101
+ throw Error(
102
+ `[@use-gesture]: \`useTouch\` option has been renamed to \`pointer.touch\`. Use it as in \`{ pointer: { touch: true } }\`.`
103
+ )
104
+ }
105
+ return NaN
106
+ },
107
+ experimental_preventWindowScrollY(value: any) {
108
+ if (value !== undefined) {
109
+ throw Error(
110
+ `[@use-gesture]: \`experimental_preventWindowScrollY\` option has been renamed to \`preventScroll\`.`
111
+ )
112
+ }
113
+ return NaN
114
+ },
115
+ swipeVelocity(value: any) {
116
+ if (value !== undefined) {
117
+ throw Error(
118
+ `[@use-gesture]: \`swipeVelocity\` option has been renamed to \`swipe.velocity\`. Use it as in \`{ swipe: { velocity: 0.5 } }\`.`
119
+ )
120
+ }
121
+ return NaN
122
+ },
123
+ swipeDistance(value: any) {
124
+ if (value !== undefined) {
125
+ throw Error(
126
+ `[@use-gesture]: \`swipeDistance\` option has been renamed to \`swipe.distance\`. Use it as in \`{ swipe: { distance: 50 } }\`.`
127
+ )
128
+ }
129
+ return NaN
130
+ },
131
+ swipeDuration(value: any) {
132
+ if (value !== undefined) {
133
+ throw Error(
134
+ `[@use-gesture]: \`swipeDuration\` option has been renamed to \`swipe.duration\`. Use it as in \`{ swipe: { duration: 250 } }\`.`
135
+ )
136
+ }
137
+ return NaN
138
+ }
139
+ })
140
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { coordinatesConfigResolver } from './coordinatesConfigResolver'
7
+
8
+ export const hoverConfigResolver = {
9
+ ...coordinatesConfigResolver,
10
+ mouseOnly: (value = true) => value
11
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { coordinatesConfigResolver } from './coordinatesConfigResolver'
7
+
8
+ export const moveConfigResolver = {
9
+ ...coordinatesConfigResolver,
10
+ mouseOnly: (value = true) => value
11
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { ModifierKey } from '../types'
7
+ import { PinchConfig, GenericOptions, InternalPinchOptions, State, Vector2 } from '../types'
8
+ import { call, assignDefault } from '../utils/fn'
9
+ import { V } from '../utils/maths'
10
+ import { commonConfigResolver } from './commonConfigResolver'
11
+ import { SUPPORT } from './support'
12
+
13
+ export const pinchConfigResolver = {
14
+ ...commonConfigResolver,
15
+ device(
16
+ this: InternalPinchOptions,
17
+ _v: any,
18
+ _k: string,
19
+ { shared, pointer: { touch = false } = {} }: { shared: GenericOptions } & PinchConfig
20
+ ) {
21
+ // Only try to use gesture events when they are supported and domTarget is set
22
+ // as React doesn't support gesture handlers.
23
+ const sharedConfig = shared
24
+ if (sharedConfig.target && !SUPPORT.touch && SUPPORT.gesture) return 'gesture'
25
+ if (SUPPORT.touch && touch) return 'touch'
26
+ if (SUPPORT.touchscreen) {
27
+ if (SUPPORT.pointer) return 'pointer'
28
+ if (SUPPORT.touch) return 'touch'
29
+ }
30
+ // device is undefined and that's ok, we're going to use wheel to zoom.
31
+ },
32
+ bounds(_v: any, _k: string, { scaleBounds = {}, angleBounds = {} }: PinchConfig) {
33
+ const _scaleBounds = (state?: State) => {
34
+ const D = assignDefault(call(scaleBounds, state), { min: -Infinity, max: Infinity })
35
+ return [D.min, D.max]
36
+ }
37
+
38
+ const _angleBounds = (state?: State) => {
39
+ const A = assignDefault(call(angleBounds, state), { min: -Infinity, max: Infinity })
40
+ return [A.min, A.max]
41
+ }
42
+
43
+ if (typeof scaleBounds !== 'function' && typeof angleBounds !== 'function') return [_scaleBounds(), _angleBounds()]
44
+
45
+ return (state: State) => [_scaleBounds(state), _angleBounds(state)]
46
+ },
47
+ threshold(this: InternalPinchOptions, value: number | Vector2, _k: string, config: PinchConfig) {
48
+ this.lockDirection = config.axis === 'lock'
49
+ const threshold = V.toVector(value, this.lockDirection ? [0.1, 3] : 0)
50
+ return threshold
51
+ },
52
+ modifierKey(value: ModifierKey | ModifierKey[]) {
53
+ if (value === undefined) return 'ctrlKey'
54
+ return value
55
+ },
56
+ pinchOnWheel(value = true) {
57
+ return value
58
+ }
59
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { sharedConfigResolver } from './sharedConfigResolver'
7
+ import { ConfigResolverMap } from '../actions'
8
+ import { GestureKey, InternalConfig, UserGestureConfig } from '../types'
9
+
10
+ export type Resolver = (x: any, key: string, obj: any) => any
11
+ export type ResolverMap = { [k: string]: Resolver | ResolverMap | boolean }
12
+
13
+ export function resolveWith<T extends { [k: string]: any }, V extends { [k: string]: any }>(
14
+ config: Partial<T> = {},
15
+ resolvers: ResolverMap
16
+ ): V {
17
+ const result: any = {}
18
+
19
+ for (const [key, resolver] of Object.entries(resolvers)) {
20
+ switch (typeof resolver) {
21
+ case 'function':
22
+ if (process.env.NODE_ENV === 'development') {
23
+ const r = resolver.call(result, config[key], key, config)
24
+ // prevents deprecated resolvers from applying in dev mode
25
+ if (!Number.isNaN(r)) result[key] = r
26
+ } else {
27
+ result[key] = resolver.call(result, config[key], key, config)
28
+ }
29
+ break
30
+ case 'object':
31
+ result[key] = resolveWith(config[key], resolver)
32
+ break
33
+ case 'boolean':
34
+ if (resolver) result[key] = config[key]
35
+ break
36
+ }
37
+ }
38
+
39
+ return result
40
+ }
41
+
42
+ export function parse(newConfig: UserGestureConfig, gestureKey?: GestureKey, _config: any = {}): InternalConfig {
43
+ const { target, eventOptions, window, enabled, transform, ...rest } = newConfig as any
44
+
45
+ _config.shared = resolveWith({ target, eventOptions, window, enabled, transform }, sharedConfigResolver)
46
+
47
+ if (gestureKey) {
48
+ const resolver = ConfigResolverMap.get(gestureKey)!
49
+ _config[gestureKey] = resolveWith({ shared: _config.shared, ...rest }, resolver)
50
+ } else {
51
+ for (const key in rest) {
52
+ const resolver = ConfigResolverMap.get(key as GestureKey)!
53
+
54
+ if (resolver) {
55
+ _config[key] = resolveWith({ shared: _config.shared, ...rest[key] }, resolver)
56
+ } else if (process.env.NODE_ENV === 'development') {
57
+ if (!['drag', 'pinch', 'scroll', 'wheel', 'move', 'hover'].includes(key)) {
58
+ if (key === 'domTarget') {
59
+ throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`)
60
+ }
61
+ // eslint-disable-next-line no-console
62
+ console.warn(
63
+ `[@use-gesture]: Unknown config key \`${key}\` was used. Please read the documentation for further information.`
64
+ )
65
+ }
66
+ }
67
+ }
68
+ }
69
+ return _config
70
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { coordinatesConfigResolver } from './coordinatesConfigResolver'
7
+
8
+ export const scrollConfigResolver = coordinatesConfigResolver
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { Target } from '../types'
7
+ import { SUPPORT } from './support'
8
+
9
+ export const sharedConfigResolver = {
10
+ target(value: Target) {
11
+ if (value) {
12
+ return () => ('current' in value ? value.current : value)
13
+ }
14
+ return undefined
15
+ },
16
+ enabled(value = true) {
17
+ return value
18
+ },
19
+ window(value = SUPPORT.isBrowser ? window : undefined) {
20
+ return value
21
+ },
22
+ eventOptions({ passive = true, capture = false } = {}) {
23
+ return { passive, capture }
24
+ },
25
+ transform(value: any) {
26
+ return value
27
+ }
28
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ const isBrowser = typeof window !== 'undefined' && window.document && window.document.createElement
7
+
8
+ function supportsTouchEvents(): boolean {
9
+ return isBrowser && 'ontouchstart' in window
10
+ }
11
+
12
+ function isTouchScreen(): boolean {
13
+ return supportsTouchEvents() || (isBrowser && window.navigator.maxTouchPoints > 1)
14
+ }
15
+
16
+ function supportsPointerEvents(): boolean {
17
+ return isBrowser && 'onpointerdown' in window
18
+ }
19
+
20
+ function supportsPointerLock(): boolean {
21
+ return isBrowser && 'exitPointerLock' in window.document
22
+ }
23
+
24
+ function supportsGestureEvents(): boolean {
25
+ try {
26
+ // TODO [TS] possibly find GestureEvent definitions?
27
+ // @ts-ignore: no type definitions for webkit GestureEvents
28
+ return 'constructor' in GestureEvent
29
+ } catch (e) {
30
+ return false
31
+ }
32
+ }
33
+
34
+ export const SUPPORT = {
35
+ isBrowser,
36
+ gesture: supportsGestureEvents(),
37
+ /**
38
+ * It looks from https://github.com/pmndrs/use-gesture/discussions/421 that
39
+ * some touchscreens using webkits don't have 'ontouchstart' in window. So
40
+ * we're considering that browsers support TouchEvent if they have
41
+ * `maxTouchPoints > 1`
42
+ *
43
+ * Update 16/09/2023: This generates failure on other Windows systems, so reverting
44
+ * back to detecting TouchEvent support only.
45
+ * https://github.com/pmndrs/use-gesture/issues/626
46
+ */
47
+ touch: supportsTouchEvents(),
48
+ // touch: isTouchScreen(),
49
+ touchscreen: isTouchScreen(),
50
+ pointer: supportsPointerEvents(),
51
+ pointerLock: supportsPointerLock()
52
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { coordinatesConfigResolver } from './coordinatesConfigResolver'
7
+
8
+ export const wheelConfigResolver = coordinatesConfigResolver
@@ -0,0 +1,78 @@
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 { getPointerType } from '../utils/events';
8
+ import { CoordinatesKey, Vector2 } from '../types';
9
+ import { Engine } from './Engine';
10
+
11
+ function selectAxis([dx, dy]: Vector2, threshold: number) {
12
+ const absDx = Math.abs(dx);
13
+ const absDy = Math.abs(dy);
14
+
15
+ if (absDx > absDy && absDx > threshold) {
16
+ return 'x';
17
+ }
18
+ if (absDy > absDx && absDy > threshold) {
19
+ return 'y';
20
+ }
21
+ return undefined;
22
+ }
23
+
24
+ export abstract class CoordinatesEngine<Key extends CoordinatesKey> extends Engine<Key> {
25
+ aliasKey = 'xy';
26
+
27
+ reset() {
28
+ super.reset();
29
+ this.state.axis = undefined;
30
+ }
31
+
32
+ init() {
33
+ this.state.offset = [0, 0];
34
+ this.state.lastOffset = [0, 0];
35
+ }
36
+
37
+ computeOffset() {
38
+ this.state.offset = V.add(this.state.lastOffset, this.state.movement);
39
+ }
40
+
41
+ computeMovement() {
42
+ this.state.movement = V.sub(this.state.offset, this.state.lastOffset);
43
+ }
44
+
45
+ axisIntent(event?: UIEvent) {
46
+ const state = this.state;
47
+ const config = this.config;
48
+
49
+ if (!state.axis && event) {
50
+ const threshold =
51
+ typeof config.axisThreshold === 'object'
52
+ ? config.axisThreshold[getPointerType(event)]
53
+ : config.axisThreshold;
54
+
55
+ state.axis = selectAxis(state._movement, threshold);
56
+ }
57
+
58
+ // We block the movement if either:
59
+ // - config.lockDirection or config.axis was set but axis isn't detected yet
60
+ // - config.axis was set but is different than detected axis
61
+ state._blocked =
62
+ ((config.lockDirection || !!config.axis) && !state.axis) ||
63
+ (!!config.axis && config.axis !== state.axis);
64
+ }
65
+
66
+ restrictToAxis(v: Vector2) {
67
+ if (this.config.axis || this.config.lockDirection) {
68
+ switch (this.state.axis) {
69
+ case 'x':
70
+ v[1] = 0;
71
+ break; // [ x, 0 ]
72
+ case 'y':
73
+ v[0] = 0;
74
+ break; // [ 0, y ]
75
+ }
76
+ }
77
+ }
78
+ }