UNPKG

@zhsz/cool-design-crud

Version:

216 lines (215 loc) 5.82 kB
import { h, render, defineComponent, ref, reactive, onMounted, createVNode, nextTick } from "vue"; import { contains, removeClass, isString, addClass } from "../../utils/index.mjs"; import "../../utils/test.mjs"; import { useRefs } from "../../hooks/core.mjs"; import "@formily/core"; import { isFunction } from "lodash-es"; import "../../hooks/table.mjs"; const isComponent = (obj) => { if (obj && typeof obj.render === "function") { return true; } else { return false; } }; const ClContextMenu = /* @__PURE__ */ defineComponent({ name: "cl-context-menu", props: { show: Boolean, options: { type: Object, default: () => { return {}; } }, customVnode: [Function, Object], customClass: String, event: { type: Object, default: () => { return {}; } } }, setup(props, { expose, slots }) { const { refs, setRefs } = useRefs(); const visible = ref(props.show || false); const list = ref([]); const style = reactive({ left: "0px", top: "0px" }); const customVnode = ref(false); const customClass = ref(""); const ids = ref(""); function stopDefault(e) { if (e.preventDefault) { e.preventDefault(); } if (e.stopPropagation) { e.stopPropagation(); } } function parseList(list2) { function deep(list3) { list3.forEach((e) => { e.showChildren = false; if (e.children) { deep(e.children); } }); } deep(list2); return list2; } let targetEl = null; function close() { visible.value = false; ids.value = ""; removeClass(targetEl, "cl-context-menu__target"); } function open(event, options) { let left = event.pageX; let top = event.pageY; if (!options) { options = {}; } if (options.hover) { const d = options.hover === true ? {} : options.hover; targetEl = event.target; if (targetEl && isString(targetEl.className)) { if (d.target) { while (!targetEl.className.includes(d.target)) { targetEl = targetEl.parentNode; } } addClass(targetEl, d.className || "cl-context-menu__target"); } } if (options.list) { list.value = parseList(options.list); } if (options.customVnode) { if (isFunction(options.customVnode)) { customVnode.value = options.customVnode(); } if (isComponent(options.customVnode)) { customVnode.value = h(options.customVnode); } } if (options.customClass) { customClass.value = options.customClass; } stopDefault(event); visible.value = true; nextTick(() => { const { clientHeight: h1, clientWidth: w1 } = event.target.ownerDocument.body; const { clientHeight: h2, clientWidth: w2 } = refs["context-menu"].querySelector(".cl-context-menu__box"); if (top + h2 > h1) { top = h1 - h2 - 5; } if (left + w2 > w1) { left = w1 - w2 - 5; } style.left = `${left}px`; style.top = `${top}px`; }); return { close }; } function rowClick(item, id) { ids.value = id; if (item.disabled) { return false; } if (item.callback) { return item.callback(close); } if (item.children) { item.showChildren = !item.showChildren; } else { close(); } } expose({ open, close }); onMounted(() => { if (visible.value) { const { body, documentElement } = props.event.target.ownerDocument; body.appendChild(refs["context-menu"]); (documentElement || body).addEventListener("mousedown", (e) => { const el = refs["context-menu"]; if (!contains(el, e.target) && el !== e.target) { close(); } }); open(props.event, props.options); } }); return () => { function deep(list2, pId, level) { return createVNode("div", { "class": ["cl-context-menu__box", level > 1 && "is-append"] }, [list2.filter((e) => !e.hidden).map((e, i) => { const id = `${pId}-${i}`; return createVNode("div", { "class": { "is-active": ids.value.includes(id), "is-ellipsis": e.ellipsis, "is-disabled": e.disabled } }, [e.prefixIcon && createVNode("i", { "class": e.prefixIcon }, null), createVNode("span", { "onClick": () => { rowClick(e, id); } }, [e.label]), e.suffixIcon && createVNode("i", { "class": e.suffixIcon }, null), e.children && e.showChildren && deep(e.children, id, level + 1)]); })]); } return visible.value && createVNode("div", { "class": ["cl-context-menu", `${customClass.value}_parent`], "ref": setRefs("context-menu"), "style": style, "onContextmenu": stopDefault }, [slots.default ? slots.default() : customVnode.value === false ? deep(list.value, "0", 1) : createVNode("div", { "class": ["cl-context-menu__box", customClass.value] }, [customVnode.value])]); }; } }); const ContextMenu = { open(event, options) { const vm = h(ClContextMenu, { show: true, event, options }); render(vm, event.target.ownerDocument.createElement("div")); } }; export { ContextMenu, ClContextMenu as default, isComponent };