@storipress/vue-slicksort
Version:
Set of mixins to turn any list into a sortable, touch-friendly, animated list
1,372 lines • 56 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
// Export Sortable Element Component Mixin
var ElementMixin = vue.defineComponent({
inject: ['manager'],
props: {
index: {
type: Number,
required: true
},
disabled: {
type: Boolean,
"default": false
}
},
data: function () {
return {};
},
watch: {
index: function (newIndex) {
if (this.$el && this.$el.sortableInfo) {
this.$el.sortableInfo.index = newIndex;
}
},
disabled: function (isDisabled) {
if (isDisabled) {
this.removeDraggable();
}
else {
this.setDraggable(this.index);
}
}
},
mounted: function () {
var _a = this.$props, disabled = _a.disabled, index = _a.index;
if (!disabled) {
this.setDraggable(index);
}
},
beforeUnmount: function () {
if (!this.disabled)
this.removeDraggable();
},
methods: {
setDraggable: function (index) {
var node = this.$el;
node.sortableInfo = {
index: index,
manager: this.manager
};
this.ref = { node: node };
this.manager.add(this.ref);
},
removeDraggable: function () {
this.manager.remove(this.ref);
}
}
});
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var Manager = /** @class */ (function () {
function Manager() {
this.refs = [];
this.active = null;
}
Manager.prototype.add = function (ref) {
if (!this.refs) {
this.refs = [];
}
this.refs.push(ref);
};
Manager.prototype.remove = function (ref) {
var index = this.getIndex(ref);
if (index !== -1) {
this.refs.splice(index, 1);
}
};
Manager.prototype.isActive = function () {
return !!this.active;
};
Manager.prototype.getActive = function () {
var _this = this;
return this.refs.find(function (_a) {
var _b, _c;
var node = _a.node;
return ((_b = node === null || node === void 0 ? void 0 : node.sortableInfo) === null || _b === void 0 ? void 0 : _b.index) == ((_c = _this === null || _this === void 0 ? void 0 : _this.active) === null || _c === void 0 ? void 0 : _c.index);
}) || null;
};
Manager.prototype.getIndex = function (ref) {
return this.refs.indexOf(ref);
};
Manager.prototype.getRefs = function () {
return this.refs;
};
Manager.prototype.getOrderedRefs = function () {
return this.refs.sort(function (a, b) {
return a.node.sortableInfo.index - b.node.sortableInfo.index;
});
};
return Manager;
}());
var isTouch = function (e) {
return e.touches != null;
};
// eslint-disable-next-line @typescript-eslint/ban-types
function hasOwnProperty(obj, prop) {
return !!obj && Object.prototype.hasOwnProperty.call(obj, prop);
}
function arrayMove(arr, previousIndex, newIndex) {
var array = arr.slice(0);
if (newIndex >= array.length) {
var k = newIndex - array.length;
while (k-- + 1) {
array.push(undefined);
}
}
array.splice(newIndex, 0, array.splice(previousIndex, 1)[0]);
return array;
}
function arrayRemove(arr, previousIndex) {
var array = arr.slice(0);
if (previousIndex >= array.length)
return array;
array.splice(previousIndex, 1);
return array;
}
function arrayInsert(arr, newIndex, value) {
var array = arr.slice(0);
if (newIndex === array.length) {
array.push(value);
}
else {
array.splice(newIndex, 0, value);
}
return array;
}
var events = {
start: ['touchstart', 'mousedown'],
move: ['touchmove', 'mousemove'],
end: ['touchend', 'mouseup'],
cancel: ['touchcancel', 'keyup']
};
function closest(el, fn) {
while (el) {
if (fn(el))
return el;
el = el.parentNode;
}
}
function limit(min, max, value) {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
}
function getCSSPixelValue(stringValue) {
if (stringValue.substr(-2) === 'px') {
return parseFloat(stringValue);
}
return 0;
}
function getElementMargin(element) {
var style = window.getComputedStyle(element);
return {
top: getCSSPixelValue(style.marginTop),
right: getCSSPixelValue(style.marginRight),
bottom: getCSSPixelValue(style.marginBottom),
left: getCSSPixelValue(style.marginLeft)
};
}
function getPointerOffset(e, reference) {
if (reference === void 0) { reference = 'page'; }
var x = "".concat(reference, "X");
var y = "".concat(reference, "Y");
return {
x: isTouch(e) ? e.touches[0][x] : e[x],
y: isTouch(e) ? e.touches[0][y] : e[y]
};
}
function offsetParents(node) {
var nodes = [node];
for (; node; node = node.offsetParent) {
nodes.unshift(node);
}
return nodes;
}
function commonOffsetParent(node1, node2) {
var parents1 = offsetParents(node1);
var parents2 = offsetParents(node2);
if (parents1[0] != parents2[0])
throw 'No common ancestor!';
for (var i = 0; i < parents1.length; i++) {
if (parents1[i] != parents2[i])
return parents1[i - 1];
}
}
function getEdgeOffset(node, container, offset) {
if (offset === void 0) { offset = { top: 0, left: 0 }; }
// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested
if (node) {
var nodeOffset = {
top: offset.top + node.offsetTop,
left: offset.left + node.offsetLeft
};
if (node.offsetParent !== container.offsetParent) {
return getEdgeOffset(node.offsetParent, container, nodeOffset);
}
else {
return nodeOffset;
}
}
return { top: 0, left: 0 };
}
function cloneNode(node) {
var fields = node.querySelectorAll('input, textarea, select');
var clonedNode = node.cloneNode(true);
var clonedFields = __spreadArray([], __read(clonedNode.querySelectorAll('input, textarea, select')), false); // Convert NodeList to Array
clonedFields.forEach(function (field, index) {
if (field.type !== 'file' && fields[index]) {
field.value = fields[index].value;
}
});
return clonedNode;
}
function getLockPixelOffsets(lockOffset, width, height) {
if (typeof lockOffset == 'string') {
lockOffset = +lockOffset;
}
if (!Array.isArray(lockOffset)) {
lockOffset = [lockOffset, lockOffset];
}
if (lockOffset.length !== 2) {
throw new Error("lockOffset prop of SortableContainer should be a single value or an array of exactly two values. Given ".concat(lockOffset));
}
var _a = __read(lockOffset, 2), minLockOffset = _a[0], maxLockOffset = _a[1];
return [getLockPixelOffset(minLockOffset, width, height), getLockPixelOffset(maxLockOffset, width, height)];
}
function getLockPixelOffset(lockOffset, width, height) {
var offsetX = lockOffset;
var offsetY = lockOffset;
var unit = 'px';
if (typeof lockOffset === 'string') {
var match = /^[+-]?\d*(?:\.\d*)?(px|%)$/.exec(lockOffset);
if (match === null) {
throw new Error("lockOffset value should be a number or a string of a number followed by \"px\" or \"%\". Given ".concat(lockOffset));
}
offsetX = offsetY = parseFloat(lockOffset);
unit = match[1];
}
if (!isFinite(offsetX) || !isFinite(offsetY)) {
throw new Error("lockOffset value should be a finite. Given ".concat(lockOffset));
}
if (unit === '%') {
offsetX = (offsetX * width) / 100;
offsetY = (offsetY * height) / 100;
}
return {
x: offsetX,
y: offsetY
};
}
function getDistance(x1, y1, x2, y2) {
var x = x1 - x2;
var y = y1 - y2;
return Math.sqrt(x * x + y * y);
}
function getRectCenter(clientRect) {
return {
x: clientRect.left + clientRect.width / 2,
y: clientRect.top + clientRect.height / 2
};
}
function resetTransform(nodes) {
if (nodes === void 0) { nodes = []; }
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i];
var el = node.node;
if (!el)
return;
// Clear the cached offsetTop / offsetLeft value
node.edgeOffset = null;
// Remove the transforms / transitions
setTransform(el);
}
}
function setTransform(el, transform, duration) {
if (transform === void 0) { transform = ''; }
if (duration === void 0) { duration = ''; }
if (!el)
return;
el.style['transform'] = transform;
el.style['transitionDuration'] = duration;
}
function withinBounds(pos, top, bottom) {
var upper = Math.max(top, bottom);
var lower = Math.min(top, bottom);
return lower <= pos && pos <= upper;
}
function isPointWithinRect(_a, _b) {
var x = _a.x, y = _a.y;
var top = _b.top, left = _b.left, width = _b.width, height = _b.height;
var withinX = withinBounds(x, left, left + width);
var withinY = withinBounds(y, top, top + height);
return withinX && withinY;
}
// eslint-disable-next-line @typescript-eslint/ban-types
var timeout = setTimeout;
// Export Sortable Container Component Mixin
var ContainerMixin = vue.defineComponent({
inject: {
SlicksortHub: {
from: 'SlicksortHub',
"default": null
}
},
provide: function () {
return {
manager: this.manager
};
},
props: {
list: { type: Array, required: true },
axis: { type: String, "default": 'y' },
distance: { type: Number, "default": 0 },
pressDelay: { type: Number, "default": 0 },
pressThreshold: { type: Number, "default": 5 },
useDragHandle: { type: Boolean, "default": false },
useWindowAsScrollContainer: { type: Boolean, "default": false },
hideSortableGhost: { type: Boolean, "default": true },
lockToContainerEdges: { type: Boolean, "default": false },
lockOffset: { type: [String, Number, Array], "default": '50%' },
transitionDuration: { type: Number, "default": 300 },
appendTo: { type: String, "default": 'body' },
draggedSettlingDuration: { type: Number, "default": null },
group: { type: String, "default": '' },
accept: { type: [Boolean, Array, Function], "default": null },
cancelKey: { type: String, "default": 'Escape' },
block: { type: Array, "default": function () { return []; } },
lockAxis: { type: String, "default": '' },
helperClass: { type: String, "default": '' },
contentWindow: { type: Object, "default": null },
shouldCancelStart: {
type: Function,
"default": function (e) {
// Cancel sorting if the event target is an `input`, `textarea`, `select` or `option`
var disabledElements = ['input', 'textarea', 'select', 'option', 'button'];
return disabledElements.indexOf(e.target.tagName.toLowerCase()) !== -1;
}
},
getHelperDimensions: {
type: Function,
"default": function (_a) {
var node = _a.node;
return ({
width: node.offsetWidth,
height: node.offsetHeight
});
}
},
setHelperStyle: {
type: Function,
"default": function (el, data) {
if (data) {
setTransform(el, "translate3d(".concat(data.targetX, "px, ").concat(data.targetY, "px, 0)"), "".concat(data.duration, "ms"));
}
else {
setTransform(el);
}
}
}
},
emits: ['sort-start', 'sort-move', 'sort-end', 'sort-cancel', 'sort-insert', 'sort-remove', 'drag-in', 'drag-out', 'drag-end', 'update:list'],
data: function () {
var useHub = false;
if (this.group) {
// If the group option is set, it is assumed the user intends
// to drag between containers and the required plugin has been installed
if (this.SlicksortHub) {
useHub = true;
}
else if (process.env.NODE_ENV !== 'production') {
throw new Error('Slicksort plugin required to use "group" prop');
}
}
return {
sorting: false,
hub: useHub ? this.SlicksortHub : null,
manager: new Manager()
};
},
mounted: function () {
var _this = this;
if (this.hub) {
this.id = this.hub.getId();
}
this.container = this.$el;
this.document = this.container.ownerDocument || document;
this._window = this.contentWindow || window;
this.scrollContainer = this.useWindowAsScrollContainer ? { scrollLeft: 0, scrollTop: 0 } : this.container;
this.events = {
start: this.handleStart,
move: this.handleMove,
end: this.handleEnd
};
var _loop_1 = function (key) {
if (hasOwnProperty(this_1.events, key)) {
// @ts-ignore
events[key].forEach(function (eventName) { return _this.container.addEventListener(eventName, _this.events[key]); });
}
};
var this_1 = this;
for (var key in this.events) {
_loop_1(key);
}
if (this.hub) {
this.hub.addContainer(this);
}
},
beforeUnmount: function () {
var _this = this;
var _loop_2 = function (key) {
if (hasOwnProperty(this_2.events, key)) {
// @ts-ignore
events[key].forEach(function (eventName) { return _this.container.removeEventListener(eventName, _this.events[key]); });
}
};
var this_2 = this;
for (var key in this.events) {
_loop_2(key);
}
if (this.hub) {
this.hub.removeContainer(this);
}
if (this.dragendTimer)
clearTimeout(this.dragendTimer);
if (this.cancelTimer)
clearTimeout(this.cancelTimer);
if (this.pressTimer)
clearTimeout(this.pressTimer);
if (this.autoscrollInterval)
clearInterval(this.autoscrollInterval);
},
methods: {
handleStart: function (e) {
var _this = this;
var _a = this.$props, distance = _a.distance, shouldCancelStart = _a.shouldCancelStart;
if ((!isTouch(e) && e.button === 2) || shouldCancelStart(e)) {
return false;
}
this._touched = true;
this._pos = getPointerOffset(e);
var target = e.target;
var node = closest(target, function (el) { return el.sortableInfo != null; });
if (node && node.sortableInfo && this.nodeIsChild(node) && !this.sorting) {
var useDragHandle = this.$props.useDragHandle;
var index = node.sortableInfo.index;
if (useDragHandle && !closest(target, function (el) { return el.sortableHandle != null; }))
return;
this.manager.active = { index: index };
/*
* Fixes a bug in Firefox where the :active state of anchor tags
* prevent subsequent 'mousemove' events from being fired
* (see https://github.com/clauderic/react-sortable-hoc/issues/118)
*/
if (target.tagName.toLowerCase() === 'a') {
e.preventDefault();
}
if (!distance) {
if (this.pressDelay === 0) {
this.handlePress(e);
}
else {
this.pressTimer = timeout(function () { return _this.handlePress(e); }, this.pressDelay);
}
}
}
},
nodeIsChild: function (node) {
return node.sortableInfo.manager === this.manager;
},
handleMove: function (e) {
var _a = this.$props, distance = _a.distance, pressThreshold = _a.pressThreshold;
if (!this.sorting && this._touched) {
var offset = getPointerOffset(e);
this._delta = {
x: this._pos.x - offset.x,
y: this._pos.y - offset.y
};
var delta = Math.abs(this._delta.x) + Math.abs(this._delta.y);
if (!distance && (!pressThreshold || (pressThreshold && delta >= pressThreshold))) {
if (this.cancelTimer)
clearTimeout(this.cancelTimer);
this.cancelTimer = timeout(this.cancel, 0);
}
else if (distance && delta >= distance && this.manager.isActive()) {
this.handlePress(e);
}
}
},
handleEnd: function () {
if (!this._touched)
return;
var distance = this.$props.distance;
this._touched = false;
if (!distance) {
this.cancel();
}
},
cancel: function () {
if (!this.sorting) {
if (this.pressTimer)
clearTimeout(this.pressTimer);
this.manager.active = null;
if (this.hub)
this.hub.cancel();
}
},
handleSortCancel: function (e) {
if (isTouch(e) || e.key === this.cancelKey) {
this.newIndex = this.index;
this.canceling = true;
this.translate = { x: 0, y: 0 };
this.animateNodes();
this.handleSortEnd(e);
}
},
handlePress: function (e) {
var _a;
var _this = this;
e.stopPropagation();
var active = this.manager.getActive();
if (active) {
var _b = this.$props, getHelperDimensions = _b.getHelperDimensions, helperClass = _b.helperClass, hideSortableGhost = _b.hideSortableGhost, appendTo = _b.appendTo;
var node = active.node;
var index = node.sortableInfo.index;
var margin = getElementMargin(node);
var containerBoundingRect = this.container.getBoundingClientRect();
var dimensions = getHelperDimensions({ index: index, node: node });
this.node = node;
this.margin = margin;
this.width = dimensions.width;
this.height = dimensions.height;
this.marginOffset = {
x: this.margin.left + this.margin.right,
y: Math.max(this.margin.top, this.margin.bottom)
};
this.boundingClientRect = node.getBoundingClientRect();
this.containerBoundingRect = containerBoundingRect;
this.index = index;
this.newIndex = index;
var clonedNode = cloneNode(node);
this.helper = this.document.querySelector(appendTo).appendChild(clonedNode);
this.helper.style.position = 'fixed';
this.helper.style.top = "".concat(this.boundingClientRect.top - margin.top, "px");
this.helper.style.left = "".concat(this.boundingClientRect.left - margin.left, "px");
this.helper.style.width = "".concat(this.width, "px");
this.helper.style.height = "".concat(this.height, "px");
this.helper.style.boxSizing = 'border-box';
this.helper.style.pointerEvents = 'none';
if (hideSortableGhost) {
this.sortableGhost = node;
node.style.visibility = 'hidden';
node.style.opacity = '0';
}
if (this.hub) {
this.hub.sortStart(this);
this.hub.helper = this.helper;
this.hub.ghost = this.sortableGhost;
}
this.intializeOffsets(e, this.boundingClientRect);
this.offsetEdge = getEdgeOffset(node, this.container);
if (helperClass) {
(_a = this.helper.classList).add.apply(_a, __spreadArray([], __read(helperClass.split(' ')), false));
}
this.listenerNode = isTouch(e) ? node : this._window;
// @ts-ignore
events.move.forEach(function (eventName) { return _this.listenerNode.addEventListener(eventName, _this.handleSortMove); });
// @ts-ignore
events.end.forEach(function (eventName) { return _this.listenerNode.addEventListener(eventName, _this.handleSortEnd); });
// @ts-ignore
events.cancel.forEach(function (eventName) { return _this.listenerNode.addEventListener(eventName, _this.handleSortCancel); });
this.sorting = true;
this.$emit('sort-start', { event: e, node: node, index: index });
}
},
handleSortMove: function (e) {
e.preventDefault(); // Prevent scrolling on mobile
this.updatePosition(e);
if (this.hub) {
var payload = this.list[this.index];
this.hub.handleSortMove(e, payload);
}
if (!this.hub || this.hub.isDest(this)) {
this.animateNodes();
this.autoscroll();
}
this.$emit('sort-move', { event: e });
},
handleDropOut: function () {
var removed = this.list[this.index];
var newValue = arrayRemove(this.list, this.index);
this.$emit('sort-remove', {
oldIndex: this.index
});
this.$emit('update:list', newValue);
return removed;
},
handleDropIn: function (payload) {
var newValue = arrayInsert(this.list, this.newIndex, payload);
this.$emit('sort-insert', {
newIndex: this.newIndex,
value: payload
});
this.$emit('update:list', newValue);
this.handleDragEnd();
},
handleDragOut: function () {
if (this.autoscrollInterval) {
clearInterval(this.autoscrollInterval);
this.autoscrollInterval = null;
}
if (this.hub.isSource(this)) {
// Trick to animate all nodes up
this.translate = {
x: 10000,
y: 10000
};
this.animateNodes();
}
else {
this.manager.getRefs().forEach(function (ref) {
ref.node.style['transform'] = '';
});
this.dragendTimer = timeout(this.handleDragEnd, this.transitionDuration || 0);
}
this.$emit('drag-out');
},
handleDragEnd: function () {
if (this.autoscrollInterval) {
clearInterval(this.autoscrollInterval);
this.autoscrollInterval = null;
}
resetTransform(this.manager.getRefs());
if (this.sortableGhost) {
this.sortableGhost.remove();
this.sortableGhost = null;
}
this.$emit('drag-end');
if (this.dragendTimer) {
clearTimeout(this.dragendTimer);
this.dragendTimer = null;
}
this.manager.active = null;
this._touched = false;
this.sorting = false;
},
intializeOffsets: function (e, clientRect) {
var _a = this, useWindowAsScrollContainer = _a.useWindowAsScrollContainer, containerBoundingRect = _a.containerBoundingRect, _window = _a._window;
this.marginOffset = {
x: this.margin.left + this.margin.right,
y: Math.max(this.margin.top, this.margin.bottom)
};
this._axis = {
x: this.axis.indexOf('x') >= 0,
y: this.axis.indexOf('y') >= 0
};
this.initialOffset = getPointerOffset(e);
// initialScroll;
this.initialScroll = {
top: this.scrollContainer.scrollTop,
left: this.scrollContainer.scrollLeft
};
// initialWindowScroll;
this.initialWindowScroll = {
top: window.pageYOffset,
left: window.pageXOffset
};
this.translate = { x: 0, y: 0 };
this.minTranslate = {};
this.maxTranslate = {};
if (this._axis.x) {
this.minTranslate.x =
(useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - clientRect.left - this.width / 2;
this.maxTranslate.x =
(useWindowAsScrollContainer ? _window.innerWidth : containerBoundingRect.left + containerBoundingRect.width) -
clientRect.left -
this.width / 2;
}
if (this._axis.y) {
this.minTranslate.y =
(useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - clientRect.top - this.height / 2;
this.maxTranslate.y =
(useWindowAsScrollContainer
? _window.innerHeight
: containerBoundingRect.top + containerBoundingRect.height) -
clientRect.top -
this.height / 2;
}
},
handleDragIn: function (e, sortableGhost, helper) {
if (this.hub.isSource(this)) {
return;
}
if (this.dragendTimer) {
this.handleDragEnd();
clearTimeout(this.dragendTimer);
this.dragendTimer = null;
}
var nodes = this.manager.getRefs();
this.index = nodes.length;
this.manager.active = { index: this.index };
var containerBoundingRect = this.container.getBoundingClientRect();
var helperBoundingRect = helper.getBoundingClientRect();
this.containerBoundingRect = containerBoundingRect;
this.sortableGhost = cloneNode(sortableGhost);
this.container.appendChild(this.sortableGhost);
var ghostRect = this.sortableGhost.getBoundingClientRect();
this.boundingClientRect = ghostRect;
this.margin = getElementMargin(this.sortableGhost);
this.width = ghostRect.width;
this.height = ghostRect.height;
// XY coords of the inserted node, relative to the top-left corner of the container
this.offsetEdge = getEdgeOffset(this.sortableGhost, this.container);
this.intializeOffsets(e, ghostRect);
// Move the initialOffset back to the insertion point of the
// sortableGhost (end of the list), as if we had started the drag there.
this.initialOffset.x += ghostRect.x - helperBoundingRect.x;
this.initialOffset.y += ghostRect.y - helperBoundingRect.y;
// Turn on dragging
this.sorting = true;
this.$emit('drag-in');
},
handleSortEnd: function (e) {
var _a;
var _this = this;
// Remove the event listeners if the node is still in the DOM
if (this.listenerNode) {
events.move.forEach(function (eventName) {
// @ts-ignore
return _this.listenerNode.removeEventListener(eventName, _this.handleSortMove);
});
events.end.forEach(function (eventName) {
// @ts-ignore
return _this.listenerNode.removeEventListener(eventName, _this.handleSortEnd);
});
events.cancel.forEach(function (eventName) {
// @ts-ignore
return _this.listenerNode.removeEventListener(eventName, _this.handleSortCancel);
});
}
var nodes = this.manager.getRefs();
// Remove the helper class(es) early to give it a chance to transition back
if (this.helper && this.helperClass) {
(_a = this.helper.classList).remove.apply(_a, __spreadArray([], __read(this.helperClass.split(' ')), false));
}
// Stop autoscroll
if (this.autoscrollInterval)
clearInterval(this.autoscrollInterval);
this.autoscrollInterval = null;
var onEnd = function () {
// Remove the helper from the DOM
if (_this.helper) {
_this.helper.remove();
_this.helper = null;
}
if (_this.hideSortableGhost && _this.sortableGhost) {
_this.sortableGhost.style.visibility = '';
_this.sortableGhost.style.opacity = '';
_this.sortableGhost = null;
}
resetTransform(nodes);
// Update state
if (_this.hub && !_this.hub.isDest(_this)) {
_this.canceling ? _this.hub.cancel() : _this.hub.handleSortEnd();
}
else if (_this.canceling) {
_this.$emit('sort-cancel', { event: e });
}
else {
_this.$emit('sort-end', {
event: e,
oldIndex: _this.index,
newIndex: _this.newIndex
});
_this.$emit('update:list', arrayMove(_this.list, _this.index, _this.newIndex));
}
_this.manager.active = null;
_this._touched = false;
_this.canceling = false;
_this.sorting = false;
};
if (this.transitionDuration || this.draggedSettlingDuration) {
this.transitionHelperIntoPlace(nodes, onEnd);
}
else {
onEnd();
}
},
transitionHelperIntoPlace: function (nodes, cb) {
var _this = this;
if (this.draggedSettlingDuration === 0 || nodes.length === 0 || !this.helper) {
return Promise.resolve();
}
var indexNode = nodes[this.index].node;
var targetX = 0;
var targetY = 0;
var scrollDifference = {
top: window.pageYOffset - this.initialWindowScroll.top,
left: window.pageXOffset - this.initialWindowScroll.left
};
if (this.hub && !this.hub.isDest(this) && !this.canceling) {
var dest = this.hub.getDest();
if (!dest)
return;
var destIndex = dest.newIndex;
var destRefs = dest.manager.getOrderedRefs();
var destNode = destIndex < destRefs.length ? destRefs[destIndex].node : dest.sortableGhost;
var ancestor = commonOffsetParent(indexNode, destNode);
var sourceOffset = getEdgeOffset(indexNode, ancestor);
var targetOffset = getEdgeOffset(destNode, ancestor);
targetX = targetOffset.left - sourceOffset.left - scrollDifference.left;
targetY = targetOffset.top - sourceOffset.top - scrollDifference.top;
}
else {
var newIndexNode = nodes[this.newIndex].node;
var deltaScroll = {
left: this.scrollContainer.scrollLeft - this.initialScroll.left + scrollDifference.left,
top: this.scrollContainer.scrollTop - this.initialScroll.top + scrollDifference.top
};
targetX = -deltaScroll.left;
if (this.translate && this.translate.x > 0) {
// Diff against right edge when moving to the right
targetX +=
newIndexNode.offsetLeft + newIndexNode.offsetWidth - (indexNode.offsetLeft + indexNode.offsetWidth);
}
else {
targetX += newIndexNode.offsetLeft - indexNode.offsetLeft;
}
targetY = -deltaScroll.top;
if (this.translate && this.translate.y > 0) {
// Diff against the bottom edge when moving down
targetY +=
newIndexNode.offsetTop + newIndexNode.offsetHeight - (indexNode.offsetTop + indexNode.offsetHeight);
}
else {
targetY += newIndexNode.offsetTop - indexNode.offsetTop;
}
}
var duration = this.draggedSettlingDuration !== null ? this.draggedSettlingDuration : this.transitionDuration;
this.setHelperStyle(this.helper, { targetX: targetX, targetY: targetY, duration: duration });
// Register an event handler to clean up styles when the transition
// finishes.
var cleanup = function (event) {
if (!event || event.propertyName === 'transform') {
clearTimeout(cleanupTimer);
_this.setHelperStyle(_this.helper);
cb();
}
};
// Force cleanup in case 'transitionend' never fires
var cleanupTimer = setTimeout(cleanup, duration + 10);
this.helper.addEventListener('transitionend', cleanup);
},
updatePosition: function (e) {
var _a = this.$props, lockAxis = _a.lockAxis, lockToContainerEdges = _a.lockToContainerEdges;
var offset = getPointerOffset(e);
var translate = {
x: offset.x - this.initialOffset.x,
y: offset.y - this.initialOffset.y
};
// Adjust for window scroll
translate.y -= window.pageYOffset - this.initialWindowScroll.top;
translate.x -= window.pageXOffset - this.initialWindowScroll.left;
this.translate = translate;
if (lockToContainerEdges) {
var _b = __read(getLockPixelOffsets(this.lockOffset, this.height, this.width), 2), minLockOffset = _b[0], maxLockOffset = _b[1];
var minOffset = {
x: this.width / 2 - minLockOffset.x,
y: this.height / 2 - minLockOffset.y
};
var maxOffset = {
x: this.width / 2 - maxLockOffset.x,
y: this.height / 2 - maxLockOffset.y
};
if (this.minTranslate.x && this.maxTranslate.x)
translate.x = limit(this.minTranslate.x + minOffset.x, this.maxTranslate.x - maxOffset.x, translate.x);
if (this.minTranslate.y && this.maxTranslate.y)
translate.y = limit(this.minTranslate.y + minOffset.y, this.maxTranslate.y - maxOffset.y, translate.y);
}
if (lockAxis === 'x') {
translate.y = 0;
}
else if (lockAxis === 'y') {
translate.x = 0;
}
if (this.helper) {
this.setHelperStyle(this.helper, {
targetX: translate.x,
targetY: translate.y,
duration: 0
});
}
},
animateNodes: function () {
var _a = this.$props, transitionDuration = _a.transitionDuration, hideSortableGhost = _a.hideSortableGhost;
var nodes = this.manager.getOrderedRefs();
var deltaScroll = {
left: this.scrollContainer.scrollLeft - this.initialScroll.left,
top: this.scrollContainer.scrollTop - this.initialScroll.top
};
var sortingOffset = {
left: this.offsetEdge.left + this.translate.x + deltaScroll.left,
top: this.offsetEdge.top + this.translate.y + deltaScroll.top
};
var scrollDifference = {
top: window.pageYOffset - this.initialWindowScroll.top,
left: window.pageXOffset - this.initialWindowScroll.left
};
this.newIndex = null;
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i].node;
var index = node.sortableInfo.index;
var width = node.offsetWidth;
var height = node.offsetHeight;
var offset = {
width: this.width > width ? width / 2 : this.width / 2,
height: this.height > height ? height / 2 : this.height / 2
};
var translate = {
x: 0,
y: 0
};
var edgeOffset = nodes[i].edgeOffset;
// If we haven't cached the node's offsetTop / offsetLeft value
if (!edgeOffset) {
nodes[i].edgeOffset = edgeOffset = getEdgeOffset(node, this.container);
}
// Get a reference to the next and previous node
var nextNode = i < nodes.length - 1 && nodes[i + 1];
var prevNode = i > 0 && nodes[i - 1];
// Also cache the next node's edge offset if needed.
// We need this for calculating the animation in a grid setup
if (nextNode && !nextNode.edgeOffset) {
nextNode.edgeOffset = getEdgeOffset(nextNode.node, this.container);
}
// If the node is the one we're currently animating, skip it
if (index === this.index) {
/*
* With windowing libraries such as `react-virtualized`, the sortableGhost
* node may change while scrolling down and then back up (or vice-versa),
* so we need to update the reference to the new node just to be safe.
*/
if (hideSortableGhost) {
this.sortableGhost = node;
node.style.visibility = 'hidden';
node.style.opacity = '0';
}
continue;
}
if (transitionDuration) {
node.style['transitionDuration'] = "".concat(transitionDuration, "ms");
}
if (this._axis.x) {
if (this._axis.y) {
// Calculations for a grid setup
if (index < this.index &&
((sortingOffset.left + scrollDifference.left - offset.width <= edgeOffset.left &&
sortingOffset.top + scrollDifference.top <= edgeOffset.top + offset.height) ||
sortingOffset.top + scrollDifference.top + offset.height <= edgeOffset.top)) {
// If the current node is to the left on the same row, or above the node that's being dragged
// then move it to the right
translate.x = this.width + this.marginOffset.x;
if (edgeOffset.left + translate.x > this.containerBoundingRect.width - offset.width && nextNode) {
// If it moves passed the right bounds, then animate it to the first position of the next row.
// We just use the offset of the next node to calculate where to move, because that node's original position
// is exactly where we want to go
translate.x = nextNode.edgeOffset.left - edgeOffset.left;
translate.y = nextNode.edgeOffset.top - edgeOffset.top;
}
if (this.newIndex === null) {
this.newIndex = index;
}
}
else if (index > this.index &&
((sortingOffset.left + scrollDifference.left + offset.width >= edgeOffset.left &&
sortingOffset.top + scrollDifference.top + offset.height >= edgeOffset.top) ||
sortingOffset.top + scrollDifference.top + offset.height >= edgeOffset.top + height)) {
// If the current node is to the right on the same row, or below the node that's being dragged
// then move it to the left
translate.x = -(this.width + this.marginOffset.x);
if (edgeOffset.left + translate.x < this.containerBoundingRect.left + offset.width && prevNode) {
// If it moves passed the left bounds, then animate it to the last position of the previous row.
// We just use the offset of the previous node to calculate where to move, because that node's original position
// is exactly where we want to go
translate.x = prevNode.edgeOffset.left - edgeOffset.left;
translate.y = prevNode.edgeOffset.top - edgeOffset.top;
}
this.newIndex = index;
}
}
else {
if (index > this.index && sortingOffset.left + scrollDifference.left + offset.width >= edgeOffset.left) {
translate.x = -(this.width + this.marginOffset.x);
this.newIndex = index;
}
else if (index < this.index &&
sortingOffset.left + scrollDifference.left <= edgeOffset.left + offset.width) {
translate.x = this.width + this.marginOffset.x;
if (this.newIndex == null) {
this.newIndex = index;
}
}
}
}
else if (this._axis.y) {
if (index > this.index && sortingOffset.top + scrollDifference.top + offset.height >= edgeOffset.top) {
translate.y = -(this.height + this.marginOffset.y);
this.newIndex = index;
}
else if (index < this.index &&
sortingOffset.top + scrollDifference.top <= edgeOffset.top + offset.height) {
translate.y = this.height + this.marginOffset.y;
if (this.newIndex == null) {
this.newIndex = index;
}
}
}
node.style['transform'] = "translate3d(".concat(translate.x, "px,").concat(translate.y, "px,0)");
}
if (this.newIndex == null) {
this.newIndex = this.index;
}
},
autoscroll: function () {
var _this = this;
var translate = this.translate;
var direction = {
x: 0,
y: 0
};
var speed = {
x: 1,
y: 1
};
var acceleration = {
x: 10,
y: 10
};
if (translate.y >= this.maxTranslate.y - this.height / 2) {
direction.y = 1; // Scroll Down
speed.y = acceleration.y * Math.abs((this.maxTranslate.y - this.height / 2 - translate.y) / this.height);
}
else if (translate.x >= this.maxTranslate.x - this.width / 2) {
direction.x = 1; // Scroll Right
speed.x = acceleration.x * Math.abs((this.maxTranslate.x - this.width / 2 - translate.x) / this.width);
}
else if (translate.y <= this.minTranslate.y + this.height / 2) {
direction.y = -1; // Scroll Up
speed.y = acceleration.y * Math.abs((translate.y - this.height / 2 - this.minTranslate.y) / this.height);
}
else if (translate.x <= this.minTranslate.x + this.width / 2) {
direction.x = -1; // Scroll Left
speed.x = acceleration.x * Math.abs((translate.x - this.width / 2 - this.minTranslate.x) / this.width);
}
if (this.autoscrollInterval) {
clearInterval(this.autoscrollInterval);
this.autoscrollInterval = null;
}
if (direction.x !== 0 || direction.y !== 0) {
this.autoscrollInterval = window.setInterval(function () {
var offset = {
left: 1 * speed.x * direction.x,
top: 1 * speed.y * direction.y
};
if (_this.useWindowAsScrollContainer) {
_this._window.scrollBy(offset.left, offset.top);
}
else {
_this.scrollContainer.scrollTop += offset.top;
_this.scrollContainer.scrollLeft += offset.left;
}
_this.translate.x += offset.left;
_this.translate.y += offset.top;
_this.animateNodes();
}, 5);
}
}
}
});
// Export Sortable Element Handle Directive
var HandleDirective = {
beforeMount: function (el) {
el.sortableHandle = true;
}
};
var SlickItem = vue.defineComponent({
name: 'SlickItem',
mixins: [ElementMixin],
props: {
tag: {
type: String,
"default": 'div'
}
},
render: function () {
var _a, _b;
return vue.h(this.tag, (_b = (_a = this.$slots)["default"]) === null || _b === void 0 ? void 0 : _b.call(_a));
}
});
var SlickList = vue.defineComponent({
name: 'SlickList',
mixins: [ContainerMixin],
props: {
tag: {
type: String,
"default": 'div'
},
itemKey: {
type: [String, Function],
"default": 'id'
}
},
render: function () {
var _this = this;
var _a, _b;
if (this.$slots.item) {
return vue.h(this.tag, this.list.map(function (item, index) {
var key;
if (item == null) {
return;
}
else if (typeof _this.itemKey === 'function') {
key = _this.itemKey(item);
}
else if (typeof item === 'object' &&
hasOwnProperty(item, _this.itemKey) &&
typeof item[_this.itemKey] == 'string') {
key = item[_this.itemKey];
}
else if (typeof item === 'string') {
key = item;
}
else {
throw new Error('Cannot find key for item, use the item-key prop and pass a function or string');
}
return vue.h(SlickItem, {
key: key,
index: index
}, {
"default": function () { var _a, _b; return (_b = (_a = _this.$slots).item) === null || _b === void 0 ? void 0 : _b.call(_a, { item: item, index: index }); }
});
}));
}
return vue.h(this.tag, (_b = (_a = this.$slots)["default"]) === null || _b === void 0 ? void 0 : _b.call(_a));
}
});
var DragHandle = vue.defineComponent({
props: {
tag: {
type: String,
"default": 'span'
}
},
mounted: function () {
this.$el.sortableHandle = true;
},
render: function () {
var _a, _b;
return vue.h(this.tag, (_b = (_a = this.$slots)["default"]) === null || _b === void 0 ? void 0 : _b.call(_a));
}
});
var containerIDCounter = 1;
/**
* Always allow when dest === source
* Defer to 'dest.accept()' if it is a function
* Allow any group in the accept lists
* Deny any group in the block list
* Allow the same group by default, this can be overridden with the block prop
*/
function canAcceptElement(dest, source, payload) {
if (source.id === dest.id)
return true;
if (dest.block && dest.block.includes(source.group))
return false;
if (typeof dest.accept === 'function') {
return dest.accept({ dest: dest, source: source, payload: payload });
}
if (typeof dest.accept === 'boolean') {
return dest.accept;
}
if (dest.accept && dest.accept.includes(source.group))
return true;
if (dest.group === source.group)
return true;
return false;
}
function findClosestDest(_a, refs, currentDest) {
var x = _a.x, y = _a.y;
// Quickly check if we are within the bounds of the current destination
if (isPointWithinRect({ x: x, y: y }, currentDest.container.getBoundingClientRect())) {
return currentDest;
}
var closest = null;
var minDistance = Infinity;
for (var i = 0; i < refs.length; i++) {
var ref = refs[i];
var rect = ref.container.getBoundingClientRect();
var isWithin = isPointWithinRect({ x: x, y: y }, rect);
if (isWithin) {
// If we are within another destination, stop here
return ref;
}
var center = getRectCenter(rect);
var distance = getDistance(x, y, center.x, center.y);
if (distance < minDistance) {
closest = ref;
minDistance = distance;
}
}
// Try to guess the closest destination
return closest;
}
var SlicksortHub = /** @class */ (function () {
function SlicksortHub() {
this.helper = null;
this.ghost = null;
this.refs = [];
this.source = null;
this.dest = null;
}
SlicksortHub.prototype.getId = function () {
return '' + containerIDCounter++;
};
SlicksortHub.prototype.isSource = function (_a) {
var _b;
var id = _a.id;
return ((_b = this.source) === null || _b === void 0 ? void 0 : _b.id) === id;
};
SlicksortHub.prototype.getSource = function () {
return this.source;
};
SlicksortHub.prototype.isDest = function (_a) {
var _b;
var id = _a.id;
return ((_b = this.dest) === null || _b === void 0 ? void 0 : _b.id) === id;
};
SlicksortHub.prototype.getDest = function () {
return this.dest;
};
SlicksortHub.prototype.addContainer = function (ref) {
this.refs.push(ref);
};
SlicksortHub.prototype.removeContainer = function (ref) {
this.refs = this.refs.filter(function (c) { return c.id !== ref.id; });
};
SlicksortHub.prototype.sortStart = function (ref) {
this.source = ref;
this.dest = ref;
};
SlicksortHub.prototype.handleSortMove = function (e, payload) {
var _a, _b, _c, _d;
var dest = this.dest;
var source = this.source;
if (!dest || !source)
return;
var refs = this.refs;
var pointer = getPointerOffset(e, 'client');
var newDest = findClosestDest(pointer, refs, dest) || dest;
if (dest.id !== newDest.id && canAcceptElement(newDest, source, payload)) {
this.dest = newDest;
dest.handleDragOut();
newDest.handleDragIn(e, this.ghost, this.helper);
}
if (dest.id !== ((_a = this.source) === null || _a === void 0 ? void 0 : _a.id)) {
(_b = this.dest) === null || _b === void 0 ? void 0 : _b.updatePosition(e);
(_c = this.dest) === null || _c === void 0 ? void 0 : _c.animateNodes();
(_d = this.dest) === null || _d === void 0 ? void 0 : _d.autoscroll();
}
};
SlicksortHub.prototype.handleSortEnd = function () {
var _a, _b, _c, _d;
if (((_a = this.source) === null || _a === void 0 ? void 0 : _a.id) === ((_b = this.dest) === null || _b === void 0 ? void 0 : _b.id))
return;
var payload = (_c = this.source) === null || _c === void 0 ? void 0 : _c.handleDropOut();
(_d = this.dest) === null || _d === void 0 ? void 0 : _d.handleDropIn(payload);
this.reset();
};
SlicksortHub.prototype.reset = function () {
this.source = null;
this.dest = null;
this.helper = null;
this.ghost = null;
};
SlicksortHub.prototype.cancel = function () {
var _a;
(_a = this.dest) === null || _a === void 0 ? void 0 : _a.handleDragEnd();
this.reset();
};
return SlicksortHub;
}());
var plugin = {
install: function (app) {
app.directive('drag-handle', HandleDirective);
app.provide('SlicksortHub', new SlicksortHub());
}
};
exports.ContainerMixin = ContainerMixin;
exports.DragHandle = DragHandle;
exports.ElementMixin = ElementMixin;
exports.HandleDirective = HandleDirective;
exports.SlickItem = SlickItem;
exports.SlickList = SlickList;
exports.arrayMove = arrayMove;
exports.plugin = plugin;