@fesjs/fes-design
Version:
fes-design for PC
192 lines (189 loc) • 4.43 kB
JavaScript
import { ref, computed, onUnmounted } from 'vue';
import getPrefixCls from '../_util/getPrefixCls';
const prefixCls = getPrefixCls('tree-node');
function allowDrop(node, dropPosition) {
if (node.isLeaf === false) {
return true;
}
if (node.children) {
return true;
}
return dropPosition !== 'inside';
}
var useDrag = _ref => {
let {
nodeList,
emit,
expandNode
} = _ref;
let dragNode;
let overBeginTimeMap = {};
const dragOverInfo = ref();
let timer;
const dragHighlightNode = computed(() => {
if (!dragOverInfo.value) {
return;
}
const node = dragOverInfo.value.node;
const position = dragOverInfo.value.position;
if (position === 'after' || position === 'before') {
return node.parent;
}
return node;
});
onUnmounted(() => {
if (timer) {
clearTimeout(timer);
}
});
function resetDragState() {
dragNode = null;
overBeginTimeMap = {};
dragOverInfo.value = null;
}
const handleDragstart = (value, event) => {
const node = nodeList.get(value);
if (!node.draggable) {
// 阻止默认事件,默认事件会有拖拽效果
event.preventDefault();
return;
}
dragNode = node;
emit('dragstart', {
node,
event
});
};
const handleDragend = (value, event) => {
resetDragState();
const node = nodeList.get(value);
if (!node.draggable) {
event.preventDefault();
return;
}
emit('dragend', {
node,
event
});
};
function getTargetNode(value) {
if (!dragNode) {
return;
}
const node = nodeList.get(value);
if (!node) {
return;
}
if (node.indexPath.includes(dragNode.value)) {
return;
}
return node;
}
const handleDragenter = (value, event) => {
const node = getTargetNode(value);
if (!node) {
return;
}
emit('dragenter', {
node,
event
});
};
const handleDragleave = (value, event) => {
const node = getTargetNode(value);
if (!node) {
return;
}
emit('dragleave', {
node,
event
});
};
const handleDragover = (value, event) => {
event.preventDefault();
const node = getTargetNode(value);
if (!node) {
dragOverInfo.value = null;
return;
}
emit('dragover', {
node,
event
});
// 悬浮1s以上展开节点
if (!overBeginTimeMap[value]) {
overBeginTimeMap[value] = Date.now();
} else {
if (Date.now() - overBeginTimeMap[value] > 1000 && node.hasChildren && !node.isExpanded.value) {
expandNode(value, event);
}
}
const targetNodeEl = document.querySelector(`.${prefixCls}[data-value='${value}']`);
// 悬浮节点大小位置信息
const {
height: targetElOffsetHeight
} = targetNodeEl.getBoundingClientRect();
let mousePosition;
const targeEl = event.currentTarget;
// 焦点节点大小位置信息
const {
top: elClientTop
} = targeEl.getBoundingClientRect();
const eventOffsetY = event.clientY - elClientTop;
const allowDropInside = allowDrop(node, 'inside');
if (allowDropInside) {
if (eventOffsetY <= 8) {
mousePosition = 'before';
} else if (eventOffsetY >= targetElOffsetHeight - 8) {
mousePosition = 'after';
} else {
mousePosition = 'inside';
}
} else {
if (eventOffsetY <= targetElOffsetHeight / 2) {
mousePosition = 'before';
} else {
mousePosition = 'after';
}
}
dragOverInfo.value = {
node,
position: mousePosition
};
// 300毫秒后没有后续则表示已经移出
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
dragOverInfo.value = null;
}, 300);
};
const handleDrop = (value, event) => {
const node = getTargetNode(value);
if (!node) {
return;
}
if (!dragOverInfo.value) {
return;
}
emit('drop', {
position: dragOverInfo.value.position,
node: dragOverInfo.value.node,
dragNode,
originNode: dragOverInfo.value.node.origin,
originDragNode: dragNode.origin,
event
});
};
return {
handleDragstart,
handleDragenter,
handleDragover,
handleDragleave,
handleDragend,
handleDrop,
dragOverInfo,
dragHighlightNode
};
};
export { useDrag as default };