UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

198 lines (195 loc) 6.24 kB
import { reactive, provide } from 'vue'; import { removeClass, addClass } from '../../../utils/assist.mjs'; import { NODE_KEY } from '../utils.mjs'; const dragEventsKey = Symbol("IvueTreeDragEvents"); function useDragNodeHandler({ props, ctx, treeRef, dropIndicator, store }) { const dragState = reactive({ showDropIndicator: false, draggingStartNode: null, dropNode: null, allowDrop: true, dropType: null }); const treeNodeDragStart = ({ event, treeNode }) => { if (typeof props.allowDrag === "function" && !props.allowDrag(treeNode.node)) { event.preventDefault(); return false; } event.dataTransfer.effectAllowed = "move"; try { event.dataTransfer.setData("text/plain", ""); } catch (e) { } dragState.draggingStartNode = treeNode; ctx.emit( "on-node-drag-start", treeNode.node, event ); }; const treeNodeDragOver = ({ event, treeNode }) => { const dropNode = treeNode; const oldDropNode = dragState.dropNode; if (oldDropNode && oldDropNode !== dropNode) { removeClass(oldDropNode.$el, "ivue-tree-drop-indicator"); } const draggingStartNode = dragState.draggingStartNode; if (!draggingStartNode || !dropNode) { return; } let dropPrev = true; let dropInner = true; let dropNext = true; let userAllowDropInner = true; if (typeof props.allowDrop === "function") { dropPrev = props.allowDrop(draggingStartNode.node, dropNode.node, "prev"); dropInner = props.allowDrop( draggingStartNode.node, dropNode.node, "inner" ); userAllowDropInner = dropInner; dropNext = props.allowDrop(draggingStartNode.node, dropNode.node, "next"); } event.dataTransfer.dropEffect = dropInner || dropPrev || dropNext ? "move" : "none"; if ((dropInner || dropPrev || dropNext) && oldDropNode !== dropNode) { if (oldDropNode && oldDropNode.node.data[NODE_KEY] !== dropNode.node.data[NODE_KEY]) { ctx.emit( "on-node-drag-leave", draggingStartNode.node, oldDropNode.node, event ); } ctx.emit( "on-node-drag-enter", draggingStartNode.node, dropNode.node, event ); } if (dropPrev || dropInner || dropNext) { dragState.dropNode = dropNode; } if (dropNode.node.nextSibling === draggingStartNode.node) { dropNext = false; } if (dropNode.node.prevSibling === draggingStartNode.node) { dropPrev = false; } if (dropNode.node.contains(draggingStartNode.node, false)) { dropInner = false; } if (draggingStartNode.node === dropNode.node || draggingStartNode.node.contains(dropNode.node)) { dropPrev = false; dropInner = false; dropNext = false; } const targetPosition = dropNode.$el.getBoundingClientRect(); const treePosition = treeRef.value.getBoundingClientRect(); let dropType; const prevPercent = dropPrev ? dropInner ? 0.25 : dropNext ? 0.45 : 1 : -1; const nextPercent = dropNext ? dropInner ? 0.75 : dropPrev ? 0.55 : 0 : 1; let indicatorTop = -9999; const distance = event.clientY - targetPosition.top; if (distance < targetPosition.height * prevPercent) { dropType = "before"; } else if (distance > targetPosition.height * nextPercent) { dropType = "after"; } else if (dropInner) { dropType = "inner"; } else { dropType = "none"; } const iconPosition = dropNode.$el.querySelector(".ivue-tree-node--expand-icon").getBoundingClientRect(); const _dropIndicator = dropIndicator.value; if (dropType === "before") { indicatorTop = iconPosition.top - treePosition.top; } else if (dropType === "after") { indicatorTop = iconPosition.bottom - treePosition.top; } _dropIndicator.style.top = `${indicatorTop}px`; _dropIndicator.style.left = `${iconPosition.right - treePosition.left}px`; if (dropType === "inner") { addClass(dropNode.$el, "is-drop-inner"); } else { removeClass(dropNode.$el, "is-drop-inner"); oldDropNode && removeClass(oldDropNode.$el, "is-drop-inner"); } dragState.showDropIndicator = dropType === "before" || dropType === "after"; dragState.allowDrop = dragState.showDropIndicator || userAllowDropInner; dragState.dropType = dropType; ctx.emit( "on-node-drag-over", draggingStartNode.node, dropNode.node, event ); }; const treeNodeDragEnd = (event) => { const { draggingStartNode, dropNode, dropType } = dragState; event.dataTransfer.dropEffect = "move"; if (draggingStartNode && dropNode) { const draggingStartNodeCopy = { data: draggingStartNode.node.data }; if (dropType !== "none") { draggingStartNode.node.remove(); } if (dropType === "before") { dropNode.node.parent.insertBefore(draggingStartNodeCopy, dropNode.node); } else if (dropType === "after") { dropNode.node.parent.insertAfter(draggingStartNodeCopy, dropNode.node); } else if (dropType === "inner") { dropNode.node.insertChild(draggingStartNodeCopy); } if (dropType !== "none") { store.value.registerNode(draggingStartNodeCopy); } removeClass(dropNode.$el, "is-drop-inner"); ctx.emit( "on-node-drag-end", draggingStartNode.node, dropNode.node, dropType, event ); if (dropType !== "none") { ctx.emit( "on-node-drop", draggingStartNode.node, dropNode.node, dropType, event ); } } if (draggingStartNode && !dropNode) { ctx.emit( "on-node-drag-end", draggingStartNode.node, null, dropType, event ); } dragState.showDropIndicator = false; dragState.draggingStartNode = null; dragState.dropNode = null; dragState.allowDrop = true; }; provide(dragEventsKey, { treeNodeDragStart, treeNodeDragOver, treeNodeDragEnd }); return { dragState }; } export { dragEventsKey, useDragNodeHandler }; //# sourceMappingURL=useDragNode.mjs.map