@vielzeug/gesture 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @vielzeug/gesture
2
+
3
+ Framework-neutral one-axis pointer pan recognition.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pnpm add @vielzeug/gesture
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ import { createPanGesture } from '@vielzeug/gesture';
15
+
16
+ const pan = createPanGesture(element, {
17
+ axis: 'x',
18
+ onMove: ({ distance }) => {
19
+ element.style.transform = `translateX(${distance}px)`;
20
+ },
21
+ onEnd: ({ distance, reason }) => {
22
+ element.style.transform = '';
23
+
24
+ if (reason === 'release' && Math.abs(distance) >= 48) {
25
+ dismiss();
26
+ }
27
+ },
28
+ });
29
+
30
+ pan.dispose();
31
+ ```
32
+
33
+ Pointer capture is enabled by default. Set `pointerCapture: false` for surfaces whose nested or
34
+ newly revealed controls must retain native pointer-up targeting.
35
+
36
+ [Full documentation](https://vielzeug.dev/gesture/)
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=6,t=(e,t)=>typeof e==`function`?e():e??t,n=e=>!(!e.isPrimary||e.pointerType===`mouse`&&e.button!==0),r=(e,t)=>t===`x`?e.clientX:e.clientY,i=(e,t)=>t===`x`?e.startX:e.startY,a=(a,o={})=>{let s=new AbortController,c=a.ownerDocument,l=null,u=null,d=!1,f=()=>!!t(o.disabled,!1),p=e=>{if(!u)return null;let t=i(u,u.axis),n=r(e,u.axis);return{axis:u.axis,current:n,distance:n-t,event:e,pointerId:u.pointerId,pointerType:u.pointerType,start:t,target:a}},m=()=>{c.removeEventListener(`pointermove`,O,!0),c.removeEventListener(`pointerup`,k,!0),c.removeEventListener(`pointercancel`,A,!0),a.removeEventListener(`lostpointercapture`,j)},h=e=>{!e.captured||typeof a.releasePointerCapture!=`function`||typeof a.hasPointerCapture==`function`&&!a.hasPointerCapture(e.pointerId)||a.releasePointerCapture(e.pointerId)},g=()=>{let e=u;l=null,u=null,m(),e&&h(e)},_=(e,t)=>{if(!u)return!1;u.event=e;let n=p(e);return g(),n&&o.onEnd?.({...n,reason:t}),!0},v=()=>u?_(u.event,`cancel`):l?(g(),!0):!1,y=()=>{d||(d=!0,s.abort(),g(),a.removeEventListener(`pointerdown`,D))},b=e=>(u??l)?.pointerId===e.pointerId,x=()=>{c.addEventListener(`pointermove`,O,!0),c.addEventListener(`pointerup`,k,!0),c.addEventListener(`pointercancel`,A,!0),a.addEventListener(`lostpointercapture`,j)},S=t=>{if(!l)return!1;let n=t.clientX-l.startX,r=t.clientY-l.startY,i=l.axis===`x`?Math.abs(n):Math.abs(r),s=l.axis===`x`?Math.abs(r):Math.abs(n);if(Math.max(i,s)<e)return!1;if(s>i)return g(),!1;u={...l,captured:!1,event:t},l=null,o.pointerCapture!==!1&&typeof a.setPointerCapture==`function`&&(a.setPointerCapture(t.pointerId),u.captured=!0);let c=p(t);return c&&o.onStart?.(c),u?.pointerId===t.pointerId},C=e=>d||l||u||f()||!n(e)||o.shouldStart&&!o.shouldStart(e)?!1:(l={axis:t(o.axis,`x`),event:e,pointerId:e.pointerId,pointerType:e.pointerType,startX:e.clientX,startY:e.clientY},x(),!0),w=e=>{if(!b(e))return!1;if(f())return u?_(e,`cancel`):(g(),!0);if(!u&&!S(e)||!u)return!0;u.event=e;let t=p(e);return t&&o.onMove?.(t),!0},T=e=>b(e)?u?_(e,f()?`cancel`:`release`):(g(),!0):!1,E=e=>b(e)?u?_(e,`cancel`):(g(),!0):!1,D=e=>{e instanceof PointerEvent&&C(e)},O=e=>{e instanceof PointerEvent&&w(e)},k=e=>{e instanceof PointerEvent&&T(e)},A=e=>{e instanceof PointerEvent&&E(e)},j=e=>{e instanceof PointerEvent&&E(e)};return a.addEventListener(`pointerdown`,D),{get active(){return u!=null},cancel:v,get disposalSignal(){return s.signal},dispose:y,get disposed(){return d},[Symbol.dispose]:y}};exports.createPanGesture=a;
2
+ //# sourceMappingURL=gesture.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gesture.cjs","names":[],"sources":["../src/pan-gesture.ts"],"sourcesContent":["export type PanAxis = 'x' | 'y';\n\nexport type PanEndReason = 'cancel' | 'release';\n\nexport type PanGestureDetail = {\n axis: PanAxis;\n current: number;\n distance: number;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n start: number;\n target: Element;\n};\n\nexport type PanGestureEndDetail = PanGestureDetail & {\n reason: PanEndReason;\n};\n\nexport type PanGestureOptions = {\n axis?: PanAxis | (() => PanAxis);\n disabled?: boolean | (() => boolean | undefined);\n onEnd?: (detail: PanGestureEndDetail) => void;\n onMove?: (detail: PanGestureDetail) => void;\n onStart?: (detail: PanGestureDetail) => void;\n pointerCapture?: boolean;\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\nexport type PanGesture = {\n readonly active: boolean;\n [Symbol.dispose](): void;\n cancel(): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n};\n\ntype PendingPan = {\n axis: PanAxis;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n startX: number;\n startY: number;\n};\n\ntype ActivePan = PendingPan & {\n captured: boolean;\n};\n\nconst ACTIVATION_DISTANCE = 6;\n\nconst read = <T>(value: T | (() => T) | undefined, fallback: T): T =>\n typeof value === 'function' ? (value as () => T)() : (value ?? fallback);\n\nconst isPrimaryPointer = (event: PointerEvent): boolean => {\n if (!event.isPrimary) return false;\n if (event.pointerType === 'mouse' && event.button !== 0) return false;\n\n return true;\n};\n\nconst getCoordinate = (event: PointerEvent, axis: PanAxis): number => {\n return axis === 'x' ? event.clientX : event.clientY;\n};\n\nconst getStartCoordinate = (pan: PendingPan, axis: PanAxis): number => {\n return axis === 'x' ? pan.startX : pan.startY;\n};\n\nexport const createPanGesture = (target: Element, options: PanGestureOptions = {}): PanGesture => {\n const disposalController = new AbortController();\n const ownerDocument = target.ownerDocument;\n let pending: PendingPan | null = null;\n let active: ActivePan | null = null;\n let disposed = false;\n\n const isDisabled = (): boolean => Boolean(read(options.disabled, false));\n\n const createDetail = (event: PointerEvent): PanGestureDetail | null => {\n if (!active) return null;\n\n const start = getStartCoordinate(active, active.axis);\n const current = getCoordinate(event, active.axis);\n\n return {\n axis: active.axis,\n current,\n distance: current - start,\n event,\n pointerId: active.pointerId,\n pointerType: active.pointerType,\n start,\n target,\n };\n };\n\n const removeTrackingListeners = (): void => {\n ownerDocument.removeEventListener('pointermove', onPointerMove, true);\n ownerDocument.removeEventListener('pointerup', onPointerUp, true);\n ownerDocument.removeEventListener('pointercancel', onPointerCancel, true);\n target.removeEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const releaseCapture = (pan: ActivePan): void => {\n if (!pan.captured || typeof target.releasePointerCapture !== 'function') return;\n if (typeof target.hasPointerCapture === 'function' && !target.hasPointerCapture(pan.pointerId)) return;\n\n target.releasePointerCapture(pan.pointerId);\n };\n\n const clearSession = (): void => {\n const previousActive = active;\n\n pending = null;\n active = null;\n removeTrackingListeners();\n\n if (previousActive) releaseCapture(previousActive);\n };\n\n const finish = (event: PointerEvent, reason: PanEndReason): boolean => {\n if (!active) return false;\n\n active.event = event;\n const detail = createDetail(event);\n\n clearSession();\n\n if (detail) options.onEnd?.({ ...detail, reason });\n\n return true;\n };\n\n const cancel = (): boolean => {\n if (active) return finish(active.event, 'cancel');\n if (!pending) return false;\n\n clearSession();\n\n return true;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n clearSession();\n target.removeEventListener('pointerdown', onPointerDown);\n };\n\n const matchesPointer = (event: PointerEvent): boolean => {\n return (active ?? pending)?.pointerId === event.pointerId;\n };\n\n const startTracking = (): void => {\n ownerDocument.addEventListener('pointermove', onPointerMove, true);\n ownerDocument.addEventListener('pointerup', onPointerUp, true);\n ownerDocument.addEventListener('pointercancel', onPointerCancel, true);\n target.addEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const activate = (event: PointerEvent): boolean => {\n if (!pending) return false;\n\n const deltaX = event.clientX - pending.startX;\n const deltaY = event.clientY - pending.startY;\n const primaryDistance = pending.axis === 'x' ? Math.abs(deltaX) : Math.abs(deltaY);\n const crossDistance = pending.axis === 'x' ? Math.abs(deltaY) : Math.abs(deltaX);\n\n if (Math.max(primaryDistance, crossDistance) < ACTIVATION_DISTANCE) return false;\n\n if (crossDistance > primaryDistance) {\n clearSession();\n\n return false;\n }\n\n active = { ...pending, captured: false, event };\n pending = null;\n\n if (options.pointerCapture !== false && typeof target.setPointerCapture === 'function') {\n target.setPointerCapture(event.pointerId);\n active.captured = true;\n }\n\n const detail = createDetail(event);\n\n if (detail) options.onStart?.(detail);\n\n return active?.pointerId === event.pointerId;\n };\n\n const handlePointerDown = (event: PointerEvent): boolean => {\n if (disposed || pending || active || isDisabled()) return false;\n if (!isPrimaryPointer(event)) return false;\n if (options.shouldStart && !options.shouldStart(event)) return false;\n\n pending = {\n axis: read(options.axis, 'x'),\n event,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n startX: event.clientX,\n startY: event.clientY,\n };\n startTracking();\n\n return true;\n };\n\n const handlePointerMove = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (isDisabled()) {\n if (active) return finish(event, 'cancel');\n\n clearSession();\n\n return true;\n }\n\n if (!active && !activate(event)) return true;\n if (!active) return true;\n\n active.event = event;\n const detail = createDetail(event);\n\n if (detail) options.onMove?.(detail);\n\n return true;\n };\n\n const handlePointerUp = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, isDisabled() ? 'cancel' : 'release');\n };\n\n const handlePointerCancel = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, 'cancel');\n };\n\n const onPointerDown: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerDown(event);\n };\n\n const onPointerMove: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerMove(event);\n };\n\n const onPointerUp: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerUp(event);\n };\n\n const onPointerCancel: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n const onLostPointerCapture: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n target.addEventListener('pointerdown', onPointerDown);\n\n return {\n get active() {\n return active != null;\n },\n cancel,\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ var Gesture=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=6,n=(e,t)=>typeof e==`function`?e():e??t,r=e=>!(!e.isPrimary||e.pointerType===`mouse`&&e.button!==0),i=(e,t)=>t===`x`?e.clientX:e.clientY,a=(e,t)=>t===`x`?e.startX:e.startY;return e.createPanGesture=(e,o={})=>{let s=new AbortController,c=e.ownerDocument,l=null,u=null,d=!1,f=()=>!!n(o.disabled,!1),p=t=>{if(!u)return null;let n=a(u,u.axis),r=i(t,u.axis);return{axis:u.axis,current:r,distance:r-n,event:t,pointerId:u.pointerId,pointerType:u.pointerType,start:n,target:e}},m=()=>{c.removeEventListener(`pointermove`,O,!0),c.removeEventListener(`pointerup`,k,!0),c.removeEventListener(`pointercancel`,A,!0),e.removeEventListener(`lostpointercapture`,j)},h=t=>{!t.captured||typeof e.releasePointerCapture!=`function`||typeof e.hasPointerCapture==`function`&&!e.hasPointerCapture(t.pointerId)||e.releasePointerCapture(t.pointerId)},g=()=>{let e=u;l=null,u=null,m(),e&&h(e)},_=(e,t)=>{if(!u)return!1;u.event=e;let n=p(e);return g(),n&&o.onEnd?.({...n,reason:t}),!0},v=()=>u?_(u.event,`cancel`):l?(g(),!0):!1,y=()=>{d||(d=!0,s.abort(),g(),e.removeEventListener(`pointerdown`,D))},b=e=>(u??l)?.pointerId===e.pointerId,x=()=>{c.addEventListener(`pointermove`,O,!0),c.addEventListener(`pointerup`,k,!0),c.addEventListener(`pointercancel`,A,!0),e.addEventListener(`lostpointercapture`,j)},S=n=>{if(!l)return!1;let r=n.clientX-l.startX,i=n.clientY-l.startY,a=l.axis===`x`?Math.abs(r):Math.abs(i),s=l.axis===`x`?Math.abs(i):Math.abs(r);if(Math.max(a,s)<t)return!1;if(s>a)return g(),!1;u={...l,captured:!1,event:n},l=null,o.pointerCapture!==!1&&typeof e.setPointerCapture==`function`&&(e.setPointerCapture(n.pointerId),u.captured=!0);let c=p(n);return c&&o.onStart?.(c),u?.pointerId===n.pointerId},C=e=>d||l||u||f()||!r(e)||o.shouldStart&&!o.shouldStart(e)?!1:(l={axis:n(o.axis,`x`),event:e,pointerId:e.pointerId,pointerType:e.pointerType,startX:e.clientX,startY:e.clientY},x(),!0),w=e=>{if(!b(e))return!1;if(f())return u?_(e,`cancel`):(g(),!0);if(!u&&!S(e)||!u)return!0;u.event=e;let t=p(e);return t&&o.onMove?.(t),!0},T=e=>b(e)?u?_(e,f()?`cancel`:`release`):(g(),!0):!1,E=e=>b(e)?u?_(e,`cancel`):(g(),!0):!1,D=e=>{e instanceof PointerEvent&&C(e)},O=e=>{e instanceof PointerEvent&&w(e)},k=e=>{e instanceof PointerEvent&&T(e)},A=e=>{e instanceof PointerEvent&&E(e)},j=e=>{e instanceof PointerEvent&&E(e)};return e.addEventListener(`pointerdown`,D),{get active(){return u!=null},cancel:v,get disposalSignal(){return s.signal},dispose:y,get disposed(){return d},[Symbol.dispose]:y}},e})({});
2
+ //# sourceMappingURL=gesture.iife.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gesture.iife.js","names":[],"sources":["../src/pan-gesture.ts"],"sourcesContent":["export type PanAxis = 'x' | 'y';\n\nexport type PanEndReason = 'cancel' | 'release';\n\nexport type PanGestureDetail = {\n axis: PanAxis;\n current: number;\n distance: number;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n start: number;\n target: Element;\n};\n\nexport type PanGestureEndDetail = PanGestureDetail & {\n reason: PanEndReason;\n};\n\nexport type PanGestureOptions = {\n axis?: PanAxis | (() => PanAxis);\n disabled?: boolean | (() => boolean | undefined);\n onEnd?: (detail: PanGestureEndDetail) => void;\n onMove?: (detail: PanGestureDetail) => void;\n onStart?: (detail: PanGestureDetail) => void;\n pointerCapture?: boolean;\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\nexport type PanGesture = {\n readonly active: boolean;\n [Symbol.dispose](): void;\n cancel(): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n};\n\ntype PendingPan = {\n axis: PanAxis;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n startX: number;\n startY: number;\n};\n\ntype ActivePan = PendingPan & {\n captured: boolean;\n};\n\nconst ACTIVATION_DISTANCE = 6;\n\nconst read = <T>(value: T | (() => T) | undefined, fallback: T): T =>\n typeof value === 'function' ? (value as () => T)() : (value ?? fallback);\n\nconst isPrimaryPointer = (event: PointerEvent): boolean => {\n if (!event.isPrimary) return false;\n if (event.pointerType === 'mouse' && event.button !== 0) return false;\n\n return true;\n};\n\nconst getCoordinate = (event: PointerEvent, axis: PanAxis): number => {\n return axis === 'x' ? event.clientX : event.clientY;\n};\n\nconst getStartCoordinate = (pan: PendingPan, axis: PanAxis): number => {\n return axis === 'x' ? pan.startX : pan.startY;\n};\n\nexport const createPanGesture = (target: Element, options: PanGestureOptions = {}): PanGesture => {\n const disposalController = new AbortController();\n const ownerDocument = target.ownerDocument;\n let pending: PendingPan | null = null;\n let active: ActivePan | null = null;\n let disposed = false;\n\n const isDisabled = (): boolean => Boolean(read(options.disabled, false));\n\n const createDetail = (event: PointerEvent): PanGestureDetail | null => {\n if (!active) return null;\n\n const start = getStartCoordinate(active, active.axis);\n const current = getCoordinate(event, active.axis);\n\n return {\n axis: active.axis,\n current,\n distance: current - start,\n event,\n pointerId: active.pointerId,\n pointerType: active.pointerType,\n start,\n target,\n };\n };\n\n const removeTrackingListeners = (): void => {\n ownerDocument.removeEventListener('pointermove', onPointerMove, true);\n ownerDocument.removeEventListener('pointerup', onPointerUp, true);\n ownerDocument.removeEventListener('pointercancel', onPointerCancel, true);\n target.removeEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const releaseCapture = (pan: ActivePan): void => {\n if (!pan.captured || typeof target.releasePointerCapture !== 'function') return;\n if (typeof target.hasPointerCapture === 'function' && !target.hasPointerCapture(pan.pointerId)) return;\n\n target.releasePointerCapture(pan.pointerId);\n };\n\n const clearSession = (): void => {\n const previousActive = active;\n\n pending = null;\n active = null;\n removeTrackingListeners();\n\n if (previousActive) releaseCapture(previousActive);\n };\n\n const finish = (event: PointerEvent, reason: PanEndReason): boolean => {\n if (!active) return false;\n\n active.event = event;\n const detail = createDetail(event);\n\n clearSession();\n\n if (detail) options.onEnd?.({ ...detail, reason });\n\n return true;\n };\n\n const cancel = (): boolean => {\n if (active) return finish(active.event, 'cancel');\n if (!pending) return false;\n\n clearSession();\n\n return true;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n clearSession();\n target.removeEventListener('pointerdown', onPointerDown);\n };\n\n const matchesPointer = (event: PointerEvent): boolean => {\n return (active ?? pending)?.pointerId === event.pointerId;\n };\n\n const startTracking = (): void => {\n ownerDocument.addEventListener('pointermove', onPointerMove, true);\n ownerDocument.addEventListener('pointerup', onPointerUp, true);\n ownerDocument.addEventListener('pointercancel', onPointerCancel, true);\n target.addEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const activate = (event: PointerEvent): boolean => {\n if (!pending) return false;\n\n const deltaX = event.clientX - pending.startX;\n const deltaY = event.clientY - pending.startY;\n const primaryDistance = pending.axis === 'x' ? Math.abs(deltaX) : Math.abs(deltaY);\n const crossDistance = pending.axis === 'x' ? Math.abs(deltaY) : Math.abs(deltaX);\n\n if (Math.max(primaryDistance, crossDistance) < ACTIVATION_DISTANCE) return false;\n\n if (crossDistance > primaryDistance) {\n clearSession();\n\n return false;\n }\n\n active = { ...pending, captured: false, event };\n pending = null;\n\n if (options.pointerCapture !== false && typeof target.setPointerCapture === 'function') {\n target.setPointerCapture(event.pointerId);\n active.captured = true;\n }\n\n const detail = createDetail(event);\n\n if (detail) options.onStart?.(detail);\n\n return active?.pointerId === event.pointerId;\n };\n\n const handlePointerDown = (event: PointerEvent): boolean => {\n if (disposed || pending || active || isDisabled()) return false;\n if (!isPrimaryPointer(event)) return false;\n if (options.shouldStart && !options.shouldStart(event)) return false;\n\n pending = {\n axis: read(options.axis, 'x'),\n event,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n startX: event.clientX,\n startY: event.clientY,\n };\n startTracking();\n\n return true;\n };\n\n const handlePointerMove = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (isDisabled()) {\n if (active) return finish(event, 'cancel');\n\n clearSession();\n\n return true;\n }\n\n if (!active && !activate(event)) return true;\n if (!active) return true;\n\n active.event = event;\n const detail = createDetail(event);\n\n if (detail) options.onMove?.(detail);\n\n return true;\n };\n\n const handlePointerUp = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, isDisabled() ? 'cancel' : 'release');\n };\n\n const handlePointerCancel = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, 'cancel');\n };\n\n const onPointerDown: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerDown(event);\n };\n\n const onPointerMove: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerMove(event);\n };\n\n const onPointerUp: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerUp(event);\n };\n\n const onPointerCancel: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n const onLostPointerCapture: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n target.addEventListener('pointerdown', onPointerDown);\n\n return {\n get active() {\n return active != null;\n },\n cancel,\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ var e=(e,t)=>typeof e==`function`?e():e??t,t=e=>!(!e.isPrimary||e.pointerType===`mouse`&&e.button!==0),n=(e,t)=>t===`x`?e.clientX:e.clientY,r=(e,t)=>t===`x`?e.startX:e.startY,i=(i,a={})=>{let o=new AbortController,s=i.ownerDocument,c=null,l=null,u=!1,d=()=>!!e(a.disabled,!1),f=e=>{if(!l)return null;let t=r(l,l.axis),a=n(e,l.axis);return{axis:l.axis,current:a,distance:a-t,event:e,pointerId:l.pointerId,pointerType:l.pointerType,start:t,target:i}},p=()=>{s.removeEventListener(`pointermove`,D,!0),s.removeEventListener(`pointerup`,O,!0),s.removeEventListener(`pointercancel`,k,!0),i.removeEventListener(`lostpointercapture`,A)},m=e=>{!e.captured||typeof i.releasePointerCapture!=`function`||typeof i.hasPointerCapture==`function`&&!i.hasPointerCapture(e.pointerId)||i.releasePointerCapture(e.pointerId)},h=()=>{let e=l;c=null,l=null,p(),e&&m(e)},g=(e,t)=>{if(!l)return!1;l.event=e;let n=f(e);return h(),n&&a.onEnd?.({...n,reason:t}),!0},_=()=>l?g(l.event,`cancel`):c?(h(),!0):!1,v=()=>{u||(u=!0,o.abort(),h(),i.removeEventListener(`pointerdown`,E))},y=e=>(l??c)?.pointerId===e.pointerId,b=()=>{s.addEventListener(`pointermove`,D,!0),s.addEventListener(`pointerup`,O,!0),s.addEventListener(`pointercancel`,k,!0),i.addEventListener(`lostpointercapture`,A)},x=e=>{if(!c)return!1;let t=e.clientX-c.startX,n=e.clientY-c.startY,r=c.axis===`x`?Math.abs(t):Math.abs(n),o=c.axis===`x`?Math.abs(n):Math.abs(t);if(Math.max(r,o)<6)return!1;if(o>r)return h(),!1;l={...c,captured:!1,event:e},c=null,a.pointerCapture!==!1&&typeof i.setPointerCapture==`function`&&(i.setPointerCapture(e.pointerId),l.captured=!0);let s=f(e);return s&&a.onStart?.(s),l?.pointerId===e.pointerId},S=n=>u||c||l||d()||!t(n)||a.shouldStart&&!a.shouldStart(n)?!1:(c={axis:e(a.axis,`x`),event:n,pointerId:n.pointerId,pointerType:n.pointerType,startX:n.clientX,startY:n.clientY},b(),!0),C=e=>{if(!y(e))return!1;if(d())return l?g(e,`cancel`):(h(),!0);if(!l&&!x(e)||!l)return!0;l.event=e;let t=f(e);return t&&a.onMove?.(t),!0},w=e=>y(e)?l?g(e,d()?`cancel`:`release`):(h(),!0):!1,T=e=>y(e)?l?g(e,`cancel`):(h(),!0):!1,E=e=>{e instanceof PointerEvent&&S(e)},D=e=>{e instanceof PointerEvent&&C(e)},O=e=>{e instanceof PointerEvent&&w(e)},k=e=>{e instanceof PointerEvent&&T(e)},A=e=>{e instanceof PointerEvent&&T(e)};return i.addEventListener(`pointerdown`,E),{get active(){return l!=null},cancel:_,get disposalSignal(){return o.signal},dispose:v,get disposed(){return u},[Symbol.dispose]:v}};export{i as createPanGesture};
2
+ //# sourceMappingURL=gesture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gesture.js","names":[],"sources":["../src/pan-gesture.ts"],"sourcesContent":["export type PanAxis = 'x' | 'y';\n\nexport type PanEndReason = 'cancel' | 'release';\n\nexport type PanGestureDetail = {\n axis: PanAxis;\n current: number;\n distance: number;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n start: number;\n target: Element;\n};\n\nexport type PanGestureEndDetail = PanGestureDetail & {\n reason: PanEndReason;\n};\n\nexport type PanGestureOptions = {\n axis?: PanAxis | (() => PanAxis);\n disabled?: boolean | (() => boolean | undefined);\n onEnd?: (detail: PanGestureEndDetail) => void;\n onMove?: (detail: PanGestureDetail) => void;\n onStart?: (detail: PanGestureDetail) => void;\n pointerCapture?: boolean;\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\nexport type PanGesture = {\n readonly active: boolean;\n [Symbol.dispose](): void;\n cancel(): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n};\n\ntype PendingPan = {\n axis: PanAxis;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n startX: number;\n startY: number;\n};\n\ntype ActivePan = PendingPan & {\n captured: boolean;\n};\n\nconst ACTIVATION_DISTANCE = 6;\n\nconst read = <T>(value: T | (() => T) | undefined, fallback: T): T =>\n typeof value === 'function' ? (value as () => T)() : (value ?? fallback);\n\nconst isPrimaryPointer = (event: PointerEvent): boolean => {\n if (!event.isPrimary) return false;\n if (event.pointerType === 'mouse' && event.button !== 0) return false;\n\n return true;\n};\n\nconst getCoordinate = (event: PointerEvent, axis: PanAxis): number => {\n return axis === 'x' ? event.clientX : event.clientY;\n};\n\nconst getStartCoordinate = (pan: PendingPan, axis: PanAxis): number => {\n return axis === 'x' ? pan.startX : pan.startY;\n};\n\nexport const createPanGesture = (target: Element, options: PanGestureOptions = {}): PanGesture => {\n const disposalController = new AbortController();\n const ownerDocument = target.ownerDocument;\n let pending: PendingPan | null = null;\n let active: ActivePan | null = null;\n let disposed = false;\n\n const isDisabled = (): boolean => Boolean(read(options.disabled, false));\n\n const createDetail = (event: PointerEvent): PanGestureDetail | null => {\n if (!active) return null;\n\n const start = getStartCoordinate(active, active.axis);\n const current = getCoordinate(event, active.axis);\n\n return {\n axis: active.axis,\n current,\n distance: current - start,\n event,\n pointerId: active.pointerId,\n pointerType: active.pointerType,\n start,\n target,\n };\n };\n\n const removeTrackingListeners = (): void => {\n ownerDocument.removeEventListener('pointermove', onPointerMove, true);\n ownerDocument.removeEventListener('pointerup', onPointerUp, true);\n ownerDocument.removeEventListener('pointercancel', onPointerCancel, true);\n target.removeEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const releaseCapture = (pan: ActivePan): void => {\n if (!pan.captured || typeof target.releasePointerCapture !== 'function') return;\n if (typeof target.hasPointerCapture === 'function' && !target.hasPointerCapture(pan.pointerId)) return;\n\n target.releasePointerCapture(pan.pointerId);\n };\n\n const clearSession = (): void => {\n const previousActive = active;\n\n pending = null;\n active = null;\n removeTrackingListeners();\n\n if (previousActive) releaseCapture(previousActive);\n };\n\n const finish = (event: PointerEvent, reason: PanEndReason): boolean => {\n if (!active) return false;\n\n active.event = event;\n const detail = createDetail(event);\n\n clearSession();\n\n if (detail) options.onEnd?.({ ...detail, reason });\n\n return true;\n };\n\n const cancel = (): boolean => {\n if (active) return finish(active.event, 'cancel');\n if (!pending) return false;\n\n clearSession();\n\n return true;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n clearSession();\n target.removeEventListener('pointerdown', onPointerDown);\n };\n\n const matchesPointer = (event: PointerEvent): boolean => {\n return (active ?? pending)?.pointerId === event.pointerId;\n };\n\n const startTracking = (): void => {\n ownerDocument.addEventListener('pointermove', onPointerMove, true);\n ownerDocument.addEventListener('pointerup', onPointerUp, true);\n ownerDocument.addEventListener('pointercancel', onPointerCancel, true);\n target.addEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const activate = (event: PointerEvent): boolean => {\n if (!pending) return false;\n\n const deltaX = event.clientX - pending.startX;\n const deltaY = event.clientY - pending.startY;\n const primaryDistance = pending.axis === 'x' ? Math.abs(deltaX) : Math.abs(deltaY);\n const crossDistance = pending.axis === 'x' ? Math.abs(deltaY) : Math.abs(deltaX);\n\n if (Math.max(primaryDistance, crossDistance) < ACTIVATION_DISTANCE) return false;\n\n if (crossDistance > primaryDistance) {\n clearSession();\n\n return false;\n }\n\n active = { ...pending, captured: false, event };\n pending = null;\n\n if (options.pointerCapture !== false && typeof target.setPointerCapture === 'function') {\n target.setPointerCapture(event.pointerId);\n active.captured = true;\n }\n\n const detail = createDetail(event);\n\n if (detail) options.onStart?.(detail);\n\n return active?.pointerId === event.pointerId;\n };\n\n const handlePointerDown = (event: PointerEvent): boolean => {\n if (disposed || pending || active || isDisabled()) return false;\n if (!isPrimaryPointer(event)) return false;\n if (options.shouldStart && !options.shouldStart(event)) return false;\n\n pending = {\n axis: read(options.axis, 'x'),\n event,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n startX: event.clientX,\n startY: event.clientY,\n };\n startTracking();\n\n return true;\n };\n\n const handlePointerMove = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (isDisabled()) {\n if (active) return finish(event, 'cancel');\n\n clearSession();\n\n return true;\n }\n\n if (!active && !activate(event)) return true;\n if (!active) return true;\n\n active.event = event;\n const detail = createDetail(event);\n\n if (detail) options.onMove?.(detail);\n\n return true;\n };\n\n const handlePointerUp = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, isDisabled() ? 'cancel' : 'release');\n };\n\n const handlePointerCancel = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, 'cancel');\n };\n\n const onPointerDown: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerDown(event);\n };\n\n const onPointerMove: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerMove(event);\n };\n\n const onPointerUp: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerUp(event);\n };\n\n const onPointerCancel: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n const onLostPointerCapture: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n target.addEventListener('pointerdown', onPointerDown);\n\n return {\n get active() {\n return active != null;\n },\n cancel,\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"AAmDA,IAEM,GAAW,EAAkC,IACjD,OAAO,GAAU,WAAc,EAAkB,EAAK,GAAS,EAE3D,EAAoB,GAExB,EADI,CAAC,EAAM,WACP,EAAM,cAAgB,SAAW,EAAM,SAAW,GAKlD,GAAiB,EAAqB,IACnC,IAAS,IAAM,EAAM,QAAU,EAAM,QAGxC,GAAsB,EAAiB,IACpC,IAAS,IAAM,EAAI,OAAS,EAAI,OAG5B,GAAoB,EAAiB,EAA6B,CAAC,IAAkB,CAChG,IAAM,EAAqB,IAAI,gBACzB,EAAgB,EAAO,cACzB,EAA6B,KAC7B,EAA2B,KAC3B,EAAW,GAET,MAA4B,EAAQ,EAAK,EAAQ,SAAU,EAAK,EAEhE,EAAgB,GAAiD,CACrE,GAAI,CAAC,EAAQ,OAAO,KAEpB,IAAM,EAAQ,EAAmB,EAAQ,EAAO,IAAI,EAC9C,EAAU,EAAc,EAAO,EAAO,IAAI,EAEhD,MAAO,CACL,KAAM,EAAO,KACb,UACA,SAAU,EAAU,EACpB,QACA,UAAW,EAAO,UAClB,YAAa,EAAO,YACpB,QACA,QACF,CACF,EAEM,MAAsC,CAC1C,EAAc,oBAAoB,cAAe,EAAe,EAAI,EACpE,EAAc,oBAAoB,YAAa,EAAa,EAAI,EAChE,EAAc,oBAAoB,gBAAiB,EAAiB,EAAI,EACxE,EAAO,oBAAoB,qBAAsB,CAAoB,CACvE,EAEM,EAAkB,GAAyB,CAC3C,CAAC,EAAI,UAAY,OAAO,EAAO,uBAA0B,YACzD,OAAO,EAAO,mBAAsB,YAAc,CAAC,EAAO,kBAAkB,EAAI,SAAS,GAE7F,EAAO,sBAAsB,EAAI,SAAS,CAC5C,EAEM,MAA2B,CAC/B,IAAM,EAAiB,EAEvB,EAAU,KACV,EAAS,KACT,EAAwB,EAEpB,GAAgB,EAAe,CAAc,CACnD,EAEM,GAAU,EAAqB,IAAkC,CACrE,GAAI,CAAC,EAAQ,MAAO,GAEpB,EAAO,MAAQ,EACf,IAAM,EAAS,EAAa,CAAK,EAMjC,OAJA,EAAa,EAET,GAAQ,EAAQ,QAAQ,CAAE,GAAG,EAAQ,QAAO,CAAC,EAE1C,EACT,EAEM,MACA,EAAe,EAAO,EAAO,MAAO,QAAQ,EAC3C,GAEL,EAAa,EAEN,IAJc,GAOjB,MAAsB,CACtB,IAEJ,EAAW,GACX,EAAmB,MAAM,EACzB,EAAa,EACb,EAAO,oBAAoB,cAAe,CAAa,EACzD,EAEM,EAAkB,IACd,GAAU,EAAA,EAAU,YAAc,EAAM,UAG5C,MAA4B,CAChC,EAAc,iBAAiB,cAAe,EAAe,EAAI,EACjE,EAAc,iBAAiB,YAAa,EAAa,EAAI,EAC7D,EAAc,iBAAiB,gBAAiB,EAAiB,EAAI,EACrE,EAAO,iBAAiB,qBAAsB,CAAoB,CACpE,EAEM,EAAY,GAAiC,CACjD,GAAI,CAAC,EAAS,MAAO,GAErB,IAAM,EAAS,EAAM,QAAU,EAAQ,OACjC,EAAS,EAAM,QAAU,EAAQ,OACjC,EAAkB,EAAQ,OAAS,IAAM,KAAK,IAAI,CAAM,EAAI,KAAK,IAAI,CAAM,EAC3E,EAAgB,EAAQ,OAAS,IAAM,KAAK,IAAI,CAAM,EAAI,KAAK,IAAI,CAAM,EAE/E,GAAI,KAAK,IAAI,EAAiB,CAAa,EAAI,EAAqB,MAAO,GAE3E,GAAI,EAAgB,EAGlB,OAFA,EAAa,EAEN,GAGT,EAAS,CAAE,GAAG,EAAS,SAAU,GAAO,OAAM,EAC9C,EAAU,KAEN,EAAQ,iBAAmB,IAAS,OAAO,EAAO,mBAAsB,aAC1E,EAAO,kBAAkB,EAAM,SAAS,EACxC,EAAO,SAAW,IAGpB,IAAM,EAAS,EAAa,CAAK,EAIjC,OAFI,GAAQ,EAAQ,UAAU,CAAM,EAE7B,GAAQ,YAAc,EAAM,SACrC,EAEM,EAAqB,GACrB,GAAY,GAAW,GAAU,EAAW,GAC5C,CAAC,EAAiB,CAAK,GACvB,EAAQ,aAAe,CAAC,EAAQ,YAAY,CAAK,EAAU,IAE/D,EAAU,CACR,KAAM,EAAK,EAAQ,KAAM,GAAG,EAC5B,QACA,UAAW,EAAM,UACjB,YAAa,EAAM,YACnB,OAAQ,EAAM,QACd,OAAQ,EAAM,OAChB,EACA,EAAc,EAEP,IAGH,EAAqB,GAAiC,CAC1D,GAAI,CAAC,EAAe,CAAK,EAAG,MAAO,GAEnC,GAAI,EAAW,EAKb,OAJI,EAAe,EAAO,EAAO,QAAQ,GAEzC,EAAa,EAEN,IAIT,GADI,CAAC,GAAU,CAAC,EAAS,CAAK,GAC1B,CAAC,EAAQ,MAAO,GAEpB,EAAO,MAAQ,EACf,IAAM,EAAS,EAAa,CAAK,EAIjC,OAFI,GAAQ,EAAQ,SAAS,CAAM,EAE5B,EACT,EAEM,EAAmB,GAClB,EAAe,CAAK,EAEpB,EAME,EAAO,EAAO,EAAW,EAAI,SAAW,SAAS,GALtD,EAAa,EAEN,IAL0B,GAW/B,EAAuB,GACtB,EAAe,CAAK,EAEpB,EAME,EAAO,EAAO,QAAQ,GAL3B,EAAa,EAEN,IAL0B,GAW/B,EAAgC,GAAU,CAC1C,aAAiB,cAAc,EAAkB,CAAK,CAC5D,EAEM,EAAgC,GAAU,CAC1C,aAAiB,cAAc,EAAkB,CAAK,CAC5D,EAEM,EAA8B,GAAU,CACxC,aAAiB,cAAc,EAAgB,CAAK,CAC1D,EAEM,EAAkC,GAAU,CAC5C,aAAiB,cAAc,EAAoB,CAAK,CAC9D,EAEM,EAAuC,GAAU,CACjD,aAAiB,cAAc,EAAoB,CAAK,CAC9D,EAIA,OAFA,EAAO,iBAAiB,cAAe,CAAa,EAE7C,CACL,IAAI,QAAS,CACX,OAAO,GAAU,IACnB,EACA,SACA,IAAI,gBAAiB,CACnB,OAAO,EAAmB,MAC5B,EACA,UACA,IAAI,UAAW,CACb,OAAO,CACT,GACC,OAAO,SAAU,CACpB,CACF"}
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./pan-gesture.cjs");exports.createPanGesture=e.createPanGesture;
@@ -0,0 +1,3 @@
1
+ export type { PanAxis, PanEndReason, PanGesture, PanGestureDetail, PanGestureEndDetail, PanGestureOptions, } from './pan-gesture';
2
+ export { createPanGesture } from './pan-gesture';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { createPanGesture as e } from "./pan-gesture.js";
2
+ export { e as createPanGesture };
@@ -0,0 +1,2 @@
1
+ var e=(e,t)=>typeof e==`function`?e():e??t,t=e=>!(!e.isPrimary||e.pointerType===`mouse`&&e.button!==0),n=(e,t)=>t===`x`?e.clientX:e.clientY,r=(e,t)=>t===`x`?e.startX:e.startY,i=(i,a={})=>{let o=new AbortController,s=i.ownerDocument,c=null,l=null,u=!1,d=()=>!!e(a.disabled,!1),f=e=>{if(!l)return null;let t=r(l,l.axis),a=n(e,l.axis);return{axis:l.axis,current:a,distance:a-t,event:e,pointerId:l.pointerId,pointerType:l.pointerType,start:t,target:i}},p=()=>{s.removeEventListener(`pointermove`,D,!0),s.removeEventListener(`pointerup`,O,!0),s.removeEventListener(`pointercancel`,k,!0),i.removeEventListener(`lostpointercapture`,A)},m=e=>{!e.captured||typeof i.releasePointerCapture!=`function`||typeof i.hasPointerCapture==`function`&&!i.hasPointerCapture(e.pointerId)||i.releasePointerCapture(e.pointerId)},h=()=>{let e=l;c=null,l=null,p(),e&&m(e)},g=(e,t)=>{if(!l)return!1;l.event=e;let n=f(e);return h(),n&&a.onEnd?.({...n,reason:t}),!0},_=()=>l?g(l.event,`cancel`):c?(h(),!0):!1,v=()=>{u||(u=!0,o.abort(),h(),i.removeEventListener(`pointerdown`,E))},y=e=>(l??c)?.pointerId===e.pointerId,b=()=>{s.addEventListener(`pointermove`,D,!0),s.addEventListener(`pointerup`,O,!0),s.addEventListener(`pointercancel`,k,!0),i.addEventListener(`lostpointercapture`,A)},x=e=>{if(!c)return!1;let t=e.clientX-c.startX,n=e.clientY-c.startY,r=c.axis===`x`?Math.abs(t):Math.abs(n),o=c.axis===`x`?Math.abs(n):Math.abs(t);if(Math.max(r,o)<6)return!1;if(o>r)return h(),!1;l={...c,captured:!1,event:e},c=null,a.pointerCapture!==!1&&typeof i.setPointerCapture==`function`&&(i.setPointerCapture(e.pointerId),l.captured=!0);let s=f(e);return s&&a.onStart?.(s),l?.pointerId===e.pointerId},S=n=>u||c||l||d()||!t(n)||a.shouldStart&&!a.shouldStart(n)?!1:(c={axis:e(a.axis,`x`),event:n,pointerId:n.pointerId,pointerType:n.pointerType,startX:n.clientX,startY:n.clientY},b(),!0),C=e=>{if(!y(e))return!1;if(d())return l?g(e,`cancel`):(h(),!0);if(!l&&!x(e)||!l)return!0;l.event=e;let t=f(e);return t&&a.onMove?.(t),!0},w=e=>y(e)?l?g(e,d()?`cancel`:`release`):(h(),!0):!1,T=e=>y(e)?l?g(e,`cancel`):(h(),!0):!1,E=e=>{e instanceof PointerEvent&&S(e)},D=e=>{e instanceof PointerEvent&&C(e)},O=e=>{e instanceof PointerEvent&&w(e)},k=e=>{e instanceof PointerEvent&&T(e)},A=e=>{e instanceof PointerEvent&&T(e)};return i.addEventListener(`pointerdown`,E),{get active(){return l!=null},cancel:_,get disposalSignal(){return o.signal},dispose:v,get disposed(){return u},[Symbol.dispose]:v}};exports.createPanGesture=i;
2
+ //# sourceMappingURL=pan-gesture.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pan-gesture.cjs","names":[],"sources":["../src/pan-gesture.ts"],"sourcesContent":["export type PanAxis = 'x' | 'y';\n\nexport type PanEndReason = 'cancel' | 'release';\n\nexport type PanGestureDetail = {\n axis: PanAxis;\n current: number;\n distance: number;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n start: number;\n target: Element;\n};\n\nexport type PanGestureEndDetail = PanGestureDetail & {\n reason: PanEndReason;\n};\n\nexport type PanGestureOptions = {\n axis?: PanAxis | (() => PanAxis);\n disabled?: boolean | (() => boolean | undefined);\n onEnd?: (detail: PanGestureEndDetail) => void;\n onMove?: (detail: PanGestureDetail) => void;\n onStart?: (detail: PanGestureDetail) => void;\n pointerCapture?: boolean;\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\nexport type PanGesture = {\n readonly active: boolean;\n [Symbol.dispose](): void;\n cancel(): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n};\n\ntype PendingPan = {\n axis: PanAxis;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n startX: number;\n startY: number;\n};\n\ntype ActivePan = PendingPan & {\n captured: boolean;\n};\n\nconst ACTIVATION_DISTANCE = 6;\n\nconst read = <T>(value: T | (() => T) | undefined, fallback: T): T =>\n typeof value === 'function' ? (value as () => T)() : (value ?? fallback);\n\nconst isPrimaryPointer = (event: PointerEvent): boolean => {\n if (!event.isPrimary) return false;\n if (event.pointerType === 'mouse' && event.button !== 0) return false;\n\n return true;\n};\n\nconst getCoordinate = (event: PointerEvent, axis: PanAxis): number => {\n return axis === 'x' ? event.clientX : event.clientY;\n};\n\nconst getStartCoordinate = (pan: PendingPan, axis: PanAxis): number => {\n return axis === 'x' ? pan.startX : pan.startY;\n};\n\nexport const createPanGesture = (target: Element, options: PanGestureOptions = {}): PanGesture => {\n const disposalController = new AbortController();\n const ownerDocument = target.ownerDocument;\n let pending: PendingPan | null = null;\n let active: ActivePan | null = null;\n let disposed = false;\n\n const isDisabled = (): boolean => Boolean(read(options.disabled, false));\n\n const createDetail = (event: PointerEvent): PanGestureDetail | null => {\n if (!active) return null;\n\n const start = getStartCoordinate(active, active.axis);\n const current = getCoordinate(event, active.axis);\n\n return {\n axis: active.axis,\n current,\n distance: current - start,\n event,\n pointerId: active.pointerId,\n pointerType: active.pointerType,\n start,\n target,\n };\n };\n\n const removeTrackingListeners = (): void => {\n ownerDocument.removeEventListener('pointermove', onPointerMove, true);\n ownerDocument.removeEventListener('pointerup', onPointerUp, true);\n ownerDocument.removeEventListener('pointercancel', onPointerCancel, true);\n target.removeEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const releaseCapture = (pan: ActivePan): void => {\n if (!pan.captured || typeof target.releasePointerCapture !== 'function') return;\n if (typeof target.hasPointerCapture === 'function' && !target.hasPointerCapture(pan.pointerId)) return;\n\n target.releasePointerCapture(pan.pointerId);\n };\n\n const clearSession = (): void => {\n const previousActive = active;\n\n pending = null;\n active = null;\n removeTrackingListeners();\n\n if (previousActive) releaseCapture(previousActive);\n };\n\n const finish = (event: PointerEvent, reason: PanEndReason): boolean => {\n if (!active) return false;\n\n active.event = event;\n const detail = createDetail(event);\n\n clearSession();\n\n if (detail) options.onEnd?.({ ...detail, reason });\n\n return true;\n };\n\n const cancel = (): boolean => {\n if (active) return finish(active.event, 'cancel');\n if (!pending) return false;\n\n clearSession();\n\n return true;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n clearSession();\n target.removeEventListener('pointerdown', onPointerDown);\n };\n\n const matchesPointer = (event: PointerEvent): boolean => {\n return (active ?? pending)?.pointerId === event.pointerId;\n };\n\n const startTracking = (): void => {\n ownerDocument.addEventListener('pointermove', onPointerMove, true);\n ownerDocument.addEventListener('pointerup', onPointerUp, true);\n ownerDocument.addEventListener('pointercancel', onPointerCancel, true);\n target.addEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const activate = (event: PointerEvent): boolean => {\n if (!pending) return false;\n\n const deltaX = event.clientX - pending.startX;\n const deltaY = event.clientY - pending.startY;\n const primaryDistance = pending.axis === 'x' ? Math.abs(deltaX) : Math.abs(deltaY);\n const crossDistance = pending.axis === 'x' ? Math.abs(deltaY) : Math.abs(deltaX);\n\n if (Math.max(primaryDistance, crossDistance) < ACTIVATION_DISTANCE) return false;\n\n if (crossDistance > primaryDistance) {\n clearSession();\n\n return false;\n }\n\n active = { ...pending, captured: false, event };\n pending = null;\n\n if (options.pointerCapture !== false && typeof target.setPointerCapture === 'function') {\n target.setPointerCapture(event.pointerId);\n active.captured = true;\n }\n\n const detail = createDetail(event);\n\n if (detail) options.onStart?.(detail);\n\n return active?.pointerId === event.pointerId;\n };\n\n const handlePointerDown = (event: PointerEvent): boolean => {\n if (disposed || pending || active || isDisabled()) return false;\n if (!isPrimaryPointer(event)) return false;\n if (options.shouldStart && !options.shouldStart(event)) return false;\n\n pending = {\n axis: read(options.axis, 'x'),\n event,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n startX: event.clientX,\n startY: event.clientY,\n };\n startTracking();\n\n return true;\n };\n\n const handlePointerMove = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (isDisabled()) {\n if (active) return finish(event, 'cancel');\n\n clearSession();\n\n return true;\n }\n\n if (!active && !activate(event)) return true;\n if (!active) return true;\n\n active.event = event;\n const detail = createDetail(event);\n\n if (detail) options.onMove?.(detail);\n\n return true;\n };\n\n const handlePointerUp = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, isDisabled() ? 'cancel' : 'release');\n };\n\n const handlePointerCancel = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, 'cancel');\n };\n\n const onPointerDown: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerDown(event);\n };\n\n const onPointerMove: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerMove(event);\n };\n\n const onPointerUp: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerUp(event);\n };\n\n const onPointerCancel: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n const onLostPointerCapture: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n target.addEventListener('pointerdown', onPointerDown);\n\n return {\n get active() {\n return active != null;\n },\n cancel,\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export type PanAxis = 'x' | 'y';
2
+ export type PanEndReason = 'cancel' | 'release';
3
+ export type PanGestureDetail = {
4
+ axis: PanAxis;
5
+ current: number;
6
+ distance: number;
7
+ event: PointerEvent;
8
+ pointerId: number;
9
+ pointerType: string;
10
+ start: number;
11
+ target: Element;
12
+ };
13
+ export type PanGestureEndDetail = PanGestureDetail & {
14
+ reason: PanEndReason;
15
+ };
16
+ export type PanGestureOptions = {
17
+ axis?: PanAxis | (() => PanAxis);
18
+ disabled?: boolean | (() => boolean | undefined);
19
+ onEnd?: (detail: PanGestureEndDetail) => void;
20
+ onMove?: (detail: PanGestureDetail) => void;
21
+ onStart?: (detail: PanGestureDetail) => void;
22
+ pointerCapture?: boolean;
23
+ shouldStart?: (event: PointerEvent) => boolean;
24
+ };
25
+ export type PanGesture = {
26
+ readonly active: boolean;
27
+ [Symbol.dispose](): void;
28
+ cancel(): boolean;
29
+ readonly disposalSignal: AbortSignal;
30
+ dispose(): void;
31
+ readonly disposed: boolean;
32
+ };
33
+ export declare const createPanGesture: (target: Element, options?: PanGestureOptions) => PanGesture;
34
+ //# sourceMappingURL=pan-gesture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pan-gesture.d.ts","sourceRoot":"","sources":["../src/pan-gesture.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC;AAEhC,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG;IACnD,MAAM,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC9C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,MAAM,IAAI,OAAO,CAAC;IAClB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,CAAC;AAmCF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,EAAE,UAAS,iBAAsB,KAAG,UAgOnF,CAAC"}
@@ -0,0 +1,90 @@
1
+ //#region src/pan-gesture.ts
2
+ var e = (e, t) => typeof e == "function" ? e() : e ?? t, t = (e) => !(!e.isPrimary || e.pointerType === "mouse" && e.button !== 0), n = (e, t) => t === "x" ? e.clientX : e.clientY, r = (e, t) => t === "x" ? e.startX : e.startY, i = (i, a = {}) => {
3
+ let o = new AbortController(), s = i.ownerDocument, c = null, l = null, u = !1, d = () => !!e(a.disabled, !1), f = (e) => {
4
+ if (!l) return null;
5
+ let t = r(l, l.axis), a = n(e, l.axis);
6
+ return {
7
+ axis: l.axis,
8
+ current: a,
9
+ distance: a - t,
10
+ event: e,
11
+ pointerId: l.pointerId,
12
+ pointerType: l.pointerType,
13
+ start: t,
14
+ target: i
15
+ };
16
+ }, p = () => {
17
+ s.removeEventListener("pointermove", D, !0), s.removeEventListener("pointerup", O, !0), s.removeEventListener("pointercancel", k, !0), i.removeEventListener("lostpointercapture", A);
18
+ }, m = (e) => {
19
+ !e.captured || typeof i.releasePointerCapture != "function" || typeof i.hasPointerCapture == "function" && !i.hasPointerCapture(e.pointerId) || i.releasePointerCapture(e.pointerId);
20
+ }, h = () => {
21
+ let e = l;
22
+ c = null, l = null, p(), e && m(e);
23
+ }, g = (e, t) => {
24
+ if (!l) return !1;
25
+ l.event = e;
26
+ let n = f(e);
27
+ return h(), n && a.onEnd?.({
28
+ ...n,
29
+ reason: t
30
+ }), !0;
31
+ }, _ = () => l ? g(l.event, "cancel") : c ? (h(), !0) : !1, v = () => {
32
+ u || (u = !0, o.abort(), h(), i.removeEventListener("pointerdown", E));
33
+ }, y = (e) => (l ?? c)?.pointerId === e.pointerId, b = () => {
34
+ s.addEventListener("pointermove", D, !0), s.addEventListener("pointerup", O, !0), s.addEventListener("pointercancel", k, !0), i.addEventListener("lostpointercapture", A);
35
+ }, x = (e) => {
36
+ if (!c) return !1;
37
+ let t = e.clientX - c.startX, n = e.clientY - c.startY, r = c.axis === "x" ? Math.abs(t) : Math.abs(n), o = c.axis === "x" ? Math.abs(n) : Math.abs(t);
38
+ if (Math.max(r, o) < 6) return !1;
39
+ if (o > r) return h(), !1;
40
+ l = {
41
+ ...c,
42
+ captured: !1,
43
+ event: e
44
+ }, c = null, a.pointerCapture !== !1 && typeof i.setPointerCapture == "function" && (i.setPointerCapture(e.pointerId), l.captured = !0);
45
+ let s = f(e);
46
+ return s && a.onStart?.(s), l?.pointerId === e.pointerId;
47
+ }, S = (n) => u || c || l || d() || !t(n) || a.shouldStart && !a.shouldStart(n) ? !1 : (c = {
48
+ axis: e(a.axis, "x"),
49
+ event: n,
50
+ pointerId: n.pointerId,
51
+ pointerType: n.pointerType,
52
+ startX: n.clientX,
53
+ startY: n.clientY
54
+ }, b(), !0), C = (e) => {
55
+ if (!y(e)) return !1;
56
+ if (d()) return l ? g(e, "cancel") : (h(), !0);
57
+ if (!l && !x(e) || !l) return !0;
58
+ l.event = e;
59
+ let t = f(e);
60
+ return t && a.onMove?.(t), !0;
61
+ }, w = (e) => y(e) ? l ? g(e, d() ? "cancel" : "release") : (h(), !0) : !1, T = (e) => y(e) ? l ? g(e, "cancel") : (h(), !0) : !1, E = (e) => {
62
+ e instanceof PointerEvent && S(e);
63
+ }, D = (e) => {
64
+ e instanceof PointerEvent && C(e);
65
+ }, O = (e) => {
66
+ e instanceof PointerEvent && w(e);
67
+ }, k = (e) => {
68
+ e instanceof PointerEvent && T(e);
69
+ }, A = (e) => {
70
+ e instanceof PointerEvent && T(e);
71
+ };
72
+ return i.addEventListener("pointerdown", E), {
73
+ get active() {
74
+ return l != null;
75
+ },
76
+ cancel: _,
77
+ get disposalSignal() {
78
+ return o.signal;
79
+ },
80
+ dispose: v,
81
+ get disposed() {
82
+ return u;
83
+ },
84
+ [Symbol.dispose]: v
85
+ };
86
+ };
87
+ //#endregion
88
+ export { i as createPanGesture };
89
+
90
+ //# sourceMappingURL=pan-gesture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pan-gesture.js","names":[],"sources":["../src/pan-gesture.ts"],"sourcesContent":["export type PanAxis = 'x' | 'y';\n\nexport type PanEndReason = 'cancel' | 'release';\n\nexport type PanGestureDetail = {\n axis: PanAxis;\n current: number;\n distance: number;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n start: number;\n target: Element;\n};\n\nexport type PanGestureEndDetail = PanGestureDetail & {\n reason: PanEndReason;\n};\n\nexport type PanGestureOptions = {\n axis?: PanAxis | (() => PanAxis);\n disabled?: boolean | (() => boolean | undefined);\n onEnd?: (detail: PanGestureEndDetail) => void;\n onMove?: (detail: PanGestureDetail) => void;\n onStart?: (detail: PanGestureDetail) => void;\n pointerCapture?: boolean;\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\nexport type PanGesture = {\n readonly active: boolean;\n [Symbol.dispose](): void;\n cancel(): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n};\n\ntype PendingPan = {\n axis: PanAxis;\n event: PointerEvent;\n pointerId: number;\n pointerType: string;\n startX: number;\n startY: number;\n};\n\ntype ActivePan = PendingPan & {\n captured: boolean;\n};\n\nconst ACTIVATION_DISTANCE = 6;\n\nconst read = <T>(value: T | (() => T) | undefined, fallback: T): T =>\n typeof value === 'function' ? (value as () => T)() : (value ?? fallback);\n\nconst isPrimaryPointer = (event: PointerEvent): boolean => {\n if (!event.isPrimary) return false;\n if (event.pointerType === 'mouse' && event.button !== 0) return false;\n\n return true;\n};\n\nconst getCoordinate = (event: PointerEvent, axis: PanAxis): number => {\n return axis === 'x' ? event.clientX : event.clientY;\n};\n\nconst getStartCoordinate = (pan: PendingPan, axis: PanAxis): number => {\n return axis === 'x' ? pan.startX : pan.startY;\n};\n\nexport const createPanGesture = (target: Element, options: PanGestureOptions = {}): PanGesture => {\n const disposalController = new AbortController();\n const ownerDocument = target.ownerDocument;\n let pending: PendingPan | null = null;\n let active: ActivePan | null = null;\n let disposed = false;\n\n const isDisabled = (): boolean => Boolean(read(options.disabled, false));\n\n const createDetail = (event: PointerEvent): PanGestureDetail | null => {\n if (!active) return null;\n\n const start = getStartCoordinate(active, active.axis);\n const current = getCoordinate(event, active.axis);\n\n return {\n axis: active.axis,\n current,\n distance: current - start,\n event,\n pointerId: active.pointerId,\n pointerType: active.pointerType,\n start,\n target,\n };\n };\n\n const removeTrackingListeners = (): void => {\n ownerDocument.removeEventListener('pointermove', onPointerMove, true);\n ownerDocument.removeEventListener('pointerup', onPointerUp, true);\n ownerDocument.removeEventListener('pointercancel', onPointerCancel, true);\n target.removeEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const releaseCapture = (pan: ActivePan): void => {\n if (!pan.captured || typeof target.releasePointerCapture !== 'function') return;\n if (typeof target.hasPointerCapture === 'function' && !target.hasPointerCapture(pan.pointerId)) return;\n\n target.releasePointerCapture(pan.pointerId);\n };\n\n const clearSession = (): void => {\n const previousActive = active;\n\n pending = null;\n active = null;\n removeTrackingListeners();\n\n if (previousActive) releaseCapture(previousActive);\n };\n\n const finish = (event: PointerEvent, reason: PanEndReason): boolean => {\n if (!active) return false;\n\n active.event = event;\n const detail = createDetail(event);\n\n clearSession();\n\n if (detail) options.onEnd?.({ ...detail, reason });\n\n return true;\n };\n\n const cancel = (): boolean => {\n if (active) return finish(active.event, 'cancel');\n if (!pending) return false;\n\n clearSession();\n\n return true;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n clearSession();\n target.removeEventListener('pointerdown', onPointerDown);\n };\n\n const matchesPointer = (event: PointerEvent): boolean => {\n return (active ?? pending)?.pointerId === event.pointerId;\n };\n\n const startTracking = (): void => {\n ownerDocument.addEventListener('pointermove', onPointerMove, true);\n ownerDocument.addEventListener('pointerup', onPointerUp, true);\n ownerDocument.addEventListener('pointercancel', onPointerCancel, true);\n target.addEventListener('lostpointercapture', onLostPointerCapture);\n };\n\n const activate = (event: PointerEvent): boolean => {\n if (!pending) return false;\n\n const deltaX = event.clientX - pending.startX;\n const deltaY = event.clientY - pending.startY;\n const primaryDistance = pending.axis === 'x' ? Math.abs(deltaX) : Math.abs(deltaY);\n const crossDistance = pending.axis === 'x' ? Math.abs(deltaY) : Math.abs(deltaX);\n\n if (Math.max(primaryDistance, crossDistance) < ACTIVATION_DISTANCE) return false;\n\n if (crossDistance > primaryDistance) {\n clearSession();\n\n return false;\n }\n\n active = { ...pending, captured: false, event };\n pending = null;\n\n if (options.pointerCapture !== false && typeof target.setPointerCapture === 'function') {\n target.setPointerCapture(event.pointerId);\n active.captured = true;\n }\n\n const detail = createDetail(event);\n\n if (detail) options.onStart?.(detail);\n\n return active?.pointerId === event.pointerId;\n };\n\n const handlePointerDown = (event: PointerEvent): boolean => {\n if (disposed || pending || active || isDisabled()) return false;\n if (!isPrimaryPointer(event)) return false;\n if (options.shouldStart && !options.shouldStart(event)) return false;\n\n pending = {\n axis: read(options.axis, 'x'),\n event,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n startX: event.clientX,\n startY: event.clientY,\n };\n startTracking();\n\n return true;\n };\n\n const handlePointerMove = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (isDisabled()) {\n if (active) return finish(event, 'cancel');\n\n clearSession();\n\n return true;\n }\n\n if (!active && !activate(event)) return true;\n if (!active) return true;\n\n active.event = event;\n const detail = createDetail(event);\n\n if (detail) options.onMove?.(detail);\n\n return true;\n };\n\n const handlePointerUp = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, isDisabled() ? 'cancel' : 'release');\n };\n\n const handlePointerCancel = (event: PointerEvent): boolean => {\n if (!matchesPointer(event)) return false;\n\n if (!active) {\n clearSession();\n\n return true;\n }\n\n return finish(event, 'cancel');\n };\n\n const onPointerDown: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerDown(event);\n };\n\n const onPointerMove: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerMove(event);\n };\n\n const onPointerUp: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerUp(event);\n };\n\n const onPointerCancel: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n const onLostPointerCapture: EventListener = (event) => {\n if (event instanceof PointerEvent) handlePointerCancel(event);\n };\n\n target.addEventListener('pointerdown', onPointerDown);\n\n return {\n get active() {\n return active != null;\n },\n cancel,\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@vielzeug/gesture",
3
+ "version": "1.1.0",
4
+ "description": "Framework-neutral one-axis pointer pan recognition with lifecycle-owned handles",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/helmuthdu/vielzeug",
8
+ "directory": "packages/gesture"
9
+ },
10
+ "type": "module",
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.js",
19
+ "types": "dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs",
24
+ "types": "./dist/index.d.ts"
25
+ }
26
+ },
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "registry": "https://registry.npmjs.org/"
30
+ },
31
+ "scripts": {
32
+ "build": "vite build && pnpm run build:bundle && pnpm run build:types",
33
+ "build:bundle": "vite build --config vite.bundle.config.ts",
34
+ "build:types": "tsc -p tsconfig.declarations.json",
35
+ "fix": "biome check --write src",
36
+ "lint": "biome ci src",
37
+ "prepublishOnly": "pnpm run build",
38
+ "test": "vitest"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^26.2.0",
42
+ "typescript": "^6.0.3",
43
+ "vite": "^8.2.1",
44
+ "vitest": "^4.1.10"
45
+ }
46
+ }