UNPKG

ember-sortable

Version:
1,011 lines (959 loc) 31 kB
import { a as _defineProperty, _ as _applyDecoratedDescriptor, b as _initializerDefineProperty } from '../_rollupPluginBabelHelpers-a7bede49.js'; import Modifier from 'ember-modifier'; import { action, set } from '@ember/object'; import { DRAG_ACTIONS, END_ACTIONS, ELEMENT_CLICK_ACTION } from '../utils/constant.js'; import { bind, scheduleOnce, throttle, later, run } from '@ember/runloop'; import { isTesting, macroCondition, isDevelopingApp } from '@embroider/macros'; import { getX, getY } from '../utils/coordinate.js'; import { getBorderSpacing } from '../utils/css-calculation.js'; import { buildWaiter } from '@ember/test-waiters'; import * as s from '@ember/service'; import { assert, deprecate } from '@ember/debug'; import { registerDestructor } from '@ember/destroyable'; class ScrollContainer { constructor(element) { _defineProperty(this, "element", void 0); _defineProperty(this, "isWindow", void 0); _defineProperty(this, "top", void 0); _defineProperty(this, "left", void 0); _defineProperty(this, "width", void 0); _defineProperty(this, "height", void 0); _defineProperty(this, "scrollWidth", void 0); _defineProperty(this, "scrollHeight", void 0); _defineProperty(this, "maxScrollTop", void 0); _defineProperty(this, "maxScrollLeft", void 0); this.isWindow = element === document; this.element = this.isWindow ? document.documentElement : element; if (this.isWindow) { this.top = 0; this.left = 0; this.width = document.documentElement.clientWidth; this.height = document.documentElement.clientHeight; } else { // Absolute position in document const { top, left } = this.element.getBoundingClientRect(); this.top = top; this.left = left; // Viewport size of the container element this.width = parseFloat(getComputedStyle(this.element).width); this.height = parseFloat(getComputedStyle(this.element).height); } // Total size of the container element (including scrollable part) this.scrollWidth = this.element.scrollWidth; this.scrollHeight = this.element.scrollHeight; // Max scroll pos this.maxScrollTop = this.scrollHeight - this.height; this.maxScrollLeft = this.scrollWidth - this.width; } get bottom() { return this.top + this.height; } get right() { return this.left + this.width; } scrollTop(value) { if (value) { value = Math.max(0, Math.min(this.maxScrollTop, value)); this.element.scrollTop = value; return value; } return this.element.scrollTop; } scrollLeft(value) { if (value) { value = Math.max(0, Math.min(this.maxScrollLeft, value)); this.element.scrollLeft = value; return value; } return this.element.scrollLeft; } } function getParentElements(element) { const parentsArray = []; if (!element) { return parentsArray; } let currentParent = element.parentElement; while (currentParent !== null) { parentsArray.push(currentParent); currentParent = currentParent.parentElement; } return parentsArray; } function scrollParent (element) { const position = getComputedStyle(element).position; const excludeStaticParent = position === 'absolute'; let scrollParent = getParentElements(element).filter(function (parent) { const parentElemStyles = getComputedStyle(parent); if (excludeStaticParent && parentElemStyles.position === 'static') { return false; } const { overflow, overflowX, overflowY } = parentElemStyles; return /(auto|scroll)/.test(overflow + overflowX + overflowY); })[0]; if (!scrollParent || scrollParent === document.body) { scrollParent = document; } return scrollParent; } var _dec, _class, _descriptor; const service = s.service ?? s.inject; const sortableItemWaiter = buildWaiter('sortable-item-waiter'); /** * Modifier to mark an element as an item to be reordered * * @param {Object} model The model that this item will represent * @param {boolean} [disabled=false] Set to true to make this item not sortable * @param {Function} [onDragStart] An optional callback for when dragging starts. * @param {Function} [onDragStop] An optional callback for when dragging stops. * * @module drag-drop/draggable-group * @example * <ol {{sortable-group onChange=this.update a11yAnnouncementConfig=this.myA11yConfig}}> * {{#each model.items as |item|}} * <li {{sortable-item model=item}}> * {{item.name}} * <span class="handle" {{sortable-handle}}>&varr;</span> * </li> * {{/each}} * </ol> */ let SortableItemModifier = (_dec = service('ember-sortable-internal-state'), _class = class SortableItemModifier extends Modifier { /** * The SortableGroupModifier this item belongs to. Assigned by the group * when it inspects all the items in the list * * @type SortableGroupModifier */ get sortableGroup() { if (this._sortableGroup === undefined) { this._sortableGroup = this.sortableService.fetchGroup(this.groupName); assert(`No sortable group named ${this.groupName} found. Please check that the groups and items have the same groupName`, this._sortableGroup !== undefined); } return this._sortableGroup.groupModifier; } get model() { return this.named.model; } get direction() { return this.sortableGroup?.direction; } get groupDisabled() { return this.sortableGroup?.disabled; } /** * This is the group name used to keep groups separate if there are more than one on the screen at a time. * If no group is assigned a default is used * * @default "_EmberSortableGroup" * @returns {string} */ get groupName() { return this.named.groupName || '_EmberSortableGroup'; } /** The frequency with which the group is informed that an update is required. @property updateInterval @type Number @default 125 */ get updateInterval() { return this.named.updateInterval || 125; } /** Additional spacing between active item and the rest of the elements. @property spacing @type Number @default 0[px] */ get spacing() { return this.named.spacing || 0; } /** Removes the ability for the current item to be sorted @property disabled @type boolean @default false */ get isDisabled() { deprecate('"isDraggingDisabled" is deprecated. Please migrate to "disabled" named argument', !('isDraggingDisabled' in this.named), { id: 'ember-sortable.is-dragging-disabled', url: 'https://github.com/adopted-ember-addons/ember-sortable#readme', until: '3.0.0', for: 'ember-sortable', since: { available: '2.2.6', enabled: '2.2.6' } }); return this.groupDisabled || this.named.disabled || this.named.isDraggingDisabled || false; } /** Selector for the element to use as handle. 1. By default, we will hook it the yielded sortable-handle. 2. If you don't use the sortable-handle, the entire element will be used as the handle. 3. In very rare situations, if you want to use a handle, but not the sortable-handle, you can override this class with your own handle's selector. This behavior will be synonymous with v1 @property handle @type String @default "[data-sortable-handle]" */ get handle() { return this.named.handle || '[data-sortable-handle]'; } /** * Tolerance, in pixels, for when sorting should start. * If specified, sorting will not start until after mouse * is dragged beyond distance. Can be used to allow for clicks * on elements within a handle. * * @property distance * @type Integer * @default 0 */ get distance() { return this.named.distance || 0; } /** * True if the item is currently being dragged. * * @property isDragging * @type boolean * @default false * @protected */ get isDragging() { return this._isDragging; } set isDragging(value) { if (value) { this.element.classList.add('is-dragging'); } else { this.element.classList.remove('is-dragging'); } this._isDragging = value; } /** * Gives info in which direction the element will be moved * * @property moveDirection * @type Object */ get moveDirection() { const moveDirection = { left: false, right: false, top: false, bottom: false }; if (!this.isDragging) { return moveDirection; } const dragOriginX = this._dragOriginX; const dragOriginY = this._dragOriginY; if (dragOriginX && this._pageX && dragOriginX > this._pageX) { moveDirection.left = true; } if (dragOriginX && this._pageX && dragOriginX < this._pageX) { moveDirection.right = true; } if (dragOriginY && this._pageY && dragOriginY > this._pageY) { moveDirection.top = true; } if (dragOriginY && this._pageY && dragOriginY < this._pageY) { moveDirection.bottom = true; } return moveDirection; } /** Action that fires when the item starts being dragged. @property onDragStart @type Function @param {Object} item model @default null */ get onDragStart() { return this.named.onDragStart || (item => item); } /** Action that fires when the item stops being dragged. @property onDragStop @type Function @param {Object} item model @default null */ get onDragStop() { return this.named.onDragStop || (item => item); } /** True if the item is currently dropping. @property isDropping @type Boolean @default false */ get isDropping() { return this._isDropping; } set isDropping(value) { if (value) { this.element.classList.add('is-dropping'); } else { this.element.classList.remove('is-dropping'); } this._isDropping = value; } /** True if the item was dropped during the interaction @property wasDropped @type Boolean @default false */ /** @property isBusy @type Boolean */ get isBusy() { return this.isDragging || this.isDropping; } /** @property disableCheckScrollBounds */ get disableCheckScrollBounds() { return this.named.disableCheckScrollBounds !== undefined ? this.named.disableCheckScrollBounds : isTesting(); } /** @method mouseDown */ mouseDown(event) { if (event.which !== 1) { return; } if (event.ctrlKey) { return; } this._primeDrag(event); } keyDown(event) { if (this.isDisabled) { return; } this.setupHandleElement(); // If the event is coming from within the item, we do not want to activate keyboard reorder mode. if (event.target === this.handleElement || event.target === this.element) { this.sortableGroup.activateKeyDown(this); } else { this.sortableGroup.deactivateKeyDown(); } } /** @method touchStart */ touchStart(event) { this._primeDrag(event); } /** @method freeze */ freeze() { const el = this.element; if (!el) { return; } el.style.transition = 'none'; } /** @method reset */ reset() { const el = this.element; if (!el) { return; } delete this._y; delete this._x; el.style.transform = ''; } /** @method thaw */ thaw() { const el = this.element; if (!el) { return; } el.style.transition = ''; } /** * Setup event listeners for drag and drop * * @method _primeDrag * @param {Event} startEvent JS Event object * @private */ _primeDrag(startEvent) { if (this.isDisabled) { return; } if (this.handleElement && !startEvent.target?.closest(this.handle)) { return; } startEvent.preventDefault(); startEvent.stopPropagation(); this._prepareDragListener = bind(this, this._prepareDrag, startEvent); DRAG_ACTIONS.forEach(event => window.addEventListener(event, this._prepareDragListener)); this._cancelStartDragListener = () => { DRAG_ACTIONS.forEach(event => window.removeEventListener(event, this._prepareDragListener)); }; const selfCancellingCallback = () => { END_ACTIONS.forEach(event => window.removeEventListener(event, selfCancellingCallback)); this._cancelStartDragListener(); }; END_ACTIONS.forEach(event => window.addEventListener(event, selfCancellingCallback)); } /** * Prepares for the drag event * * @method _prepareDrag * @param {Event} startEvent JS Event object * @param {Event} event JS Event object * @private */ _prepareDrag(startEvent, event) { // Block drag start while any item has busy state if (this.sortableGroup.sortedItems.some(x => x.isBusy)) { return; } const distance = this.distance; const dx = Math.abs(getX(startEvent) - getX(event)); const dy = Math.abs(getY(startEvent) - getY(event)); if (distance <= dx || distance <= dy) { DRAG_ACTIONS.forEach(event => window.removeEventListener(event, this._prepareDragListener)); this._startDrag(startEvent); } } /** * Start dragging & setup more event listeners * * @method _startDrag * @param {Event} event JS Event object * @private */ _startDrag(event) { if (this.isBusy) { return; } const drag = this._makeDragHandler(event); const dragThrottled = ev => throttle(this, drag, ev, 16, false); const drop = () => { DRAG_ACTIONS.forEach(event => window.removeEventListener(event, dragThrottled)); END_ACTIONS.forEach(event => window.removeEventListener(event, drop)); run(() => { this._drop(); }); }; DRAG_ACTIONS.forEach(event => window.addEventListener(event, dragThrottled)); END_ACTIONS.forEach(event => window.addEventListener(event, drop)); this.sortableGroup.prepare(); set(this, 'isDragging', true); this.onDragStart(this.model); this._scrollOnEdges(drag); } /** The maximum scroll speed when dragging element. @property maxScrollSpeed @default 20 */ _scrollOnEdges(drag) { const groupDirection = this.direction; const element = this.element; const scrollContainer = new ScrollContainer(scrollParent(element)); const itemContainer = { width: parseInt(getComputedStyle(element).width, 10), get height() { return parseInt(getComputedStyle(element).height, 10); }, get left() { return element.getBoundingClientRect().left; }, get right() { return this.left + this.width; }, get top() { return element.getBoundingClientRect().top; }, get bottom() { return this.top + this.height; } }; let leadingEdgeKey, trailingEdgeKey, scrollKey, pageKey; if (groupDirection === 'grid' || groupDirection === 'x') { leadingEdgeKey = 'left'; trailingEdgeKey = 'right'; scrollKey = 'scrollLeft'; pageKey = 'pageX'; } else { leadingEdgeKey = 'top'; trailingEdgeKey = 'bottom'; scrollKey = 'scrollTop'; pageKey = 'pageY'; } const createFakeEvent = () => { if (this._pageX == null && this._pageY == null) { return; } return { pageX: this._pageX ?? 0, pageY: this._pageY ?? 0, clientX: this._pageX ?? 0, clientY: this._pageY ?? 0 }; }; // Set a trigger padding that will start scrolling // the box when the item reaches within padding pixels // of the edge of the scroll container. const checkScrollBounds = () => { const leadingEdge = itemContainer[leadingEdgeKey]; const trailingEdge = itemContainer[trailingEdgeKey]; const scroll = scrollContainer[scrollKey](); let delta = 0; if (trailingEdge >= scrollContainer[trailingEdgeKey]) { delta = trailingEdge - scrollContainer[trailingEdgeKey]; } else if (leadingEdge <= scrollContainer[leadingEdgeKey]) { delta = leadingEdge - scrollContainer[leadingEdgeKey]; } if (delta !== 0) { const speed = this.maxScrollSpeed; delta = Math.min(Math.max(delta, -1 * speed), speed); delta = scrollContainer[scrollKey](scroll + delta) - scroll; const event = createFakeEvent(); if (event) { if (scrollContainer.isWindow) { event[pageKey] += delta; } run(() => drag(event)); } } if (this.isDragging) { requestAnimationFrame(checkScrollBounds); } }; if (!this.disableCheckScrollBounds) { requestAnimationFrame(checkScrollBounds); } } /** @method _makeDragHandler @param {Event} startEvent @return {Function} @private */ _makeDragHandler(startEvent) { const groupDirection = this.direction; let dragOrigin; let elementOrigin; let scrollOrigin; const parentElement = this.element.parentNode; if (!parentElement) { return () => {}; } if (groupDirection === 'grid') { this.startEvent = startEvent; const dragOriginX = getX(startEvent); this._dragOriginX = getX(startEvent); const elementOriginX = this.x; const scrollOriginX = parentElement.getBoundingClientRect().left; const dragOriginY = getY(startEvent); this._dragOriginY = dragOriginY; const elementOriginY = this.y; const scrollOriginY = parentElement.getBoundingClientRect().top; return event => { this._pageX = getX(event); const dx = this._pageX - dragOriginX; const scrollX = parentElement.getBoundingClientRect().left; const x = elementOriginX + dx + (scrollOriginX - scrollX); this._pageY = getY(event); const dy = this._pageY - dragOriginY; const scrollY = parentElement.getBoundingClientRect().top; const y = elementOriginY + dy + (scrollOriginY - scrollY); this._drag(x, y); }; } if (groupDirection === 'x') { dragOrigin = getX(startEvent); elementOrigin = this.x; scrollOrigin = parentElement.getBoundingClientRect().left; return event => { this._pageX = getX(event); const dx = this._pageX - dragOrigin; const scrollX = parentElement.getBoundingClientRect().left; const x = elementOrigin + dx + (scrollOrigin - scrollX); this._drag(x, 0); }; } if (groupDirection === 'y') { dragOrigin = getY(startEvent); elementOrigin = this.y; scrollOrigin = parentElement.getBoundingClientRect().top; return event => { this._pageY = getY(event); const dy = this._pageY - dragOrigin; const scrollY = parentElement.getBoundingClientRect().top; const y = elementOrigin + dy + (scrollOrigin - scrollY); this._drag(0, y); }; } return () => {}; } /** @method _scheduleApplyPosition @private */ _scheduleApplyPosition() { scheduleOnce('render', this, this._applyPosition); } /** @method _applyPosition @private */ _applyPosition() { if (!this.element || !this.element) { return; } const groupDirection = this.direction; if (groupDirection === 'grid') { const x = this.x; const dx = x - this.element.offsetLeft + parseFloat(getComputedStyle(this.element).marginLeft); const y = this.y; const dy = y - this.element.offsetTop; this.element.style.transform = `translate(${dx}px, ${dy}px)`; } if (groupDirection === 'x') { const x = this.x; const dx = x - this.element.offsetLeft + parseFloat(getComputedStyle(this.element).marginLeft); this.element.style.transform = `translateX(${dx}px)`; } if (groupDirection === 'y') { const y = this.y; const dy = y - this.element.offsetTop; this.element.style.transform = `translateY(${dy}px)`; } } /** @method _drag @private */ _drag(dimensionX, dimensionY) { if (!this.isDragging) { return; } const updateInterval = this.updateInterval; this.x = dimensionX; this.y = dimensionY; // @ts-expect-error Argument of type 'this' is not assignable to parameter of type 'AnyFn'. throttle(this, this.sortableGroup.update, updateInterval); } /** @method _drop @private */ _drop() { if (!this.element) { return; } const transitionPromise = this._waitForTransition(); this._preventClick(); // Get sortableItems before making drop end and pass it to update function // This is necessary for direction grid, otherwise ordering is not working correctly (because in sortedItems we check if item isDragged) // Calling this getter here, makes no difference for other directions const sortedItems = this.sortableGroup.sortedItems; set(this, 'isDragging', false); set(this, 'isDropping', true); this.sortableGroup.update(sortedItems); const allTransitionPromise = this._waitForAllTransitions(); Promise.all([transitionPromise, allTransitionPromise]).then(() => this._complete()); } /** @method _preventClick @private */ _preventClick() { const selfCancellingCallback = event => { this.element.removeEventListener(ELEMENT_CLICK_ACTION, selfCancellingCallback); this._preventClickHandler(event); }; this.element.addEventListener(ELEMENT_CLICK_ACTION, selfCancellingCallback); } /** @method _preventClickHandler @private */ _preventClickHandler(e) { e.stopPropagation(); e.preventDefault(); e.stopImmediatePropagation(); } /** @method _waitForTransition @private @return Promise */ _waitForTransition() { let waiterToken; if (macroCondition(isDevelopingApp())) { waiterToken = sortableItemWaiter.beginAsync(); } let transitionPromise; if (this.isAnimated) { transitionPromise = new Promise(resolve => { let resolved = false; const handler = () => { if (resolved) return; resolved = true; this.element.removeEventListener('transitionend', handler); resolve(); }; this.element.addEventListener('transitionend', handler); const duration = this.transitionDuration; // When transition is ended before we have added the event (found this issue already with 125ms), the dragging is blocked, since fully page refresh // To ensure that this would never happen, we need an later, to resolve the promise, when it wasn't resolved by transitionEnd // The duration addition with 200ms is just a choice (taken from else case), its just a way to let transitionend a little bit more time // Note: Unfortunately this issue is also not solvable with Element.getAnimations(), getAnimations brings no active animation at this point later(() => { handler(); }, duration + 200); }); } else { transitionPromise = new Promise(resolve => later(resolve, 200)); } if (macroCondition(isDevelopingApp())) { transitionPromise = transitionPromise.finally(() => { sortableItemWaiter.endAsync(waiterToken); }); } return transitionPromise; } /** @method _waitForTransitions @private @return Promise */ _waitForAllTransitions() { let waiterToken; if (macroCondition(isDevelopingApp())) { waiterToken = sortableItemWaiter.beginAsync(); } let transitionPromise; if (this.isAnimated) { const animations = this.sortableGroup.sortedItems.map(x => x.element.getAnimations()); const animationPromises = animations.flatMap(animationList => { return animationList.map(animation => animation.finished); }); transitionPromise = Promise.all(animationPromises); } else { const duration = this.isAnimated ? this.transitionDuration : 200; transitionPromise = new Promise(resolve => later(resolve, duration)); } if (macroCondition(isDevelopingApp())) { transitionPromise = transitionPromise.finally(() => { sortableItemWaiter.endAsync(waiterToken); }); } return transitionPromise; } /** @method _complete @private */ _complete() { this.onDragStop(this.model); set(this, 'isDropping', false); set(this, 'wasDropped', true); this.sortableGroup.commit(); } get isAnimated() { if (!this.element) { return undefined; } const el = this.element; const transitionProperty = getComputedStyle(el).transitionProperty; return /all|transform/.test(transitionProperty) && this.transitionDuration > 0; } /** The current transition duration in milliseconds. @property transitionDuration @type Number */ get transitionDuration() { const items = this.sortableGroup.sortedItems.filter(x => !x.isDragging && !x.isDropping); const el = items[0]?.element ?? this.element; // Fallback when only one element is present in list const rule = getComputedStyle(el).transitionDuration; const match = rule.match(/([\d.]+)([ms]*)/); if (match) { let value = parseFloat(match[1] ?? ''); const unit = match[2]; if (unit === 's') { value = value * 1000; } return value; } return 0; } /** Horizontal position of the item. @property x @type Number */ get x() { if (this._x === undefined) { const marginLeft = parseFloat(getComputedStyle(this.element).marginLeft); this._x = this.element.scrollLeft + this.element.offsetLeft - marginLeft; } return this._x; } set x(value) { if (value !== this._x) { this._x = value; this._scheduleApplyPosition(); } } /** Vertical position of the item relative to its offset parent. @property y @type Number */ get y() { if (this._y === undefined) { this._y = this.element.offsetTop; } return this._y; } set y(value) { if (value !== this._y) { this._y = value; this._scheduleApplyPosition(); } } /** Width of the item. @property height @type Number */ get width() { const el = this.element; let width = el.offsetWidth; const elStyles = getComputedStyle(el); width += parseInt(elStyles.marginLeft) + parseInt(elStyles.marginRight); // equal to jQuery.outerWidth(true) width += getBorderSpacing(el).horizontal; return width; } /** Height of the item including margins. @property height @type Number */ get height() { const el = this.element; let height = el.offsetHeight; const elStyles = getComputedStyle(el); // This is needed atm only for grid, to fix jumping on drag-start. // In test-app it looks like there is a side-effect when we activate also for direction vertical. // If any user will anytime report a jumping in vertical direction, we should activate for every direction and fix our test-app if (this.direction === 'grid') { height += parseFloat(elStyles.marginTop); } height += parseFloat(elStyles.marginBottom); height += getBorderSpacing(el).vertical; return height; } addEventListener() { this.element.addEventListener('keydown', this.keyDown); this.element.addEventListener('mousedown', this.mouseDown); this.element.addEventListener('touchstart', this.touchStart); this.listenersRegistered = true; } removeEventListener() { this.element.removeEventListener('keydown', this.keyDown); this.element.removeEventListener('mousedown', this.mouseDown); this.element.removeEventListener('touchstart', this.touchStart); this.listenersRegistered = false; } setupHandleElement(disabled = false) { this.handleElement = this.element.querySelector(this.handle); const touchAction = disabled ? 'initial' : 'none'; if (this.handleElement) { this.handleElement.style['touchAction'] = touchAction; } else { this.element.style['touchAction'] = touchAction; } } constructor(owner, args) { super(owner, args); _defineProperty(this, "className", 'sortable-item'); _initializerDefineProperty(this, "sortableService", _descriptor, this); _defineProperty(this, "startEvent", void 0); _defineProperty(this, "_sortableGroup", void 0); _defineProperty(this, "_x", void 0); _defineProperty(this, "_y", void 0); _defineProperty(this, "_dragOriginX", void 0); _defineProperty(this, "_dragOriginY", void 0); _defineProperty(this, "_pageX", void 0); _defineProperty(this, "_pageY", void 0); _defineProperty(this, "handleElement", void 0); _defineProperty(this, "_isDragging", false); _defineProperty(this, "_isDropping", false); _defineProperty(this, "wasDropped", false); _defineProperty(this, "_prepareDragListener", void 0); _defineProperty(this, "_cancelStartDragListener", void 0); _defineProperty(this, "maxScrollSpeed", 20); _defineProperty(this, "element", void 0); _defineProperty(this, "didSetup", false); _defineProperty(this, "named", void 0); /** * tracks if event listeners have been registered. Registering event handlers is unnecessary if item is disabled. */ _defineProperty(this, "listenersRegistered", false); registerDestructor(this, cleanup); } modify(element, _positional, named) { this.element = element; this.named = named; this.element.classList.add(this.className); // Instead of using `event.preventDefault()` in the 'primeDrag' event, // (doesn't work in Chrome 56), we set touch-action: none as a workaround. this.setupHandleElement(this.named.disabled); if (!this.didSetup) { this.element.dataset['sortableItem'] = 'true'; this.sortableService.registerItem(this.groupName, this); this.didSetup = true; } if (this.named.disabled && this.listenersRegistered) { this.removeEventListener(); } else if (!this.named.disabled && !this.listenersRegistered) { this.addEventListener(); } } }, _descriptor = _applyDecoratedDescriptor(_class.prototype, "sortableService", [_dec], { configurable: true, enumerable: true, writable: true, initializer: null }), _applyDecoratedDescriptor(_class.prototype, "mouseDown", [action], Object.getOwnPropertyDescriptor(_class.prototype, "mouseDown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "keyDown", [action], Object.getOwnPropertyDescriptor(_class.prototype, "keyDown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "touchStart", [action], Object.getOwnPropertyDescriptor(_class.prototype, "touchStart"), _class.prototype), _class); /** * * @param {SortableItemModifier} instance */ function cleanup(instance) { instance.removeEventListener(); instance.sortableService.deregisterItem(instance.groupName, instance); } export { SortableItemModifier as default }; //# sourceMappingURL=sortable-item.js.map