UNPKG

double-ui-vue

Version:
557 lines (556 loc) 14.7 kB
import { openBlock, createElementBlock, createElementVNode, createVNode, render as render$2, defineComponent, reactive, getCurrentInstance, watch, onMounted, onBeforeUnmount, Transition, withDirectives, vShow, mergeProps, createStaticVNode, ref } from "vue"; var style = ""; const _hoisted_1$1 = { viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg" }; const _hoisted_2$1 = /* @__PURE__ */ createElementVNode("path", { d: "m8.39 5.988 2.96 3.7a.5.5 0 0 1-.39.812H5.04a.5.5 0 0 1-.39-.812l2.96-3.7a.5.5 0 0 1 .78 0Z", class: "svg-fill-grey-500" }, null, -1); const _hoisted_3$1 = [ _hoisted_2$1 ]; function render$1(_ctx, _cache) { return openBlock(), createElementBlock("svg", _hoisted_1$1, _hoisted_3$1); } var Triangle = { render: render$1 }; var V = (e, t) => { let r = e.tagName.toLocaleLowerCase(); return r === "body" || t.some((o) => o.toLocaleLowerCase() === r) ? e : V(e.parentNode, t); }, M = V; var Ze = ({ trigger: e, dom: t, offset: r = 8, isRight: o = false }) => { let n, a, i = true, { clientWidth: s, clientHeight: l } = document.documentElement, { pageXOffset: c, pageYOffset: f } = window, h = document.body, g = t.cloneNode(true); g.style.position = "absolute", g.style.left = "0", g.style.top = "0", g.style.display = "inline-block", h.appendChild(g); let { width: u, height: b } = g.getBoundingClientRect(); h.removeChild(g), g = null; let { left: m, top: w, width: D, height: L } = e.getBoundingClientRect(), K = w, X = l - w - L - r, p = m + D, x = s - m, T = m < 0, k = m + D > s; return o ? k && T ? n = s - u : k ? (x = s - m, x > u ? n = m : n = s - u) : T ? (p = D + m, p >= u ? n = p - u : n = 0) : p >= u ? n = p - u : x >= u ? n = m : n = s - u : T && k ? n = 0 : m < 0 ? (p = D + m, p >= u ? n = p - u : n = 0) : m + D > s ? (x = s - m, x >= u ? n = m : n = s - u) : x >= u ? n = m : p >= u ? n = p - u : n = s - u, X >= b ? a = w + L + r : K >= b ? (a = w - b - r, i = false) : a = l - b, n = n + c, a = a + f, { left: n, top: a, isDown: i }; }, qe = Ze; var _t = (e, t) => { let r = e.target; t && (r = M(r, [t])); let { clientWidth: o, scrollWidth: n } = r; n > o ? r.title = r.innerText : r.title = ""; }, Kt = _t; let dom; const CreateInstance = (options) => { const { tag, props, component, resetPosition: resetPosition2 } = options; if (!dom) { dom = document.createElement("div"); document.body.appendChild(dom); } const vm = createVNode(component, props); const instance = { vm, tag, resetPosition() { if (resetPosition2) resetPosition2(instance); }, remove() { if (vm.component.isUnmounted) return; render$2(null, dom); } }; render$2(vm, dom); return instance; }; const ClickOutside = (e, dom2, cb) => { if (!dom2.contains(e.target)) cb(); }; const _hoisted_1 = { viewBox: "0 0 14 14", xmlns: "http://www.w3.org/2000/svg" }; const _hoisted_2 = /* @__PURE__ */ createElementVNode("path", { d: "M7 0a7 7 0 1 0 0 14A7 7 0 0 0 7 0Zm2.784 8.637a.656.656 0 0 1-.928.929L7 7.709 5.144 9.566a.656.656 0 0 1-.928-.929l1.856-1.856-1.856-1.856a.656.656 0 0 1 .928-.928L7 5.853l1.856-1.856a.656.656 0 0 1 .928.928L7.928 6.781l1.856 1.856Z", class: "svg-fill-grey-400" }, null, -1); const _hoisted_3 = [ _hoisted_2 ]; function render(_ctx, _cache) { return openBlock(), createElementBlock("svg", _hoisted_1, _hoisted_3); } var ClearSvg = { render }; const OptionItem = (props) => createVNode("section", { "key": props.id, "class": ["d-drop-option-item", props.value === props.id && "d-drop-option-selected", props.disabled && "d-drop-option-disable"], "data-id": props.id }, [props.icon && createVNode("i", { "class": "d-drop-option-svg" }, null), createVNode("span", null, [createStaticVNode(props.name, 0)])]); const DOption = defineComponent({ name: "DOption", props: { parentState: { type: Object, default: () => ({}) }, position: { type: Boolean, default: true }, data: { type: Array, default: () => [], required: true }, value: { type: [String, Number], default: "" }, minWidth: { type: [String, Number], default: "" }, maxWidth: { type: [String, Number], default: "" }, theme: { type: String, default: "light" }, trigger: { type: String, default: "hover" }, openSearch: { type: Boolean, default: false }, placeholder: { type: String, default: "\u8BF7\u641C\u7D22" }, alignRight: { type: Boolean, default: false }, arrow: { type: Boolean, default: false }, translateX: { type: [String, Number], default: 0 }, maxCount: { type: [String, Number], default: 5 }, optionClick: { type: Function, default: () => { } } }, setup(props) { const state = reactive({ inputVal: "", optionData: [], scrollTop: 0 }); const { proxy } = getCurrentInstance(); let timer; watch(() => props.parentState.optionStatus, (n) => { if (n) { setTimeout(() => { proxy.$el.style.pointerEvents = "auto"; proxy.$el.focus(); }, 300); } else { proxy.$el.style.pointerEvents = "none"; } }); watch(() => props.data, (n, o) => { const nData = JSON.stringify(n); const oData = JSON.stringify(o); if (nData === oData) return; state.optionData = JSON.parse(nData); }, { deep: true, immediate: true }); const inputHandle = (e) => { state.inputVal = e.target.value; }; const searchHandle = (str) => { const data = JSON.parse(JSON.stringify(props.data)); if (str) { state.optionData = data.filter((d) => { if (d.name.includes(str)) return d; return null; }); } else { state.optionData = data; } }; watch(() => state.inputVal, (n, o) => { if (n === o) return; if (timer) clearTimeout(timer); timer = window.setTimeout(() => { searchHandle(n); }, 300); }); const clearInput = () => { state.inputVal = ""; }; const dropClick = (e) => { const { dataset: { id } } = M(e.target, ["SECTION"]); const { optionData } = state; const { name = "", disabled = false } = optionData.find((d) => d.id === id); if (disabled) return; props.optionClick(id, name); }; const dropClose = () => { const { parentState } = props; parentState.optionStatus = false; }; const dropEnter = () => { if (props.parentState.dropTimer) clearTimeout(props.parentState.dropTimer); }; const dropLeave = () => { const { trigger, parentState } = props; if (trigger === "hover") parentState.dropTimer = window.setTimeout(dropClose, 300); }; const scrollTopHandle = (e) => { state.scrollTop = e.target.scrollTop; }; const clickOutSide = (e) => { ClickOutside(e, proxy.$el, dropClose); }; onMounted(() => { window.addEventListener("click", clickOutSide, true); window.addEventListener("blur", dropClose, true); }); onBeforeUnmount(() => { window.removeEventListener("click", clickOutSide); window.removeEventListener("blur", dropClose); }); return () => { const { parentState: { optionStatus }, position, theme, arrow, minWidth, maxWidth, openSearch, placeholder, value } = props; const { scrollTop, inputVal, optionData } = state; return createVNode(Transition, { "name": position ? "selectDownUpExtend" : "selectDownUpExtendTop" }, { default: () => [withDirectives(createVNode("div", { "class": ["d-drop-content", `d-drop-content-${theme}`, arrow && (position ? "d-drop-content-top-arrow" : "d-drop-content-bottom-arrow")], "style": { minWidth: `${minWidth}px`, maxWidth: `${maxWidth}px` }, "onWheel": (e) => { e.stopPropagation(); }, "onMouseenter": dropEnter, "onMouseleave": dropLeave }, [openSearch && createVNode("span", { "class": ["d-drop-search", scrollTop > 12 && "d-drop-search-shadow"] }, [createVNode("input", { "class": "d-drop-input", "type": "text", "placeholder": placeholder, "value": inputVal, "onInput": inputHandle }, null), withDirectives(createVNode("i", { "class": "d-drop-clear", "onClick": clearInput }, [createVNode(ClearSvg, null, null)]), [[vShow, inputVal]])]), createVNode("div", { "class": "d-drop-option", "ref": "dropOption", "onScroll": scrollTopHandle, "onClick": dropClick, "onMouseover": (e) => { Kt(e, "SECTION"); } }, [optionData.map((item) => createVNode(OptionItem, mergeProps(item, { "value": value }), null))])]), [[vShow, optionStatus]])] }); }; } }); const resetPosition = (instance) => { const { vm, tag } = instance; const { component: { props: { alignRight, translateX, maxCount }, refs: { dropOption } }, el } = vm; const maxHeiByCount = maxCount * 38; dropOption.style.maxHeight = `${maxHeiByCount}px`; const div = document.createElement("div"); div.className = "m-drop-content"; div.innerHTML = el.innerHTML; const { left, top, isDown } = qe({ trigger: tag, dom: el, isRight: !!alignRight }); vm.component.props.position = isDown; el.style.top = `${top}px`; el.style.left = `${left + Number(translateX)}px`; }; const DropOption = ({ tag, props }) => CreateInstance({ tag, props, component: DOption, resetPosition }); const Dropdown = defineComponent({ name: "DDropdown", props: { data: { type: Array, default: () => [], required: true }, value: { type: [String, Number], default: "" }, minWidth: { type: [String, Number], default: "" }, maxWidth: { type: [String, Number], default: "" }, triangle: { type: Boolean, default: true }, transfer: { type: String, default: "parent" }, theme: { type: String, default: "light" }, trigger: { type: String, default: "hover" }, openSearch: { type: Boolean, default: false }, placeholder: { type: String, default: "\u8BF7\u641C\u7D22" }, alignRight: { type: Boolean, default: false }, arrow: { type: Boolean, default: false }, translateX: { type: [String, Number], default: 0 }, disabled: { type: Boolean, default: false }, maxCount: { type: [String, Number], default: 5 }, onChangeEvent: { type: Function } }, emits: ["changeEvent", "getStatus"], setup(props, { slots, emit }) { const pDrop = ref(null); const state = reactive({ optionStatus: false, dropShow: false, dropTimer: null }); let dOption; watch(() => props.value, (n, o) => { if (n === o) return; if (dOption) dOption.vm.component.props.value = n; }); watch(() => props.data, (n, o) => { if (n === o) return; if (dOption) dOption.vm.component.props.data = n; }); watch(() => state.optionStatus, (n, o) => { if (n === o) return; if (n) state.dropShow = true; else { setTimeout(() => { state.dropShow = false; }, 300); } }); watch(() => state.dropShow, (n, o) => { if (n === o) return; emit("getStatus", n); }); const setDropdownStatus = (status) => { state.optionStatus = status; if (dOption && status) dOption.resetPosition(); }; const optionClick = (id, name) => { setDropdownStatus(false); emit("changeEvent", id, name); }; const openDrop = () => { const { data } = props; if (JSON.stringify(data).length <= 4) return; if (dOption) { setDropdownStatus(true); } else { dOption = DropOption({ tag: pDrop.value, props: { parentState: state, optionClick, ...props } }); setDropdownStatus(true); } }; const dropEnter = () => { const { disabled, trigger } = props; const { optionStatus } = state; if (disabled) return; if (trigger === "hover") { if (!optionStatus) openDrop(); } }; const dropLeave = () => { const { disabled, trigger } = props; if (disabled) return; if (trigger === "hover" && dOption) { state.dropTimer = window.setTimeout(() => { state.optionStatus = false; }, 300); } }; const dropClick = (e) => { e.stopPropagation(); const { disabled, trigger } = props; const { optionStatus, dropShow } = state; if (disabled || dropShow) return; if (trigger === "click" && !optionStatus) openDrop(); }; onBeforeUnmount(() => { if (dOption) dOption.remove(); }); return () => { const { theme, disabled, triangle } = props; const { dropShow, optionStatus } = state; return createVNode("div", { "class": ["d-drop", `d-drop-${theme}`, dropShow && "d-drop-show", disabled && "d-drop-disabled"], "ref": pDrop, "onMouseenter": dropEnter, "onMouseleave": dropLeave, "onClick": dropClick }, [createVNode("section", { "class": "d-drop-title" }, [createVNode("article", { "class": "d-drop-title-content" }, [slots.default()]), triangle && createVNode("article", { "class": ["d-drop-triangle", !optionStatus && "d-drop-triangle-rotate"] }, [createVNode(Triangle, null, null)])])]); }; } }); export { Dropdown as default };