'use strict'; var maths = require('./maths-267f0992.cjs.dev.js'); function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } const EVENT_TYPE_MAP = { 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) { if (!string) return ''; return string[0].toUpperCase() + string.slice(1); } const actionsWithoutCaptureSupported = ['enter', 'leave']; function hasCapture(capture = false, actionKey) { return capture && !actionsWithoutCaptureSupported.includes(actionKey); } function toHandlerProp(device, action = '', capture = 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']; function parseProp(prop) { let eventKey = prop.substring(2).toLowerCase(); const passive = !!~eventKey.indexOf('passive'); if (passive) eventKey = eventKey.replace('passive', ''); const captureKey = pointerCaptureEvents.includes(eventKey) ? 'capturecapture' : 'capture'; const capture = !!~eventKey.indexOf(captureKey); if (capture) eventKey = eventKey.replace('capture', ''); return { device: eventKey, capture, passive }; } function toDomEventType(device, action = '') { const deviceProps = EVENT_TYPE_MAP[device]; const actionKey = deviceProps ? deviceProps[action] || action : action; return device + actionKey; } function isTouch(event) { return 'touches' in event; } function getPointerType(event) { if (isTouch(event)) return 'touch'; if ('pointerType' in event) return event.pointerType; return 'mouse'; } function getCurrentTargetTouchList(event) { return Array.from(event.touches).filter(e => { var _event$currentTarget, _event$currentTarget$; return e.target === event.currentTarget || ((_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 || (_event$currentTarget$ = _event$currentTarget.contains) === null || _event$currentTarget$ === void 0 ? void 0 : _event$currentTarget$.call(_event$currentTarget, e.target)); }); } function getTouchList(event) { return event.type === 'touchend' || event.type === 'touchcancel' ? event.changedTouches : event.targetTouches; } function getValueEvent(event) { return isTouch(event) ? getTouchList(event)[0] : event; } function distanceAngle(P1, P2) { 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]; return { angle, distance, origin }; } catch (_unused) {} return null; } function touchIds(event) { return getCurrentTargetTouchList(event).map(touch => touch.identifier); } function touchDistanceAngle(event, ids) { const [P1, P2] = Array.from(event.touches).filter(touch => ids.includes(touch.identifier)); return distanceAngle(P1, P2); } function pointerId(event) { const valueEvent = getValueEvent(event); return isTouch(event) ? valueEvent.identifier : valueEvent.pointerId; } function pointerValues(event) { const valueEvent = getValueEvent(event); return [valueEvent.clientX, valueEvent.clientY]; } const LINE_HEIGHT = 40; const PAGE_HEIGHT = 800; function wheelValues(event) { let { deltaX, deltaY, deltaMode } = event; if (deltaMode === 1) { deltaX *= LINE_HEIGHT; deltaY *= LINE_HEIGHT; } else if (deltaMode === 2) { deltaX *= PAGE_HEIGHT; deltaY *= PAGE_HEIGHT; } return [deltaX, deltaY]; } function scrollValues(event) { var _ref, _ref2; const { scrollX, scrollY, scrollLeft, scrollTop } = event.currentTarget; return [(_ref = scrollX !== null && scrollX !== void 0 ? scrollX : scrollLeft) !== null && _ref !== void 0 ? _ref : 0, (_ref2 = scrollY !== null && scrollY !== void 0 ? scrollY : scrollTop) !== null && _ref2 !== void 0 ? _ref2 : 0]; } function getEventDetails(event) { const payload = {}; 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; } function call(v, ...args) { if (typeof v === 'function') { return v(...args); } else { return v; } } function noop() {} function chain(...fns) { if (fns.length === 0) return noop; if (fns.length === 1) return fns[0]; return function () { let result; for (const fn of fns) { result = fn.apply(this, arguments) || result; } return result; }; } function assignDefault(value, fallback) { return Object.assign({}, fallback, value || {}); } const BEFORE_LAST_KINEMATICS_DELAY = 32; class Engine { constructor(ctrl, args, key) { this.ctrl = ctrl; this.args = args; this.key = key; if (!this.state) { this.state = {}; this.computeValues([0, 0]); this.computeInitial(); if (this.init) this.init(); this.reset(); } } get state() { return this.ctrl.state[this.key]; } set state(state) { this.ctrl.state[this.key] = state; } get shared() { return this.ctrl.state.shared; } get eventStore() { return this.ctrl.gestureEventStores[this.key]; } get timeoutStore() { return this.ctrl.gestureTimeoutStores[this.key]; } get config() { return this.ctrl.config[this.key]; } get sharedConfig() { return this.ctrl.config.shared; } 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]; 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; } start(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; } } computeValues(values) { const state = this.state; state._values = values; state.values = this.config.transform(values); } computeInitial() { const state = this.state; state._initial = state._values; state.initial = state.values; } compute(event) { const { state, config, shared } = this; state.args = this.args; let dt = 0; if (event) { state.event = event; 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; dt = event.timeStamp - state.timeStamp; state.timeStamp = event.timeStamp; state.elapsedTime = state.timeStamp - state.startTime; } if (state._active) { const _absoluteDelta = state._delta.map(Math.abs); maths.V.addTo(state._distance, _absoluteDelta); } if (this.axisIntent) this.axisIntent(event); const [_m0, _m1] = state._movement; const [t0, t1] = config.threshold; const { _step, values } = state; if (config.hasCustomTransform) { 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 { 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 = [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]; 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; const rubberband = state._active ? config.rubberband || [0, 0] : [0, 0]; state.offset = maths.computeRubberband(state._bounds, state.offset, rubberband); state.delta = maths.V.sub(state.offset, previousOffset); this.computeMovement(); if (gestureIsActive && (!state.last || dt > BEFORE_LAST_KINEMATICS_DELAY)) { state.delta = maths.V.sub(state.offset, previousOffset); const absoluteDelta = state.delta.map(Math.abs); maths.V.addTo(state.distance, absoluteDelta); state.direction = state.delta.map(Math.sign); state._direction = state._delta.map(Math.sign); if (!state.first && dt > 0) { state.velocity = [absoluteDelta[0] / dt, absoluteDelta[1] / dt]; state.timeDelta = dt; } } } emit() { const state = this.state; const shared = this.shared; const config = this.config; if (!state._active) this.clean(); if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return; const memo = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, { [this.aliasKey]: state.values })); if (memo !== undefined) state.memo = memo; } clean() { this.eventStore.clean(); this.timeoutStore.clean(); } } function selectAxis([dx, dy], threshold) { 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; } class CoordinatesEngine extends Engine { constructor(...args) { super(...args); _defineProperty(this, "aliasKey", 'xy'); } reset() { super.reset(); this.state.axis = undefined; } init() { this.state.offset = [0, 0]; this.state.lastOffset = [0, 0]; } computeOffset() { this.state.offset = maths.V.add(this.state.lastOffset, this.state.movement); } computeMovement() { this.state.movement = maths.V.sub(this.state.offset, this.state.lastOffset); } axisIntent(event) { 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); } state._blocked = (config.lockDirection || !!config.axis) && !state.axis || !!config.axis && config.axis !== state.axis; } restrictToAxis(v) { if (this.config.axis || this.config.lockDirection) { switch (this.state.axis) { case 'x': v[1] = 0; break; case 'y': v[0] = 0; break; } } } } const identity = v => v; const DEFAULT_RUBBERBAND = 0.15; const commonConfigResolver = { enabled(value = true) { return value; }, eventOptions(value, _k, config) { return _objectSpread2(_objectSpread2({}, config.shared.eventOptions), value); }, preventDefault(value = false) { return value; }, triggerAllEvents(value = false) { return value; }, rubberband(value = 0) { switch (value) { case true: return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND]; case false: return [0, 0]; default: return maths.V.toVector(value); } }, from(value) { if (typeof value === 'function') return value; if (value != null) return maths.V.toVector(value); }, transform(value, _k, config) { const transform = value || config.shared.transform; this.hasCustomTransform = !!transform; if (process.env.NODE_ENV === 'development') { const originalTransform = transform || identity; return v => { const r = originalTransform(v); if (!isFinite(r[0]) || !isFinite(r[1])) { console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r[0]},${[1]}]`); } return r; }; } return transform || identity; }, threshold(value) { return maths.V.toVector(value, 0); } }; if (process.env.NODE_ENV === 'development') { Object.assign(commonConfigResolver, { domTarget(value) { if (value !== undefined) { throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`); } return NaN; }, lockDirection(value) { if (value !== undefined) { throw Error(`[@use-gesture]: \`lockDirection\` option has been merged with \`axis\`. Use it as in \`{ axis: 'lock' }\``); } return NaN; }, initial(value) { if (value !== undefined) { throw Error(`[@use-gesture]: \`initial\` option has been renamed to \`from\`.`); } return NaN; } }); } const DEFAULT_AXIS_THRESHOLD = 0; const coordinatesConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, { axis(_v, _k, { axis }) { this.lockDirection = axis === 'lock'; if (!this.lockDirection) return axis; }, axisThreshold(value = DEFAULT_AXIS_THRESHOLD) { return value; }, bounds(value = {}) { if (typeof value === 'function') { return 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; return [[left, right], [top, bottom]]; } }); const KEYS_DELTA_MAP = { ArrowRight: (displacement, factor = 1) => [displacement * factor, 0], ArrowLeft: (displacement, factor = 1) => [-1 * displacement * factor, 0], ArrowUp: (displacement, factor = 1) => [0, -1 * displacement * factor], ArrowDown: (displacement, factor = 1) => [0, displacement * factor] }; class DragEngine extends CoordinatesEngine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'dragging'); } reset() { 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.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); } } cancel() { const state = this.state; if (state.canceled) return; state.canceled = true; state._active = false; setTimeout(() => { this.compute(); this.emit(); }, 0); } setActive() { this.state._active = this.state._pointerActive || this.state._keyboardActive; } clean() { this.pointerClean(); this.state._pointerActive = false; this.state._keyboardActive = false; super.clean(); } pointerDown(event) { const config = this.config; const state = this.state; if (event.buttons != null && (Array.isArray(config.pointerButtons) ? !config.pointerButtons.includes(event.buttons) : config.pointerButtons !== -1 && config.pointerButtons !== event.buttons)) return; const ctrlIds = this.ctrl.setEventIds(event); if (config.pointerCapture) { event.target.setPointerCapture(event.pointerId); } if (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') { state._active = false; this.setupScrollPrevention(event); } else if (config.delay > 0) { this.setupDelayTrigger(event); if (config.triggerAllEvents) { this.compute(event); this.emit(); } } else { this.startPointerDrag(event); } } startPointerDrag(event) { const state = this.state; state._active = true; state._preventScroll = true; state._delayed = false; this.compute(event); this.emit(); } pointerMove(event) { 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 = maths.V.sub(_values, state._values); this.computeValues(_values); } maths.V.addTo(state._movement, state._delta); this.compute(event); if (state._delayed && state.intentional) { this.timeoutStore.remove('dragDelay'); 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) { this.ctrl.setEventIds(event); try { if (this.config.pointerCapture && event.target.hasPointerCapture(event.pointerId)) { ; event.target.releasePointerCapture(event.pointerId); } } catch (_unused) { if (process.env.NODE_ENV === 'development') { 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) { if (!this.state.tap && event.detail > 0) { event.preventDefault(); event.stopPropagation(); } } setupPointer(event) { const config = this.config; const device = config.device; if (process.env.NODE_ENV === 'development') { try { if (device === 'pointer' && config.preventScrollDelay === undefined) { const currentTarget = 'uv' in event ? event.sourceEvent.currentTarget : event.currentTarget; const style = window.getComputedStyle(currentTarget); if (style.touchAction === 'auto') { 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 (_unused2) {} } if (config.pointerLock) { event.currentTarget.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) { if (this.state._preventScroll && event.cancelable) { event.preventDefault(); } } setupScrollPrevention(event) { this.state._preventScroll = false; persistEvent(event); 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) { this.state._delayed = true; this.timeoutStore.add('dragDelay', () => { this.state._step = [0, 0]; this.startPointerDrag(event); }, this.config.delay); } keyDown(event) { 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; maths.V.addTo(state._movement, state._delta); this.compute(event); this.emit(); } } keyUp(event) { if (!(event.key in KEYS_DELTA_MAP)) return; this.state._keyboardActive = false; this.setActive(); this.compute(event); this.emit(); } bind(bindFunction) { 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) { 'persist' in event && typeof event.persist === 'function' && event.persist(); } const isBrowser = typeof window !== 'undefined' && window.document && window.document.createElement; function supportsTouchEvents() { return isBrowser && 'ontouchstart' in window; } function isTouchScreen() { return supportsTouchEvents() || isBrowser && window.navigator.maxTouchPoints > 1; } function supportsPointerEvents() { return isBrowser && 'onpointerdown' in window; } function supportsPointerLock() { return isBrowser && 'exitPointerLock' in window.document; } function supportsGestureEvents() { try { return 'constructor' in GestureEvent; } catch (e) { return false; } } const SUPPORT = { isBrowser, gesture: supportsGestureEvents(), touch: supportsTouchEvents(), touchscreen: isTouchScreen(), pointer: supportsPointerEvents(), pointerLock: supportsPointerLock() }; const DEFAULT_PREVENT_SCROLL_DELAY = 250; const DEFAULT_DRAG_DELAY = 180; const DEFAULT_SWIPE_VELOCITY = 0.5; const DEFAULT_SWIPE_DISTANCE = 50; const DEFAULT_SWIPE_DURATION = 250; const DEFAULT_KEYBOARD_DISPLACEMENT = 10; const DEFAULT_DRAG_AXIS_THRESHOLD = { mouse: 0, touch: 0, pen: 8 }; const dragConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, { device(_v, _k, { pointer: { touch = false, lock = false, mouse = false } = {} }) { 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(value, _k, { preventScroll }) { 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(_v, _k, { pointer: { capture = true, buttons = 1, keys = true } = {} }) { this.pointerButtons = buttons; this.keys = keys; return !this.pointerLock && this.device === 'pointer' && capture; }, threshold(value, _k, { filterTaps = false, tapsThreshold = 3, axis = undefined }) { const threshold = maths.V.toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0); this.filterTaps = filterTaps; this.tapsThreshold = tapsThreshold; return threshold; }, swipe({ velocity = DEFAULT_SWIPE_VELOCITY, distance = DEFAULT_SWIPE_DISTANCE, duration = DEFAULT_SWIPE_DURATION } = {}) { return { velocity: this.transform(maths.V.toVector(velocity)), distance: this.transform(maths.V.toVector(distance)), duration }; }, delay(value = 0) { switch (value) { case true: return DEFAULT_DRAG_DELAY; case false: return 0; default: return value; } }, axisThreshold(value) { if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD; return _objectSpread2(_objectSpread2({}, DEFAULT_DRAG_AXIS_THRESHOLD), value); }, keyboardDisplacement(value = DEFAULT_KEYBOARD_DISPLACEMENT) { return value; } }); if (process.env.NODE_ENV === 'development') { Object.assign(dragConfigResolver, { useTouch(value) { 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) { if (value !== undefined) { throw Error(`[@use-gesture]: \`experimental_preventWindowScrollY\` option has been renamed to \`preventScroll\`.`); } return NaN; }, swipeVelocity(value) { 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) { 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) { if (value !== undefined) { throw Error(`[@use-gesture]: \`swipeDuration\` option has been renamed to \`swipe.duration\`. Use it as in \`{ swipe: { duration: 250 } }\`.`); } return NaN; } }); } function clampStateInternalMovementToBounds(state) { 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]; } if (oy < 0 && dy > 0 && diry < 0 || oy > 0 && dy < 0 && diry > 0) { state._movement[1] = state._movementBound[1]; } } const SCALE_ANGLE_RATIO_INTENT_DEG = 30; const PINCH_WHEEL_RATIO = 100; class PinchEngine extends Engine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'pinching'); _defineProperty(this, "aliasKey", 'da'); } init() { this.state.offset = [1, 0]; this.state.lastOffset = [1, 0]; this.state._pointerEvents = new Map(); } 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 = maths.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) { 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; this.compute(); this.emit(); }, 0); } touchStart(event) { this.ctrl.setEventIds(event); const state = this.state; const ctrlTouchIds = this.ctrl.touchIds; if (state._active) { if (state._touchIds.every(id => ctrlTouchIds.has(id))) return; } if (ctrlTouchIds.size < 2) return; this.start(event); state._touchIds = Array.from(ctrlTouchIds).slice(0, 2); const payload = touchDistanceAngle(event, state._touchIds); if (!payload) return; this.pinchStart(event, payload); } pointerStart(event) { if (event.buttons != null && event.buttons % 2 !== 1) return; this.ctrl.setEventIds(event); event.target.setPointerCapture(event.pointerId); const state = this.state; const _pointerEvents = state._pointerEvents; const ctrlPointerIds = this.ctrl.pointerIds; if (state._active) { 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); const payload = distanceAngle(...Array.from(_pointerEvents.values())); if (!payload) return; this.pinchStart(event, payload); } pinchStart(event, payload) { const state = this.state; state.origin = payload.origin; this.computeValues([payload.distance, payload.angle]); this.computeInitial(); this.compute(event); this.emit(); } touchMove(event) { if (!this.state._active) return; const payload = touchDistanceAngle(event, this.state._touchIds); if (!payload) return; this.pinchMove(event, payload); } pointerMove(event) { const _pointerEvents = this.state._pointerEvents; if (_pointerEvents.has(event.pointerId)) { _pointerEvents.set(event.pointerId, event); } if (!this.state._active) return; const payload = distanceAngle(...Array.from(_pointerEvents.values())); if (!payload) return; this.pinchMove(event, payload); } pinchMove(event, payload) { 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) { 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) { const state = this.state; this.ctrl.setEventIds(event); try { event.target.releasePointerCapture(event.pointerId); } catch (_unused) {} 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) { 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) { 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 = maths.V.sub(state._movement, _previousMovement); this.compute(event); this.emit(); } gestureEnd(event) { if (!this.state._active) return; this.state._active = false; this.compute(event); this.emit(); } wheel(event) { 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) { this.start(event); this.wheelChange(event); } wheelChange(event) { const isR3f = ('uv' in event); if (!isR3f) { if (event.cancelable) { event.preventDefault(); } if (process.env.NODE_ENV === 'development' && !event.defaultPrevented) { 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]; maths.V.addTo(state._movement, state._delta); 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) { const device = this.config.device; if (!!device) { bindFunction(device, 'start', this[device + 'Start'].bind(this)); bindFunction(device, 'change', this[device + 'Move'].bind(this)); bindFunction(device, 'end', this[device + 'End'].bind(this)); bindFunction(device, 'cancel', this[device + 'End'].bind(this)); bindFunction('lostPointerCapture', '', this[device + 'End'].bind(this)); } if (this.config.pinchOnWheel) { bindFunction('wheel', '', this.wheel.bind(this), { passive: false }); } } } const pinchConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, { device(_v, _k, { shared, pointer: { touch = false } = {} }) { 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'; } }, bounds(_v, _k, { scaleBounds = {}, angleBounds = {} }) { const _scaleBounds = state => { const D = assignDefault(call(scaleBounds, state), { min: -Infinity, max: Infinity }); return [D.min, D.max]; }; const _angleBounds = 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 => [_scaleBounds(state), _angleBounds(state)]; }, threshold(value, _k, config) { this.lockDirection = config.axis === 'lock'; const threshold = maths.V.toVector(value, this.lockDirection ? [0.1, 3] : 0); return threshold; }, modifierKey(value) { if (value === undefined) return 'ctrlKey'; return value; }, pinchOnWheel(value = true) { return value; } }); class MoveEngine extends CoordinatesEngine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'moving'); } move(event) { 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) { this.start(event); this.computeValues(pointerValues(event)); this.compute(event); this.computeInitial(); this.emit(); } moveChange(event) { if (!this.state._active) return; const values = pointerValues(event); const state = this.state; state._delta = maths.V.sub(values, state._values); maths.V.addTo(state._movement, state._delta); this.computeValues(values); this.compute(event); this.emit(); } moveEnd(event) { if (!this.state._active) return; this.state._active = false; this.compute(event); this.emit(); } bind(bindFunction) { bindFunction('pointer', 'change', this.move.bind(this)); bindFunction('pointer', 'leave', this.moveEnd.bind(this)); } } const moveConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, { mouseOnly: (value = true) => value }); class ScrollEngine extends CoordinatesEngine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'scrolling'); } scroll(event) { if (!this.state._active) this.start(event); this.scrollChange(event); this.timeoutStore.add('scrollEnd', this.scrollEnd.bind(this)); } scrollChange(event) { if (event.cancelable) event.preventDefault(); const state = this.state; const values = scrollValues(event); state._delta = maths.V.sub(values, state._values); maths.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) { bindFunction('scroll', '', this.scroll.bind(this)); } } const scrollConfigResolver = coordinatesConfigResolver; class WheelEngine extends CoordinatesEngine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'wheeling'); } wheel(event) { if (!this.state._active) this.start(event); this.wheelChange(event); this.timeoutStore.add('wheelEnd', this.wheelEnd.bind(this)); } wheelChange(event) { const state = this.state; state._delta = wheelValues(event); maths.V.addTo(state._movement, state._delta); clampStateInternalMovementToBounds(state); this.compute(event); this.emit(); } wheelEnd() { if (!this.state._active) return; this.state._active = false; this.compute(); this.emit(); } bind(bindFunction) { bindFunction('wheel', '', this.wheel.bind(this)); } } const wheelConfigResolver = coordinatesConfigResolver; class HoverEngine extends CoordinatesEngine { constructor(...args) { super(...args); _defineProperty(this, "ingKey", 'hovering'); } enter(event) { if (this.config.mouseOnly && event.pointerType !== 'mouse') return; this.start(event); this.computeValues(pointerValues(event)); this.compute(event); this.emit(); } leave(event) { 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 = maths.V.sub(values, state._values); this.computeValues(values); this.compute(event); state.delta = state.movement; this.emit(); } bind(bindFunction) { bindFunction('pointer', 'enter', this.enter.bind(this)); bindFunction('pointer', 'leave', this.leave.bind(this)); } } const hoverConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, { mouseOnly: (value = true) => value }); const EngineMap = new Map(); const ConfigResolverMap = new Map(); function registerAction(action) { EngineMap.set(action.key, action.engine); ConfigResolverMap.set(action.key, action.resolver); } const dragAction = { key: 'drag', engine: DragEngine, resolver: dragConfigResolver }; const hoverAction = { key: 'hover', engine: HoverEngine, resolver: hoverConfigResolver }; const moveAction = { key: 'move', engine: MoveEngine, resolver: moveConfigResolver }; const pinchAction = { key: 'pinch', engine: PinchEngine, resolver: pinchConfigResolver }; const scrollAction = { key: 'scroll', engine: ScrollEngine, resolver: scrollConfigResolver }; const wheelAction = { key: 'wheel', engine: WheelEngine, resolver: wheelConfigResolver }; exports.ConfigResolverMap = ConfigResolverMap; exports.EngineMap = EngineMap; exports.SUPPORT = SUPPORT; exports._defineProperty = _defineProperty; exports._objectSpread2 = _objectSpread2; exports.chain = chain; exports.dragAction = dragAction; exports.hoverAction = hoverAction; exports.isTouch = isTouch; exports.moveAction = moveAction; exports.parseProp = parseProp; exports.pinchAction = pinchAction; exports.registerAction = registerAction; exports.scrollAction = scrollAction; exports.toDomEventType = toDomEventType; exports.toHandlerProp = toHandlerProp; exports.touchIds = touchIds; exports.wheelAction = wheelAction;