double-ui-vue
Version:
557 lines (556 loc) • 14.7 kB
JavaScript
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 };