x-drag
Version:
<h1 align="center">XDrag</h1> <p align="center">A <strong>highly interactive draggable</strong> component based on <code><a href="https://v3.vuejs.org/">Vue 3</a></code></p>
189 lines (188 loc) • 7.61 kB
text/typescript
import { defineComponent, getCurrentInstance, inject, ref, provide, openBlock, createBlock, TransitionGroup, withCtx, resolveDynamicComponent, nextTick, watch, createElementBlock, normalizeStyle, withModifiers, renderSlot } from "vue";
var XDrag_vue_vue_type_style_index_0_scoped_true_lang = "";
var XDrag_vue_vue_type_style_index_1_lang = "";
var _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
props: {
modelValue: null,
activeClass: null,
appendTo: { default: "#app" }
},
emits: ["onDragEnd"],
setup(__props, { emit: emits }) {
var _a, _b;
const props = __props;
const instance = getCurrentInstance();
const setNewNode = inject("setNewNode");
const src = (_a = inject("src")) != null ? _a : ref(null);
provide("src", src);
const setSrc = (_b = inject("setSrc")) != null ? _b : (val) => src.value = val;
provide("setSrc", setSrc);
provide("dragIns", instance);
provide("props", props);
provide("emits", emits);
const handleSort = (targetInfo) => {
var _a2, _b2, _c, _d;
const { instance: targetIns, index: targetIndex } = targetInfo;
if (!((_a2 = src.value) == null ? void 0 : _a2.instance))
return;
if (((_b2 = src.value) == null ? void 0 : _b2.instance.uid) === targetIns.uid) {
const { modelValue } = props;
[modelValue[targetIndex], modelValue[(_c = src.value) == null ? void 0 : _c.index]] = [modelValue[(_d = src.value) == null ? void 0 : _d.index], modelValue[targetIndex]];
src.value.index = targetIndex;
} else {
const { modelValue: srcVal } = src.value.instance.props;
const { modelValue: targetVal } = targetIns.props;
targetVal.splice(targetIndex, 0, ...srcVal.splice(src.value.index, 1));
nextTick(() => {
const node = targetIns.ctx.$el.children[targetIndex];
setNewNode && setNewNode(node);
setSrc({ instance: targetIns, index: targetIndex });
});
}
};
provide("handleSort", handleSort);
return (_ctx, _cache) => {
return openBlock(), createBlock(TransitionGroup, {
tag: "ul",
name: "x-drag",
class: "x-drag-container"
}, {
default: withCtx(() => [
(openBlock(), createBlock(resolveDynamicComponent(_ctx.$slots.default && _ctx.$slots.default()[0])))
]),
_: 1
});
};
}
});
var XDrag = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-1e3a3735"]]);
var XDragItem_vue_vue_type_style_index_0_scoped_true_lang = "";
const _hoisted_1$1 = ["onDragstart", "onDrag", "onDragend", "onDragenter"];
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
props: {
itemIndex: null,
identityClass: null
},
setup(__props) {
const props = __props;
const dragItem = ref();
let cloneNode;
const newNode = inject("newNode");
const startPos = ref([NaN, NaN]);
const opacity = ref(1);
const setSrc = inject("setSrc");
const dragIns = inject("dragIns");
const handleSort = inject("handleSort");
const _props = inject("props");
const emits = inject("emits");
const identityClass = inject("identityClass");
const setIdentityClass = inject("setIdentityClass");
const container = _props.appendTo ? document.querySelector(_props.appendTo) : document.body;
watch(newNode, (newVal) => {
opacity.value = newVal === dragItem.value ? 0 : 1;
});
const onDragStart = (e) => {
var _a, _b;
const { offsetX, offsetY } = e;
const img = new Image();
img.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E";
e.dataTransfer.setDragImage(img, 0, 0);
startPos.value = [offsetX, offsetY];
const { left, top } = (_a = dragItem.value) == null ? void 0 : _a.getBoundingClientRect();
cloneNode = (_b = dragItem.value) == null ? void 0 : _b.cloneNode(true);
cloneNode.classList.add("dragging-item");
_props.activeClass && cloneNode.classList.add(_props.activeClass);
cloneNode.classList.remove("x-drag-item");
cloneNode.style.transform = `translate(${left}px, ${top}px)`;
setIdentityClass && props.identityClass && setIdentityClass(props.identityClass);
opacity.value = 0;
setSrc({ instance: dragIns, index: props.itemIndex });
container.appendChild(cloneNode);
};
const onDrag = (e) => {
if (cloneNode) {
const { clientX, clientY } = e;
if (clientX && clientY) {
const [startX, startY] = startPos.value;
cloneNode.style.transform = `translate(${clientX - startX}px, ${clientY - startY}px)`;
}
}
};
const onDragEnter = (e) => {
e.preventDefault();
if (identityClass && props.identityClass) {
identityClass.value === props.identityClass && handleSort({ instance: dragIns, index: props.itemIndex });
} else {
handleSort({ instance: dragIns, index: props.itemIndex });
}
};
const onDragEnd = () => {
nextTick(() => {
var _a, _b, _c;
const { left, top } = (_c = (_a = dragItem.value) == null ? void 0 : _a.getBoundingClientRect()) != null ? _c : (_b = newNode == null ? void 0 : newNode.value) == null ? void 0 : _b.getBoundingClientRect();
const reset = cloneNode.animate([{ transform: cloneNode.style.transform }, { transform: `translate(${left}px, ${top}px)` }], {
duration: 300,
easing: "linear"
});
reset.onfinish = () => {
container.removeChild(cloneNode);
opacity.value = 1;
startPos.value = [NaN, NaN];
setSrc(null);
newNode && (newNode.value = null);
emits("onDragEnd", _props.modelValue);
};
});
};
return (_ctx, _cache) => {
return openBlock(), createElementBlock("li", {
draggable: "true",
ref_key: "dragItem",
ref: dragItem,
class: "x-drag-item",
style: normalizeStyle({ opacity: opacity.value }),
onDragstart: withModifiers(onDragStart, ["stop"]),
onDrag: withModifiers(onDrag, ["stop"]),
onDragover: _cache[0] || (_cache[0] = (e) => e.preventDefault()),
onDragend: withModifiers(onDragEnd, ["stop"]),
onDragenter: withModifiers(onDragEnter, ["stop"])
}, [
renderSlot(_ctx.$slots, "default", {}, void 0, true)
], 44, _hoisted_1$1);
};
}
});
var XDragItem = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-62c67f34"]]);
const _hoisted_1 = { class: "x-multi-conrainer" };
const _sfc_main = /* @__PURE__ */ defineComponent({
setup(__props) {
const src = ref(null);
provide("src", src);
provide("setSrc", (val) => src.value = val);
const newNode = ref(null);
provide("newNode", newNode);
provide("setNewNode", (node) => newNode.value = node);
const identityClass = ref(null);
provide("identityClass", identityClass);
provide("setIdentityClass", (className) => identityClass.value = className);
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", _hoisted_1, [
renderSlot(_ctx.$slots, "default")
]);
};
}
});
const components = [XDrag, XDragItem, _sfc_main];
const install = function(App) {
components.forEach((component) => {
App.component(component.name, component);
});
};
export { XDrag, XDragItem, _sfc_main as XMultiContainer, install };