snap-dnd 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/behaviors/AutoScroll.d.ts +20 -0
- package/dist/behaviors/ConstraintAxis.d.ts +37 -0
- package/dist/behaviors/SnapGrid.d.ts +38 -0
- package/dist/behaviors/index.d.ts +3 -0
- package/dist/core/DragEngine.d.ts +60 -0
- package/dist/core/DragState.d.ts +67 -0
- package/dist/core/DropZone.d.ts +97 -0
- package/dist/core/Snap.d.ts +85 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/index.d.ts +62 -0
- package/dist/plugins/FileDrop.d.ts +33 -0
- package/dist/plugins/Kanban.d.ts +40 -0
- package/dist/plugins/Sortable.d.ts +33 -0
- package/dist/plugins/index.d.ts +3 -0
- package/dist/sensors/FileSensor.d.ts +51 -0
- package/dist/sensors/PointerSensor.d.ts +79 -0
- package/dist/sensors/index.d.ts +2 -0
- package/dist/snap.core.js +2 -2
- package/dist/snap.core.js.map +4 -4
- package/dist/snap.esm.js +11 -11
- package/dist/snap.esm.js.map +4 -4
- package/dist/snap.umd.js +11 -11
- package/dist/snap.umd.js.map +4 -4
- package/dist/types/index.d.ts +161 -0
- package/dist/utils/BoundsCache.d.ts +54 -0
- package/dist/utils/DataTransfer.d.ts +32 -0
- package/dist/utils/EventEmitter.d.ts +37 -0
- package/dist/utils/ObjectPool.d.ts +38 -0
- package/dist/utils/RAFThrottle.d.ts +39 -0
- package/dist/utils/index.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sortable plugin - enables reordering items within a container
|
|
3
|
+
*/
|
|
4
|
+
import type { Plugin, SnapInstance, SortableOptions } from '../types/index.js';
|
|
5
|
+
export declare class Sortable implements Plugin {
|
|
6
|
+
name: string;
|
|
7
|
+
private _snap;
|
|
8
|
+
private _options;
|
|
9
|
+
private _placeholder;
|
|
10
|
+
private _originalIndex;
|
|
11
|
+
private _currentIndex;
|
|
12
|
+
private _container;
|
|
13
|
+
private _items;
|
|
14
|
+
private _unsubscribers;
|
|
15
|
+
constructor(options?: SortableOptions);
|
|
16
|
+
init(snap: SnapInstance): void;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
private _onDragStart;
|
|
19
|
+
private _onDragMove;
|
|
20
|
+
private _onDragEnd;
|
|
21
|
+
private _createPlaceholder;
|
|
22
|
+
private _movePlaceholder;
|
|
23
|
+
private _animateItems;
|
|
24
|
+
private _cleanup;
|
|
25
|
+
/**
|
|
26
|
+
* Get the current insertion index during drag
|
|
27
|
+
*/
|
|
28
|
+
getCurrentIndex(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Get the original index of the dragged item
|
|
31
|
+
*/
|
|
32
|
+
getOriginalIndex(): number;
|
|
33
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File drop sensor for handling external file drags
|
|
3
|
+
* Uses native HTML5 drag and drop API since pointer events
|
|
4
|
+
* don't work for external drags
|
|
5
|
+
*/
|
|
6
|
+
import type { Point, Sensor } from '../types/index.js';
|
|
7
|
+
import { EventEmitter } from '../utils/EventEmitter.js';
|
|
8
|
+
export interface FileSensorEvents {
|
|
9
|
+
dragenter: FileDragEvent;
|
|
10
|
+
dragover: FileDragEvent;
|
|
11
|
+
dragleave: FileDragEvent;
|
|
12
|
+
drop: FileDropEvent;
|
|
13
|
+
}
|
|
14
|
+
export interface FileDragEvent {
|
|
15
|
+
position: Point;
|
|
16
|
+
dropZone: HTMLElement;
|
|
17
|
+
originalEvent: DragEvent;
|
|
18
|
+
}
|
|
19
|
+
export interface FileDropEvent {
|
|
20
|
+
files: File[];
|
|
21
|
+
position: Point;
|
|
22
|
+
dropZone: HTMLElement;
|
|
23
|
+
originalEvent: DragEvent;
|
|
24
|
+
}
|
|
25
|
+
export interface FileSensorOptions {
|
|
26
|
+
container: HTMLElement | ShadowRoot;
|
|
27
|
+
dropZoneSelector: string;
|
|
28
|
+
accept?: string[];
|
|
29
|
+
multiple?: boolean;
|
|
30
|
+
maxSize?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare class FileSensor extends EventEmitter<FileSensorEvents> implements Sensor {
|
|
33
|
+
private _container;
|
|
34
|
+
private _options;
|
|
35
|
+
private _attached;
|
|
36
|
+
private _dragCount;
|
|
37
|
+
private _currentDropZone;
|
|
38
|
+
constructor(options: FileSensorOptions);
|
|
39
|
+
attach(): void;
|
|
40
|
+
detach(): void;
|
|
41
|
+
private _getEventTarget;
|
|
42
|
+
private _onDragEnter;
|
|
43
|
+
private _onDragOver;
|
|
44
|
+
private _onDragLeave;
|
|
45
|
+
private _onDrop;
|
|
46
|
+
private _findDropZone;
|
|
47
|
+
private _hasFiles;
|
|
48
|
+
private _getFiles;
|
|
49
|
+
private _matchesAccept;
|
|
50
|
+
destroy(): void;
|
|
51
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified pointer event sensor
|
|
3
|
+
* Handles mouse, touch, and pointer events through event delegation
|
|
4
|
+
*/
|
|
5
|
+
import type { Point, Sensor } from '../types/index.js';
|
|
6
|
+
import { EventEmitter } from '../utils/EventEmitter.js';
|
|
7
|
+
export interface PointerSensorEvents {
|
|
8
|
+
pointerdown: PointerStartEvent;
|
|
9
|
+
pointermove: PointerMoveEvent;
|
|
10
|
+
pointerup: PointerEndEvent;
|
|
11
|
+
pointercancel: PointerEndEvent;
|
|
12
|
+
}
|
|
13
|
+
export interface PointerStartEvent {
|
|
14
|
+
element: HTMLElement;
|
|
15
|
+
position: Point;
|
|
16
|
+
pointerId: number;
|
|
17
|
+
originalEvent: PointerEvent;
|
|
18
|
+
}
|
|
19
|
+
export interface PointerMoveEvent {
|
|
20
|
+
position: Point;
|
|
21
|
+
delta: Point;
|
|
22
|
+
pointerId: number;
|
|
23
|
+
originalEvent: PointerEvent;
|
|
24
|
+
}
|
|
25
|
+
export interface PointerEndEvent {
|
|
26
|
+
position: Point;
|
|
27
|
+
pointerId: number;
|
|
28
|
+
originalEvent: PointerEvent;
|
|
29
|
+
}
|
|
30
|
+
export interface PointerSensorOptions {
|
|
31
|
+
container: HTMLElement | ShadowRoot;
|
|
32
|
+
draggableSelector: string;
|
|
33
|
+
handleSelector?: string;
|
|
34
|
+
delay?: number;
|
|
35
|
+
distance?: number;
|
|
36
|
+
}
|
|
37
|
+
export declare class PointerSensor extends EventEmitter<PointerSensorEvents> implements Sensor {
|
|
38
|
+
private _container;
|
|
39
|
+
private _options;
|
|
40
|
+
private _attached;
|
|
41
|
+
private _activePointerId;
|
|
42
|
+
private _activeElement;
|
|
43
|
+
private _startPosition;
|
|
44
|
+
private _isDragging;
|
|
45
|
+
private _delayTimer;
|
|
46
|
+
private _moveThrottle;
|
|
47
|
+
constructor(options: PointerSensorOptions);
|
|
48
|
+
/**
|
|
49
|
+
* Attach event listeners
|
|
50
|
+
*/
|
|
51
|
+
attach(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Detach event listeners
|
|
54
|
+
*/
|
|
55
|
+
detach(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Check if currently tracking a drag
|
|
58
|
+
*/
|
|
59
|
+
get isActive(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Check if drag has started (past delay/distance threshold)
|
|
62
|
+
*/
|
|
63
|
+
get isDragging(): boolean;
|
|
64
|
+
private _getEventTarget;
|
|
65
|
+
private _onPointerDown;
|
|
66
|
+
private _onPointerMove;
|
|
67
|
+
private _processMove;
|
|
68
|
+
private _onPointerUp;
|
|
69
|
+
private _onPointerCancel;
|
|
70
|
+
private _startDrag;
|
|
71
|
+
private _findDraggable;
|
|
72
|
+
private _findHandle;
|
|
73
|
+
private _clearDelayTimer;
|
|
74
|
+
private _cleanup;
|
|
75
|
+
/**
|
|
76
|
+
* Cleanup resources
|
|
77
|
+
*/
|
|
78
|
+
destroy(): void;
|
|
79
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { PointerSensor, type PointerSensorOptions, type PointerSensorEvents, type PointerStartEvent, type PointerMoveEvent, type PointerEndEvent } from './PointerSensor.js';
|
|
2
|
+
export { FileSensor, type FileSensorOptions, type FileSensorEvents, type FileDragEvent, type FileDropEvent } from './FileSensor.js';
|
package/dist/snap.core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var p=class{constructor(){this._listeners=new Map}on(e,t){let n=this._listeners.get(e);return n||(n=new Set,this._listeners.set(e,n)),n.add(t),()=>{n.delete(t),n.size===0&&this._listeners.delete(e)}}once(e,t){let n=this.on(e,i=>{n(),t(i)});return n}emit(e,t){let n=this._listeners.get(e);if(n)for(let i of[...n])i(t)}off(e){e?this._listeners.delete(e):this._listeners.clear()}hasListeners(e){let t=this._listeners.get(e);return t!==void 0&&t.size>0}listenerCount(e){return this._listeners.get(e)?.size??0}destroy(){this._listeners.clear()}};var E=class o{constructor(){this._data=new Map}setData(e,t){this._data.set(e,t)}getData(e){return this._data.get(e)}hasType(e){return this._data.has(e)}get types(){return[...this._data.keys()]}clear(){this._data.clear()}clone(){let e=new o;for(let[t,n]of this._data)e.setData(t,n);return e}};var c=class extends p{constructor(){super(...arguments);this._session=null;this._idCounter=0}get session(){return this._session}isDragging(){return this._session!==null&&this._session.phase==="dragging"}getActiveElement(){return this._session?.element??null}getCurrentDropZone(){return this._session?.dropZone??null}startDrag(t,n,i){this._session&&this.cancelDrag();let s=new E;if(i)for(let[a,h]of Object.entries(i))s.setData(a,h);return this._session={id:`drag-${++this._idCounter}`,element:t,origin:{x:n.x,y:n.y},current:{x:n.x,y:n.y},delta:{x:0,y:0},data:s,dropZone:null,phase:"dragging"},this.emit("dragstart",this._session),this._session}updatePosition(t){!this._session||this._session.phase!=="dragging"||(this._session.current.x=t.x,this._session.current.y=t.y,this._session.delta.x=t.x-this._session.origin.x,this._session.delta.y=t.y-this._session.origin.y,this.emit("dragmove",this._session))}setDropTarget(t){if(!this._session)return;let n=this._session.dropZone;n!==t&&(n&&(this._session.dropZone=null,this.emit("dropzoneleave",this._session)),t&&(this._session.dropZone=t,this.emit("dropzoneenter",this._session)))}endDrag(){if(!this._session)return null;let t=this._session;return t.phase="dropping",t.dropZone&&this.emit("drop",t),this.emit("dragend",t),this._session=null,t}cancelDrag(){if(!this._session)return null;let t=this._session;return t.phase="cancelled",t.dropZone=null,this.emit("dragend",t),this._session=null,t}subscribe(t,n){return this.on(t,n)}reset(){this._session&&this.cancelDrag()}destroy(){this.reset(),super.destroy()}};var y=class{constructor(e){this._rafId=null;this._pending=null;this._process=()=>{if(this._rafId=null,this._pending!==null){let e=this._pending;this._pending=null,this._callback(e)}};this._callback=e}queue(e){this._pending=e,this._rafId===null&&(this._rafId=requestAnimationFrame(this._process))}cancel(){this._rafId!==null&&(cancelAnimationFrame(this._rafId),this._rafId=null),this._pending=null}flush(){this._pending!==null&&(this.cancel(),this._callback(this._pending),this._pending=null)}get isPending(){return this._rafId!==null}destroy(){this.cancel()}};var D=class{constructor(e,t,n=10,i=100){this._pool=[];this._factory=e,this._reset=t,this._maxSize=i;for(let s=0;s<n;s++)this._pool.push(e())}acquire(){return this._pool.pop()??this._factory()}release(e){this._pool.length<this._maxSize&&(this._reset(e),this._pool.push(e))}clear(){this._pool.length=0}get size(){return this._pool.length}},_=new D(()=>({x:0,y:0}),o=>{o.x=0,o.y=0}),j=new D(()=>({x:0,y:0,width:0,height:0}),o=>{o.x=0,o.y=0,o.width=0,o.height=0});function d(o,e){let t=_.acquire();return t.x=o,t.y=e,t}var x=class extends p{constructor(t){super();this._attached=!1;this._activePointerId=null;this._activeElement=null;this._startPosition=null;this._isDragging=!1;this._delayTimer=null;this._onPointerDown=t=>{if(!t.isPrimary||t.button!==0||this._activePointerId!==null)return;let n=this._findDraggable(t);if(!n||this._options.handleSelector&&!this._findHandle(t,n))return;t.preventDefault(),this._activePointerId=t.pointerId,this._activeElement=n,this._startPosition=d(t.clientX,t.clientY),this._isDragging=!1,t.target.setPointerCapture(t.pointerId);let i=this._getEventTarget();i.addEventListener("pointermove",this._onPointerMove,{passive:!0}),i.addEventListener("pointerup",this._onPointerUp),i.addEventListener("pointercancel",this._onPointerCancel);let s=this._options.delay??0;s>0?this._delayTimer=window.setTimeout(()=>{this._delayTimer=null,this._startDrag(t)},s):(this._options.distance??0)===0&&this._startDrag(t)};this._onPointerMove=t=>{t.pointerId===this._activePointerId&&this._moveThrottle.queue(t)};this._processMove=t=>{if(!this._startPosition||!this._activeElement)return;let n=d(t.clientX,t.clientY);if(!this._isDragging){let i=this._options.distance??0;if(i>0){let s=n.x-this._startPosition.x,a=n.y-this._startPosition.y;if(Math.sqrt(s*s+a*a)<i){_.release(n);return}this._clearDelayTimer(),this._startDrag(t)}}if(this._isDragging){let i=d(n.x-this._startPosition.x,n.y-this._startPosition.y);this.emit("pointermove",{position:n,delta:i,pointerId:t.pointerId,originalEvent:t})}else _.release(n)};this._onPointerUp=t=>{t.pointerId===this._activePointerId&&(this._moveThrottle.flush(),this._isDragging&&this.emit("pointerup",{position:d(t.clientX,t.clientY),pointerId:t.pointerId,originalEvent:t}),this._cleanup())};this._onPointerCancel=t=>{t.pointerId===this._activePointerId&&(this._moveThrottle.cancel(),this._isDragging&&this.emit("pointercancel",{position:d(t.clientX,t.clientY),pointerId:t.pointerId,originalEvent:t}),this._cleanup())};this._container=t.container,this._options=t,this._moveThrottle=new y(n=>this._processMove(n))}attach(){if(this._attached)return;this._getEventTarget().addEventListener("pointerdown",this._onPointerDown,{passive:!1}),this._attached=!0}detach(){if(!this._attached)return;this._getEventTarget().removeEventListener("pointerdown",this._onPointerDown),this._cleanup(),this._attached=!1}get isActive(){return this._activePointerId!==null}get isDragging(){return this._isDragging}_getEventTarget(){return this._container instanceof ShadowRoot?this._container.host:this._container}_startDrag(t){this._isDragging||!this._activeElement||!this._startPosition||(this._isDragging=!0,this.emit("pointerdown",{element:this._activeElement,position:{x:this._startPosition.x,y:this._startPosition.y},pointerId:t.pointerId,originalEvent:t}))}_findDraggable(t){let n=t.target,i=t.composedPath();for(let s of i)if(s instanceof HTMLElement){if(s.matches(this._options.draggableSelector))return s;if(s===this._container||s===this._container.host)break}return n.closest?.(this._options.draggableSelector)}_findHandle(t,n){if(!this._options.handleSelector)return n;let s=t.target.closest?.(this._options.handleSelector);return s&&n.contains(s)?s:null}_clearDelayTimer(){this._delayTimer!==null&&(clearTimeout(this._delayTimer),this._delayTimer=null)}_cleanup(){this._clearDelayTimer(),this._moveThrottle.cancel(),this._startPosition&&(_.release(this._startPosition),this._startPosition=null);let t=this._getEventTarget();t.removeEventListener("pointermove",this._onPointerMove),t.removeEventListener("pointerup",this._onPointerUp),t.removeEventListener("pointercancel",this._onPointerCancel),this._activePointerId=null,this._activeElement=null,this._isDragging=!1}destroy(){this.detach(),this._moveThrottle.destroy(),super.destroy()}};var L=class{constructor(){this._cache=new WeakMap;this._dirty=new WeakSet;this._invalidateAll=!1}get(e){if(this._invalidateAll||this._dirty.has(e))return this._update(e);let t=this._cache.get(e);return t||this._update(e)}invalidate(e){this._dirty.add(e)}invalidateAll(){this._invalidateAll=!0}update(e){return this._update(e)}remove(e){this._cache.delete(e)}clearDirty(){this._invalidateAll=!1}_update(e){let t=e.getBoundingClientRect();return this._cache.set(e,t),this._dirty.delete(e),t}},r=new L;function T(o,e,t){return o>=t.left&&o<=t.right&&e>=t.top&&e<=t.bottom}function H(o){return{x:o.left+o.width/2,y:o.top+o.height/2}}var P=class{constructor(e){this._enabled=!1;this._listenerUnsubscribers=[];this._ghost=null;this._ghostOffset={x:0,y:0};this._onPointerDown=e=>{let{element:t,position:n}=e,i=this._getItemData(t)??this._extractDataAttributes(t),s=this._state.startDrag(t,n,i),a={element:t,position:{x:n.x,y:n.y},data:s.data,cancel:()=>{this._state.cancelDrag()}};if(this._options.onDragStart?.(a)===!1){this._state.cancelDrag();return}this._createGhost(t,n),t.classList.add("snap-dragging"),this._options.ghostClass&&t.classList.add(this._options.ghostClass),r.invalidateAll()};this._onPointerMove=e=>{let t=this._state.session;if(!t)return;let{position:n}=e,i=this._getItemAxis(t.element)??this._options.axis??"both";i!=="both"&&(n=this._applyAxisConstraint(n,t.origin,i)),this._options.grid&&(n=this._applyGridSnap(n,this._options.grid)),this._state.updatePosition(n),this._updateGhost(n),this._updateDropZone(n),this._options.onDragMove?.({element:t.element,position:{x:t.current.x,y:t.current.y},delta:{x:t.delta.x,y:t.delta.y},dropZone:t.dropZone})};this._onPointerUp=e=>{if(!this._state.session)return;let n=this._state.endDrag();n&&(this._cleanup(n.element),n.dropZone&&this._options.onDrop?.({element:n.element,dropZone:n.dropZone,position:{x:n.current.x,y:n.current.y},data:n.data}),this._options.onDragEnd?.({element:n.element,position:{x:n.current.x,y:n.current.y},delta:{x:n.delta.x,y:n.delta.y},cancelled:!1}))};this._onPointerCancel=e=>{let t=this._state.session;if(!t)return;let n=t.element;this._state.cancelDrag(),this._cleanup(n),this._options.onDragEnd?.({element:n,position:e.position,delta:{x:0,y:0},cancelled:!0})};this._container=e.container,this._state=e.state,this._options=e.options,this._getDropZones=e.getDropZones,this._getItemData=e.getItemData,this._getItemAxis=e.getItemAxis,this._pointerSensor=new x({container:this._container,draggableSelector:this._options.draggableSelector??"[data-draggable]",handleSelector:this._options.handleSelector,delay:this._options.delay,distance:this._options.distance}),this._setupListeners()}enable(){this._enabled||(this._pointerSensor.attach(),this._enabled=!0)}disable(){this._enabled&&(this._pointerSensor.detach(),this._state.reset(),this._removeGhost(),this._enabled=!1)}get isEnabled(){return this._enabled}updateOptions(e){Object.assign(this._options,e)}_setupListeners(){this._listenerUnsubscribers.push(this._pointerSensor.on("pointerdown",this._onPointerDown),this._pointerSensor.on("pointermove",this._onPointerMove),this._pointerSensor.on("pointerup",this._onPointerUp),this._pointerSensor.on("pointercancel",this._onPointerCancel))}_applyAxisConstraint(e,t,n){return n==="x"?{x:e.x,y:t.y}:n==="y"?{x:t.x,y:e.y}:e}_applyGridSnap(e,t){return{x:Math.round(e.x/t.x)*t.x,y:Math.round(e.y/t.y)*t.y}}_updateDropZone(e){let t=this._getDropZones(),n=null;for(let s of t){let a=r.get(s);if(T(e.x,e.y,a)){n=s;break}}let i=this._state.session;i&&n!==i.dropZone&&(i.dropZone&&this._options.onDropZoneLeave?.({element:i.element,dropZone:i.dropZone}),this._state.setDropTarget(n),n&&this._options.onDropZoneEnter?.({element:i.element,dropZone:n,position:e}))}_createGhost(e,t){let n=e.getBoundingClientRect();this._ghostOffset={x:t.x-n.left,y:t.y-n.top},this._ghost=e.cloneNode(!0),this._ghost.style.cssText=`
|
|
1
|
+
var d=class{constructor(){this._listeners=new Map}on(t,e){let n=this._listeners.get(t);return n||(n=new Set,this._listeners.set(t,n)),n.add(e),()=>{n.delete(e),n.size===0&&this._listeners.delete(t)}}once(t,e){let n=this.on(t,i=>{n(),e(i)});return n}emit(t,e){let n=this._listeners.get(t);if(n)for(let i of[...n])i(e)}off(t){t?this._listeners.delete(t):this._listeners.clear()}hasListeners(t){let e=this._listeners.get(t);return e!==void 0&&e.size>0}listenerCount(t){return this._listeners.get(t)?.size??0}destroy(){this._listeners.clear()}};var E=class o{constructor(){this._data=new Map}setData(t,e){this._data.set(t,e)}getData(t){return this._data.get(t)}hasType(t){return this._data.has(t)}get types(){return[...this._data.keys()]}clear(){this._data.clear()}clone(){let t=new o;for(let[e,n]of this._data)t.setData(e,n);return t}};var _=class extends d{constructor(){super(...arguments);this._session=null;this._idCounter=0}get session(){return this._session}isDragging(){return this._session!==null&&this._session.phase==="dragging"}getActiveElement(){return this._session?.element??null}getCurrentDropZone(){return this._session?.dropZone??null}startDrag(e,n,i){this._session&&this.cancelDrag();let s=new E;if(i)for(let[r,p]of Object.entries(i))s.setData(r,p);return this._session={id:`drag-${++this._idCounter}`,element:e,origin:{x:n.x,y:n.y},current:{x:n.x,y:n.y},delta:{x:0,y:0},data:s,dropZone:null,phase:"dragging"},this.emit("dragstart",this._session),this._session}updatePosition(e){!this._session||this._session.phase!=="dragging"||(this._session.current.x=e.x,this._session.current.y=e.y,this._session.delta.x=e.x-this._session.origin.x,this._session.delta.y=e.y-this._session.origin.y,this.emit("dragmove",this._session))}setDropTarget(e){if(!this._session)return;let n=this._session.dropZone;n!==e&&(n&&(this._session.dropZone=null,this.emit("dropzoneleave",this._session)),e&&(this._session.dropZone=e,this.emit("dropzoneenter",this._session)))}endDrag(){if(!this._session)return null;let e=this._session;return e.phase="dropping",e.dropZone&&this.emit("drop",e),this.emit("dragend",e),this._session=null,e}cancelDrag(){if(!this._session)return null;let e=this._session;return e.phase="cancelled",e.dropZone=null,this.emit("dragend",e),this._session=null,e}subscribe(e,n){return this.on(e,n)}reset(){this._session&&this.cancelDrag()}destroy(){this.reset(),super.destroy()}};var D=class{constructor(t){this._rafId=null;this._pending=null;this._process=()=>{if(this._rafId=null,this._pending!==null){let t=this._pending;this._pending=null,this._callback(t)}};this._callback=t}queue(t){this._pending=t,this._rafId===null&&(this._rafId=requestAnimationFrame(this._process))}cancel(){this._rafId!==null&&(cancelAnimationFrame(this._rafId),this._rafId=null),this._pending=null}flush(){this._pending!==null&&(this.cancel(),this._callback(this._pending),this._pending=null)}get isPending(){return this._rafId!==null}destroy(){this.cancel()}};var S=class{constructor(t,e,n=10,i=100){this._pool=[];this._factory=t,this._reset=e,this._maxSize=i;for(let s=0;s<n;s++)this._pool.push(t())}acquire(){return this._pool.pop()??this._factory()}release(t){this._pool.length<this._maxSize&&(this._reset(t),this._pool.push(t))}clear(){this._pool.length=0}get size(){return this._pool.length}},f=new S(()=>({x:0,y:0}),o=>{o.x=0,o.y=0}),V=new S(()=>({x:0,y:0,width:0,height:0}),o=>{o.x=0,o.y=0,o.width=0,o.height=0});function u(o,t){let e=f.acquire();return e.x=o,e.y=t,e}var T=class extends d{constructor(e){super();this._attached=!1;this._activePointerId=null;this._activeElement=null;this._startPosition=null;this._isDragging=!1;this._delayTimer=null;this._onPointerDown=e=>{if(!e.isPrimary||e.button!==0||this._activePointerId!==null)return;let n=this._findDraggable(e);if(!n||this._options.handleSelector&&!this._findHandle(e,n))return;e.preventDefault(),this._activePointerId=e.pointerId,this._activeElement=n,this._startPosition=u(e.clientX,e.clientY),this._isDragging=!1,e.target.setPointerCapture(e.pointerId);let i=this._getEventTarget();i.addEventListener("pointermove",this._onPointerMove,{passive:!0}),i.addEventListener("pointerup",this._onPointerUp),i.addEventListener("pointercancel",this._onPointerCancel);let s=this._options.delay??0;s>0?this._delayTimer=window.setTimeout(()=>{this._delayTimer=null,this._startDrag(e)},s):(this._options.distance??0)===0&&this._startDrag(e)};this._onPointerMove=e=>{e.pointerId===this._activePointerId&&this._moveThrottle.queue(e)};this._processMove=e=>{if(!this._startPosition||!this._activeElement)return;let n=u(e.clientX,e.clientY);if(!this._isDragging){let i=this._options.distance??0;if(i>0){let s=n.x-this._startPosition.x,r=n.y-this._startPosition.y;if(Math.sqrt(s*s+r*r)<i){f.release(n);return}this._clearDelayTimer(),this._startDrag(e)}}if(this._isDragging){let i=u(n.x-this._startPosition.x,n.y-this._startPosition.y);this.emit("pointermove",{position:n,delta:i,pointerId:e.pointerId,originalEvent:e})}else f.release(n)};this._onPointerUp=e=>{e.pointerId===this._activePointerId&&(this._moveThrottle.flush(),this._isDragging&&this.emit("pointerup",{position:u(e.clientX,e.clientY),pointerId:e.pointerId,originalEvent:e}),this._cleanup())};this._onPointerCancel=e=>{e.pointerId===this._activePointerId&&(this._moveThrottle.cancel(),this._isDragging&&this.emit("pointercancel",{position:u(e.clientX,e.clientY),pointerId:e.pointerId,originalEvent:e}),this._cleanup())};this._container=e.container,this._options=e,this._moveThrottle=new D(n=>this._processMove(n))}attach(){if(this._attached)return;this._getEventTarget().addEventListener("pointerdown",this._onPointerDown,{passive:!1}),this._attached=!0}detach(){if(!this._attached)return;this._getEventTarget().removeEventListener("pointerdown",this._onPointerDown),this._cleanup(),this._attached=!1}get isActive(){return this._activePointerId!==null}get isDragging(){return this._isDragging}_getEventTarget(){return this._container instanceof ShadowRoot?this._container.host:this._container}_startDrag(e){this._isDragging||!this._activeElement||!this._startPosition||(this._isDragging=!0,this.emit("pointerdown",{element:this._activeElement,position:{x:this._startPosition.x,y:this._startPosition.y},pointerId:e.pointerId,originalEvent:e}))}_findDraggable(e){let n=e.target,i=e.composedPath();for(let s of i)if(s instanceof HTMLElement){if(s.matches(this._options.draggableSelector))return s;if(s===this._container||s===this._container.host)break}return n.closest?.(this._options.draggableSelector)}_findHandle(e,n){if(!this._options.handleSelector)return n;let s=e.target.closest?.(this._options.handleSelector);return s&&n.contains(s)?s:null}_clearDelayTimer(){this._delayTimer!==null&&(clearTimeout(this._delayTimer),this._delayTimer=null)}_cleanup(){this._clearDelayTimer(),this._moveThrottle.cancel(),this._startPosition&&(f.release(this._startPosition),this._startPosition=null);let e=this._getEventTarget();e.removeEventListener("pointermove",this._onPointerMove),e.removeEventListener("pointerup",this._onPointerUp),e.removeEventListener("pointercancel",this._onPointerCancel),this._activePointerId=null,this._activeElement=null,this._isDragging=!1}destroy(){this.detach(),this._moveThrottle.destroy(),super.destroy()}};var Z=class{constructor(){this._cache=new WeakMap;this._dirty=new WeakSet;this._invalidateAll=!1}get(t){if(this._invalidateAll||this._dirty.has(t))return this._update(t);let e=this._cache.get(t);return e||this._update(t)}invalidate(t){this._dirty.add(t)}invalidateAll(){this._invalidateAll=!0}update(t){return this._update(t)}remove(t){this._cache.delete(t)}clearDirty(){this._invalidateAll=!1}_update(t){let e=t.getBoundingClientRect();return this._cache.set(t,e),this._dirty.delete(t),e}},a=new Z;function P(o,t,e){return o>=e.left&&o<=e.right&&t>=e.top&&t<=e.bottom}function H(o){return{x:o.left+o.width/2,y:o.top+o.height/2}}function c(o,...t){let e=["__proto__","constructor","prototype"];for(let n of t)if(!(!n||typeof n!="object"))for(let i of Object.keys(n)){if(e.includes(i))continue;let s=n[i];s!==void 0&&(o[i]=s)}return o}function k(o){if(!o||typeof o!="string"||o.length>500)return!1;let t=[/javascript:/i,/expression\s*\(/i,/url\s*\(/i,/@import/i,/<script/i,/on\w+\s*=/i];for(let e of t)if(e.test(o))return!1;try{return document.createElement("div").matches(o),!0}catch{return!1}}function h(o,t){return k(o)?o:(console.warn(`[Snap] Invalid selector "${o}", using default`),t)}function A(o){return typeof o!="string"?"":o.replace(/<[^>]*>/g,"").slice(0,1e3)}var M=class{constructor(t){this._enabled=!1;this._listenerUnsubscribers=[];this._ghost=null;this._ghostOffset={x:0,y:0};this._onPointerDown=t=>{let{element:e,position:n}=t,i=this._getItemData(e)??this._extractDataAttributes(e),s=this._state.startDrag(e,n,i),r={element:e,position:{x:n.x,y:n.y},data:s.data,cancel:()=>{this._state.cancelDrag()}};if(this._options.onDragStart?.(r)===!1){this._state.cancelDrag();return}this._createGhost(e,n),e.classList.add("snap-dragging"),this._options.ghostClass&&e.classList.add(this._options.ghostClass),a.invalidateAll()};this._onPointerMove=t=>{let e=this._state.session;if(!e)return;let{position:n}=t,i=this._getItemAxis(e.element)??this._options.axis??"both";i!=="both"&&(n=this._applyAxisConstraint(n,e.origin,i)),this._options.grid&&(n=this._applyGridSnap(n,this._options.grid)),this._state.updatePosition(n),this._updateGhost(n),this._updateDropZone(n),this._options.onDragMove?.({element:e.element,position:{x:e.current.x,y:e.current.y},delta:{x:e.delta.x,y:e.delta.y},dropZone:e.dropZone})};this._onPointerUp=t=>{if(!this._state.session)return;let n=this._state.endDrag();n&&(this._cleanup(n.element),n.dropZone&&this._options.onDrop?.({element:n.element,dropZone:n.dropZone,position:{x:n.current.x,y:n.current.y},data:n.data}),this._options.onDragEnd?.({element:n.element,position:{x:n.current.x,y:n.current.y},delta:{x:n.delta.x,y:n.delta.y},cancelled:!1}))};this._onPointerCancel=t=>{let e=this._state.session;if(!e)return;let n=e.element;this._state.cancelDrag(),this._cleanup(n),this._options.onDragEnd?.({element:n,position:t.position,delta:{x:0,y:0},cancelled:!0})};this._container=t.container,this._state=t.state,this._options=t.options,this._getDropZones=t.getDropZones,this._getItemData=t.getItemData,this._getItemAxis=t.getItemAxis,this._pointerSensor=new T({container:this._container,draggableSelector:this._options.draggableSelector??"[data-draggable]",handleSelector:this._options.handleSelector,delay:this._options.delay,distance:this._options.distance}),this._setupListeners()}enable(){this._enabled||(this._pointerSensor.attach(),this._enabled=!0)}disable(){this._enabled&&(this._pointerSensor.detach(),this._state.reset(),this._removeGhost(),this._enabled=!1)}get isEnabled(){return this._enabled}updateOptions(t){c(this._options,t)}_setupListeners(){this._listenerUnsubscribers.push(this._pointerSensor.on("pointerdown",this._onPointerDown),this._pointerSensor.on("pointermove",this._onPointerMove),this._pointerSensor.on("pointerup",this._onPointerUp),this._pointerSensor.on("pointercancel",this._onPointerCancel))}_applyAxisConstraint(t,e,n){return n==="x"?{x:t.x,y:e.y}:n==="y"?{x:e.x,y:t.y}:t}_applyGridSnap(t,e){return{x:Math.round(t.x/e.x)*e.x,y:Math.round(t.y/e.y)*e.y}}_updateDropZone(t){let e=this._getDropZones(),n=null;for(let s of e){let r=a.get(s);if(P(t.x,t.y,r)){n=s;break}}let i=this._state.session;i&&n!==i.dropZone&&(i.dropZone&&this._options.onDropZoneLeave?.({element:i.element,dropZone:i.dropZone}),this._state.setDropTarget(n),n&&this._options.onDropZoneEnter?.({element:i.element,dropZone:n,position:t}))}_createGhost(t,e){let n=t.getBoundingClientRect();this._ghostOffset={x:e.x-n.left,y:e.y-n.top},this._ghost=t.cloneNode(!0),this._ghost.style.cssText=`
|
|
2
2
|
position: fixed;
|
|
3
3
|
left: ${n.left}px;
|
|
4
4
|
top: ${n.top}px;
|
|
@@ -9,5 +9,5 @@ var p=class{constructor(){this._listeners=new Map}on(e,t){let n=this._listeners.
|
|
|
9
9
|
z-index: 9999;
|
|
10
10
|
opacity: 0.8;
|
|
11
11
|
will-change: transform;
|
|
12
|
-
`,this._ghost.classList.add("snap-ghost"),document.body.appendChild(this._ghost)}_updateGhost(
|
|
12
|
+
`,this._ghost.classList.add("snap-ghost"),document.body.appendChild(this._ghost)}_updateGhost(t){if(!this._ghost)return;let e=t.x-this._ghostOffset.x,n=t.y-this._ghostOffset.y;this._ghost.style.transform=`translate(${e-parseFloat(this._ghost.style.left)}px, ${n-parseFloat(this._ghost.style.top)}px)`}_removeGhost(){this._ghost&&(this._ghost.remove(),this._ghost=null)}_cleanup(t){t.classList.remove("snap-dragging"),this._options.ghostClass&&t.classList.remove(this._options.ghostClass),this._removeGhost()}_extractDataAttributes(t){let e={},n=["id","type","group","axis","disabled"];for(let s of t.attributes)if(s.name.startsWith("data-drag-")){let r=s.name.slice(10);if(!n.includes(r))continue;e[r]=A(s.value)}let i=t.dataset.draggable;return i&&i!==""&&(e.type=A(i)),e}destroy(){this.disable();for(let t of this._listenerUnsubscribers)t();this._listenerUnsubscribers=[],this._pointerSensor.destroy()}};var L=class{constructor(t,e={}){this._isActive=!1;this._element=t,this._options=e}get element(){return this._element}get isActive(){return this._isActive}setOptions(t){c(this._options,t)}containsPoint(t,e){let n=a.get(this._element);return P(t,e,n)}accepts(t){let{accepts:e}=this._options;if(!e)return!0;if(typeof e=="function")return e(t);for(let i of e)if(t.hasType(i)||t.getData("type")===i)return!0;let n=this._element.dataset.accepts;if(n){let i=n.split(",").map(s=>s.trim());for(let s of i)if(t.hasType(s)||t.getData("type")===s)return!0}return!1}setActive(t){this._isActive!==t&&(this._isActive=t,t?this._element.classList.add("snap-drop-active"):this._element.classList.remove("snap-drop-active"))}getInsertionIndex(t,e,n,i){let s=Array.from(this._element.querySelectorAll(n)).filter(l=>l!==i);if(s.length===0)return 0;let r=a.get(s[0]),p=a.get(s[s.length-1]),v=Math.abs(p.top-r.top)>Math.abs(p.left-r.left);for(let l=0;l<s.length;l++){let m=a.get(s[l]),b=H(m);if(v){if(e<b.y)return l}else if(t<b.x)return l}return s.length}getClosestItem(t,e,n,i){let s=Array.from(this._element.querySelectorAll(n)).filter(x=>x!==i);if(s.length===0)return null;let r=null,p=1/0,v="after",l=a.get(s[0]),m=a.get(s[s.length-1]),b=Math.abs(m.top-l.top)>Math.abs(m.left-l.left);for(let x of s){let O=a.get(x),y=H(O),I=t-y.x,R=e-y.y,z=Math.sqrt(I*I+R*R);z<p&&(p=z,r=x,v=b?e<y.y?"before":"after":t<y.x?"before":"after")}return r?{element:r,position:v}:null}updateBounds(){a.update(this._element)}destroy(){this.setActive(!1),a.remove(this._element)}},g=class{constructor(){this._zones=new Map}register(t,e){let n=this._zones.get(t);return n?(e&&n.setOptions(e),n):(n=new L(t,e),this._zones.set(t,n),n)}unregister(t){let e=this._zones.get(t);e&&(e.destroy(),this._zones.delete(t))}get(t){return this._zones.get(t)}getElements(){return[...this._zones.keys()]}getAll(){return[...this._zones.values()]}findAtPoint(t,e){for(let n of this._zones.values())if(n.containsPoint(t,e))return n;return null}clear(){for(let t of this._zones.values())t.destroy();this._zones.clear()}updateAllBounds(){a.invalidateAll()}destroy(){this.clear()}};var C={draggableSelector:"[data-draggable]",dropZoneSelector:"[data-droppable]",axis:"both",autoRefresh:!1},w=class{constructor(t,e={}){this._imperativeDraggables=new Map;this._imperativeDropZones=new Map;this._plugins=[];this._behaviors=[];this._stateUnsubscribers=[];this._observer=null;this._refreshScheduled=!1;this._destroyed=!1;this._scrollHandler=null;this._resizeHandler=null;this._container=t,this._options=c({},C,e),this._options.draggableSelector&&(this._options.draggableSelector=h(this._options.draggableSelector,"[data-draggable]")),this._options.dropZoneSelector&&(this._options.dropZoneSelector=h(this._options.dropZoneSelector,"[data-droppable]")),this._options.handleSelector&&(this._options.handleSelector=h(this._options.handleSelector,"[data-drag-handle]")),this._state=new _,this._dropZoneManager=new g,this._engine=new M({container:this._container,state:this._state,options:this._options,getDropZones:()=>this._getDropZones(),getItemData:n=>this._getItemData(n),getItemAxis:n=>this._getItemAxis(n)}),this._setupStateListeners(),this._scanDeclarativeElements(),this._options.autoRefresh&&this._setupAutoRefresh(),this._setupScrollResize(),this.enable()}get options(){return this._options}enable(){this._engine.enable()}disable(){this._engine.disable()}destroy(){this._destroyed=!0,this.disable();for(let t of this._stateUnsubscribers)t();this._stateUnsubscribers=[];for(let t of this._plugins)t.destroy();this._plugins=[];for(let t of this._behaviors)t.destroy();this._behaviors=[],this._engine.destroy(),this._state.destroy(),this._dropZoneManager.destroy(),this._observer?.disconnect(),this._observer=null,this._scrollHandler&&(window.removeEventListener("scroll",this._scrollHandler,!0),this._scrollHandler=null),this._resizeHandler&&(window.removeEventListener("resize",this._resizeHandler),this._resizeHandler=null),this._imperativeDraggables.clear(),this._imperativeDropZones.clear()}refresh(){this._scanDeclarativeElements(),a.invalidateAll()}addDraggable(t,e){this._imperativeDraggables.set(t,e??{})}removeDraggable(t){this._imperativeDraggables.delete(t)}addDropZone(t,e){this._imperativeDropZones.set(t,e??{}),this._dropZoneManager.register(t,e)}removeDropZone(t){this._imperativeDropZones.delete(t),this._dropZoneManager.unregister(t)}isDragging(){return this._state.isDragging()}getActiveElement(){return this._state.getActiveElement()}use(t){return this._plugins.push(t),t.init(this),this}addBehavior(t){return this._behaviors.push(t),this}setOptions(t){t.draggableSelector&&(t.draggableSelector=h(t.draggableSelector,this._options.draggableSelector??"[data-draggable]")),t.dropZoneSelector&&(t.dropZoneSelector=h(t.dropZoneSelector,this._options.dropZoneSelector??"[data-droppable]")),t.handleSelector&&(t.handleSelector=h(t.handleSelector,this._options.handleSelector??"[data-drag-handle]")),c(this._options,t),this._engine.updateOptions(this._options)}_getDropZones(){let t=this._options.dropZoneSelector??"[data-droppable]",e=this._container instanceof ShadowRoot?this._container:this._container,n=Array.from(e.querySelectorAll(t)),i=[...this._imperativeDropZones.keys()];return[...new Set([...n,...i])]}_getItemData(t){return this._imperativeDraggables.get(t)?.data}_getItemAxis(t){let e=this._imperativeDraggables.get(t);if(e?.axis)return e.axis;let n=t.dataset.dragAxis;if(n==="x"||n==="y"||n==="both")return n}_scanDeclarativeElements(){let t=this._options.dropZoneSelector??"[data-droppable]",n=(this._container instanceof ShadowRoot?this._container:this._container).querySelectorAll(t);for(let i of n)this._imperativeDropZones.has(i)||this._dropZoneManager.register(i)}_setupStateListeners(){this._stateUnsubscribers.push(this._state.subscribe("dragstart",t=>{for(let e of this._behaviors)e.onDragStart?.(t)})),this._stateUnsubscribers.push(this._state.subscribe("dragmove",t=>{for(let e of this._behaviors)e.onDragMove?.(t)})),this._stateUnsubscribers.push(this._state.subscribe("dragend",t=>{for(let e of this._behaviors)e.onDragEnd?.(t)}))}_setupAutoRefresh(){this._observer=new MutationObserver(e=>{if(this._destroyed)return;let n=!1;for(let i of e)if(i.type==="childList"){n=!0;break}n&&!this._refreshScheduled&&(this._refreshScheduled=!0,requestAnimationFrame(()=>{this._destroyed||(this._refreshScheduled=!1,this.refresh())}))});let t=this._container instanceof ShadowRoot?this._container:this._container;this._observer.observe(t,{childList:!0,subtree:!0})}_setupScrollResize(){this._scrollHandler=()=>{this._state.isDragging()&&a.invalidateAll()},window.addEventListener("scroll",this._scrollHandler,!0),this._resizeHandler=()=>{a.invalidateAll()},window.addEventListener("resize",this._resizeHandler)}},F=w;export{_ as DragState,L as DropZone,g as DropZoneManager,w as Snap,F as default};
|
|
13
13
|
//# sourceMappingURL=snap.core.js.map
|