vue3-drag-drop
Version:
Simple drag and drop using native event API for Vue 3
307 lines (306 loc) • 13.5 kB
JavaScript
import { openBlock as c, createBlock as D, resolveDynamicComponent as y, withCtx as E, renderSlot as u, createElementBlock as T, normalizeStyle as P, withModifiers as m } from "vue";
var v;
(function(o) {
var a = function() {
function r() {
this._dropEffect = "move", this._effectAllowed = "all", this._data = {};
}
return Object.defineProperty(r.prototype, "dropEffect", {
get: function() {
return this._dropEffect;
},
set: function(t) {
this._dropEffect = t;
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(r.prototype, "effectAllowed", {
get: function() {
return this._effectAllowed;
},
set: function(t) {
this._effectAllowed = t;
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(r.prototype, "types", {
get: function() {
return Object.keys(this._data);
},
enumerable: !0,
configurable: !0
}), r.prototype.clearData = function(t) {
t !== null ? delete this._data[t.toLowerCase()] : this._data = {};
}, r.prototype.getData = function(t) {
return this._data[t.toLowerCase()] || "";
}, r.prototype.setData = function(t, e) {
this._data[t.toLowerCase()] = e;
}, r.prototype.setDragImage = function(t, e, i) {
var s = n._instance;
s._imgCustom = t, s._imgOffset = { x: e, y: i };
}, r;
}();
o.DataTransfer = a;
var n = function() {
function r() {
if (this._lastClick = 0, r._instance)
throw "DragDropTouch instance already created.";
var t = !1;
if (document.addEventListener("test", function() {
}, {
get passive() {
return t = !0, !0;
}
}), navigator.maxTouchPoints) {
var e = document, i = this._touchstart.bind(this), s = this._touchmove.bind(this), d = this._touchend.bind(this), l = t ? { passive: !1, capture: !1 } : !1;
e.addEventListener("touchstart", i, l), e.addEventListener("touchmove", s, l), e.addEventListener("touchend", d), e.addEventListener("touchcancel", d);
}
}
return r.getInstance = function() {
return r._instance;
}, r.prototype._touchstart = function(t) {
var e = this;
if (this._shouldHandle(t)) {
this._reset();
var i = this._closestDraggable(t.target);
i && !this._dispatchEvent(t, "mousemove", t.target) && !this._dispatchEvent(t, "mousedown", t.target) && (this._dragSource = i, this._ptDown = this._getPoint(t), this._lastTouch = t, t.preventDefault(), setTimeout(function() {
e._dragSource === i && e._img === null && e._dispatchEvent(t, "contextmenu", i) && e._reset();
}, r._CTXMENU), r._ISPRESSHOLDMODE && (this._pressHoldInterval = setTimeout(function() {
e._isDragEnabled = !0, e._touchmove(t);
}, r._PRESSHOLDAWAIT)));
}
}, r.prototype._touchmove = function(t) {
if (this._shouldCancelPressHoldMove(t)) {
this._reset();
return;
}
if (this._shouldHandleMove(t) || this._shouldHandlePressHoldMove(t)) {
var e = this._getTarget(t);
if (this._dispatchEvent(t, "mousemove", e)) {
this._lastTouch = t, t.preventDefault();
return;
}
if (this._dragSource && !this._img && this._shouldStartDragging(t)) {
if (this._dispatchEvent(this._lastTouch, "dragstart", this._dragSource)) {
this._dragSource = null;
return;
}
this._createImage(t), this._dispatchEvent(t, "dragenter", e);
}
this._img && (this._lastTouch = t, t.preventDefault(), this._dispatchEvent(t, "drag", this._dragSource), e !== this._lastTarget && (this._dispatchEvent(this._lastTouch, "dragleave", this._lastTarget), this._dispatchEvent(t, "dragenter", e), this._lastTarget = e), this._moveImage(t), this._isDropZone = this._dispatchEvent(t, "dragover", e));
}
}, r.prototype._touchend = function(t) {
if (this._shouldHandle(t)) {
if (this._dispatchEvent(this._lastTouch, "mouseup", t.target)) {
t.preventDefault();
return;
}
this._img || (this._dragSource = null, this._dispatchEvent(this._lastTouch, "click", t.target), this._lastClick = Date.now()), this._destroyImage(), this._dragSource && (t.type.indexOf("cancel") < 0 && this._isDropZone && this._dispatchEvent(this._lastTouch, "drop", this._lastTarget), this._dispatchEvent(this._lastTouch, "dragend", this._dragSource), this._reset());
}
}, r.prototype._shouldHandle = function(t) {
return t && !t.defaultPrevented && t.touches && t.touches.length < 2;
}, r.prototype._shouldHandleMove = function(t) {
return !r._ISPRESSHOLDMODE && this._shouldHandle(t);
}, r.prototype._shouldHandlePressHoldMove = function(t) {
return r._ISPRESSHOLDMODE && this._isDragEnabled && t && t.touches && t.touches.length;
}, r.prototype._shouldCancelPressHoldMove = function(t) {
return r._ISPRESSHOLDMODE && !this._isDragEnabled && this._getDelta(t) > r._PRESSHOLDMARGIN;
}, r.prototype._shouldStartDragging = function(t) {
var e = this._getDelta(t);
return e > r._THRESHOLD || r._ISPRESSHOLDMODE && e >= r._PRESSHOLDTHRESHOLD;
}, r.prototype._reset = function() {
this._destroyImage(), this._dragSource = null, this._lastTouch = null, this._lastTarget = null, this._ptDown = null, this._isDragEnabled = !1, this._isDropZone = !1, this._dataTransfer = new a(), clearInterval(this._pressHoldInterval);
}, r.prototype._getPoint = function(t, e) {
return t && t.touches && (t = t.touches[0]), { x: e ? t.pageX : t.clientX, y: e ? t.pageY : t.clientY };
}, r.prototype._getDelta = function(t) {
if (r._ISPRESSHOLDMODE && !this._ptDown)
return 0;
var e = this._getPoint(t);
return Math.abs(e.x - this._ptDown.x) + Math.abs(e.y - this._ptDown.y);
}, r.prototype._getTarget = function(t) {
for (var e = this._getPoint(t), i = document.elementFromPoint(e.x, e.y); i && getComputedStyle(i).pointerEvents == "none"; )
i = i.parentElement;
return i;
}, r.prototype._createImage = function(t) {
this._img && this._destroyImage();
var e = this._imgCustom || this._dragSource;
if (this._img = e.cloneNode(!0), this._copyStyle(e, this._img), this._img.style.top = this._img.style.left = "-9999px", !this._imgCustom) {
var i = e.getBoundingClientRect(), s = this._getPoint(t);
this._imgOffset = { x: s.x - i.left, y: s.y - i.top }, this._img.style.opacity = r._OPACITY.toString();
}
this._moveImage(t), document.body.appendChild(this._img);
}, r.prototype._destroyImage = function() {
this._img && this._img.parentElement && this._img.parentElement.removeChild(this._img), this._img = null, this._imgCustom = null;
}, r.prototype._moveImage = function(t) {
var e = this;
requestAnimationFrame(function() {
if (e._img) {
var i = e._getPoint(t, !0), s = e._img.style;
s.position = "absolute", s.pointerEvents = "none", s.zIndex = "999999", s.left = Math.round(i.x - e._imgOffset.x) + "px", s.top = Math.round(i.y - e._imgOffset.y) + "px";
}
});
}, r.prototype._copyProps = function(t, e, i) {
for (var s = 0; s < i.length; s++) {
var d = i[s];
t[d] = e[d];
}
}, r.prototype._copyStyle = function(t, e) {
if (r._rmvAtts.forEach(function(O) {
e.removeAttribute(O);
}), t instanceof HTMLCanvasElement) {
var i = t, s = e;
s.width = i.width, s.height = i.height, s.getContext("2d").drawImage(i, 0, 0);
}
for (var d = getComputedStyle(t), l = 0; l < d.length; l++) {
var g = d[l];
g.indexOf("transition") < 0 && (e.style[g] = d[g]);
}
e.style.pointerEvents = "none";
for (var l = 0; l < t.children.length; l++)
this._copyStyle(t.children[l], e.children[l]);
}, r.prototype._setOffsetAndLayerProps = function(t, e) {
var i = void 0;
t.offsetX === void 0 && (i = e.getBoundingClientRect(), t.offsetX = t.clientX - i.x, t.offsetY = t.clientY - i.y), t.layerX === void 0 && (i = i || e.getBoundingClientRect(), t.layerX = t.pageX - i.left, t.layerY = t.pageY - i.top);
}, r.prototype._dispatchEvent = function(t, e, i) {
if (t && i) {
var s = document.createEvent("Event"), d = t.touches ? t.touches[0] : t;
return s.initEvent(e, !0, !0), s.button = 0, s.which = s.buttons = 1, this._copyProps(s, t, r._kbdProps), this._copyProps(s, d, r._ptProps), this._setOffsetAndLayerProps(s, i), s.dataTransfer = this._dataTransfer, i.dispatchEvent(s), s.defaultPrevented;
}
return !1;
}, r.prototype._closestDraggable = function(t) {
for (; t; t = t.parentElement)
if (t.hasAttribute("draggable") && t.draggable)
return t;
return null;
}, r;
}();
n._instance = new n(), n._THRESHOLD = 5, n._OPACITY = 0.5, n._DBLCLICK = 500, n._CTXMENU = 900, n._ISPRESSHOLDMODE = !1, n._PRESSHOLDAWAIT = 400, n._PRESSHOLDMARGIN = 25, n._PRESSHOLDTHRESHOLD = 0, n._rmvAtts = "id,class,style,draggable".split(","), n._kbdProps = "altKey,ctrlKey,metaKey,shiftKey".split(","), n._ptProps = "pageX,pageY,clientX,clientY,screenX,screenY,offsetX,offsetY".split(","), o.DragDropTouch = n;
})(v || (v = {}));
const _ = { data: void 0 }, p = (o) => o.reduce((a, n) => (a[n] = n) && a, {}), f = p([
"drag",
"dragend",
"dragenter",
"dragleave",
"dragstart",
"dragover",
"drop"
]), b = p(["copy", "move", "link", "none"]), H = p([
"none",
"copy",
"copyLink",
"copyMove",
"link",
"linkMove",
"move",
"all",
"uninitialized"
]), S = (o, a) => {
const n = o.__vccOpts || o;
for (const [r, t] of a)
n[r] = t;
return n;
}, w = {
props: {
draggable: { type: Boolean, default: !0 },
transferData: {},
dropEffect: { validator: (o) => o in b },
effectAllowed: { validator: (o) => o in H },
image: String,
imageXOffset: { type: Number, default: 0 },
imageYOffset: { type: Number, default: 0 },
hideImageHtml: { type: Boolean, default: !0 },
tag: { type: String, default: "div" }
},
emits: f,
data() {
return { dragging: !1 };
},
computed: {
events: () => f,
scopedData() {
return this.dragging && this.transferData;
},
hideImageStyle: () => ({ position: "fixed", top: "-1000px" })
},
methods: {
emitEvent(o, a) {
const n = a.dataTransfer;
if ([f.dragenter, f.dragover].includes(o) && this.dropEffect && (n.dropEffect = this.dropEffect), o === f.dragstart) {
if (this.effectAllowed && (n.effectAllowed = this.effectAllowed), this.image || this.$slots.image) {
let r;
this.image ? (r = new Image(), r.src = this.image) : this.$slots.image && (r = this.$slots.image[0].elm), n.setDragImage && n.setDragImage(r, this.imageXOffset, this.imageYOffset);
}
this.transferData !== void 0 && (_.data = this.transferData, a.dataTransfer.setData("text", "")), this.dragging = !0;
}
this.$emit(o, this.transferData, a), o === f.dragend && (_.data = void 0, this.dragging = !1);
}
}
};
function I(o, a, n, r, t, e) {
return c(), D(y(n.tag), {
draggable: n.draggable,
onDrag: a[0] || (a[0] = (i) => e.emitEvent(e.events.drag, i)),
onDragstart: a[1] || (a[1] = (i) => e.emitEvent(e.events.dragstart, i)),
onDragenter: a[2] || (a[2] = (i) => e.emitEvent(e.events.dragenter, i)),
onDragleave: a[3] || (a[3] = (i) => e.emitEvent(e.events.dragleave, i)),
onDragend: a[4] || (a[4] = (i) => e.emitEvent(e.events.dragend, i))
}, {
default: E(() => [
u(o.$slots, "default", { transferData: e.scopedData }),
n.hideImageHtml ? (c(), T("div", {
key: 0,
style: P(e.hideImageStyle)
}, [
u(o.$slots, "image", { transferData: e.scopedData })
], 4)) : u(o.$slots, "image", {
key: 1,
transferData: e.scopedData
})
]),
_: 3
}, 40, ["draggable"]);
}
const L = /* @__PURE__ */ S(w, [["render", I]]), h = /* @__PURE__ */ new Set(), C = {
data() {
return { transferData: void 0, isDraggingOver: !1 };
},
props: {
tag: { type: String, default: "div" }
},
emits: f,
computed: {
events: () => f,
scopedData() {
return this.isDraggingOver && this.transferData;
}
},
methods: {
emitEvent(o, a) {
this.transferData = _.data, this.$emit(o, this.transferData, a), o === f.dragenter && (h.size || a.target === this.$el) && h.add(a.target), o === f.dragleave && h.delete(a.target), o === f.drop && h.clear(), this.isDraggingOver = Boolean(h.size);
}
}
};
function M(o, a, n, r, t, e) {
return c(), D(y(n.tag), {
onDragenter: a[0] || (a[0] = (i) => e.emitEvent(e.events.dragenter, i)),
onDragleave: a[1] || (a[1] = (i) => e.emitEvent(e.events.dragleave, i)),
onDragover: a[2] || (a[2] = m((i) => e.emitEvent(e.events.dragover, i), ["prevent"])),
onDrop: a[3] || (a[3] = m((i) => e.emitEvent(e.events.drop, i), ["prevent"]))
}, {
default: E(() => [
u(o.$slots, "default", { transferData: e.scopedData })
]),
_: 3
}, 32);
}
const A = /* @__PURE__ */ S(C, [["render", M]]), x = {
install(o) {
o.component("drag", L), o.component("drop", A);
}
};
typeof window < "u" && window.Vue && window.Vue.use(x);
export {
L as Drag,
A as Drop,
x as default
};