@shopify/draggable
Version:
The JavaScript Drag & Drop library your grandparents warned you about.
118 lines (103 loc) • 3.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var Draggable = require('../Draggable/Draggable.cjs');
require('../Draggable/DragEvent/DragEvent.cjs');
require('../Draggable/DraggableEvent/DraggableEvent.cjs');
require('../Draggable/Plugins/Announcement/Announcement.cjs');
require('../Draggable/Plugins/Mirror/MirrorEvent/MirrorEvent.cjs');
require('../Draggable/Sensors/SensorEvent/SensorEvent.cjs');
require('../Draggable/Sensors/TouchSensor/TouchSensor.cjs');
var SwappableEvent = require('./SwappableEvent/SwappableEvent.cjs');
const onDragStart = Symbol('onDragStart');
const onDragOver = Symbol('onDragOver');
const onDragStop = Symbol('onDragStop');
function onSwappableSwappedDefaultAnnouncement({
dragEvent,
swappedElement
}) {
const sourceText = dragEvent.source.textContent.trim() || dragEvent.source.id || 'swappable element';
const overText = swappedElement.textContent.trim() || swappedElement.id || 'swappable element';
return `Swapped ${sourceText} with ${overText}`;
}
const defaultAnnouncements = {
'swappabled:swapped': onSwappableSwappedDefaultAnnouncement
};
class Swappable extends Draggable.default {
constructor(containers = [], options = {}) {
super(containers, {
...options,
announcements: {
...defaultAnnouncements,
...(options.announcements || {})
}
});
this.lastOver = null;
this[onDragStart] = this[onDragStart].bind(this);
this[onDragOver] = this[onDragOver].bind(this);
this[onDragStop] = this[onDragStop].bind(this);
this.on('drag:start', this[onDragStart]).on('drag:over', this[onDragOver]).on('drag:stop', this[onDragStop]);
}
destroy() {
super.destroy();
this.off('drag:start', this._onDragStart).off('drag:over', this._onDragOver).off('drag:stop', this._onDragStop);
}
[onDragStart](event) {
const swappableStartEvent = new SwappableEvent.SwappableStartEvent({
dragEvent: event
});
this.trigger(swappableStartEvent);
if (swappableStartEvent.canceled()) {
event.cancel();
}
}
[onDragOver](event) {
if (event.over === event.originalSource || event.over === event.source || event.canceled()) {
return;
}
const swappableSwapEvent = new SwappableEvent.SwappableSwapEvent({
dragEvent: event,
over: event.over,
overContainer: event.overContainer
});
this.trigger(swappableSwapEvent);
if (swappableSwapEvent.canceled()) {
return;
}
if (this.lastOver && this.lastOver !== event.over) {
swap(this.lastOver, event.source);
}
if (this.lastOver === event.over) {
this.lastOver = null;
} else {
this.lastOver = event.over;
}
swap(event.source, event.over);
const swappableSwappedEvent = new SwappableEvent.SwappableSwappedEvent({
dragEvent: event,
swappedElement: event.over
});
this.trigger(swappableSwappedEvent);
}
[onDragStop](event) {
const swappableStopEvent = new SwappableEvent.SwappableStopEvent({
dragEvent: event
});
this.trigger(swappableStopEvent);
this.lastOver = null;
}
}
function withTempElement(callback) {
const tmpElement = document.createElement('div');
callback(tmpElement);
tmpElement.remove();
}
function swap(source, over) {
const overParent = over.parentNode;
const sourceParent = source.parentNode;
withTempElement(tmpElement => {
sourceParent.insertBefore(tmpElement, source);
overParent.insertBefore(source, over);
sourceParent.insertBefore(over, tmpElement);
});
}
exports.default = Swappable;