Initial project import
This commit is contained in:
184
node_modules/@use-gesture/core/src/Controller.ts
generated
vendored
Normal file
184
node_modules/@use-gesture/core/src/Controller.ts
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
import { EngineMap } from './actions'
|
||||
import { parse } from './config/resolver'
|
||||
import { isTouch, parseProp, toHandlerProp, touchIds } from './utils/events'
|
||||
import { EventStore } from './EventStore'
|
||||
import { TimeoutStore } from './TimeoutStore'
|
||||
import { chain } from './utils/fn'
|
||||
import { GestureKey, InternalConfig, InternalHandlers, NativeHandlers, State, UserGestureConfig } from './types'
|
||||
|
||||
export class Controller {
|
||||
/**
|
||||
* The list of gestures handled by the Controller.
|
||||
*/
|
||||
public gestures = new Set<GestureKey>()
|
||||
/**
|
||||
* The event store that keeps track of the config.target listeners.
|
||||
*/
|
||||
private _targetEventStore = new EventStore(this)
|
||||
/**
|
||||
* Object that keeps track of all gesture event listeners.
|
||||
*/
|
||||
public gestureEventStores: { [key in GestureKey]?: EventStore } = {}
|
||||
public gestureTimeoutStores: { [key in GestureKey]?: TimeoutStore } = {}
|
||||
public handlers: InternalHandlers = {}
|
||||
private nativeHandlers?: NativeHandlers
|
||||
public config = {} as InternalConfig
|
||||
public pointerIds = new Set<number>()
|
||||
public touchIds = new Set<number>()
|
||||
public state = {
|
||||
shared: {
|
||||
shiftKey: false,
|
||||
metaKey: false,
|
||||
ctrlKey: false,
|
||||
altKey: false
|
||||
}
|
||||
} as State
|
||||
|
||||
constructor(handlers: InternalHandlers) {
|
||||
resolveGestures(this, handlers)
|
||||
}
|
||||
/**
|
||||
* Sets pointer or touch ids based on the event.
|
||||
* @param event
|
||||
*/
|
||||
setEventIds(event: TouchEvent | PointerEvent) {
|
||||
if (isTouch(event)) {
|
||||
this.touchIds = new Set(touchIds(event as TouchEvent))
|
||||
return this.touchIds
|
||||
} else if ('pointerId' in event) {
|
||||
if (event.type === 'pointerup' || event.type === 'pointercancel') this.pointerIds.delete(event.pointerId)
|
||||
else if (event.type === 'pointerdown') this.pointerIds.add(event.pointerId)
|
||||
return this.pointerIds
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Attaches handlers to the controller.
|
||||
* @param handlers
|
||||
* @param nativeHandlers
|
||||
*/
|
||||
applyHandlers(handlers: InternalHandlers, nativeHandlers?: NativeHandlers) {
|
||||
this.handlers = handlers
|
||||
this.nativeHandlers = nativeHandlers
|
||||
}
|
||||
/**
|
||||
* Compute and attaches a config to the controller.
|
||||
* @param config
|
||||
* @param gestureKey
|
||||
*/
|
||||
applyConfig(config: UserGestureConfig, gestureKey?: GestureKey) {
|
||||
this.config = parse(config, gestureKey, this.config)
|
||||
}
|
||||
/**
|
||||
* Cleans all side effects (listeners, timeouts). When the gesture is
|
||||
* destroyed (in React, when the component is unmounted.)
|
||||
*/
|
||||
clean() {
|
||||
this._targetEventStore.clean()
|
||||
for (const key of this.gestures) {
|
||||
this.gestureEventStores[key]!.clean()
|
||||
this.gestureTimeoutStores[key]!.clean()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Executes side effects (attaching listeners to a `config.target`). Ran on
|
||||
* each render.
|
||||
*/
|
||||
effect() {
|
||||
if (this.config.shared.target) this.bind()
|
||||
return () => this._targetEventStore.clean()
|
||||
}
|
||||
/**
|
||||
* The bind function that can be returned by the gesture handler (a hook in
|
||||
* React for example.)
|
||||
* @param args
|
||||
*/
|
||||
bind(...args: any[]) {
|
||||
const sharedConfig = this.config.shared
|
||||
const props: any = {}
|
||||
|
||||
let target
|
||||
if (sharedConfig.target) {
|
||||
target = sharedConfig.target()
|
||||
// if target is undefined let's stop
|
||||
if (!target) return
|
||||
}
|
||||
|
||||
if (sharedConfig.enabled) {
|
||||
// Adding gesture handlers
|
||||
for (const gestureKey of this.gestures) {
|
||||
const gestureConfig = this.config[gestureKey]!
|
||||
const bindFunction = bindToProps(props, gestureConfig.eventOptions, !!target)
|
||||
if (gestureConfig.enabled) {
|
||||
const Engine = EngineMap.get(gestureKey)!
|
||||
// @ts-ignore
|
||||
new Engine(this, args, gestureKey).bind(bindFunction)
|
||||
}
|
||||
}
|
||||
|
||||
// Adding native handlers
|
||||
const nativeBindFunction = bindToProps(props, sharedConfig.eventOptions, !!target)
|
||||
for (const eventKey in this.nativeHandlers) {
|
||||
nativeBindFunction(
|
||||
eventKey,
|
||||
'',
|
||||
// @ts-ignore
|
||||
(event) => this.nativeHandlers[eventKey]({ ...this.state.shared, event, args }),
|
||||
undefined,
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// If target isn't set, we return an object that contains gesture handlers
|
||||
// mapped to props handler event keys.
|
||||
for (const handlerProp in props) {
|
||||
props[handlerProp] = chain(...props[handlerProp])
|
||||
}
|
||||
|
||||
// When target isn't specified then return hanlder props.
|
||||
if (!target) return props
|
||||
|
||||
// When target is specified, then add listeners to the controller target
|
||||
// store.
|
||||
for (const handlerProp in props) {
|
||||
const { device, capture, passive } = parseProp(handlerProp)
|
||||
this._targetEventStore.add(target, device, '', props[handlerProp], { capture, passive })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupGesture(ctrl: Controller, gestureKey: GestureKey) {
|
||||
ctrl.gestures.add(gestureKey)
|
||||
ctrl.gestureEventStores[gestureKey] = new EventStore(ctrl, gestureKey)
|
||||
ctrl.gestureTimeoutStores[gestureKey] = new TimeoutStore()
|
||||
}
|
||||
|
||||
function resolveGestures(ctrl: Controller, internalHandlers: InternalHandlers) {
|
||||
// make sure hover handlers are added first to prevent bugs such as #322
|
||||
// where the hover pointerLeave handler is removed before the move
|
||||
// pointerLeave, which prevents hovering: false to be fired.
|
||||
if (internalHandlers.drag) setupGesture(ctrl, 'drag')
|
||||
if (internalHandlers.wheel) setupGesture(ctrl, 'wheel')
|
||||
if (internalHandlers.scroll) setupGesture(ctrl, 'scroll')
|
||||
if (internalHandlers.move) setupGesture(ctrl, 'move')
|
||||
if (internalHandlers.pinch) setupGesture(ctrl, 'pinch')
|
||||
if (internalHandlers.hover) setupGesture(ctrl, 'hover')
|
||||
}
|
||||
|
||||
const bindToProps =
|
||||
(props: any, eventOptions: AddEventListenerOptions, withPassiveOption: boolean) =>
|
||||
(
|
||||
device: string,
|
||||
action: string,
|
||||
handler: (event: any) => void,
|
||||
options: AddEventListenerOptions = {},
|
||||
isNative = false
|
||||
) => {
|
||||
const capture = options.capture ?? eventOptions.capture
|
||||
const passive = options.passive ?? eventOptions.passive
|
||||
// a native handler is already passed as a prop like "onMouseDown"
|
||||
let handlerProp = isNative ? device : toHandlerProp(device, action, capture)
|
||||
if (withPassiveOption && passive) handlerProp += 'Passive'
|
||||
props[handlerProp] = props[handlerProp] || []
|
||||
props[handlerProp].push(handler)
|
||||
}
|
||||
38
node_modules/@use-gesture/core/src/EventStore.ts
generated
vendored
Normal file
38
node_modules/@use-gesture/core/src/EventStore.ts
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import type { Controller } from './Controller'
|
||||
import { GestureKey } from './types'
|
||||
import { toDomEventType } from './utils/events'
|
||||
|
||||
export class EventStore {
|
||||
private _listeners = new Set<() => void>()
|
||||
private _ctrl: Controller
|
||||
private _gestureKey?: GestureKey
|
||||
constructor(ctrl: Controller, gestureKey?: GestureKey) {
|
||||
this._ctrl = ctrl
|
||||
this._gestureKey = gestureKey
|
||||
}
|
||||
|
||||
add(
|
||||
element: EventTarget,
|
||||
device: string,
|
||||
action: string,
|
||||
handler: (event: any) => void,
|
||||
options?: AddEventListenerOptions
|
||||
) {
|
||||
const listeners = this._listeners
|
||||
const type = toDomEventType(device, action)
|
||||
const _options = this._gestureKey ? this._ctrl.config[this._gestureKey]!.eventOptions : {}
|
||||
const eventOptions = { ..._options, ...options }
|
||||
element.addEventListener(type, handler, eventOptions)
|
||||
const remove = () => {
|
||||
element.removeEventListener(type, handler, eventOptions)
|
||||
listeners.delete(remove)
|
||||
}
|
||||
listeners.add(remove)
|
||||
return remove
|
||||
}
|
||||
|
||||
clean() {
|
||||
this._listeners.forEach((remove) => remove())
|
||||
this._listeners.clear() // just for safety
|
||||
}
|
||||
}
|
||||
23
node_modules/@use-gesture/core/src/TimeoutStore.ts
generated
vendored
Normal file
23
node_modules/@use-gesture/core/src/TimeoutStore.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export class TimeoutStore {
|
||||
private _timeouts = new Map<string, number>()
|
||||
|
||||
add<FunctionType extends (...args: any[]) => any>(
|
||||
key: string,
|
||||
callback: FunctionType,
|
||||
ms = 140,
|
||||
...args: Parameters<FunctionType>
|
||||
) {
|
||||
this.remove(key)
|
||||
this._timeouts.set(key, window.setTimeout(callback, ms, ...args))
|
||||
}
|
||||
|
||||
remove(key: string) {
|
||||
const timeout = this._timeouts.get(key)
|
||||
if (timeout) window.clearTimeout(timeout)
|
||||
}
|
||||
|
||||
clean() {
|
||||
this._timeouts.forEach((timeout) => void window.clearTimeout(timeout))
|
||||
this._timeouts.clear()
|
||||
}
|
||||
}
|
||||
64
node_modules/@use-gesture/core/src/actions.ts
generated
vendored
Normal file
64
node_modules/@use-gesture/core/src/actions.ts
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
import { GestureKey, EngineClass, Action } from './types'
|
||||
import { ResolverMap } from './config/resolver'
|
||||
|
||||
import { DragEngine } from './engines/DragEngine'
|
||||
import { dragConfigResolver } from './config/dragConfigResolver'
|
||||
|
||||
import { PinchEngine } from './engines/PinchEngine'
|
||||
import { pinchConfigResolver } from './config/pinchConfigResolver'
|
||||
|
||||
import { MoveEngine } from './engines/MoveEngine'
|
||||
import { moveConfigResolver } from './config/moveConfigResolver'
|
||||
|
||||
import { ScrollEngine } from './engines/ScrollEngine'
|
||||
import { scrollConfigResolver } from './config/scrollConfigResolver'
|
||||
|
||||
import { WheelEngine } from './engines/WheelEngine'
|
||||
import { wheelConfigResolver } from './config/wheelConfigResolver'
|
||||
|
||||
import { HoverEngine } from './engines/HoverEngine'
|
||||
import { hoverConfigResolver } from './config/hoverConfigResolver'
|
||||
|
||||
export const EngineMap = new Map<GestureKey, EngineClass<any>>()
|
||||
export const ConfigResolverMap = new Map<GestureKey, ResolverMap>()
|
||||
|
||||
export function registerAction(action: Action) {
|
||||
EngineMap.set(action.key, action.engine)
|
||||
ConfigResolverMap.set(action.key, action.resolver)
|
||||
}
|
||||
|
||||
export const dragAction: Action = {
|
||||
key: 'drag',
|
||||
engine: DragEngine as any,
|
||||
resolver: dragConfigResolver
|
||||
}
|
||||
|
||||
export const hoverAction: Action = {
|
||||
key: 'hover',
|
||||
engine: HoverEngine as any,
|
||||
resolver: hoverConfigResolver
|
||||
}
|
||||
|
||||
export const moveAction: Action = {
|
||||
key: 'move',
|
||||
engine: MoveEngine as any,
|
||||
resolver: moveConfigResolver
|
||||
}
|
||||
|
||||
export const pinchAction: Action = {
|
||||
key: 'pinch',
|
||||
engine: PinchEngine as any,
|
||||
resolver: pinchConfigResolver
|
||||
}
|
||||
|
||||
export const scrollAction: Action = {
|
||||
key: 'scroll',
|
||||
engine: ScrollEngine as any,
|
||||
resolver: scrollConfigResolver
|
||||
}
|
||||
|
||||
export const wheelAction: Action = {
|
||||
key: 'wheel',
|
||||
engine: WheelEngine as any,
|
||||
resolver: wheelConfigResolver
|
||||
}
|
||||
81
node_modules/@use-gesture/core/src/config/commonConfigResolver.ts
generated
vendored
Normal file
81
node_modules/@use-gesture/core/src/config/commonConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { InternalGestureOptions } from '../types'
|
||||
import { Vector2, State, GenericOptions } from '../types'
|
||||
import { V } from '../utils/maths'
|
||||
|
||||
export const identity = (v: Vector2) => v
|
||||
export const DEFAULT_RUBBERBAND = 0.15
|
||||
|
||||
export const commonConfigResolver = {
|
||||
enabled(value = true) {
|
||||
return value
|
||||
},
|
||||
eventOptions(value: AddEventListenerOptions | undefined, _k: string, config: { shared: GenericOptions }) {
|
||||
return { ...config.shared.eventOptions, ...value }
|
||||
},
|
||||
preventDefault(value = false) {
|
||||
return value
|
||||
},
|
||||
triggerAllEvents(value = false) {
|
||||
return value
|
||||
},
|
||||
rubberband(value: number | boolean | Vector2 = 0): Vector2 {
|
||||
switch (value) {
|
||||
case true:
|
||||
return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND]
|
||||
case false:
|
||||
return [0, 0]
|
||||
default:
|
||||
return V.toVector(value)
|
||||
}
|
||||
},
|
||||
from(value: number | Vector2 | ((s: State) => Vector2)) {
|
||||
if (typeof value === 'function') return value
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (value != null) return V.toVector(value)
|
||||
},
|
||||
transform(this: InternalGestureOptions, value: any, _k: string, config: { shared: GenericOptions }) {
|
||||
const transform = value || config.shared.transform
|
||||
this.hasCustomTransform = !!transform
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const originalTransform = transform || identity
|
||||
return (v: Vector2) => {
|
||||
const r = originalTransform(v)
|
||||
if (!isFinite(r[0]) || !isFinite(r[1])) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r[0]},${[1]}]`)
|
||||
}
|
||||
return r
|
||||
}
|
||||
}
|
||||
return transform || identity
|
||||
},
|
||||
threshold(value: any) {
|
||||
return V.toVector(value, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
Object.assign(commonConfigResolver, {
|
||||
domTarget(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
lockDirection(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`lockDirection\` option has been merged with \`axis\`. Use it as in \`{ axis: 'lock' }\``
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
initial(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(`[@use-gesture]: \`initial\` option has been renamed to \`from\`.`)
|
||||
}
|
||||
return NaN
|
||||
}
|
||||
})
|
||||
}
|
||||
43
node_modules/@use-gesture/core/src/config/coordinatesConfigResolver.ts
generated
vendored
Normal file
43
node_modules/@use-gesture/core/src/config/coordinatesConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { commonConfigResolver } from './commonConfigResolver'
|
||||
import { InternalCoordinatesOptions, CoordinatesConfig, Bounds, DragBounds, State, Vector2 } from '../types'
|
||||
|
||||
const DEFAULT_AXIS_THRESHOLD = 0
|
||||
|
||||
export const coordinatesConfigResolver = {
|
||||
...commonConfigResolver,
|
||||
axis(
|
||||
this: InternalCoordinatesOptions,
|
||||
_v: any,
|
||||
_k: string,
|
||||
{ axis }: CoordinatesConfig
|
||||
): InternalCoordinatesOptions['axis'] {
|
||||
this.lockDirection = axis === 'lock'
|
||||
if (!this.lockDirection) return axis as any
|
||||
},
|
||||
axisThreshold(value = DEFAULT_AXIS_THRESHOLD) {
|
||||
return value
|
||||
},
|
||||
bounds(
|
||||
value: DragBounds | ((state: State) => DragBounds) = {}
|
||||
): (() => EventTarget | null) | HTMLElement | [Vector2, Vector2] {
|
||||
if (typeof value === 'function') {
|
||||
// @ts-ignore
|
||||
return (state: State) => coordinatesConfigResolver.bounds(value(state))
|
||||
}
|
||||
|
||||
if ('current' in value) {
|
||||
return () => value.current
|
||||
}
|
||||
|
||||
if (typeof HTMLElement === 'function' && value instanceof HTMLElement) {
|
||||
return value
|
||||
}
|
||||
|
||||
const { left = -Infinity, right = Infinity, top = -Infinity, bottom = Infinity } = value as Bounds
|
||||
|
||||
return [
|
||||
[left, right],
|
||||
[top, bottom]
|
||||
]
|
||||
}
|
||||
}
|
||||
135
node_modules/@use-gesture/core/src/config/dragConfigResolver.ts
generated
vendored
Normal file
135
node_modules/@use-gesture/core/src/config/dragConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import { PointerType } from '../types'
|
||||
import { DragConfig, InternalDragOptions, Vector2 } from '../types'
|
||||
import { V } from '../utils/maths'
|
||||
import { coordinatesConfigResolver } from './coordinatesConfigResolver'
|
||||
import { SUPPORT } from './support'
|
||||
|
||||
export const DEFAULT_PREVENT_SCROLL_DELAY = 250
|
||||
export const DEFAULT_DRAG_DELAY = 180
|
||||
export const DEFAULT_SWIPE_VELOCITY = 0.5
|
||||
export const DEFAULT_SWIPE_DISTANCE = 50
|
||||
export const DEFAULT_SWIPE_DURATION = 250
|
||||
export const DEFAULT_KEYBOARD_DISPLACEMENT = 10
|
||||
|
||||
const DEFAULT_DRAG_AXIS_THRESHOLD: Record<PointerType, number> = { mouse: 0, touch: 0, pen: 8 }
|
||||
|
||||
export const dragConfigResolver = {
|
||||
...coordinatesConfigResolver,
|
||||
device(
|
||||
this: InternalDragOptions,
|
||||
_v: any,
|
||||
_k: string,
|
||||
{ pointer: { touch = false, lock = false, mouse = false } = {} }: DragConfig
|
||||
) {
|
||||
this.pointerLock = lock && SUPPORT.pointerLock
|
||||
if (SUPPORT.touch && touch) return 'touch'
|
||||
if (this.pointerLock) return 'mouse'
|
||||
if (SUPPORT.pointer && !mouse) return 'pointer'
|
||||
if (SUPPORT.touch) return 'touch'
|
||||
return 'mouse'
|
||||
},
|
||||
preventScrollAxis(this: InternalDragOptions, value: 'x' | 'y' | 'xy', _k: string, { preventScroll }: DragConfig) {
|
||||
this.preventScrollDelay =
|
||||
typeof preventScroll === 'number'
|
||||
? preventScroll
|
||||
: preventScroll || (preventScroll === undefined && value)
|
||||
? DEFAULT_PREVENT_SCROLL_DELAY
|
||||
: undefined
|
||||
if (!SUPPORT.touchscreen || preventScroll === false) return undefined
|
||||
return value ? value : preventScroll !== undefined ? 'y' : undefined
|
||||
},
|
||||
pointerCapture(
|
||||
this: InternalDragOptions,
|
||||
_v: any,
|
||||
_k: string,
|
||||
{ pointer: { capture = true, buttons = 1, keys = true } = {} }
|
||||
) {
|
||||
this.pointerButtons = buttons
|
||||
this.keys = keys
|
||||
return !this.pointerLock && this.device === 'pointer' && capture
|
||||
},
|
||||
threshold(
|
||||
this: InternalDragOptions,
|
||||
value: number | Vector2,
|
||||
_k: string,
|
||||
{ filterTaps = false, tapsThreshold = 3, axis = undefined }
|
||||
) {
|
||||
// TODO add warning when value is 0 and filterTaps or axis is set
|
||||
const threshold = V.toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0)
|
||||
this.filterTaps = filterTaps
|
||||
this.tapsThreshold = tapsThreshold
|
||||
return threshold
|
||||
},
|
||||
swipe(
|
||||
this: InternalDragOptions,
|
||||
{ velocity = DEFAULT_SWIPE_VELOCITY, distance = DEFAULT_SWIPE_DISTANCE, duration = DEFAULT_SWIPE_DURATION } = {}
|
||||
) {
|
||||
return {
|
||||
velocity: this.transform(V.toVector(velocity)),
|
||||
distance: this.transform(V.toVector(distance)),
|
||||
duration
|
||||
}
|
||||
},
|
||||
delay(value: number | boolean = 0) {
|
||||
switch (value) {
|
||||
case true:
|
||||
return DEFAULT_DRAG_DELAY
|
||||
case false:
|
||||
return 0
|
||||
default:
|
||||
return value
|
||||
}
|
||||
},
|
||||
axisThreshold(value: Record<PointerType, number>) {
|
||||
if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD
|
||||
return { ...DEFAULT_DRAG_AXIS_THRESHOLD, ...value }
|
||||
},
|
||||
keyboardDisplacement(value: number = DEFAULT_KEYBOARD_DISPLACEMENT) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
Object.assign(dragConfigResolver, {
|
||||
useTouch(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`useTouch\` option has been renamed to \`pointer.touch\`. Use it as in \`{ pointer: { touch: true } }\`.`
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
experimental_preventWindowScrollY(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`experimental_preventWindowScrollY\` option has been renamed to \`preventScroll\`.`
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
swipeVelocity(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`swipeVelocity\` option has been renamed to \`swipe.velocity\`. Use it as in \`{ swipe: { velocity: 0.5 } }\`.`
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
swipeDistance(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`swipeDistance\` option has been renamed to \`swipe.distance\`. Use it as in \`{ swipe: { distance: 50 } }\`.`
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
},
|
||||
swipeDuration(value: any) {
|
||||
if (value !== undefined) {
|
||||
throw Error(
|
||||
`[@use-gesture]: \`swipeDuration\` option has been renamed to \`swipe.duration\`. Use it as in \`{ swipe: { duration: 250 } }\`.`
|
||||
)
|
||||
}
|
||||
return NaN
|
||||
}
|
||||
})
|
||||
}
|
||||
6
node_modules/@use-gesture/core/src/config/hoverConfigResolver.ts
generated
vendored
Normal file
6
node_modules/@use-gesture/core/src/config/hoverConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { coordinatesConfigResolver } from './coordinatesConfigResolver'
|
||||
|
||||
export const hoverConfigResolver = {
|
||||
...coordinatesConfigResolver,
|
||||
mouseOnly: (value = true) => value
|
||||
}
|
||||
6
node_modules/@use-gesture/core/src/config/moveConfigResolver.ts
generated
vendored
Normal file
6
node_modules/@use-gesture/core/src/config/moveConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { coordinatesConfigResolver } from './coordinatesConfigResolver'
|
||||
|
||||
export const moveConfigResolver = {
|
||||
...coordinatesConfigResolver,
|
||||
mouseOnly: (value = true) => value
|
||||
}
|
||||
54
node_modules/@use-gesture/core/src/config/pinchConfigResolver.ts
generated
vendored
Normal file
54
node_modules/@use-gesture/core/src/config/pinchConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { ModifierKey } from '../types'
|
||||
import { PinchConfig, GenericOptions, InternalPinchOptions, State, Vector2 } from '../types'
|
||||
import { call, assignDefault } from '../utils/fn'
|
||||
import { V } from '../utils/maths'
|
||||
import { commonConfigResolver } from './commonConfigResolver'
|
||||
import { SUPPORT } from './support'
|
||||
|
||||
export const pinchConfigResolver = {
|
||||
...commonConfigResolver,
|
||||
device(
|
||||
this: InternalPinchOptions,
|
||||
_v: any,
|
||||
_k: string,
|
||||
{ shared, pointer: { touch = false } = {} }: { shared: GenericOptions } & PinchConfig
|
||||
) {
|
||||
// Only try to use gesture events when they are supported and domTarget is set
|
||||
// as React doesn't support gesture handlers.
|
||||
const sharedConfig = shared
|
||||
if (sharedConfig.target && !SUPPORT.touch && SUPPORT.gesture) return 'gesture'
|
||||
if (SUPPORT.touch && touch) return 'touch'
|
||||
if (SUPPORT.touchscreen) {
|
||||
if (SUPPORT.pointer) return 'pointer'
|
||||
if (SUPPORT.touch) return 'touch'
|
||||
}
|
||||
// device is undefined and that's ok, we're going to use wheel to zoom.
|
||||
},
|
||||
bounds(_v: any, _k: string, { scaleBounds = {}, angleBounds = {} }: PinchConfig) {
|
||||
const _scaleBounds = (state?: State) => {
|
||||
const D = assignDefault(call(scaleBounds, state), { min: -Infinity, max: Infinity })
|
||||
return [D.min, D.max]
|
||||
}
|
||||
|
||||
const _angleBounds = (state?: State) => {
|
||||
const A = assignDefault(call(angleBounds, state), { min: -Infinity, max: Infinity })
|
||||
return [A.min, A.max]
|
||||
}
|
||||
|
||||
if (typeof scaleBounds !== 'function' && typeof angleBounds !== 'function') return [_scaleBounds(), _angleBounds()]
|
||||
|
||||
return (state: State) => [_scaleBounds(state), _angleBounds(state)]
|
||||
},
|
||||
threshold(this: InternalPinchOptions, value: number | Vector2, _k: string, config: PinchConfig) {
|
||||
this.lockDirection = config.axis === 'lock'
|
||||
const threshold = V.toVector(value, this.lockDirection ? [0.1, 3] : 0)
|
||||
return threshold
|
||||
},
|
||||
modifierKey(value: ModifierKey | ModifierKey[]) {
|
||||
if (value === undefined) return 'ctrlKey'
|
||||
return value
|
||||
},
|
||||
pinchOnWheel(value = true) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
65
node_modules/@use-gesture/core/src/config/resolver.ts
generated
vendored
Normal file
65
node_modules/@use-gesture/core/src/config/resolver.ts
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import { sharedConfigResolver } from './sharedConfigResolver'
|
||||
import { ConfigResolverMap } from '../actions'
|
||||
import { GestureKey, InternalConfig, UserGestureConfig } from '../types'
|
||||
|
||||
export type Resolver = (x: any, key: string, obj: any) => any
|
||||
export type ResolverMap = { [k: string]: Resolver | ResolverMap | boolean }
|
||||
|
||||
export function resolveWith<T extends { [k: string]: any }, V extends { [k: string]: any }>(
|
||||
config: Partial<T> = {},
|
||||
resolvers: ResolverMap
|
||||
): V {
|
||||
const result: any = {}
|
||||
|
||||
for (const [key, resolver] of Object.entries(resolvers)) {
|
||||
switch (typeof resolver) {
|
||||
case 'function':
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const r = resolver.call(result, config[key], key, config)
|
||||
// prevents deprecated resolvers from applying in dev mode
|
||||
if (!Number.isNaN(r)) result[key] = r
|
||||
} else {
|
||||
result[key] = resolver.call(result, config[key], key, config)
|
||||
}
|
||||
break
|
||||
case 'object':
|
||||
result[key] = resolveWith(config[key], resolver)
|
||||
break
|
||||
case 'boolean':
|
||||
if (resolver) result[key] = config[key]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export function parse(newConfig: UserGestureConfig, gestureKey?: GestureKey, _config: any = {}): InternalConfig {
|
||||
const { target, eventOptions, window, enabled, transform, ...rest } = newConfig as any
|
||||
|
||||
_config.shared = resolveWith({ target, eventOptions, window, enabled, transform }, sharedConfigResolver)
|
||||
|
||||
if (gestureKey) {
|
||||
const resolver = ConfigResolverMap.get(gestureKey)!
|
||||
_config[gestureKey] = resolveWith({ shared: _config.shared, ...rest }, resolver)
|
||||
} else {
|
||||
for (const key in rest) {
|
||||
const resolver = ConfigResolverMap.get(key as GestureKey)!
|
||||
|
||||
if (resolver) {
|
||||
_config[key] = resolveWith({ shared: _config.shared, ...rest[key] }, resolver)
|
||||
} else if (process.env.NODE_ENV === 'development') {
|
||||
if (!['drag', 'pinch', 'scroll', 'wheel', 'move', 'hover'].includes(key)) {
|
||||
if (key === 'domTarget') {
|
||||
throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`)
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`[@use-gesture]: Unknown config key \`${key}\` was used. Please read the documentation for further information.`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _config
|
||||
}
|
||||
3
node_modules/@use-gesture/core/src/config/scrollConfigResolver.ts
generated
vendored
Normal file
3
node_modules/@use-gesture/core/src/config/scrollConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { coordinatesConfigResolver } from './coordinatesConfigResolver'
|
||||
|
||||
export const scrollConfigResolver = coordinatesConfigResolver
|
||||
23
node_modules/@use-gesture/core/src/config/sharedConfigResolver.ts
generated
vendored
Normal file
23
node_modules/@use-gesture/core/src/config/sharedConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Target } from '../types'
|
||||
import { SUPPORT } from './support'
|
||||
|
||||
export const sharedConfigResolver = {
|
||||
target(value: Target) {
|
||||
if (value) {
|
||||
return () => ('current' in value ? value.current : value)
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
enabled(value = true) {
|
||||
return value
|
||||
},
|
||||
window(value = SUPPORT.isBrowser ? window : undefined) {
|
||||
return value
|
||||
},
|
||||
eventOptions({ passive = true, capture = false } = {}) {
|
||||
return { passive, capture }
|
||||
},
|
||||
transform(value: any) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
47
node_modules/@use-gesture/core/src/config/support.ts
generated
vendored
Normal file
47
node_modules/@use-gesture/core/src/config/support.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
const isBrowser = typeof window !== 'undefined' && window.document && window.document.createElement
|
||||
|
||||
function supportsTouchEvents(): boolean {
|
||||
return isBrowser && 'ontouchstart' in window
|
||||
}
|
||||
|
||||
function isTouchScreen(): boolean {
|
||||
return supportsTouchEvents() || (isBrowser && window.navigator.maxTouchPoints > 1)
|
||||
}
|
||||
|
||||
function supportsPointerEvents(): boolean {
|
||||
return isBrowser && 'onpointerdown' in window
|
||||
}
|
||||
|
||||
function supportsPointerLock(): boolean {
|
||||
return isBrowser && 'exitPointerLock' in window.document
|
||||
}
|
||||
|
||||
function supportsGestureEvents(): boolean {
|
||||
try {
|
||||
// TODO [TS] possibly find GestureEvent definitions?
|
||||
// @ts-ignore: no type definitions for webkit GestureEvents
|
||||
return 'constructor' in GestureEvent
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const SUPPORT = {
|
||||
isBrowser,
|
||||
gesture: supportsGestureEvents(),
|
||||
/**
|
||||
* It looks from https://github.com/pmndrs/use-gesture/discussions/421 that
|
||||
* some touchscreens using webkits don't have 'ontouchstart' in window. So
|
||||
* we're considering that browsers support TouchEvent if they have
|
||||
* `maxTouchPoints > 1`
|
||||
*
|
||||
* Update 16/09/2023: This generates failure on other Windows systems, so reverting
|
||||
* back to detecting TouchEvent support only.
|
||||
* https://github.com/pmndrs/use-gesture/issues/626
|
||||
*/
|
||||
touch: supportsTouchEvents(),
|
||||
// touch: isTouchScreen(),
|
||||
touchscreen: isTouchScreen(),
|
||||
pointer: supportsPointerEvents(),
|
||||
pointerLock: supportsPointerLock()
|
||||
}
|
||||
3
node_modules/@use-gesture/core/src/config/wheelConfigResolver.ts
generated
vendored
Normal file
3
node_modules/@use-gesture/core/src/config/wheelConfigResolver.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { coordinatesConfigResolver } from './coordinatesConfigResolver'
|
||||
|
||||
export const wheelConfigResolver = coordinatesConfigResolver
|
||||
70
node_modules/@use-gesture/core/src/engines/CoordinatesEngine.ts
generated
vendored
Normal file
70
node_modules/@use-gesture/core/src/engines/CoordinatesEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Engine } from './Engine'
|
||||
import { V } from '../utils/maths'
|
||||
import { CoordinatesKey, Vector2 } from '../types'
|
||||
import { getPointerType } from '../utils/events'
|
||||
|
||||
function selectAxis([dx, dy]: Vector2, threshold: number) {
|
||||
const absDx = Math.abs(dx)
|
||||
const absDy = Math.abs(dy)
|
||||
|
||||
if (absDx > absDy && absDx > threshold) {
|
||||
return 'x'
|
||||
}
|
||||
if (absDy > absDx && absDy > threshold) {
|
||||
return 'y'
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export abstract class CoordinatesEngine<Key extends CoordinatesKey> extends Engine<Key> {
|
||||
aliasKey = 'xy'
|
||||
|
||||
reset() {
|
||||
super.reset()
|
||||
this.state.axis = undefined
|
||||
}
|
||||
|
||||
init() {
|
||||
this.state.offset = [0, 0]
|
||||
this.state.lastOffset = [0, 0]
|
||||
}
|
||||
|
||||
computeOffset() {
|
||||
this.state.offset = V.add(this.state.lastOffset, this.state.movement)
|
||||
}
|
||||
|
||||
computeMovement() {
|
||||
this.state.movement = V.sub(this.state.offset, this.state.lastOffset)
|
||||
}
|
||||
|
||||
axisIntent(event?: UIEvent) {
|
||||
const state = this.state
|
||||
const config = this.config
|
||||
|
||||
if (!state.axis && event) {
|
||||
const threshold =
|
||||
typeof config.axisThreshold === 'object' ? config.axisThreshold[getPointerType(event)] : config.axisThreshold
|
||||
|
||||
state.axis = selectAxis(state._movement, threshold)
|
||||
}
|
||||
|
||||
// We block the movement if either:
|
||||
// - config.lockDirection or config.axis was set but axis isn't detected yet
|
||||
// - config.axis was set but is different than detected axis
|
||||
state._blocked =
|
||||
((config.lockDirection || !!config.axis) && !state.axis) || (!!config.axis && config.axis !== state.axis)
|
||||
}
|
||||
|
||||
restrictToAxis(v: Vector2) {
|
||||
if (this.config.axis || this.config.lockDirection) {
|
||||
switch (this.state.axis) {
|
||||
case 'x':
|
||||
v[1] = 0
|
||||
break // [ x, 0 ]
|
||||
case 'y':
|
||||
v[0] = 0
|
||||
break // [ 0, y ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
383
node_modules/@use-gesture/core/src/engines/DragEngine.ts
generated
vendored
Normal file
383
node_modules/@use-gesture/core/src/engines/DragEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,383 @@
|
||||
import { CoordinatesEngine } from './CoordinatesEngine'
|
||||
import { coordinatesConfigResolver } from '../config/coordinatesConfigResolver'
|
||||
import { pointerId, getPointerType, pointerValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
import { Vector2 } from '../types'
|
||||
|
||||
const KEYS_DELTA_MAP = {
|
||||
ArrowRight: (displacement: number, factor: number = 1) => [displacement * factor, 0],
|
||||
ArrowLeft: (displacement: number, factor: number = 1) => [-1 * displacement * factor, 0],
|
||||
ArrowUp: (displacement: number, factor: number = 1) => [0, -1 * displacement * factor],
|
||||
ArrowDown: (displacement: number, factor: number = 1) => [0, displacement * factor]
|
||||
}
|
||||
|
||||
export class DragEngine extends CoordinatesEngine<'drag'> {
|
||||
ingKey = 'dragging' as const
|
||||
|
||||
// superseeds generic Engine reset call
|
||||
reset(this: DragEngine) {
|
||||
super.reset()
|
||||
const state = this.state
|
||||
state._pointerId = undefined
|
||||
state._pointerActive = false
|
||||
state._keyboardActive = false
|
||||
state._preventScroll = false
|
||||
state._delayed = false
|
||||
state.swipe = [0, 0]
|
||||
state.tap = false
|
||||
state.canceled = false
|
||||
state.cancel = this.cancel.bind(this)
|
||||
}
|
||||
|
||||
setup() {
|
||||
const state = this.state
|
||||
|
||||
if (state._bounds instanceof HTMLElement) {
|
||||
const boundRect = state._bounds.getBoundingClientRect()
|
||||
const targetRect = (state.currentTarget as HTMLElement).getBoundingClientRect()
|
||||
const _bounds = {
|
||||
left: boundRect.left - targetRect.left + state.offset[0],
|
||||
right: boundRect.right - targetRect.right + state.offset[0],
|
||||
top: boundRect.top - targetRect.top + state.offset[1],
|
||||
bottom: boundRect.bottom - targetRect.bottom + state.offset[1]
|
||||
}
|
||||
state._bounds = coordinatesConfigResolver.bounds(_bounds) as [Vector2, Vector2]
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
const state = this.state
|
||||
if (state.canceled) return
|
||||
state.canceled = true
|
||||
state._active = false
|
||||
setTimeout(() => {
|
||||
// we run compute with no event so that kinematics won't be computed
|
||||
this.compute()
|
||||
this.emit()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
setActive() {
|
||||
this.state._active = this.state._pointerActive || this.state._keyboardActive
|
||||
}
|
||||
|
||||
// superseeds Engine clean function
|
||||
clean() {
|
||||
this.pointerClean()
|
||||
this.state._pointerActive = false
|
||||
this.state._keyboardActive = false
|
||||
super.clean()
|
||||
}
|
||||
|
||||
pointerDown(event: PointerEvent) {
|
||||
const config = this.config
|
||||
const state = this.state
|
||||
|
||||
if (
|
||||
event.buttons != null &&
|
||||
// If the user submits an array as pointer.buttons, don't start the drag
|
||||
// if event.buttons isn't included inside that array.
|
||||
(Array.isArray(config.pointerButtons)
|
||||
? !config.pointerButtons.includes(event.buttons)
|
||||
: // If the user submits a number as pointer.buttons, refuse the drag if
|
||||
// config.pointerButtons is different than `-1` and if event.buttons
|
||||
// doesn't match the combination.
|
||||
config.pointerButtons !== -1 && config.pointerButtons !== event.buttons)
|
||||
)
|
||||
return
|
||||
|
||||
const ctrlIds = this.ctrl.setEventIds(event)
|
||||
// We need to capture all pointer ids so that we can keep track of them when
|
||||
// they're released off the target
|
||||
if (config.pointerCapture) {
|
||||
;(event.target as HTMLElement).setPointerCapture(event.pointerId)
|
||||
}
|
||||
|
||||
if (
|
||||
// in some situations (https://github.com/pmndrs/use-gesture/issues/494#issuecomment-1127584116)
|
||||
// like when a new browser tab is opened during a drag gesture, the drag
|
||||
// can be interrupted mid-way, and can stall. This happens because the
|
||||
// pointerId that initiated the gesture is lost, and since the drag
|
||||
// persists until that pointerId is lifted with pointerup, it never ends.
|
||||
//
|
||||
// Therefore, when we detect that only one pointer is pressing the screen,
|
||||
// we consider that the gesture can proceed.
|
||||
ctrlIds &&
|
||||
ctrlIds.size > 1 &&
|
||||
state._pointerActive
|
||||
)
|
||||
return
|
||||
|
||||
this.start(event)
|
||||
this.setupPointer(event)
|
||||
|
||||
state._pointerId = pointerId(event)
|
||||
state._pointerActive = true
|
||||
|
||||
this.computeValues(pointerValues(event))
|
||||
this.computeInitial()
|
||||
|
||||
if (config.preventScrollAxis && getPointerType(event) !== 'mouse') {
|
||||
// when preventScrollAxis is set we don't consider the gesture active
|
||||
// until it's deliberate
|
||||
state._active = false
|
||||
this.setupScrollPrevention(event)
|
||||
} else if (config.delay > 0) {
|
||||
this.setupDelayTrigger(event)
|
||||
// makes sure we emit all events when `triggerAllEvents` flag is `true`
|
||||
if (config.triggerAllEvents) {
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
} else {
|
||||
this.startPointerDrag(event)
|
||||
}
|
||||
}
|
||||
|
||||
startPointerDrag(event: PointerEvent) {
|
||||
const state = this.state
|
||||
state._active = true
|
||||
state._preventScroll = true
|
||||
state._delayed = false
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
pointerMove(event: PointerEvent) {
|
||||
const state = this.state
|
||||
const config = this.config
|
||||
|
||||
if (!state._pointerActive) return
|
||||
|
||||
const id = pointerId(event)
|
||||
if (state._pointerId !== undefined && id !== state._pointerId) return
|
||||
const _values = pointerValues(event)
|
||||
|
||||
if (document.pointerLockElement === event.target) {
|
||||
state._delta = [event.movementX, event.movementY]
|
||||
} else {
|
||||
state._delta = V.sub(_values, state._values)
|
||||
this.computeValues(_values)
|
||||
}
|
||||
|
||||
V.addTo(state._movement, state._delta)
|
||||
this.compute(event)
|
||||
|
||||
// if the gesture is delayed but deliberate, then we can start it
|
||||
// immediately.
|
||||
if (state._delayed && state.intentional) {
|
||||
this.timeoutStore.remove('dragDelay')
|
||||
// makes sure `first` is still true when moving for the first time after a
|
||||
// delay.
|
||||
state.active = false
|
||||
this.startPointerDrag(event)
|
||||
return
|
||||
}
|
||||
|
||||
if (config.preventScrollAxis && !state._preventScroll) {
|
||||
if (state.axis) {
|
||||
if (state.axis === config.preventScrollAxis || config.preventScrollAxis === 'xy') {
|
||||
state._active = false
|
||||
this.clean()
|
||||
return
|
||||
} else {
|
||||
this.timeoutStore.remove('startPointerDrag')
|
||||
this.startPointerDrag(event)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.emit()
|
||||
}
|
||||
|
||||
pointerUp(event: PointerEvent) {
|
||||
this.ctrl.setEventIds(event)
|
||||
// We release the pointer id if it has pointer capture
|
||||
try {
|
||||
if (this.config.pointerCapture && (event.target as HTMLElement).hasPointerCapture(event.pointerId)) {
|
||||
// this shouldn't be necessary as it should be automatic when releasing the pointer
|
||||
;(event.target as HTMLElement).releasePointerCapture(event.pointerId)
|
||||
}
|
||||
} catch {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`[@use-gesture]: If you see this message, it's likely that you're using an outdated version of \`@react-three/fiber\`. \n\nPlease upgrade to the latest version.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const state = this.state
|
||||
const config = this.config
|
||||
|
||||
if (!state._active || !state._pointerActive) return
|
||||
|
||||
const id = pointerId(event)
|
||||
if (state._pointerId !== undefined && id !== state._pointerId) return
|
||||
|
||||
this.state._pointerActive = false
|
||||
this.setActive()
|
||||
this.compute(event)
|
||||
|
||||
const [dx, dy] = state._distance
|
||||
state.tap = dx <= config.tapsThreshold && dy <= config.tapsThreshold
|
||||
|
||||
if (state.tap && config.filterTaps) {
|
||||
state._force = true
|
||||
} else {
|
||||
const [_dx, _dy] = state._delta
|
||||
const [_mx, _my] = state._movement
|
||||
const [svx, svy] = config.swipe.velocity
|
||||
const [sx, sy] = config.swipe.distance
|
||||
const sdt = config.swipe.duration
|
||||
|
||||
if (state.elapsedTime < sdt) {
|
||||
const _vx = Math.abs(_dx / state.timeDelta)
|
||||
const _vy = Math.abs(_dy / state.timeDelta)
|
||||
|
||||
if (_vx > svx && Math.abs(_mx) > sx) state.swipe[0] = Math.sign(_dx)
|
||||
if (_vy > svy && Math.abs(_my) > sy) state.swipe[1] = Math.sign(_dy)
|
||||
}
|
||||
}
|
||||
|
||||
this.emit()
|
||||
}
|
||||
|
||||
pointerClick(event: MouseEvent) {
|
||||
// event.detail indicates the number of buttons being pressed. When it's
|
||||
// null, it's likely to be a keyboard event from the Enter Key that could
|
||||
// be used for accessibility, and therefore shouldn't be prevented.
|
||||
// See https://github.com/pmndrs/use-gesture/issues/530
|
||||
if (!this.state.tap && event.detail > 0) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
setupPointer(event: PointerEvent) {
|
||||
const config = this.config
|
||||
const device = config.device
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
try {
|
||||
if (device === 'pointer' && config.preventScrollDelay === undefined) {
|
||||
// @ts-ignore (warning for r3f)
|
||||
const currentTarget = 'uv' in event ? event.sourceEvent.currentTarget : event.currentTarget
|
||||
const style = window.getComputedStyle(currentTarget)
|
||||
if (style.touchAction === 'auto') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`[@use-gesture]: The drag target has its \`touch-action\` style property set to \`auto\`. It is recommended to add \`touch-action: 'none'\` so that the drag gesture behaves correctly on touch-enabled devices. For more information read this: https://use-gesture.netlify.app/docs/extras/#touch-action.\n\nThis message will only show in development mode. It won't appear in production. If this is intended, you can ignore it.`,
|
||||
currentTarget
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (config.pointerLock) {
|
||||
;(event.currentTarget as HTMLElement).requestPointerLock()
|
||||
}
|
||||
|
||||
if (!config.pointerCapture) {
|
||||
this.eventStore.add(this.sharedConfig.window, device, 'change', this.pointerMove.bind(this))
|
||||
this.eventStore.add(this.sharedConfig.window, device, 'end', this.pointerUp.bind(this))
|
||||
this.eventStore.add(this.sharedConfig.window, device, 'cancel', this.pointerUp.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
pointerClean() {
|
||||
if (this.config.pointerLock && document.pointerLockElement === this.state.currentTarget) {
|
||||
document.exitPointerLock()
|
||||
}
|
||||
}
|
||||
|
||||
preventScroll(event: PointerEvent) {
|
||||
if (this.state._preventScroll && event.cancelable) {
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
setupScrollPrevention(event: PointerEvent) {
|
||||
// fixes https://github.com/pmndrs/use-gesture/issues/497
|
||||
this.state._preventScroll = false
|
||||
persistEvent(event)
|
||||
// we add window listeners that will prevent the scroll when the user has started dragging
|
||||
const remove = this.eventStore.add(this.sharedConfig.window, 'touch', 'change', this.preventScroll.bind(this), {
|
||||
passive: false
|
||||
})
|
||||
this.eventStore.add(this.sharedConfig.window, 'touch', 'end', remove)
|
||||
this.eventStore.add(this.sharedConfig.window, 'touch', 'cancel', remove)
|
||||
this.timeoutStore.add('startPointerDrag', this.startPointerDrag.bind(this), this.config.preventScrollDelay!, event)
|
||||
}
|
||||
|
||||
setupDelayTrigger(event: PointerEvent) {
|
||||
this.state._delayed = true
|
||||
this.timeoutStore.add(
|
||||
'dragDelay',
|
||||
() => {
|
||||
// forces drag to start no matter the threshold when delay is reached
|
||||
this.state._step = [0, 0]
|
||||
this.startPointerDrag(event)
|
||||
},
|
||||
this.config.delay
|
||||
)
|
||||
}
|
||||
|
||||
keyDown(event: KeyboardEvent) {
|
||||
// @ts-ignore
|
||||
const deltaFn = KEYS_DELTA_MAP[event.key]
|
||||
if (deltaFn) {
|
||||
const state = this.state
|
||||
const factor = event.shiftKey ? 10 : event.altKey ? 0.1 : 1
|
||||
|
||||
this.start(event)
|
||||
|
||||
state._delta = deltaFn(this.config.keyboardDisplacement, factor)
|
||||
state._keyboardActive = true
|
||||
V.addTo(state._movement, state._delta)
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
}
|
||||
|
||||
keyUp(event: KeyboardEvent) {
|
||||
if (!(event.key in KEYS_DELTA_MAP)) return
|
||||
|
||||
this.state._keyboardActive = false
|
||||
this.setActive()
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
const device = this.config.device
|
||||
|
||||
bindFunction(device, 'start', this.pointerDown.bind(this))
|
||||
|
||||
if (this.config.pointerCapture) {
|
||||
bindFunction(device, 'change', this.pointerMove.bind(this))
|
||||
bindFunction(device, 'end', this.pointerUp.bind(this))
|
||||
bindFunction(device, 'cancel', this.pointerUp.bind(this))
|
||||
bindFunction('lostPointerCapture', '', this.pointerUp.bind(this))
|
||||
}
|
||||
|
||||
if (this.config.keys) {
|
||||
bindFunction('key', 'down', this.keyDown.bind(this))
|
||||
bindFunction('key', 'up', this.keyUp.bind(this))
|
||||
}
|
||||
if (this.config.filterTaps) {
|
||||
bindFunction('click', '', this.pointerClick.bind(this), { capture: true, passive: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function persistEvent(event: PointerEvent) {
|
||||
// @ts-ignore
|
||||
'persist' in event && typeof event.persist === 'function' && event.persist()
|
||||
}
|
||||
386
node_modules/@use-gesture/core/src/engines/Engine.ts
generated
vendored
Normal file
386
node_modules/@use-gesture/core/src/engines/Engine.ts
generated
vendored
Normal file
@@ -0,0 +1,386 @@
|
||||
import { Controller } from '../Controller'
|
||||
import { getEventDetails } from '../utils/events'
|
||||
import { call } from '../utils/fn'
|
||||
import { V, computeRubberband } from '../utils/maths'
|
||||
import { GestureKey, IngKey, State, Vector2 } from '../types'
|
||||
import { NonUndefined } from '../types'
|
||||
|
||||
/**
|
||||
* The lib doesn't compute the kinematics on the last event of the gesture
|
||||
* (i.e. for a drag gesture, the `pointerup` coordinates will generally match the
|
||||
* last `pointermove` coordinates which would result in all drags ending with a
|
||||
* `[0,0]` velocity). However, when the timestamp difference between the last
|
||||
* event (ie pointerup) and the before last event (ie pointermove) is greater
|
||||
* than BEFORE_LAST_KINEMATICS_DELAY, the kinematics are computed (which would
|
||||
* mean that if you release your drag after stopping for more than
|
||||
* BEFORE_LAST_KINEMATICS_DELAY, the velocity will be indeed 0).
|
||||
*
|
||||
* See https://github.com/pmndrs/use-gesture/issues/332 for more details.
|
||||
*/
|
||||
|
||||
const BEFORE_LAST_KINEMATICS_DELAY = 32
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export interface Engine<Key extends GestureKey> {
|
||||
/**
|
||||
* Function that some gestures can use to add initilization
|
||||
* properties to the state when it is created.
|
||||
*/
|
||||
init?(): void
|
||||
/**
|
||||
* Setup function that some gestures can use to set additional properties of
|
||||
* the state when the gesture starts.
|
||||
*/
|
||||
setup?(): void
|
||||
/**
|
||||
* Function used by some gestures to determine the intentionality of a
|
||||
* a movement depending on thresholds. The intent function can change the
|
||||
* `state._active` or `state._blocked` flags if the gesture isn't intentional.
|
||||
* @param event
|
||||
*/
|
||||
axisIntent?(event?: UIEvent): void
|
||||
|
||||
restrictToAxis?(movement: Vector2): void
|
||||
}
|
||||
|
||||
export abstract class Engine<Key extends GestureKey> {
|
||||
/**
|
||||
* The Controller handling state.
|
||||
*/
|
||||
ctrl: Controller
|
||||
/**
|
||||
* The gesture key ('drag' | 'pinch' | 'wheel' | 'scroll' | 'move' | 'hover')
|
||||
*/
|
||||
readonly key: Key
|
||||
/**
|
||||
* The key representing the active state of the gesture in the shared state.
|
||||
* ('dragging' | 'pinching' | 'wheeling' | 'scrolling' | 'moving' | 'hovering')
|
||||
*/
|
||||
abstract readonly ingKey: IngKey
|
||||
/**
|
||||
* The arguments passed to the `bind` function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* State prop that aliases state values (`xy` or `da`).
|
||||
*/
|
||||
abstract readonly aliasKey: string
|
||||
|
||||
args: any[]
|
||||
|
||||
constructor(ctrl: Controller, args: any[], key: Key) {
|
||||
this.ctrl = ctrl
|
||||
this.args = args
|
||||
this.key = key
|
||||
|
||||
if (!this.state) {
|
||||
this.state = {} as any
|
||||
this.computeValues([0, 0])
|
||||
this.computeInitial()
|
||||
|
||||
if (this.init) this.init()
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Function implemented by gestures that compute the offset from the state
|
||||
* movement.
|
||||
*/
|
||||
abstract computeOffset(): void
|
||||
/**
|
||||
* Function implemented by the gestures that compute the movement from the
|
||||
* corrected offset (after bounds and potential rubberbanding).
|
||||
*/
|
||||
abstract computeMovement(): void
|
||||
/**
|
||||
* Executes the bind function so that listeners are properly set by the
|
||||
* Controller.
|
||||
* @param bindFunction
|
||||
*/
|
||||
abstract bind(
|
||||
bindFunction: (
|
||||
device: string,
|
||||
action: string,
|
||||
handler: (event: any) => void,
|
||||
options?: AddEventListenerOptions
|
||||
) => void
|
||||
): void
|
||||
|
||||
/**
|
||||
* Shortcut to the gesture state read from the Controller.
|
||||
*/
|
||||
get state() {
|
||||
return this.ctrl.state[this.key]!
|
||||
}
|
||||
set state(state) {
|
||||
this.ctrl.state[this.key] = state
|
||||
}
|
||||
/**
|
||||
* Shortcut to the shared state read from the Controller
|
||||
*/
|
||||
get shared() {
|
||||
return this.ctrl.state.shared
|
||||
}
|
||||
/**
|
||||
* Shortcut to the gesture event store read from the Controller.
|
||||
*/
|
||||
get eventStore() {
|
||||
return this.ctrl.gestureEventStores[this.key]!
|
||||
}
|
||||
/**
|
||||
* Shortcut to the gesture timeout store read from the Controller.
|
||||
*/
|
||||
get timeoutStore() {
|
||||
return this.ctrl.gestureTimeoutStores[this.key]!
|
||||
}
|
||||
/**
|
||||
* Shortcut to the gesture config read from the Controller.
|
||||
*/
|
||||
get config() {
|
||||
return this.ctrl.config[this.key]!
|
||||
}
|
||||
/**
|
||||
* Shortcut to the shared config read from the Controller.
|
||||
*/
|
||||
get sharedConfig() {
|
||||
return this.ctrl.config.shared
|
||||
}
|
||||
/**
|
||||
* Shortcut to the gesture handler read from the Controller.
|
||||
*/
|
||||
get handler() {
|
||||
return this.ctrl.handlers[this.key]!
|
||||
}
|
||||
|
||||
reset() {
|
||||
const { state, shared, ingKey, args } = this
|
||||
shared[ingKey] = state._active = state.active = state._blocked = state._force = false
|
||||
state._step = [false, false]
|
||||
state.intentional = false
|
||||
state._movement = [0, 0]
|
||||
state._distance = [0, 0]
|
||||
state._direction = [0, 0]
|
||||
state._delta = [0, 0]
|
||||
// prettier-ignore
|
||||
state._bounds = [[-Infinity, Infinity], [-Infinity, Infinity]]
|
||||
state.args = args
|
||||
state.axis = undefined
|
||||
state.memo = undefined
|
||||
state.elapsedTime = state.timeDelta = 0
|
||||
state.direction = [0, 0]
|
||||
state.distance = [0, 0]
|
||||
state.overflow = [0, 0]
|
||||
state._movementBound = [false, false]
|
||||
state.velocity = [0, 0]
|
||||
state.movement = [0, 0]
|
||||
state.delta = [0, 0]
|
||||
state.timeStamp = 0
|
||||
}
|
||||
/**
|
||||
* Function ran at the start of the gesture.
|
||||
* @param event
|
||||
*/
|
||||
start(event: NonUndefined<State[Key]>['event']) {
|
||||
const state = this.state
|
||||
const config = this.config
|
||||
if (!state._active) {
|
||||
this.reset()
|
||||
this.computeInitial()
|
||||
|
||||
state._active = true
|
||||
state.target = event.target!
|
||||
state.currentTarget = event.currentTarget!
|
||||
state.lastOffset = config.from ? call(config.from, state) : state.offset
|
||||
state.offset = state.lastOffset
|
||||
state.startTime = state.timeStamp = event.timeStamp
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign raw values to `state._values` and transformed values to
|
||||
* `state.values`.
|
||||
* @param values
|
||||
*/
|
||||
computeValues(values: Vector2) {
|
||||
const state = this.state
|
||||
state._values = values
|
||||
// transforming values into user-defined coordinates (#402)
|
||||
state.values = this.config.transform(values)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign `state._values` to `state._initial` and transformed `state.values` to
|
||||
* `state.initial`.
|
||||
* @param values
|
||||
*/
|
||||
computeInitial() {
|
||||
const state = this.state
|
||||
state._initial = state._values
|
||||
state.initial = state.values
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all sorts of state attributes, including kinematics.
|
||||
* @param event
|
||||
*/
|
||||
compute(event?: NonUndefined<State[Key]>['event']) {
|
||||
const { state, config, shared } = this
|
||||
state.args = this.args
|
||||
|
||||
let dt = 0
|
||||
|
||||
if (event) {
|
||||
// sets the shared state with event properties
|
||||
state.event = event
|
||||
// if config.preventDefault is true, then preventDefault
|
||||
if (config.preventDefault && event.cancelable) state.event.preventDefault()
|
||||
state.type = event.type
|
||||
shared.touches = this.ctrl.pointerIds.size || this.ctrl.touchIds.size
|
||||
shared.locked = !!document.pointerLockElement
|
||||
Object.assign(shared, getEventDetails(event))
|
||||
shared.down = shared.pressed = shared.buttons % 2 === 1 || shared.touches > 0
|
||||
|
||||
// sets time stamps
|
||||
dt = event.timeStamp - state.timeStamp
|
||||
state.timeStamp = event.timeStamp
|
||||
state.elapsedTime = state.timeStamp - state.startTime
|
||||
}
|
||||
|
||||
// only compute _distance if the state is active otherwise we might compute it
|
||||
// twice when the gesture ends because state._delta wouldn't have changed on
|
||||
// the last frame.
|
||||
if (state._active) {
|
||||
const _absoluteDelta = state._delta.map(Math.abs) as Vector2
|
||||
V.addTo(state._distance, _absoluteDelta)
|
||||
}
|
||||
|
||||
// let's run intentionality check.
|
||||
if (this.axisIntent) this.axisIntent(event)
|
||||
|
||||
// _movement is calculated by each gesture engine
|
||||
const [_m0, _m1] = state._movement
|
||||
const [t0, t1] = config.threshold
|
||||
|
||||
const { _step, values } = state
|
||||
|
||||
if (config.hasCustomTransform) {
|
||||
// When the user is using a custom transform, we're using `_step` to store
|
||||
// the first value passing the threshold.
|
||||
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && values[0]
|
||||
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && values[1]
|
||||
} else {
|
||||
// `_step` will hold the threshold at which point the gesture was triggered.
|
||||
// The threshold is signed depending on which direction triggered it.
|
||||
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && Math.sign(_m0) * t0
|
||||
if (_step[1] === false) _step[1] = Math.abs(_m1) >= t1 && Math.sign(_m1) * t1
|
||||
}
|
||||
|
||||
state.intentional = _step[0] !== false || _step[1] !== false
|
||||
|
||||
if (!state.intentional) return
|
||||
|
||||
const movement: Vector2 = [0, 0]
|
||||
|
||||
if (config.hasCustomTransform) {
|
||||
const [v0, v1] = values
|
||||
movement[0] = _step[0] !== false ? v0 - _step[0] : 0
|
||||
movement[1] = _step[1] !== false ? v1 - _step[1] : 0
|
||||
} else {
|
||||
movement[0] = _step[0] !== false ? _m0 - _step[0] : 0
|
||||
movement[1] = _step[1] !== false ? _m1 - _step[1] : 0
|
||||
}
|
||||
|
||||
if (this.restrictToAxis && !state._blocked) this.restrictToAxis(movement)
|
||||
|
||||
const previousOffset = state.offset
|
||||
|
||||
const gestureIsActive = (state._active && !state._blocked) || state.active
|
||||
|
||||
if (gestureIsActive) {
|
||||
state.first = state._active && !state.active
|
||||
state.last = !state._active && state.active
|
||||
state.active = shared[this.ingKey] = state._active
|
||||
|
||||
if (event) {
|
||||
if (state.first) {
|
||||
if ('bounds' in config) state._bounds = call(config.bounds, state)
|
||||
if (this.setup) this.setup()
|
||||
}
|
||||
|
||||
state.movement = movement
|
||||
this.computeOffset()
|
||||
}
|
||||
}
|
||||
|
||||
const [ox, oy] = state.offset
|
||||
const [[x0, x1], [y0, y1]] = state._bounds
|
||||
state.overflow = [ox < x0 ? -1 : ox > x1 ? 1 : 0, oy < y0 ? -1 : oy > y1 ? 1 : 0]
|
||||
|
||||
// _movementBound will store the latest _movement value
|
||||
// before it went off bounds.
|
||||
state._movementBound[0] = state.overflow[0]
|
||||
? state._movementBound[0] === false
|
||||
? state._movement[0]
|
||||
: state._movementBound[0]
|
||||
: false
|
||||
|
||||
state._movementBound[1] = state.overflow[1]
|
||||
? state._movementBound[1] === false
|
||||
? state._movement[1]
|
||||
: state._movementBound[1]
|
||||
: false
|
||||
|
||||
// @ts-ignore
|
||||
const rubberband: Vector2 = state._active ? config.rubberband || [0, 0] : [0, 0]
|
||||
state.offset = computeRubberband(state._bounds, state.offset, rubberband)
|
||||
state.delta = V.sub(state.offset, previousOffset)
|
||||
|
||||
this.computeMovement()
|
||||
|
||||
if (gestureIsActive && (!state.last || dt > BEFORE_LAST_KINEMATICS_DELAY)) {
|
||||
state.delta = V.sub(state.offset, previousOffset)
|
||||
const absoluteDelta = state.delta.map(Math.abs) as Vector2
|
||||
|
||||
V.addTo(state.distance, absoluteDelta)
|
||||
state.direction = state.delta.map(Math.sign) as Vector2
|
||||
state._direction = state._delta.map(Math.sign) as Vector2
|
||||
|
||||
// calculates kinematics unless the gesture starts or ends or if the
|
||||
// dt === 0 (which can happen on high frame rate monitors, see issue #581)
|
||||
// because of privacy protection:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Event/timeStamp#reduced_time_precision
|
||||
if (!state.first && dt > 0) {
|
||||
state.velocity = [absoluteDelta[0] / dt, absoluteDelta[1] / dt]
|
||||
state.timeDelta = dt
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Fires the gesture handler.
|
||||
*/
|
||||
emit() {
|
||||
const state = this.state
|
||||
const shared = this.shared
|
||||
const config = this.config
|
||||
|
||||
if (!state._active) this.clean()
|
||||
|
||||
// we don't trigger the handler if the gesture is blocked or non intentional,
|
||||
// unless the `_force` flag was set or the `triggerAllEvents` option was set
|
||||
// to true in the config.
|
||||
if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return
|
||||
|
||||
// @ts-ignore
|
||||
const memo = this.handler({ ...shared, ...state, [this.aliasKey]: state.values })
|
||||
|
||||
// Sets memo to the returned value of the handler (unless it's undefined)
|
||||
if (memo !== undefined) state.memo = memo
|
||||
}
|
||||
/**
|
||||
* Cleans the gesture timeouts and event listeners.
|
||||
*/
|
||||
clean() {
|
||||
this.eventStore.clean()
|
||||
this.timeoutStore.clean()
|
||||
}
|
||||
}
|
||||
38
node_modules/@use-gesture/core/src/engines/HoverEngine.ts
generated
vendored
Normal file
38
node_modules/@use-gesture/core/src/engines/HoverEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { CoordinatesEngine } from './CoordinatesEngine'
|
||||
import { pointerValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
|
||||
export class HoverEngine extends CoordinatesEngine<'hover'> {
|
||||
ingKey = 'hovering' as const
|
||||
|
||||
enter(event: PointerEvent) {
|
||||
if (this.config.mouseOnly && event.pointerType !== 'mouse') return
|
||||
this.start(event)
|
||||
this.computeValues(pointerValues(event))
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
leave(event: PointerEvent) {
|
||||
if (this.config.mouseOnly && event.pointerType !== 'mouse') return
|
||||
|
||||
const state = this.state
|
||||
if (!state._active) return
|
||||
|
||||
state._active = false
|
||||
const values = pointerValues(event)
|
||||
state._movement = state._delta = V.sub(values, state._values)
|
||||
|
||||
this.computeValues(values)
|
||||
this.compute(event)
|
||||
|
||||
state.delta = state.movement
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
bindFunction('pointer', 'enter', this.enter.bind(this))
|
||||
bindFunction('pointer', 'leave', this.leave.bind(this))
|
||||
}
|
||||
}
|
||||
47
node_modules/@use-gesture/core/src/engines/MoveEngine.ts
generated
vendored
Normal file
47
node_modules/@use-gesture/core/src/engines/MoveEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import { CoordinatesEngine } from './CoordinatesEngine'
|
||||
import { pointerValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
|
||||
export class MoveEngine extends CoordinatesEngine<'move'> {
|
||||
ingKey = 'moving' as const
|
||||
|
||||
move(event: PointerEvent) {
|
||||
if (this.config.mouseOnly && event.pointerType !== 'mouse') return
|
||||
if (!this.state._active) this.moveStart(event)
|
||||
else this.moveChange(event)
|
||||
this.timeoutStore.add('moveEnd', this.moveEnd.bind(this))
|
||||
}
|
||||
|
||||
moveStart(event: PointerEvent) {
|
||||
this.start(event)
|
||||
this.computeValues(pointerValues(event))
|
||||
this.compute(event)
|
||||
this.computeInitial()
|
||||
this.emit()
|
||||
}
|
||||
|
||||
moveChange(event: PointerEvent) {
|
||||
if (!this.state._active) return
|
||||
const values = pointerValues(event)
|
||||
const state = this.state
|
||||
state._delta = V.sub(values, state._values)
|
||||
V.addTo(state._movement, state._delta)
|
||||
|
||||
this.computeValues(values)
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
moveEnd(event?: PointerEvent) {
|
||||
if (!this.state._active) return
|
||||
this.state._active = false
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
bindFunction('pointer', 'change', this.move.bind(this))
|
||||
bindFunction('pointer', 'leave', this.moveEnd.bind(this))
|
||||
}
|
||||
}
|
||||
313
node_modules/@use-gesture/core/src/engines/PinchEngine.ts
generated
vendored
Normal file
313
node_modules/@use-gesture/core/src/engines/PinchEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
import { Engine } from './Engine'
|
||||
import { touchDistanceAngle, distanceAngle, wheelValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
import { Vector2, WebKitGestureEvent } from '../types'
|
||||
import { clampStateInternalMovementToBounds } from '../utils/state'
|
||||
|
||||
const SCALE_ANGLE_RATIO_INTENT_DEG = 30
|
||||
const PINCH_WHEEL_RATIO = 100
|
||||
|
||||
export class PinchEngine extends Engine<'pinch'> {
|
||||
ingKey = 'pinching' as const
|
||||
aliasKey = 'da'
|
||||
|
||||
init() {
|
||||
this.state.offset = [1, 0]
|
||||
this.state.lastOffset = [1, 0]
|
||||
this.state._pointerEvents = new Map()
|
||||
}
|
||||
|
||||
// superseeds generic Engine reset call
|
||||
reset() {
|
||||
super.reset()
|
||||
const state = this.state
|
||||
state._touchIds = []
|
||||
state.canceled = false
|
||||
state.cancel = this.cancel.bind(this)
|
||||
state.turns = 0
|
||||
}
|
||||
|
||||
computeOffset() {
|
||||
const { type, movement, lastOffset } = this.state
|
||||
if (type === 'wheel') {
|
||||
this.state.offset = V.add(movement, lastOffset)
|
||||
} else {
|
||||
this.state.offset = [(1 + movement[0]) * lastOffset[0], movement[1] + lastOffset[1]]
|
||||
}
|
||||
}
|
||||
|
||||
computeMovement() {
|
||||
const { offset, lastOffset } = this.state
|
||||
this.state.movement = [offset[0] / lastOffset[0], offset[1] - lastOffset[1]]
|
||||
}
|
||||
|
||||
axisIntent() {
|
||||
const state = this.state
|
||||
const [_m0, _m1] = state._movement
|
||||
if (!state.axis) {
|
||||
const axisMovementDifference = Math.abs(_m0) * SCALE_ANGLE_RATIO_INTENT_DEG - Math.abs(_m1)
|
||||
if (axisMovementDifference < 0) state.axis = 'angle'
|
||||
else if (axisMovementDifference > 0) state.axis = 'scale'
|
||||
}
|
||||
}
|
||||
|
||||
restrictToAxis(v: Vector2) {
|
||||
if (this.config.lockDirection) {
|
||||
if (this.state.axis === 'scale') v[1] = 0
|
||||
else if (this.state.axis === 'angle') v[0] = 0
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
const state = this.state
|
||||
if (state.canceled) return
|
||||
setTimeout(() => {
|
||||
state.canceled = true
|
||||
state._active = false
|
||||
// we run compute with no event so that kinematics won't be computed
|
||||
this.compute()
|
||||
this.emit()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
touchStart(event: TouchEvent) {
|
||||
this.ctrl.setEventIds(event)
|
||||
const state = this.state
|
||||
const ctrlTouchIds = this.ctrl.touchIds
|
||||
|
||||
if (state._active) {
|
||||
// check that the touchIds that initiated the gesture are still enabled
|
||||
// This is useful for when the page loses track of the pointers (minifying
|
||||
// gesture on iPad).
|
||||
if (state._touchIds.every((id) => ctrlTouchIds.has(id))) return
|
||||
// The gesture is still active, but probably didn't have the opportunity to
|
||||
// end properly, so we restart the pinch.
|
||||
}
|
||||
|
||||
if (ctrlTouchIds.size < 2) return
|
||||
|
||||
this.start(event)
|
||||
state._touchIds = Array.from(ctrlTouchIds).slice(0, 2) as [number, number]
|
||||
|
||||
const payload = touchDistanceAngle(event, state._touchIds)
|
||||
|
||||
if (!payload) return
|
||||
this.pinchStart(event, payload)
|
||||
}
|
||||
|
||||
pointerStart(event: PointerEvent) {
|
||||
if (event.buttons != null && event.buttons % 2 !== 1) return
|
||||
this.ctrl.setEventIds(event)
|
||||
;(event.target as HTMLElement).setPointerCapture(event.pointerId)
|
||||
const state = this.state
|
||||
const _pointerEvents = state._pointerEvents
|
||||
const ctrlPointerIds = this.ctrl.pointerIds
|
||||
|
||||
if (state._active) {
|
||||
// see touchStart comment
|
||||
if (Array.from(_pointerEvents.keys()).every((id) => ctrlPointerIds.has(id))) return
|
||||
}
|
||||
|
||||
if (_pointerEvents.size < 2) {
|
||||
_pointerEvents.set(event.pointerId, event)
|
||||
}
|
||||
|
||||
if (state._pointerEvents.size < 2) return
|
||||
|
||||
this.start(event)
|
||||
|
||||
// @ts-ignore
|
||||
const payload = distanceAngle(...Array.from(_pointerEvents.values()))
|
||||
|
||||
if (!payload) return
|
||||
this.pinchStart(event, payload)
|
||||
}
|
||||
|
||||
pinchStart(event: PointerEvent | TouchEvent, payload: { distance: number; angle: number; origin: Vector2 }) {
|
||||
const state = this.state
|
||||
state.origin = payload.origin
|
||||
this.computeValues([payload.distance, payload.angle])
|
||||
this.computeInitial()
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
touchMove(event: TouchEvent) {
|
||||
if (!this.state._active) return
|
||||
const payload = touchDistanceAngle(event, this.state._touchIds)
|
||||
|
||||
if (!payload) return
|
||||
this.pinchMove(event, payload)
|
||||
}
|
||||
|
||||
pointerMove(event: PointerEvent) {
|
||||
const _pointerEvents = this.state._pointerEvents
|
||||
if (_pointerEvents.has(event.pointerId)) {
|
||||
_pointerEvents.set(event.pointerId, event)
|
||||
}
|
||||
if (!this.state._active) return
|
||||
// @ts-ignore
|
||||
const payload = distanceAngle(...Array.from(_pointerEvents.values()))
|
||||
|
||||
if (!payload) return
|
||||
this.pinchMove(event, payload)
|
||||
}
|
||||
|
||||
pinchMove(event: PointerEvent | TouchEvent, payload: { distance: number; angle: number; origin: Vector2 }) {
|
||||
const state = this.state
|
||||
const prev_a = state._values[1]
|
||||
const delta_a = payload.angle - prev_a
|
||||
|
||||
let delta_turns = 0
|
||||
if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a)
|
||||
|
||||
this.computeValues([payload.distance, payload.angle - 360 * delta_turns])
|
||||
|
||||
state.origin = payload.origin
|
||||
state.turns = delta_turns
|
||||
state._movement = [state._values[0] / state._initial[0] - 1, state._values[1] - state._initial[1]]
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
touchEnd(event: TouchEvent) {
|
||||
this.ctrl.setEventIds(event)
|
||||
if (!this.state._active) return
|
||||
|
||||
if (this.state._touchIds.some((id) => !this.ctrl.touchIds.has(id))) {
|
||||
this.state._active = false
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
}
|
||||
|
||||
pointerEnd(event: PointerEvent) {
|
||||
const state = this.state
|
||||
this.ctrl.setEventIds(event)
|
||||
try {
|
||||
// @ts-ignore r3f
|
||||
event.target.releasePointerCapture(event.pointerId)
|
||||
} catch {}
|
||||
|
||||
if (state._pointerEvents.has(event.pointerId)) {
|
||||
state._pointerEvents.delete(event.pointerId)
|
||||
}
|
||||
|
||||
if (!state._active) return
|
||||
|
||||
if (state._pointerEvents.size < 2) {
|
||||
state._active = false
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
}
|
||||
|
||||
gestureStart(event: WebKitGestureEvent) {
|
||||
if (event.cancelable) event.preventDefault()
|
||||
const state = this.state
|
||||
|
||||
if (state._active) return
|
||||
|
||||
this.start(event)
|
||||
this.computeValues([event.scale, event.rotation])
|
||||
state.origin = [event.clientX, event.clientY]
|
||||
this.compute(event)
|
||||
|
||||
this.emit()
|
||||
}
|
||||
|
||||
gestureMove(event: WebKitGestureEvent) {
|
||||
if (event.cancelable) event.preventDefault()
|
||||
|
||||
if (!this.state._active) return
|
||||
|
||||
const state = this.state
|
||||
|
||||
this.computeValues([event.scale, event.rotation])
|
||||
state.origin = [event.clientX, event.clientY]
|
||||
const _previousMovement = state._movement
|
||||
state._movement = [event.scale - 1, event.rotation]
|
||||
state._delta = V.sub(state._movement, _previousMovement)
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
gestureEnd(event: WebKitGestureEvent) {
|
||||
if (!this.state._active) return
|
||||
|
||||
this.state._active = false
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
wheel(event: WheelEvent) {
|
||||
const modifierKey = this.config.modifierKey
|
||||
if (modifierKey && (Array.isArray(modifierKey) ? !modifierKey.find((k) => event[k]) : !event[modifierKey])) return
|
||||
if (!this.state._active) this.wheelStart(event)
|
||||
else this.wheelChange(event)
|
||||
this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this))
|
||||
}
|
||||
|
||||
wheelStart(event: WheelEvent) {
|
||||
this.start(event)
|
||||
this.wheelChange(event)
|
||||
}
|
||||
|
||||
wheelChange(event: WheelEvent) {
|
||||
const isR3f = 'uv' in event
|
||||
if (!isR3f) {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault()
|
||||
}
|
||||
if (process.env.NODE_ENV === 'development' && !event.defaultPrevented) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`[@use-gesture]: To properly support zoom on trackpads, try using the \`target\` option.\n\nThis message will only appear in development mode.`
|
||||
)
|
||||
}
|
||||
}
|
||||
const state = this.state
|
||||
state._delta = [(-wheelValues(event)[1] / PINCH_WHEEL_RATIO) * state.offset[0], 0]
|
||||
V.addTo(state._movement, state._delta)
|
||||
|
||||
// _movement rolls back to when it passed the bounds.
|
||||
clampStateInternalMovementToBounds(state)
|
||||
|
||||
this.state.origin = [event.clientX, event.clientY]
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
wheelEnd() {
|
||||
if (!this.state._active) return
|
||||
this.state._active = false
|
||||
this.compute()
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
const device = this.config.device
|
||||
if (!!device) {
|
||||
// @ts-ignore
|
||||
bindFunction(device, 'start', this[device + 'Start'].bind(this))
|
||||
// @ts-ignore
|
||||
bindFunction(device, 'change', this[device + 'Move'].bind(this))
|
||||
// @ts-ignore
|
||||
bindFunction(device, 'end', this[device + 'End'].bind(this))
|
||||
// @ts-ignore
|
||||
bindFunction(device, 'cancel', this[device + 'End'].bind(this))
|
||||
// @ts-ignore
|
||||
bindFunction('lostPointerCapture', '', this[device + 'End'].bind(this))
|
||||
}
|
||||
// we try to set a passive listener, knowing that in any case React will
|
||||
// ignore it.
|
||||
if (this.config.pinchOnWheel) {
|
||||
bindFunction('wheel', '', this.wheel.bind(this), { passive: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
37
node_modules/@use-gesture/core/src/engines/ScrollEngine.ts
generated
vendored
Normal file
37
node_modules/@use-gesture/core/src/engines/ScrollEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { CoordinatesEngine } from './CoordinatesEngine'
|
||||
import { scrollValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
|
||||
export class ScrollEngine extends CoordinatesEngine<'scroll'> {
|
||||
ingKey = 'scrolling' as const
|
||||
|
||||
scroll(event: UIEvent) {
|
||||
if (!this.state._active) this.start(event)
|
||||
this.scrollChange(event)
|
||||
this.timeoutStore.add('scrollEnd', this.scrollEnd.bind(this))
|
||||
}
|
||||
|
||||
scrollChange(event: UIEvent) {
|
||||
if (event.cancelable) event.preventDefault()
|
||||
const state = this.state
|
||||
const values = scrollValues(event)
|
||||
state._delta = V.sub(values, state._values)
|
||||
V.addTo(state._movement, state._delta)
|
||||
|
||||
this.computeValues(values)
|
||||
this.compute(event)
|
||||
|
||||
this.emit()
|
||||
}
|
||||
|
||||
scrollEnd() {
|
||||
if (!this.state._active) return
|
||||
this.state._active = false
|
||||
this.compute()
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
bindFunction('scroll', '', this.scroll.bind(this))
|
||||
}
|
||||
}
|
||||
43
node_modules/@use-gesture/core/src/engines/WheelEngine.ts
generated
vendored
Normal file
43
node_modules/@use-gesture/core/src/engines/WheelEngine.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { CoordinatesEngine } from './CoordinatesEngine'
|
||||
import { wheelValues } from '../utils/events'
|
||||
import { V } from '../utils/maths'
|
||||
import { clampStateInternalMovementToBounds } from '../utils/state'
|
||||
|
||||
export interface WheelEngine extends CoordinatesEngine<'wheel'> {
|
||||
wheel(this: WheelEngine, event: WheelEvent): void
|
||||
wheelChange(this: WheelEngine, event: WheelEvent): void
|
||||
wheelEnd(this: WheelEngine): void
|
||||
}
|
||||
|
||||
export class WheelEngine extends CoordinatesEngine<'wheel'> {
|
||||
ingKey = 'wheeling' as const
|
||||
|
||||
wheel(event: WheelEvent) {
|
||||
if (!this.state._active) this.start(event)
|
||||
this.wheelChange(event)
|
||||
this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this))
|
||||
}
|
||||
|
||||
wheelChange(event: WheelEvent) {
|
||||
const state = this.state
|
||||
state._delta = wheelValues(event)
|
||||
V.addTo(state._movement, state._delta)
|
||||
|
||||
// _movement rolls back to when it passed the bounds.
|
||||
clampStateInternalMovementToBounds(state)
|
||||
|
||||
this.compute(event)
|
||||
this.emit()
|
||||
}
|
||||
|
||||
wheelEnd() {
|
||||
if (!this.state._active) return
|
||||
this.state._active = false
|
||||
this.compute()
|
||||
this.emit()
|
||||
}
|
||||
|
||||
bind(bindFunction: any) {
|
||||
bindFunction('wheel', '', this.wheel.bind(this))
|
||||
}
|
||||
}
|
||||
2
node_modules/@use-gesture/core/src/index.ts
generated
vendored
Normal file
2
node_modules/@use-gesture/core/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { Controller } from './Controller'
|
||||
export { parseMergedHandlers } from './parser'
|
||||
78
node_modules/@use-gesture/core/src/parser.ts
generated
vendored
Normal file
78
node_modules/@use-gesture/core/src/parser.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import { FullGestureState, GestureHandlers, GestureKey, InternalHandlers, UserGestureConfig } from './types'
|
||||
import { EngineMap } from './actions'
|
||||
|
||||
const RE_NOT_NATIVE = /^on(Drag|Wheel|Scroll|Move|Pinch|Hover)/
|
||||
|
||||
function sortHandlers(_handlers: GestureHandlers) {
|
||||
const native: any = {}
|
||||
const handlers: InternalHandlers = {}
|
||||
const actions = new Set()
|
||||
|
||||
for (let key in _handlers) {
|
||||
if (RE_NOT_NATIVE.test(key)) {
|
||||
actions.add(RegExp.lastMatch)
|
||||
// @ts-ignore
|
||||
handlers[key] = _handlers[key]
|
||||
} else {
|
||||
// @ts-ignore
|
||||
native[key] = _handlers[key]
|
||||
}
|
||||
}
|
||||
|
||||
return [handlers, native, actions]
|
||||
}
|
||||
|
||||
type HandlerKey = 'onDrag' | 'onPinch' | 'onWheel' | 'onMove' | 'onScroll' | 'onHover'
|
||||
|
||||
function registerGesture(
|
||||
actions: Set<unknown>,
|
||||
handlers: GestureHandlers,
|
||||
handlerKey: HandlerKey,
|
||||
key: GestureKey,
|
||||
internalHandlers: any,
|
||||
config: any
|
||||
) {
|
||||
if (!actions.has(handlerKey)) return
|
||||
|
||||
if (!EngineMap.has(key)) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`[@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.`
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const startKey = handlerKey + 'Start'
|
||||
const endKey = handlerKey + 'End'
|
||||
|
||||
const fn = (state: FullGestureState<GestureKey>) => {
|
||||
let memo = undefined
|
||||
// @ts-ignore
|
||||
if (state.first && startKey in handlers) handlers[startKey](state)
|
||||
// @ts-ignore
|
||||
if (handlerKey in handlers) memo = handlers[handlerKey](state)
|
||||
// @ts-ignore
|
||||
if (state.last && endKey in handlers) handlers[endKey](state)
|
||||
return memo
|
||||
}
|
||||
|
||||
internalHandlers[key] = fn
|
||||
config[key] = config[key] || {}
|
||||
}
|
||||
|
||||
export function parseMergedHandlers(mergedHandlers: GestureHandlers, mergedConfig: UserGestureConfig) {
|
||||
const [handlers, nativeHandlers, actions] = sortHandlers(mergedHandlers)
|
||||
|
||||
const internalHandlers = {}
|
||||
|
||||
registerGesture(actions, handlers, 'onDrag', 'drag', internalHandlers, mergedConfig)
|
||||
registerGesture(actions, handlers, 'onWheel', 'wheel', internalHandlers, mergedConfig)
|
||||
registerGesture(actions, handlers, 'onScroll', 'scroll', internalHandlers, mergedConfig)
|
||||
registerGesture(actions, handlers, 'onPinch', 'pinch', internalHandlers, mergedConfig)
|
||||
registerGesture(actions, handlers, 'onMove', 'move', internalHandlers, mergedConfig)
|
||||
registerGesture(actions, handlers, 'onHover', 'hover', internalHandlers, mergedConfig)
|
||||
|
||||
return { handlers: internalHandlers, config: mergedConfig, nativeHandlers }
|
||||
}
|
||||
3
node_modules/@use-gesture/core/src/types.ts
generated
vendored
Normal file
3
node_modules/@use-gesture/core/src/types.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// type exports for core
|
||||
|
||||
export * from './types/index'
|
||||
14
node_modules/@use-gesture/core/src/types/action.ts
generated
vendored
Normal file
14
node_modules/@use-gesture/core/src/types/action.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { ResolverMap } from '../config/resolver'
|
||||
import type { Controller } from '../Controller'
|
||||
import type { Engine } from '../engines/Engine'
|
||||
import { GestureKey } from './config'
|
||||
|
||||
export type EngineClass<Key extends GestureKey> = {
|
||||
new (controller: Controller, args: any[], key: Key): Engine<Key>
|
||||
}
|
||||
|
||||
export type Action = {
|
||||
key: GestureKey
|
||||
engine: EngineClass<GestureKey>
|
||||
resolver: ResolverMap
|
||||
}
|
||||
250
node_modules/@use-gesture/core/src/types/config.ts
generated
vendored
Normal file
250
node_modules/@use-gesture/core/src/types/config.ts
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
import { State } from './state'
|
||||
import { Vector2, Target, PointerType, NonUndefined } from './utils'
|
||||
|
||||
export type GestureKey = Exclude<keyof State, 'shared'>
|
||||
export type CoordinatesKey = Exclude<GestureKey, 'pinch'>
|
||||
|
||||
export type GenericOptions = {
|
||||
/**
|
||||
* Lets you specify a dom node or ref you want to attach the gesture to.
|
||||
*/
|
||||
target?: Target
|
||||
/**
|
||||
* Lets you specify which window element the gesture should bind events to
|
||||
* (only relevant for the drag gesture).
|
||||
*/
|
||||
window?: EventTarget
|
||||
/**
|
||||
* Lets you customize if you want events to be passive or captured.
|
||||
*/
|
||||
eventOptions?: AddEventListenerOptions
|
||||
/**
|
||||
* When set to false none of the handlers will be fired.
|
||||
*/
|
||||
enabled?: boolean
|
||||
/**
|
||||
* A function that you can use to transform movement and offset values. Useful
|
||||
* to map your screen coordinates to custom space coordinates such as a
|
||||
* canvas.
|
||||
*/
|
||||
transform?: (v: Vector2) => Vector2
|
||||
}
|
||||
|
||||
export type GestureOptions<T extends GestureKey> = GenericOptions & {
|
||||
/**
|
||||
* Whether the gesture is enabled.
|
||||
*/
|
||||
enabled?: boolean
|
||||
/**
|
||||
* Lets you customize if you want events to be passive or captured.
|
||||
*/
|
||||
eventOptions?: AddEventListenerOptions
|
||||
/**
|
||||
* The position `offset` will start from.
|
||||
*/
|
||||
from?: Vector2 | ((state: NonUndefined<State[T]>) => Vector2)
|
||||
/**
|
||||
* The handler will fire only when the gesture displacement is greater than
|
||||
* the threshold.
|
||||
*/
|
||||
threshold?: number | Vector2
|
||||
/**
|
||||
* The handler will preventDefault all events when `true`.
|
||||
*/
|
||||
preventDefault?: boolean
|
||||
/**
|
||||
* Forces the handler to fire even for non intentional displacement (ignores
|
||||
* the threshold). In that case, the intentional attribute from state will
|
||||
* remain false until the threshold is reached.
|
||||
*/
|
||||
triggerAllEvents?: boolean
|
||||
/**
|
||||
* The elasticity coefficient of the gesture when going out of bounds. When
|
||||
* set to true, the elasticiy coefficient will be defaulted to 0.15
|
||||
*/
|
||||
rubberband?: boolean | number | Vector2
|
||||
/**
|
||||
* A function that you can use to transform movement and offset values. Useful
|
||||
* to map your screen coordinates to custom space coordinates such as a
|
||||
* canvas.
|
||||
*/
|
||||
transform?: (v: Vector2) => Vector2
|
||||
}
|
||||
|
||||
export type Bounds = {
|
||||
top?: number
|
||||
bottom?: number
|
||||
left?: number
|
||||
right?: number
|
||||
}
|
||||
|
||||
export type CoordinatesConfig<Key extends CoordinatesKey = CoordinatesKey> = GestureOptions<Key> & {
|
||||
/**
|
||||
* The handler will only trigger if a movement is detected on the specified
|
||||
* axis.
|
||||
*/
|
||||
axis?: 'x' | 'y' | 'lock'
|
||||
/**
|
||||
* Limits the gesture `offset` to the specified bounds.
|
||||
*/
|
||||
bounds?: Bounds | ((state: State[Key]) => Bounds)
|
||||
/**
|
||||
* Determines the number of pixels in one direction needed for axises to be
|
||||
* calculated.
|
||||
*/
|
||||
axisThreshold?: number
|
||||
}
|
||||
|
||||
export type PinchBounds = { min?: number; max?: number }
|
||||
export type ModifierKey = 'ctrlKey' | 'altKey' | 'metaKey' | null
|
||||
|
||||
export type PinchConfig = GestureOptions<'pinch'> & {
|
||||
pointer?: {
|
||||
/**
|
||||
* If true, pinch will use touch events on touch-enabled devices.
|
||||
*/
|
||||
touch?: boolean
|
||||
}
|
||||
/**
|
||||
* Limits the scale `offset` to the specified bounds.
|
||||
*/
|
||||
scaleBounds?: PinchBounds | ((state: State['pinch']) => PinchBounds)
|
||||
/**
|
||||
* Limits the angle `offset` to the specified bounds.
|
||||
*/
|
||||
angleBounds?: PinchBounds | ((state: State['pinch']) => PinchBounds)
|
||||
/**
|
||||
* Scales OR rotates when set to 'lock'.
|
||||
*/
|
||||
axis?: 'lock' | undefined
|
||||
/**
|
||||
* Key that triggers scale when using the wheel. Defaults to `'ctrlKey'`.
|
||||
*/
|
||||
modifierKey?: ModifierKey | NonNullable<ModifierKey>[]
|
||||
/**
|
||||
* Whether wheel should trigger a pinch at all.
|
||||
*/
|
||||
pinchOnWheel?: boolean
|
||||
}
|
||||
|
||||
export type DragBounds = Bounds | HTMLElement | { current: HTMLElement | null }
|
||||
|
||||
type MoveAndHoverMouseOnly = {
|
||||
/**
|
||||
* If false, onMove or onHover handlers will also fire on touch devices.
|
||||
*/
|
||||
mouseOnly?: boolean
|
||||
}
|
||||
|
||||
export type MoveConfig = CoordinatesConfig<'move'> & MoveAndHoverMouseOnly
|
||||
|
||||
export type HoverConfig = MoveAndHoverMouseOnly
|
||||
|
||||
export type DragConfig = Omit<CoordinatesConfig<'drag'>, 'axisThreshold' | 'bounds'> & {
|
||||
/**
|
||||
* If true, the component won't trigger your drag logic if the user just clicked on the component.
|
||||
*/
|
||||
filterTaps?: boolean
|
||||
/**
|
||||
* The maximum total displacement a tap can have
|
||||
*/
|
||||
tapsThreshold?: number
|
||||
/**
|
||||
* Set this option to true when using with @react-three/fiber objects.
|
||||
*/
|
||||
/**
|
||||
* Limits the gesture `offset` to the specified bounds. Can be a ref or a dom
|
||||
* node.
|
||||
*/
|
||||
bounds?: DragBounds | ((state: State['drag']) => DragBounds)
|
||||
pointer?: {
|
||||
/**
|
||||
* The buttons combination that would trigger the drag. Use `-1` to allow
|
||||
* for any button combination to start the drag.
|
||||
*/
|
||||
buttons?: number | number[]
|
||||
/**
|
||||
* If true, drag will use touch events on touch-enabled devices.
|
||||
*/
|
||||
touch?: boolean
|
||||
/**
|
||||
* If true, drag will use touch events on touch-enabled devices, and use
|
||||
* mouse events on non touch devices.
|
||||
*/
|
||||
mouse?: boolean
|
||||
/**
|
||||
* If false, will disable KeyboardEvents that would otherwise trigger the
|
||||
* drag gesture when the element is focused. Defaults to true.
|
||||
*/
|
||||
keys?: boolean
|
||||
/**
|
||||
* Doesn't use setPointerCapture when false and delegate drag handling to
|
||||
* window
|
||||
*/
|
||||
capture?: boolean
|
||||
/**
|
||||
* Will perform a pointer lock when drag starts, and exit pointer lock when
|
||||
* drag ends,
|
||||
*/
|
||||
lock?: boolean
|
||||
}
|
||||
swipe?: {
|
||||
/**
|
||||
* The minimum velocity per axis (in pixels / ms) the drag gesture needs to
|
||||
* reach before the pointer is released.
|
||||
*/
|
||||
velocity?: number | Vector2
|
||||
/**
|
||||
* The minimum distance per axis (in pixels) the drag gesture needs to
|
||||
* travel to trigger a swipe. Defaults to 50.
|
||||
*/
|
||||
distance?: number | Vector2
|
||||
/**
|
||||
* The maximum duration in milliseconds that a swipe is detected. Defaults
|
||||
* to 250.
|
||||
*/
|
||||
duration?: number
|
||||
}
|
||||
/**
|
||||
* If set, the drag will be triggered after the duration of the delay (in ms).
|
||||
* When set to true, delay is defaulted to 250ms.
|
||||
*/
|
||||
preventScroll?: boolean | number
|
||||
/**
|
||||
* If set, the drag will allow scrolling in the direction of this axis until
|
||||
* the preventScroll duration has elapsed. Defaults to only 'y'.
|
||||
*/
|
||||
preventScrollAxis?: 'x' | 'y' | 'xy'
|
||||
/**
|
||||
* If set, the handler will be delayed for the duration of the delay (in ms)
|
||||
* — or if the user starts moving. When set to true, delay is defaulted
|
||||
* to 180ms.
|
||||
*/
|
||||
delay?: boolean | number
|
||||
/**
|
||||
* Key-number record that determines for each device (`'mouse'`, `'touch'`,
|
||||
* `'pen'`) the number of pixels of drag in one direction needed for axises to
|
||||
* be calculated.
|
||||
*/
|
||||
axisThreshold?: Partial<Record<PointerType, number>>
|
||||
/**
|
||||
* The distance (in pixels) emulated by arrow keys.
|
||||
*/
|
||||
keyboardDisplacement?: number
|
||||
}
|
||||
|
||||
export type UserDragConfig = GenericOptions & DragConfig
|
||||
export type UserPinchConfig = GenericOptions & PinchConfig
|
||||
export type UserWheelConfig = GenericOptions & CoordinatesConfig<'wheel'>
|
||||
export type UserScrollConfig = GenericOptions & CoordinatesConfig<'scroll'>
|
||||
export type UserMoveConfig = GenericOptions & MoveConfig
|
||||
export type UserHoverConfig = GenericOptions & HoverConfig
|
||||
|
||||
export type UserGestureConfig = GenericOptions & {
|
||||
drag?: DragConfig
|
||||
wheel?: CoordinatesConfig<'wheel'>
|
||||
scroll?: CoordinatesConfig<'scroll'>
|
||||
move?: MoveConfig
|
||||
pinch?: PinchConfig
|
||||
hover?: { enabled?: boolean } & HoverConfig
|
||||
}
|
||||
61
node_modules/@use-gesture/core/src/types/handlers.ts
generated
vendored
Normal file
61
node_modules/@use-gesture/core/src/types/handlers.ts
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import { FullGestureState, State, EventTypes } from './state'
|
||||
import { GestureKey } from './config'
|
||||
import { DOMHandlers, EventHandler } from './utils'
|
||||
|
||||
export type Handler<Key extends GestureKey, EventType = EventTypes[Key]> = (
|
||||
state: Omit<FullGestureState<Key>, 'event'> & { event: EventType }
|
||||
) => any | void
|
||||
|
||||
// if no type is provided in the user generic for a given key
|
||||
// then return the default EventTypes that key
|
||||
type check<T extends AnyHandlerEventTypes, Key extends GestureKey> = undefined extends T[Key] ? EventTypes[Key] : T[Key]
|
||||
|
||||
export type UserHandlers<T extends AnyHandlerEventTypes = EventTypes> = {
|
||||
onDrag: Handler<'drag', check<T, 'drag'>>
|
||||
onDragStart: Handler<'drag', check<T, 'drag'>>
|
||||
onDragEnd: Handler<'drag', check<T, 'drag'>>
|
||||
onPinch: Handler<'pinch', check<T, 'pinch'>>
|
||||
onPinchStart: Handler<'pinch', check<T, 'pinch'>>
|
||||
onPinchEnd: Handler<'pinch', check<T, 'pinch'>>
|
||||
onWheel: Handler<'wheel', check<T, 'wheel'>>
|
||||
onWheelStart: Handler<'wheel', check<T, 'wheel'>>
|
||||
onWheelEnd: Handler<'wheel', check<T, 'wheel'>>
|
||||
onMove: Handler<'move', check<T, 'move'>>
|
||||
onMoveStart: Handler<'move', check<T, 'move'>>
|
||||
onMoveEnd: Handler<'move', check<T, 'move'>>
|
||||
onScroll: Handler<'scroll', check<T, 'scroll'>>
|
||||
onScrollStart: Handler<'scroll', check<T, 'scroll'>>
|
||||
onScrollEnd: Handler<'scroll', check<T, 'scroll'>>
|
||||
onHover: Handler<'hover', check<T, 'hover'>>
|
||||
}
|
||||
|
||||
type NativeHandlersKeys = keyof Omit<DOMHandlers, keyof UserHandlers>
|
||||
|
||||
type GetEventType<Key extends NativeHandlersKeys> = DOMHandlers[Key] extends EventHandler<infer EventType> | undefined
|
||||
? EventType
|
||||
: UIEvent
|
||||
|
||||
export type NativeHandlers<T extends AnyHandlerEventTypes = {}> = {
|
||||
[key in NativeHandlersKeys]?: (
|
||||
state: State['shared'] & { event: undefined extends T[key] ? GetEventType<key> : T[key]; args: any },
|
||||
...args: any
|
||||
) => void
|
||||
}
|
||||
|
||||
// allows overriding the event type from the returned state in handlers
|
||||
export type AnyHandlerEventTypes = Partial<
|
||||
{
|
||||
drag: any
|
||||
wheel: any
|
||||
scroll: any
|
||||
move: any
|
||||
pinch: any
|
||||
hover: any
|
||||
} & { [key in NativeHandlersKeys]: any }
|
||||
>
|
||||
|
||||
export type GestureHandlers<HandlerType extends AnyHandlerEventTypes = EventTypes> = Partial<
|
||||
NativeHandlers<HandlerType> & UserHandlers<HandlerType>
|
||||
>
|
||||
|
||||
export type InternalHandlers = { [Key in GestureKey]?: Handler<Key, any> }
|
||||
6
node_modules/@use-gesture/core/src/types/index.ts
generated
vendored
Normal file
6
node_modules/@use-gesture/core/src/types/index.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './config'
|
||||
export * from './internalConfig'
|
||||
export * from './state'
|
||||
export * from './utils'
|
||||
export * from './handlers'
|
||||
export * from './action'
|
||||
74
node_modules/@use-gesture/core/src/types/internalConfig.ts
generated
vendored
Normal file
74
node_modules/@use-gesture/core/src/types/internalConfig.ts
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { GestureKey, CoordinatesKey, ModifierKey } from './config'
|
||||
import { State } from './state'
|
||||
import { PointerType, Vector2 } from './utils'
|
||||
|
||||
export type InternalGenericOptions = {
|
||||
target?: () => EventTarget
|
||||
eventOptions: AddEventListenerOptions
|
||||
window: EventTarget
|
||||
enabled: boolean
|
||||
transform?: (v: Vector2) => Vector2
|
||||
}
|
||||
|
||||
export type InternalGestureOptions<Key extends GestureKey = GestureKey> = {
|
||||
enabled: boolean
|
||||
eventOptions: AddEventListenerOptions
|
||||
from: Vector2 | ((state: State[Key]) => Vector2)
|
||||
threshold: Vector2
|
||||
preventDefault: boolean
|
||||
triggerAllEvents: boolean
|
||||
rubberband: Vector2
|
||||
bounds: [Vector2, Vector2] | ((state: State[Key]) => [Vector2, Vector2])
|
||||
hasCustomTransform: boolean
|
||||
transform: (v: Vector2) => Vector2
|
||||
}
|
||||
|
||||
export type InternalCoordinatesOptions<Key extends CoordinatesKey = CoordinatesKey> = InternalGestureOptions<Key> & {
|
||||
axis?: 'x' | 'y'
|
||||
lockDirection: boolean
|
||||
axisThreshold: number
|
||||
}
|
||||
|
||||
export type InternalDragOptions = Omit<InternalCoordinatesOptions<'drag'>, 'axisThreshold'> & {
|
||||
filterTaps: boolean
|
||||
tapsThreshold: number
|
||||
pointerButtons: number | number[]
|
||||
pointerCapture: boolean
|
||||
preventScrollDelay?: number
|
||||
preventScrollAxis?: 'x' | 'y' | 'xy'
|
||||
pointerLock: boolean
|
||||
keys: boolean
|
||||
device: 'pointer' | 'touch' | 'mouse'
|
||||
swipe: {
|
||||
velocity: Vector2
|
||||
distance: Vector2
|
||||
duration: number
|
||||
}
|
||||
delay: number
|
||||
axisThreshold: Record<PointerType, number>
|
||||
keyboardDisplacement: number
|
||||
}
|
||||
|
||||
export type InternalPinchOptions = InternalGestureOptions<'pinch'> & {
|
||||
/**
|
||||
* When device is undefined, we'll be using wheel to zoom.
|
||||
*/
|
||||
device: 'gesture' | 'pointer' | 'touch' | undefined
|
||||
lockDirection: boolean
|
||||
modifierKey: ModifierKey | NonNullable<ModifierKey>[]
|
||||
pinchOnWheel: boolean
|
||||
}
|
||||
|
||||
type MoveAndHoverMouseOnly = {
|
||||
mouseOnly: boolean
|
||||
}
|
||||
|
||||
export type InternalConfig = {
|
||||
shared: InternalGenericOptions
|
||||
drag?: InternalDragOptions
|
||||
wheel?: InternalCoordinatesOptions<'wheel'>
|
||||
scroll?: InternalCoordinatesOptions<'scroll'>
|
||||
move?: InternalCoordinatesOptions<'move'> & MoveAndHoverMouseOnly
|
||||
hover?: InternalCoordinatesOptions<'hover'> & MoveAndHoverMouseOnly
|
||||
pinch?: InternalPinchOptions
|
||||
}
|
||||
269
node_modules/@use-gesture/core/src/types/state.ts
generated
vendored
Normal file
269
node_modules/@use-gesture/core/src/types/state.ts
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
import { GestureKey } from './config'
|
||||
import { NonUndefined, Vector2, WebKitGestureEvent } from './utils'
|
||||
|
||||
export type IngKey = 'dragging' | 'wheeling' | 'moving' | 'hovering' | 'scrolling' | 'pinching'
|
||||
|
||||
export type SharedGestureState = {
|
||||
/**
|
||||
* True if the element is being dragged.
|
||||
*/
|
||||
dragging?: boolean
|
||||
/**
|
||||
* True if the element is being wheeled.
|
||||
*/
|
||||
wheeling?: boolean
|
||||
/**
|
||||
* True if the element is being moved.
|
||||
*/
|
||||
moving?: boolean
|
||||
/**
|
||||
* True if the element is being hovered.
|
||||
*/
|
||||
hovering?: boolean
|
||||
/**
|
||||
* True if the element is being scrolled.
|
||||
*/
|
||||
scrolling?: boolean
|
||||
/**
|
||||
* True if the element is being pinched.
|
||||
*/
|
||||
pinching?: boolean
|
||||
/**
|
||||
* Number of fingers touching the screen.
|
||||
*/
|
||||
touches: number
|
||||
/**
|
||||
* True when the main mouse button or touch is pressed.
|
||||
*/
|
||||
pressed: boolean
|
||||
/**
|
||||
* Alias for pressed.
|
||||
*/
|
||||
down: boolean
|
||||
/**
|
||||
* True if the document is in lock mode.
|
||||
*/
|
||||
locked: boolean
|
||||
/**
|
||||
* Indicates which buttons are pressed (https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons).
|
||||
*/
|
||||
buttons: number
|
||||
/**
|
||||
* True when the Shift key is pressed.
|
||||
*/
|
||||
shiftKey: boolean
|
||||
/**
|
||||
* True when the Alt key is pressed.
|
||||
*/
|
||||
altKey: boolean
|
||||
/**
|
||||
* True when the Meta key is pressed.
|
||||
*/
|
||||
metaKey: boolean
|
||||
/**
|
||||
* True when the Control key is pressed.
|
||||
*/
|
||||
ctrlKey: boolean
|
||||
}
|
||||
|
||||
export type CommonGestureState = {
|
||||
_active: boolean
|
||||
_blocked: boolean
|
||||
_force: boolean
|
||||
_step: [false | number, false | number]
|
||||
_movementBound: [false | number, false | number]
|
||||
_values: Vector2
|
||||
_initial: Vector2
|
||||
_movement: Vector2
|
||||
_distance: Vector2
|
||||
_direction: Vector2
|
||||
_delta: Vector2
|
||||
_bounds: [Vector2, Vector2]
|
||||
/**
|
||||
* The event triggering the gesture.
|
||||
*/
|
||||
event: UIEvent
|
||||
/**
|
||||
* The event target.
|
||||
*/
|
||||
target: EventTarget
|
||||
/**
|
||||
* The event current target.
|
||||
*/
|
||||
currentTarget: EventTarget
|
||||
/**
|
||||
* True when the gesture is intentional (passed the threshold).
|
||||
*/
|
||||
intentional: boolean
|
||||
/**
|
||||
* Cumulative distance of the gesture. Deltas are summed with their absolute
|
||||
* values.
|
||||
*/
|
||||
distance: Vector2
|
||||
/**
|
||||
* Displacement of the current gesture.
|
||||
*/
|
||||
movement: Vector2
|
||||
/**
|
||||
* Difference between the current movement and the previous movement.
|
||||
*/
|
||||
delta: Vector2
|
||||
/**
|
||||
* Cumulative displacements of all gestures (sum of all movements triggered
|
||||
* by the handler)
|
||||
*/
|
||||
offset: Vector2
|
||||
/**
|
||||
* Offset when the gesture started.
|
||||
*/
|
||||
lastOffset: Vector2
|
||||
/**
|
||||
* Velocity vector.
|
||||
*/
|
||||
velocity: Vector2
|
||||
/**
|
||||
* Current raw values of the gesture. Can be coordinates or distance / angle
|
||||
* depending on the gesture.
|
||||
*/
|
||||
values: Vector2
|
||||
/**
|
||||
* Raw values when the gesture started.
|
||||
*/
|
||||
initial: Vector2
|
||||
/**
|
||||
* Direction per axis. `-1` when going down, `1` when going up, `0` when still.
|
||||
*/
|
||||
direction: Vector2
|
||||
/**
|
||||
* Bound overflow per axis. `-1` when overflowing bounds to the left/top, `1` when overflowing bounds to the right/bottom.
|
||||
*/
|
||||
overflow: Vector2
|
||||
/**
|
||||
* True when it's the first event of the active gesture.
|
||||
*/
|
||||
first: boolean
|
||||
/**
|
||||
* True when it's the last event of the active gesture.
|
||||
*/
|
||||
last: boolean
|
||||
/**
|
||||
* True when the gesture is active.
|
||||
*/
|
||||
active: boolean
|
||||
/**
|
||||
* The timestamp (ms) of when the gesture started.
|
||||
*/
|
||||
startTime: number
|
||||
/**
|
||||
* The timestamp (ms) of the current event.
|
||||
*/
|
||||
timeStamp: number
|
||||
/**
|
||||
* Elapsed time (ms) of the current gesture.
|
||||
*/
|
||||
elapsedTime: number
|
||||
/**
|
||||
* Time delta (ms) with the previous event.
|
||||
*/
|
||||
timeDelta: number
|
||||
/**
|
||||
* Event type.
|
||||
*/
|
||||
type: string
|
||||
/**
|
||||
* Value returned by your handler on its previous run.
|
||||
*/
|
||||
memo?: any
|
||||
/**
|
||||
* The arguments passed to the bind function (only relevant in React when
|
||||
* using `<div {...bind(someArgument)} />`)
|
||||
*/
|
||||
args?: any
|
||||
}
|
||||
|
||||
export type CoordinatesState = CommonGestureState & {
|
||||
/**
|
||||
* The initial axis (x or y) of the gesture.
|
||||
*/
|
||||
axis: 'x' | 'y' | undefined
|
||||
/**
|
||||
* Pointer coordinates (alias to values)
|
||||
*/
|
||||
xy: Vector2
|
||||
}
|
||||
|
||||
export type DragState = CoordinatesState & {
|
||||
_pointerId?: number
|
||||
_pointerActive: boolean
|
||||
_keyboardActive: boolean
|
||||
_preventScroll: boolean
|
||||
_delayed: boolean
|
||||
/**
|
||||
* True when the drag gesture has been canceled by the `cancel` function.
|
||||
*/
|
||||
canceled: boolean
|
||||
/**
|
||||
* Function that can be called to cancel the drag.
|
||||
*/
|
||||
cancel(): void
|
||||
/**
|
||||
* True if the drag gesture is recognized as a tap (ie when the displacement
|
||||
* is lower than 3px per axis).
|
||||
*/
|
||||
tap: boolean
|
||||
/**
|
||||
* [swipeX, swipeY] is [0, 0] if no swipe detected, -1 or 1 otherwise.
|
||||
*/
|
||||
swipe: Vector2
|
||||
}
|
||||
|
||||
export interface PinchState extends CommonGestureState {
|
||||
_pointerEvents: Map<number, PointerEvent>
|
||||
_touchIds: [] | [number, number]
|
||||
/**
|
||||
* Distance and angle raw values (alias to values).
|
||||
*/
|
||||
da: Vector2
|
||||
/**
|
||||
* The initial axis (scale or angle) of the gesture.
|
||||
*/
|
||||
axis: 'scale' | 'angle' | undefined
|
||||
/**
|
||||
* Coordinates of the center of touch events, or the cursor when using wheel
|
||||
* to pinch.
|
||||
*/
|
||||
origin: Vector2
|
||||
/**
|
||||
* The number of full rotation the current gesture has performed.
|
||||
*/
|
||||
turns: number
|
||||
/**
|
||||
* True when the pinch gesture has been canceled by the `cancel` function.
|
||||
*/
|
||||
canceled: boolean
|
||||
/**
|
||||
* Function that can be called to cancel the pinch.
|
||||
*/
|
||||
cancel(): void
|
||||
}
|
||||
|
||||
export type EventTypes = {
|
||||
drag: PointerEvent | TouchEvent | MouseEvent | KeyboardEvent
|
||||
wheel: WheelEvent
|
||||
scroll: UIEvent
|
||||
move: PointerEvent
|
||||
hover: PointerEvent
|
||||
pinch: PointerEvent | TouchEvent | WheelEvent | WebKitGestureEvent
|
||||
}
|
||||
|
||||
export interface State {
|
||||
shared: SharedGestureState
|
||||
drag?: DragState & { event: EventTypes['drag'] }
|
||||
wheel?: CoordinatesState & { event: EventTypes['wheel'] }
|
||||
scroll?: CoordinatesState & { event: EventTypes['scroll'] }
|
||||
move?: CoordinatesState & { event: EventTypes['move'] }
|
||||
hover?: CoordinatesState & { event: EventTypes['hover'] }
|
||||
pinch?: PinchState & { event: EventTypes['pinch'] }
|
||||
}
|
||||
|
||||
export type FullGestureState<Key extends GestureKey> = SharedGestureState & NonUndefined<State[Key]>
|
||||
197
node_modules/@use-gesture/core/src/types/utils.ts
generated
vendored
Normal file
197
node_modules/@use-gesture/core/src/types/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
export type Vector2 = [number, number]
|
||||
export type WebKitGestureEvent = PointerEvent & { scale: number; rotation: number }
|
||||
export type Target = EventTarget | { current: EventTarget | null }
|
||||
export type PointerType = 'mouse' | 'touch' | 'pen'
|
||||
|
||||
// replaces NonUndefined from 4.7 and inferior versions
|
||||
export type NonUndefined<T> = T extends undefined ? never : T
|
||||
export type EventHandler<E extends Event = Event> = (event: E) => void
|
||||
|
||||
// rip off from React types
|
||||
export interface DOMHandlers {
|
||||
// Clipboard Events
|
||||
onCopy?: EventHandler<ClipboardEvent>
|
||||
onCopyCapture?: EventHandler<ClipboardEvent>
|
||||
onCut?: EventHandler<ClipboardEvent>
|
||||
onCutCapture?: EventHandler<ClipboardEvent>
|
||||
onPaste?: EventHandler<ClipboardEvent>
|
||||
onPasteCapture?: EventHandler<ClipboardEvent>
|
||||
|
||||
// Composition Events
|
||||
onCompositionEnd?: EventHandler<CompositionEvent>
|
||||
onCompositionEndCapture?: EventHandler<CompositionEvent>
|
||||
onCompositionStart?: EventHandler<CompositionEvent>
|
||||
onCompositionStartCapture?: EventHandler<CompositionEvent>
|
||||
onCompositionUpdate?: EventHandler<CompositionEvent>
|
||||
onCompositionUpdateCapture?: EventHandler<CompositionEvent>
|
||||
|
||||
// Focus Events
|
||||
onFocus?: EventHandler<FocusEvent>
|
||||
onFocusCapture?: EventHandler<FocusEvent>
|
||||
onBlur?: EventHandler<FocusEvent>
|
||||
onBlurCapture?: EventHandler<FocusEvent>
|
||||
|
||||
// Form Events
|
||||
onChange?: EventHandler<FormDataEvent>
|
||||
onChangeCapture?: EventHandler<FormDataEvent>
|
||||
onBeforeInput?: EventHandler<FormDataEvent>
|
||||
onBeforeInputCapture?: EventHandler<FormDataEvent>
|
||||
onInput?: EventHandler<FormDataEvent>
|
||||
onInputCapture?: EventHandler<FormDataEvent>
|
||||
onReset?: EventHandler<FormDataEvent>
|
||||
onResetCapture?: EventHandler<FormDataEvent>
|
||||
onSubmit?: EventHandler<FormDataEvent>
|
||||
onSubmitCapture?: EventHandler<FormDataEvent>
|
||||
onInvalid?: EventHandler<FormDataEvent>
|
||||
onInvalidCapture?: EventHandler<FormDataEvent>
|
||||
|
||||
// Image Events
|
||||
onLoad?: EventHandler
|
||||
onLoadCapture?: EventHandler
|
||||
onError?: EventHandler // also a Media Event
|
||||
onErrorCapture?: EventHandler // also a Media Event
|
||||
|
||||
// Keyboard Events
|
||||
onKeyDown?: EventHandler<KeyboardEvent>
|
||||
onKeyDownCapture?: EventHandler<KeyboardEvent>
|
||||
onKeyUp?: EventHandler<KeyboardEvent>
|
||||
onKeyUpCapture?: EventHandler<KeyboardEvent>
|
||||
|
||||
// Media Events
|
||||
onAbort?: EventHandler
|
||||
onAbortCapture?: EventHandler
|
||||
onCanPlay?: EventHandler
|
||||
onCanPlayCapture?: EventHandler
|
||||
onCanPlayThrough?: EventHandler
|
||||
onCanPlayThroughCapture?: EventHandler
|
||||
onDurationChange?: EventHandler
|
||||
onDurationChangeCapture?: EventHandler
|
||||
onEmptied?: EventHandler
|
||||
onEmptiedCapture?: EventHandler
|
||||
onEncrypted?: EventHandler
|
||||
onEncryptedCapture?: EventHandler
|
||||
onEnded?: EventHandler
|
||||
onEndedCapture?: EventHandler
|
||||
onLoadedData?: EventHandler
|
||||
onLoadedDataCapture?: EventHandler
|
||||
onLoadedMetadata?: EventHandler
|
||||
onLoadedMetadataCapture?: EventHandler
|
||||
onLoadStart?: EventHandler
|
||||
onLoadStartCapture?: EventHandler
|
||||
onPause?: EventHandler
|
||||
onPauseCapture?: EventHandler
|
||||
onPlay?: EventHandler
|
||||
onPlayCapture?: EventHandler
|
||||
onPlaying?: EventHandler
|
||||
onPlayingCapture?: EventHandler
|
||||
onProgress?: EventHandler
|
||||
onProgressCapture?: EventHandler
|
||||
onRateChange?: EventHandler
|
||||
onRateChangeCapture?: EventHandler
|
||||
onSeeked?: EventHandler
|
||||
onSeekedCapture?: EventHandler
|
||||
onSeeking?: EventHandler
|
||||
onSeekingCapture?: EventHandler
|
||||
onStalled?: EventHandler
|
||||
onStalledCapture?: EventHandler
|
||||
onSuspend?: EventHandler
|
||||
onSuspendCapture?: EventHandler
|
||||
onTimeUpdate?: EventHandler
|
||||
onTimeUpdateCapture?: EventHandler
|
||||
onVolumeChange?: EventHandler
|
||||
onVolumeChangeCapture?: EventHandler
|
||||
onWaiting?: EventHandler
|
||||
onWaitingCapture?: EventHandler
|
||||
|
||||
// MouseEvents
|
||||
onAuxClick?: EventHandler<MouseEvent>
|
||||
onAuxClickCapture?: EventHandler<MouseEvent>
|
||||
onClick?: EventHandler<MouseEvent>
|
||||
onClickCapture?: EventHandler<MouseEvent>
|
||||
onContextMenu?: EventHandler<MouseEvent>
|
||||
onContextMenuCapture?: EventHandler<MouseEvent>
|
||||
onDoubleClick?: EventHandler<MouseEvent>
|
||||
onDoubleClickCapture?: EventHandler<MouseEvent>
|
||||
onDrag?: EventHandler<DragEvent>
|
||||
onDragCapture?: EventHandler<DragEvent>
|
||||
onDragEnd?: EventHandler<DragEvent>
|
||||
onDragEndCapture?: EventHandler<DragEvent>
|
||||
onDragEnter?: EventHandler<DragEvent>
|
||||
onDragEnterCapture?: EventHandler<DragEvent>
|
||||
onDragExit?: EventHandler<DragEvent>
|
||||
onDragExitCapture?: EventHandler<DragEvent>
|
||||
onDragLeave?: EventHandler<DragEvent>
|
||||
onDragLeaveCapture?: EventHandler<DragEvent>
|
||||
onDragOver?: EventHandler<DragEvent>
|
||||
onDragOverCapture?: EventHandler<DragEvent>
|
||||
onDragStart?: EventHandler<DragEvent>
|
||||
onDragStartCapture?: EventHandler<DragEvent>
|
||||
onDrop?: EventHandler<DragEvent>
|
||||
onDropCapture?: EventHandler<DragEvent>
|
||||
onMouseDown?: EventHandler<MouseEvent>
|
||||
onMouseDownCapture?: EventHandler<MouseEvent>
|
||||
onMouseEnter?: EventHandler<MouseEvent>
|
||||
onMouseLeave?: EventHandler<MouseEvent>
|
||||
onMouseMove?: EventHandler<MouseEvent>
|
||||
onMouseMoveCapture?: EventHandler<MouseEvent>
|
||||
onMouseOut?: EventHandler<MouseEvent>
|
||||
onMouseOutCapture?: EventHandler<MouseEvent>
|
||||
onMouseOver?: EventHandler<MouseEvent>
|
||||
onMouseOverCapture?: EventHandler<MouseEvent>
|
||||
onMouseUp?: EventHandler<MouseEvent>
|
||||
onMouseUpCapture?: EventHandler<MouseEvent>
|
||||
|
||||
// Selection Events
|
||||
onSelect?: EventHandler
|
||||
onSelectCapture?: EventHandler
|
||||
|
||||
// Touch Events
|
||||
onTouchCancel?: EventHandler<TouchEvent>
|
||||
onTouchCancelCapture?: EventHandler<TouchEvent>
|
||||
onTouchEnd?: EventHandler<TouchEvent>
|
||||
onTouchEndCapture?: EventHandler<TouchEvent>
|
||||
onTouchMove?: EventHandler<TouchEvent>
|
||||
onTouchMoveCapture?: EventHandler<TouchEvent>
|
||||
onTouchStart?: EventHandler<TouchEvent>
|
||||
onTouchStartCapture?: EventHandler<TouchEvent>
|
||||
|
||||
// Pointer Events
|
||||
onPointerDown?: EventHandler<PointerEvent>
|
||||
onPointerDownCapture?: EventHandler<PointerEvent>
|
||||
onPointerMove?: EventHandler<PointerEvent>
|
||||
onPointerMoveCapture?: EventHandler<PointerEvent>
|
||||
onPointerUp?: EventHandler<PointerEvent>
|
||||
onPointerUpCapture?: EventHandler<PointerEvent>
|
||||
onPointerCancel?: EventHandler<PointerEvent>
|
||||
onPointerCancelCapture?: EventHandler<PointerEvent>
|
||||
onPointerEnter?: EventHandler<PointerEvent>
|
||||
onPointerLeave?: EventHandler<PointerEvent>
|
||||
onPointerOver?: EventHandler<PointerEvent>
|
||||
onPointerOverCapture?: EventHandler<PointerEvent>
|
||||
onPointerOut?: EventHandler<PointerEvent>
|
||||
onPointerOutCapture?: EventHandler<PointerEvent>
|
||||
onGotPointerCapture?: EventHandler<PointerEvent>
|
||||
onGotPointerCaptureCapture?: EventHandler<PointerEvent>
|
||||
onLostPointerCapture?: EventHandler<PointerEvent>
|
||||
onLostPointerCaptureCapture?: EventHandler<PointerEvent>
|
||||
|
||||
// UI Events
|
||||
onScroll?: EventHandler<UIEvent>
|
||||
onScrollCapture?: EventHandler<UIEvent>
|
||||
|
||||
// Wheel Events
|
||||
onWheel?: EventHandler<WheelEvent>
|
||||
onWheelCapture?: EventHandler<WheelEvent>
|
||||
|
||||
// Animation Events
|
||||
onAnimationStart?: EventHandler<AnimationEvent>
|
||||
onAnimationStartCapture?: EventHandler<AnimationEvent>
|
||||
onAnimationEnd?: EventHandler<AnimationEvent>
|
||||
onAnimationEndCapture?: EventHandler<AnimationEvent>
|
||||
onAnimationIteration?: EventHandler<AnimationEvent>
|
||||
onAnimationIterationCapture?: EventHandler<AnimationEvent>
|
||||
|
||||
// Transition Events
|
||||
onTransitionEnd?: EventHandler<TransitionEvent>
|
||||
onTransitionEndCapture?: EventHandler<TransitionEvent>
|
||||
}
|
||||
3
node_modules/@use-gesture/core/src/utils.ts
generated
vendored
Normal file
3
node_modules/@use-gesture/core/src/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// additional core exports
|
||||
|
||||
export { rubberbandIfOutOfBounds } from './utils/maths'
|
||||
144
node_modules/@use-gesture/core/src/utils/events.ts
generated
vendored
Normal file
144
node_modules/@use-gesture/core/src/utils/events.ts
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
import { PointerType } from '../types'
|
||||
import { Vector2 } from '../types'
|
||||
|
||||
const EVENT_TYPE_MAP: any = {
|
||||
pointer: { start: 'down', change: 'move', end: 'up' },
|
||||
mouse: { start: 'down', change: 'move', end: 'up' },
|
||||
touch: { start: 'start', change: 'move', end: 'end' },
|
||||
gesture: { start: 'start', change: 'change', end: 'end' }
|
||||
}
|
||||
|
||||
function capitalize(string: string) {
|
||||
if (!string) return ''
|
||||
return string[0].toUpperCase() + string.slice(1)
|
||||
}
|
||||
|
||||
const actionsWithoutCaptureSupported = ['enter', 'leave']
|
||||
|
||||
function hasCapture(capture = false, actionKey: string) {
|
||||
return capture && !actionsWithoutCaptureSupported.includes(actionKey)
|
||||
}
|
||||
|
||||
export function toHandlerProp(device: string, action = '', capture: boolean = false) {
|
||||
const deviceProps = EVENT_TYPE_MAP[device]
|
||||
const actionKey = deviceProps ? deviceProps[action] || action : action
|
||||
return 'on' + capitalize(device) + capitalize(actionKey) + (hasCapture(capture, actionKey) ? 'Capture' : '')
|
||||
}
|
||||
|
||||
const pointerCaptureEvents = ['gotpointercapture', 'lostpointercapture']
|
||||
|
||||
export function parseProp(prop: string) {
|
||||
let eventKey = prop.substring(2).toLowerCase()
|
||||
const passive = !!~eventKey.indexOf('passive')
|
||||
if (passive) eventKey = eventKey.replace('passive', '')
|
||||
|
||||
const captureKey = pointerCaptureEvents.includes(eventKey) ? 'capturecapture' : 'capture'
|
||||
// capture = true
|
||||
const capture = !!~eventKey.indexOf(captureKey)
|
||||
// pointermovecapture => pointermove
|
||||
if (capture) eventKey = eventKey.replace('capture', '')
|
||||
return { device: eventKey, capture, passive }
|
||||
}
|
||||
|
||||
export function toDomEventType(device: string, action = '') {
|
||||
const deviceProps = EVENT_TYPE_MAP[device]
|
||||
const actionKey = deviceProps ? deviceProps[action] || action : action
|
||||
return device + actionKey
|
||||
}
|
||||
|
||||
export function isTouch(event: UIEvent) {
|
||||
return 'touches' in event
|
||||
}
|
||||
|
||||
export function getPointerType(event: UIEvent): PointerType {
|
||||
if (isTouch(event)) return 'touch'
|
||||
if ('pointerType' in event) return (event as PointerEvent).pointerType as PointerType
|
||||
return 'mouse'
|
||||
}
|
||||
|
||||
function getCurrentTargetTouchList(event: TouchEvent) {
|
||||
return Array.from(event.touches).filter(
|
||||
(e) => e.target === event.currentTarget || (event.currentTarget as Node)?.contains?.(e.target as Node)
|
||||
)
|
||||
}
|
||||
|
||||
function getTouchList(event: TouchEvent) {
|
||||
return event.type === 'touchend' || event.type === 'touchcancel' ? event.changedTouches : event.targetTouches
|
||||
}
|
||||
|
||||
function getValueEvent<EventType extends TouchEvent | PointerEvent>(
|
||||
event: EventType
|
||||
): EventType extends TouchEvent ? Touch : PointerEvent {
|
||||
return (isTouch(event) ? getTouchList(event as TouchEvent)[0] : event) as any
|
||||
}
|
||||
|
||||
export function distanceAngle(P1: Touch | PointerEvent, P2: Touch | PointerEvent) {
|
||||
// add a try catch
|
||||
// attempt to fix https://github.com/pmndrs/use-gesture/issues/551
|
||||
try {
|
||||
const dx = P2.clientX - P1.clientX
|
||||
const dy = P2.clientY - P1.clientY
|
||||
const cx = (P2.clientX + P1.clientX) / 2
|
||||
const cy = (P2.clientY + P1.clientY) / 2
|
||||
|
||||
const distance = Math.hypot(dx, dy)
|
||||
const angle = -(Math.atan2(dx, dy) * 180) / Math.PI
|
||||
const origin = [cx, cy] as Vector2
|
||||
return { angle, distance, origin }
|
||||
} catch {}
|
||||
return null
|
||||
}
|
||||
|
||||
export function touchIds(event: TouchEvent) {
|
||||
return getCurrentTargetTouchList(event).map((touch) => touch.identifier)
|
||||
}
|
||||
|
||||
export function touchDistanceAngle(event: TouchEvent, ids: number[]) {
|
||||
const [P1, P2] = Array.from(event.touches).filter((touch) => ids.includes(touch.identifier))
|
||||
return distanceAngle(P1, P2)
|
||||
}
|
||||
|
||||
export function pointerId(event: PointerEvent | TouchEvent) {
|
||||
const valueEvent = getValueEvent(event)
|
||||
return isTouch(event) ? (valueEvent as Touch).identifier : (valueEvent as PointerEvent).pointerId
|
||||
}
|
||||
|
||||
export function pointerValues(event: PointerEvent | TouchEvent): Vector2 {
|
||||
// if ('spaceX' in event) return [event.spaceX, event.spaceY]
|
||||
const valueEvent = getValueEvent(event)
|
||||
return [valueEvent.clientX, valueEvent.clientY]
|
||||
}
|
||||
|
||||
// wheel delta defaults from https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js
|
||||
const LINE_HEIGHT = 40
|
||||
const PAGE_HEIGHT = 800
|
||||
|
||||
export function wheelValues(event: WheelEvent): Vector2 {
|
||||
let { deltaX, deltaY, deltaMode } = event
|
||||
// normalize wheel values, especially for Firefox
|
||||
if (deltaMode === 1) {
|
||||
deltaX *= LINE_HEIGHT
|
||||
deltaY *= LINE_HEIGHT
|
||||
} else if (deltaMode === 2) {
|
||||
deltaX *= PAGE_HEIGHT
|
||||
deltaY *= PAGE_HEIGHT
|
||||
}
|
||||
return [deltaX, deltaY]
|
||||
}
|
||||
|
||||
export function scrollValues(event: UIEvent): Vector2 {
|
||||
// If the currentTarget is the window then we return the scrollX/Y position.
|
||||
// If not (ie the currentTarget is a DOM element), then we return scrollLeft/Top
|
||||
const { scrollX, scrollY, scrollLeft, scrollTop } = event.currentTarget as Element & Window
|
||||
return [scrollX ?? scrollLeft ?? 0, scrollY ?? scrollTop ?? 0]
|
||||
}
|
||||
|
||||
export function getEventDetails(event: any) {
|
||||
const payload: any = {}
|
||||
if ('buttons' in event) payload.buttons = event.buttons
|
||||
if ('shiftKey' in event) {
|
||||
const { shiftKey, altKey, metaKey, ctrlKey } = event
|
||||
Object.assign(payload, { shiftKey, altKey, metaKey, ctrlKey })
|
||||
}
|
||||
return payload
|
||||
}
|
||||
27
node_modules/@use-gesture/core/src/utils/fn.ts
generated
vendored
Normal file
27
node_modules/@use-gesture/core/src/utils/fn.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export function call<T>(v: T | ((...args: any[]) => T), ...args: any[]): T {
|
||||
if (typeof v === 'function') {
|
||||
// @ts-ignore
|
||||
return v(...args)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
export function noop() {}
|
||||
|
||||
export function chain(...fns: Function[]): Function {
|
||||
if (fns.length === 0) return noop
|
||||
if (fns.length === 1) return fns[0]
|
||||
|
||||
return function (this: any) {
|
||||
let result
|
||||
for (const fn of fns) {
|
||||
result = fn.apply(this, arguments) || result
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export function assignDefault<T extends Object>(value: Partial<T> | undefined, fallback: T): T {
|
||||
return Object.assign({}, fallback, value || {})
|
||||
}
|
||||
49
node_modules/@use-gesture/core/src/utils/maths.ts
generated
vendored
Normal file
49
node_modules/@use-gesture/core/src/utils/maths.ts
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Vector2 } from '../types'
|
||||
|
||||
export function clamp(v: number, min: number, max: number) {
|
||||
return Math.max(min, Math.min(v, max))
|
||||
}
|
||||
|
||||
export const V = {
|
||||
toVector<T>(v: T | [T, T] | undefined, fallback?: T | [T, T]): [T, T] {
|
||||
if (v === undefined) v = fallback as T | [T, T]
|
||||
return Array.isArray(v) ? v : [v, v]
|
||||
},
|
||||
add(v1: Vector2, v2: Vector2): Vector2 {
|
||||
return [v1[0] + v2[0], v1[1] + v2[1]]
|
||||
},
|
||||
sub(v1: Vector2, v2: Vector2): Vector2 {
|
||||
return [v1[0] - v2[0], v1[1] - v2[1]]
|
||||
},
|
||||
addTo(v1: Vector2, v2: Vector2) {
|
||||
v1[0] += v2[0]
|
||||
v1[1] += v2[1]
|
||||
},
|
||||
subTo(v1: Vector2, v2: Vector2) {
|
||||
v1[0] -= v2[0]
|
||||
v1[1] -= v2[1]
|
||||
}
|
||||
}
|
||||
|
||||
// Based on @aholachek ;)
|
||||
// https://twitter.com/chpwn/status/285540192096497664
|
||||
// iOS constant = 0.55
|
||||
|
||||
// https://medium.com/@nathangitter/building-fluid-interfaces-ios-swift-9732bb934bf5
|
||||
|
||||
function rubberband(distance: number, dimension: number, constant: number) {
|
||||
if (dimension === 0 || Math.abs(dimension) === Infinity) return Math.pow(distance, constant * 5)
|
||||
return (distance * dimension * constant) / (dimension + constant * distance)
|
||||
}
|
||||
|
||||
export function rubberbandIfOutOfBounds(position: number, min: number, max: number, constant = 0.15) {
|
||||
if (constant === 0) return clamp(position, min, max)
|
||||
if (position < min) return -rubberband(min - position, max - min, constant) + min
|
||||
if (position > max) return +rubberband(position - max, max - min, constant) + max
|
||||
return position
|
||||
}
|
||||
|
||||
export function computeRubberband(bounds: [Vector2, Vector2], [Vx, Vy]: Vector2, [Rx, Ry]: Vector2): Vector2 {
|
||||
const [[X0, X1], [Y0, Y1]] = bounds
|
||||
return [rubberbandIfOutOfBounds(Vx, X0, X1, Rx), rubberbandIfOutOfBounds(Vy, Y0, Y1, Ry)]
|
||||
}
|
||||
19
node_modules/@use-gesture/core/src/utils/state.ts
generated
vendored
Normal file
19
node_modules/@use-gesture/core/src/utils/state.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { CommonGestureState } from '../types'
|
||||
|
||||
// _movement rolls back to when it passed the bounds.
|
||||
/**
|
||||
* @note code is currently used in WheelEngine and PinchEngine.
|
||||
*/
|
||||
export function clampStateInternalMovementToBounds(state: CommonGestureState) {
|
||||
const [ox, oy] = state.overflow
|
||||
const [dx, dy] = state._delta
|
||||
const [dirx, diry] = state._direction
|
||||
|
||||
if ((ox < 0 && dx > 0 && dirx < 0) || (ox > 0 && dx < 0 && dirx > 0)) {
|
||||
state._movement[0] = state._movementBound[0] as number
|
||||
}
|
||||
|
||||
if ((oy < 0 && dy > 0 && diry < 0) || (oy > 0 && dy < 0 && diry > 0)) {
|
||||
state._movement[1] = state._movementBound[1] as number
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user