UNPKG

@shopify/draggable

Version:

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

600 lines (496 loc) 15.4 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("Snappable", [], factory); else if(typeof exports === 'object') exports["Snappable"] = factory(); else root["Snappable"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 7); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _SnappableEvent = __webpack_require__(6); Object.keys(_SnappableEvent).forEach(function (key) { if (key === "default" || key === "__esModule") return; Object.defineProperty(exports, key, { enumerable: true, get: function () { return _SnappableEvent[key]; } }); }); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * All draggable plugins inherit from this class. * @abstract * @class AbstractPlugin * @module AbstractPlugin */ class AbstractPlugin { /** * AbstractPlugin constructor. * @constructs AbstractPlugin * @param {Draggable} draggable - Draggable instance */ constructor(draggable) { /** * Draggable instance * @property draggable * @type {Draggable} */ this.draggable = draggable; } /** * Override to add listeners * @abstract */ attach() { throw new Error('Not Implemented'); } /** * Override to remove listeners * @abstract */ detach() { throw new Error('Not Implemented'); } } exports.default = AbstractPlugin; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _AbstractPlugin = __webpack_require__(1); var _AbstractPlugin2 = _interopRequireDefault(_AbstractPlugin); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = _AbstractPlugin2.default; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _AbstractPlugin = __webpack_require__(2); var _AbstractPlugin2 = _interopRequireDefault(_AbstractPlugin); var _SnappableEvent = __webpack_require__(0); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const onDragStart = Symbol('onDragStart'); const onDragStop = Symbol('onDragStop'); const onDragOver = Symbol('onDragOver'); const onDragOut = Symbol('onDragOut'); const onMirrorCreated = Symbol('onMirrorCreated'); const onMirrorDestroy = Symbol('onMirrorDestroy'); /** * Snappable plugin which snaps draggable elements into place * @class Snappable * @module Snappable * @extends AbstractPlugin */ class Snappable extends _AbstractPlugin2.default { /** * Snappable constructor. * @constructs Snappable * @param {Draggable} draggable - Draggable instance */ constructor(draggable) { super(draggable); /** * Keeps track of the first source element * @property {HTMLElement|null} firstSource */ this.firstSource = null; /** * Keeps track of the mirror element * @property {HTMLElement} mirror */ 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); } /** * Attaches plugins event listeners */ 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]); } /** * Detaches plugins event listeners */ 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]); } /** * Drag start handler * @private * @param {DragStartEvent} event - Drag start event */ [onDragStart](event) { if (event.canceled()) { return; } this.firstSource = event.source; } /** * Drag stop handler * @private * @param {DragStopEvent} event - Drag stop event */ [onDragStop]() { this.firstSource = null; } /** * Drag over handler * @private * @param {DragOverEvent|DroppableOverEvent} event - Drag over event */ [onDragOver](event) { if (event.canceled()) { return; } const source = event.source || event.dragEvent.source; if (source === this.firstSource) { this.firstSource = null; return; } const snapInEvent = new _SnappableEvent.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.getClassNameFor('source:dragging')); source.classList.add(this.draggable.getClassNameFor('source:placed')); // Need to cancel this in drag out setTimeout(() => { source.classList.remove(this.draggable.getClassNameFor('source:placed')); }, this.draggable.options.placedTimeout); } /** * Drag out handler * @private * @param {DragOutEvent|DroppableOutEvent} event - Drag out event */ [onDragOut](event) { if (event.canceled()) { return; } const source = event.source || event.dragEvent.source; const snapOutEvent = new _SnappableEvent.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.getClassNameFor('source:dragging')); } /** * Mirror created handler * @param {MirrorCreatedEvent} mirrorEvent * @private */ [onMirrorCreated]({ mirror }) { this.mirror = mirror; } /** * Mirror destroy handler * @param {MirrorDestroyEvent} mirrorEvent * @private */ [onMirrorDestroy]() { this.mirror = null; } } exports.default = Snappable; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; const canceled = Symbol('canceled'); /** * All events fired by draggable inherit this class. You can call `cancel()` to * cancel a specific event or you can check if an event has been canceled by * calling `canceled()`. * @abstract * @class AbstractEvent * @module AbstractEvent */ class AbstractEvent { /** * AbstractEvent constructor. * @constructs AbstractEvent * @param {object} data - Event data */ /** * Event type * @static * @abstract * @property type * @type {String} */ constructor(data) { this[canceled] = false; this.data = data; } /** * Read-only type * @abstract * @return {String} */ /** * Event cancelable * @static * @abstract * @property cancelable * @type {Boolean} */ get type() { return this.constructor.type; } /** * Read-only cancelable * @abstract * @return {Boolean} */ get cancelable() { return this.constructor.cancelable; } /** * Cancels the event instance * @abstract */ cancel() { this[canceled] = true; } /** * Check if event has been canceled * @abstract * @return {Boolean} */ canceled() { return Boolean(this[canceled]); } /** * Returns new event instance with existing event data. * This method allows for overriding of event data. * @param {Object} data * @return {AbstractEvent} */ clone(data) { return new this.constructor(_extends({}, this.data, data)); } } exports.default = AbstractEvent; AbstractEvent.type = 'event'; AbstractEvent.cancelable = false; /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _AbstractEvent = __webpack_require__(4); var _AbstractEvent2 = _interopRequireDefault(_AbstractEvent); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = _AbstractEvent2.default; /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SnapOutEvent = exports.SnapInEvent = exports.SnapEvent = undefined; var _AbstractEvent = __webpack_require__(5); var _AbstractEvent2 = _interopRequireDefault(_AbstractEvent); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Base snap event * @class SnapEvent * @module SnapEvent * @extends AbstractEvent */ class SnapEvent extends _AbstractEvent2.default { /** * Drag event that triggered this snap event * @property dragEvent * @type {DragEvent} * @readonly */ get dragEvent() { return this.data.dragEvent; } /** * Snappable element * @property snappable * @type {HTMLElement} * @readonly */ get snappable() { return this.data.snappable; } } exports.SnapEvent = SnapEvent; /** * Snap in event * @class SnapInEvent * @module SnapInEvent * @extends SnapEvent */ SnapEvent.type = 'snap'; class SnapInEvent extends SnapEvent {} exports.SnapInEvent = SnapInEvent; /** * Snap out event * @class SnapOutEvent * @module SnapOutEvent * @extends SnapEvent */ SnapInEvent.type = 'snap:in'; SnapInEvent.cancelable = true; class SnapOutEvent extends SnapEvent {} exports.SnapOutEvent = SnapOutEvent; SnapOutEvent.type = 'snap:out'; SnapOutEvent.cancelable = true; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _SnappableEvent = __webpack_require__(0); Object.keys(_SnappableEvent).forEach(function (key) { if (key === "default" || key === "__esModule") return; Object.defineProperty(exports, key, { enumerable: true, get: function () { return _SnappableEvent[key]; } }); }); var _Snappable = __webpack_require__(3); var _Snappable2 = _interopRequireDefault(_Snappable); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = _Snappable2.default; /***/ }) /******/ ]); });