UNPKG

@shopify/draggable

Version:

The JavaScript Drag & Drop library your grandparents warned you about.

105 lines (89 loc) 3.26 kB
import { AbstractPlugin } from '../../shared/AbstractPlugin/AbstractPlugin.mjs'; import { SnapInEvent, SnapOutEvent } from './SnappableEvent/SnappableEvent.mjs'; const onDragStart = Symbol('onDragStart'); const onDragStop = Symbol('onDragStop'); const onDragOver = Symbol('onDragOver'); const onDragOut = Symbol('onDragOut'); const onMirrorCreated = Symbol('onMirrorCreated'); const onMirrorDestroy = Symbol('onMirrorDestroy'); class Snappable extends AbstractPlugin { constructor(draggable) { super(draggable); this.firstSource = null; this.mirror = null; this[onDragStart] = this[onDragStart].bind(this); this[onDragStop] = this[onDragStop].bind(this); this[onDragOver] = this[onDragOver].bind(this); this[onDragOut] = this[onDragOut].bind(this); this[onMirrorCreated] = this[onMirrorCreated].bind(this); this[onMirrorDestroy] = this[onMirrorDestroy].bind(this); } attach() { this.draggable.on('drag:start', this[onDragStart]).on('drag:stop', this[onDragStop]).on('drag:over', this[onDragOver]).on('drag:out', this[onDragOut]).on('droppable:over', this[onDragOver]).on('droppable:out', this[onDragOut]).on('mirror:created', this[onMirrorCreated]).on('mirror:destroy', this[onMirrorDestroy]); } detach() { this.draggable.off('drag:start', this[onDragStart]).off('drag:stop', this[onDragStop]).off('drag:over', this[onDragOver]).off('drag:out', this[onDragOut]).off('droppable:over', this[onDragOver]).off('droppable:out', this[onDragOut]).off('mirror:created', this[onMirrorCreated]).off('mirror:destroy', this[onMirrorDestroy]); } [onDragStart](event) { if (event.canceled()) { return; } this.firstSource = event.source; } [onDragStop]() { this.firstSource = null; } [onDragOver](event) { if (event.canceled()) { return; } const source = event.source || event.dragEvent.source; if (source === this.firstSource) { this.firstSource = null; return; } const snapInEvent = new SnapInEvent({ dragEvent: event, snappable: event.over || event.droppable }); this.draggable.trigger(snapInEvent); if (snapInEvent.canceled()) { return; } if (this.mirror) { this.mirror.style.display = 'none'; } source.classList.remove(...this.draggable.getClassNamesFor('source:dragging')); source.classList.add(...this.draggable.getClassNamesFor('source:placed')); setTimeout(() => { source.classList.remove(...this.draggable.getClassNamesFor('source:placed')); }, this.draggable.options.placedTimeout); } [onDragOut](event) { if (event.canceled()) { return; } const source = event.source || event.dragEvent.source; const snapOutEvent = new SnapOutEvent({ dragEvent: event, snappable: event.over || event.droppable }); this.draggable.trigger(snapOutEvent); if (snapOutEvent.canceled()) { return; } if (this.mirror) { this.mirror.style.display = ''; } source.classList.add(...this.draggable.getClassNamesFor('source:dragging')); } [onMirrorCreated]({ mirror }) { this.mirror = mirror; } [onMirrorDestroy]() { this.mirror = null; } } export { Snappable as default };