UNPKG

vue-devui

Version:

DevUI components based on Vite and Vue3

1,753 lines 408 kB
import { computed, ref, watchEffect, watch, getCurrentInstance, unref, defineComponent, inject, createVNode, mergeProps, toRefs, onMounted, onUnmounted, Transition, nextTick, withModifiers, Comment, Text, Fragment, h, withDirectives, cloneVNode, provide, Teleport, vShow, resolveDynamicComponent, render, reactive, resolveComponent, toRef, createTextVNode, onBeforeUnmount, isVNode, onBeforeMount, onUpdated, resolveDirective } from "vue"; import "clipboard"; import { offset, flip, arrow, computePosition } from "@floating-ui/dom"; import { onClickOutside } from "@vueuse/core"; const tableProps = { data: { type: Array, default: [] }, striped: { type: Boolean, default: false }, scrollable: { type: Boolean, default: false }, maxWidth: { type: String }, maxHeight: { type: String }, tableWidth: { type: String }, tableHeight: { type: String }, size: { type: String, validator(value) { return value === "sm" || value === "md" || value === "lg"; }, default: "sm" }, rowHoveredHighlight: { type: Boolean, default: true }, fixHeader: { type: Boolean, default: false }, checkable: { type: Boolean, default: false }, tableLayout: { type: String, default: "fixed", validator(v) { return v === "fixed" || v === "auto"; } }, showLoading: { type: Boolean, default: false }, headerBg: { type: Boolean, default: false }, spanMethod: { type: Function }, borderType: { type: String, default: "" }, empty: { type: String, default: "No Data" }, showHeader: { type: Boolean, default: true }, rowKey: { type: [Function, String], default: "id" }, defaultExpandAll: { type: Boolean, default: false }, expandRowKeys: { type: Array }, indent: { type: Number, default: 16 }, lazy: { type: Boolean, default: false } }; const TABLE_TOKEN = Symbol(); function createBem$1(namespace, element, modifier) { let cls = namespace; if (element) { cls += `__${element}`; } if (modifier) { cls += `--${modifier}`; } return cls; } function useNamespace$1(block, needDot = false) { const namespace = needDot ? `.devui-${block}` : `devui-${block}`; const b = () => createBem$1(namespace); const e = (element) => element ? createBem$1(namespace, element) : ""; const m = (modifier) => modifier ? createBem$1(namespace, "", modifier) : ""; const em = (element, modifier) => element && modifier ? createBem$1(namespace, element, modifier) : ""; return { b, e, m, em }; } function useTable(props, tableWidth) { const ns2 = useNamespace$1("table"); const classes = computed(() => ({ [ns2.e("view")]: true, [ns2.m("striped")]: props.striped, [ns2.m("header-bg")]: props.headerBg, [ns2.m("layout-auto")]: props.tableLayout === "auto", [ns2.m(`${props.size}`)]: true, [ns2.m(`${props.borderType}`)]: Boolean(props.borderType) })); const styles = computed(() => ({ maxHeight: props.maxHeight, maxWidth: props.maxWidth, height: props.tableHeight, width: props.tableWidth })); return { classes, styles }; } const useFixedColumn = (column2) => { const ns2 = useNamespace$1("table"); const stickyClass = computed(() => ({ [ns2.e("checkable-cell")]: column2.value.type === "checkable", [ns2.m("sticky-cell")]: Boolean(column2.value.fixedLeft) || Boolean(column2.value.fixedRight), left: Boolean(column2.value.fixedLeft), right: Boolean(column2.value.fixedRight), [`is-${column2.value.align}`]: true })); const stickyStyle = computed(() => ({ left: column2.value.fixedLeft, right: column2.value.fixedRight })); return { stickyClass, stickyStyle }; }; function useTableLayout(table2) { const tableWidth = ref(); const updateColgroupWidth = () => { var _a, _b; const cols = ((_b = (_a = table2 == null ? void 0 : table2.vnode) == null ? void 0 : _a.el) == null ? void 0 : _b.querySelectorAll("colgroup > col")) || []; if (!cols.length) { return; } const flatColumns = table2.store.states.flatColumns; const columnMap = {}; flatColumns.value.forEach((column2) => { columnMap[column2.id] = column2; }); for (let i = 0, len = cols.length; i < len; i++) { const col = cols[i]; const columnId = col.getAttribute("column-id"); const column2 = columnMap[columnId]; if (column2) { col.setAttribute("width", column2.realWidth); } } }; const updateColumnWidth = () => { var _a, _b; const tableClientWidth = (_b = (_a = table2 == null ? void 0 : table2.vnode) == null ? void 0 : _a.el) == null ? void 0 : _b.clientWidth; let tableMinWidth = 0; const flatColumns = table2.store.states.flatColumns; const flexColumns = flatColumns.value.filter((column2) => typeof column2.width !== "number"); if (flexColumns.length) { flatColumns.value.forEach((column2) => { tableMinWidth += Number(column2.width || 80); }); if (tableMinWidth <= tableClientWidth) { const totalFlexWidth = tableClientWidth - tableMinWidth; if (flexColumns.length === 1) { flexColumns[0].realWidth = Number(flexColumns[0].width || 80) + totalFlexWidth; } else { const allFlexColumnWidth = flexColumns.reduce((pre, column2) => pre + Number(column2.width || 80), 0); const flexWidthPercent = totalFlexWidth / allFlexColumnWidth; let exceptFistWidth = 0; flexColumns.forEach((column2, index2) => { if (index2 === 0) { return; } const perFlexWidth = Math.floor(Number(column2.width || 80) * flexWidthPercent); exceptFistWidth += perFlexWidth; column2.realWidth = Number(column2.width || 80) + perFlexWidth; }); flexColumns[0].realWidth = Number(flexColumns[0].width || 80) + totalFlexWidth - exceptFistWidth; } } else { flexColumns.forEach((column2) => { column2.realWidth = Number(column2.width || 80); }); } tableWidth.value = Math.max(tableMinWidth, tableClientWidth); } else { flatColumns.value.forEach((column2) => { column2.realWidth = column2.width || 80; tableMinWidth += Number(column2.realWidth); }); tableWidth.value = tableMinWidth; } updateColgroupWidth(); }; return { tableWidth, updateColumnWidth }; } function useTableWatcher(props, store) { watchEffect(() => { if (props.expandRowKeys) { store.setExpandRows(props.expandRowKeys); } }); watch( () => props.data, () => { store.updateRows(); store.updateColumns(); }, { deep: true } ); } function useHorizontalScroll(table2) { const ns2 = useNamespace$1("table"); const setScrollViewClass = (position) => { const element = table2.vnode.el; const className = ns2.m(`scroll-${position}`); const elClassList = element.classList; if (!elClassList.contains(className)) { for (let i = 0; i < elClassList.length; i++) { const clName = elClassList[i]; if (clName.startsWith(ns2.m("scroll-"))) { elClassList.remove(clName); } } elClassList.add(className); } }; const onTableScroll = (e) => { const target = e.currentTarget; const scrollLeft = target.scrollLeft; if (scrollLeft === 0) { if (target.clientWidth === target.scrollWidth) { setScrollViewClass("none"); } else { setScrollViewClass("left"); } } else if (scrollLeft + target.clientWidth === target.scrollWidth) { setScrollViewClass("right"); } else { setScrollViewClass("middle"); } }; return { onTableScroll }; } const inBrowser = typeof window !== "undefined"; function judgeFireIsElement(element) { const str = Object.prototype.toString.call(element); return str.includes("object") && str.includes("HTML") && str.includes("Element"); } function getElement(element) { if (element instanceof Element || judgeFireIsElement(element)) { return element; } if (element && typeof element === "object" && (element.$el instanceof Element || judgeFireIsElement(element.$el))) { return element.$el; } return null; } function lockScroll() { if (document.documentElement.scrollHeight > document.documentElement.clientHeight) { const scrollTop = document.documentElement.scrollTop; const style = document.documentElement.getAttribute("style"); document.documentElement.style.position = "fixed"; document.documentElement.style.top = `-${scrollTop}px`; document.documentElement.style.width = document.documentElement.style.width || "100%"; document.documentElement.style.overflowY = "scroll"; return () => { if (style) { document.documentElement.setAttribute("style", style); } else { document.documentElement.removeAttribute("style"); } document.documentElement.scrollTop = scrollTop; }; } return; } const isBoolean = (value) => typeof value === "boolean"; const isString = (value) => typeof value === "string"; const isFunction = (value) => Object.prototype.toString.call(value) === "[object Function]"; function createBem(namespace, element, modifier) { let cls = namespace; if (element) { cls += `__${element}`; } if (modifier) { cls += `--${modifier}`; } return cls; } function useNamespace(block, needDot = false) { const namespace = needDot ? `.devui-${block}` : `devui-${block}`; const b = () => createBem(namespace); const e = (element) => element ? createBem(namespace, element) : ""; const m = (modifier) => modifier ? createBem(namespace, "", modifier) : ""; const em = (element, modifier) => element && modifier ? createBem(namespace, element, modifier) : ""; return { b, e, m, em }; } function isUrl(value) { return /^((http|https):)?\/\//.test(value); } function formatWidth(width) { if (width === "") { return width; } if (typeof width === "number") { return width; } return parseInt(width, 10) || 80; } function getRowIdentity(row, rowKey, index2) { if (isFunction(rowKey)) { return rowKey(row, index2); } else if (isString(rowKey)) { const paths = rowKey.split("."); let obj = row; for (const p of paths) { obj = obj[p]; } return `${obj}`; } return ""; } function getRowKeysMap(data, rowKey) { const rowKeyMap = {}; (data || []).forEach((row, index2) => { rowKeyMap[getRowIdentity(row, rowKey)] = { row, index: index2 }; }); return rowKeyMap; } function toggleRowExpandStatus(rowsArr, row, status) { let isChanged = false; const index2 = rowsArr.indexOf(row); const isIncluded = index2 !== -1; const addRow = () => { rowsArr.push(row); isChanged = true; }; const deleteRow = () => { rowsArr.splice(index2, 1); isChanged = true; }; if (isBoolean(status)) { if (status && !isIncluded) { addRow(); } else if (!status && isIncluded) { deleteRow(); } } else { if (isIncluded) { deleteRow(); } else { addRow(); } } return isChanged; } function toggleRowVisible(expand, table2, key) { const rowLevelMap = (table2 == null ? void 0 : table2.store.states.rowLevelMap.value) || {}; const levelKeys = Object.keys(rowLevelMap); const hiddenRowKeys = table2 == null ? void 0 : table2.store.states.hiddenRowKeys; let start = false; for (let index2 = 0; index2 < levelKeys.length; index2++) { if (levelKeys[index2] === key) { start = true; index2++; } if (start && rowLevelMap[levelKeys[index2]] !== rowLevelMap[key] + 1) { break; } if (start && rowLevelMap[levelKeys[index2]] === rowLevelMap[key] + 1) { if (expand) { hiddenRowKeys.value = hiddenRowKeys.value.filter((rowKey) => rowKey !== levelKeys[index2]); } else { if (!hiddenRowKeys.value.includes(levelKeys[index2])) { hiddenRowKeys.value.push(levelKeys[index2]); } } } } } function useExpand(dataSource, table2) { const tableInstance = getCurrentInstance(); const rowKey = tableInstance.props.rowKey || ""; const defaultExpandAll = ref(tableInstance.props.defaultExpandAll); const _expandedRows = ref([]); const updateExpandRows = () => { if (defaultExpandAll.value) { _expandedRows.value = dataSource.value.slice(); } else { _expandedRows.value = []; } }; const setExpandRows = (rowKeys) => { const data = dataSource.value || []; const rowKeysMap = getRowKeysMap(data, rowKey); _expandedRows.value = rowKeys.reduce((pre, cur) => { const currentRow = rowKeysMap[cur]; if (currentRow) { pre.push(currentRow.row); } return pre; }, []); }; const isRowExpanded = (row) => { return _expandedRows.value.includes(row); }; const doToggleRowVisible = (expand, row) => { var _a; if ((_a = row.children) == null ? void 0 : _a.length) { const key = getRowIdentity(row, rowKey); if (expand && isRowExpanded(row)) { toggleRowVisible(true, table2, key); } if (!expand) { toggleRowVisible(false, table2, key); } row.children.forEach((child) => { doToggleRowVisible(expand, child); }); } }; const toggleRowExpansion = (row, expanded) => { const isChanged = toggleRowExpandStatus(_expandedRows.value, row, expanded); if (isChanged) { tableInstance.emit("expand-change", row, _expandedRows.value.slice()); } if (!table2.store.states.flatColumns.value.some((column2) => column2.type === "expand")) { doToggleRowVisible(isRowExpanded(row), row); } }; return { isRowExpanded, updateExpandRows, setExpandRows, toggleRowExpansion }; } function useEditTableCell() { const tableInstance = getCurrentInstance(); const rowKey = tableInstance.props.rowKey || ""; const tableCellModeMap = ref(/* @__PURE__ */ new Map()); const setCellMode = (row, rowIndex, fields, cellMode) => { if (Array.isArray(fields)) { fields.forEach((item) => { const cellKey = `${getRowIdentity(row, rowKey, rowIndex)}-${item}-cell`; tableCellModeMap.value.set(cellKey, cellMode); }); } else { const cellKey = `${getRowIdentity(row, rowKey, rowIndex)}-${fields}-cell`; tableCellModeMap.value.set(cellKey, cellMode); } }; const resetCellMode = () => { for (const item of tableCellModeMap.value.keys()) { tableCellModeMap.value.set(item, "readonly"); } }; return { tableCellModeMap, setCellMode, resetCellMode }; } function useSort$1(dataSource, _data) { const thList = []; const sortData = (direction, sortMethod) => { if (direction === "ASC") { _data.value = _data.value.sort((a, b) => sortMethod ? sortMethod(a, b) ? 1 : -1 : 0); } else if (direction === "DESC") { _data.value = _data.value.sort((a, b) => sortMethod ? sortMethod(a, b) ? -1 : 1 : 0); } else { _data.value = [...dataSource.value]; } }; const collectTh = (th) => { thList.push(th); }; return { thList, collectTh, sortData }; } function replaceColumn(array4, column2) { return array4.map((item) => { var _a; if (item.id === column2.id) { return column2; } else if ((_a = item.children) == null ? void 0 : _a.length) { item.children = replaceColumn(item.children, column2); } return item; }); } function doFlattenColumns(columns) { const result = []; columns.forEach((column2) => { if (column2.children) { result.push.apply(result, doFlattenColumns(column2.children)); } else { result.push(column2); } }); return result; } function createColumnGenerator() { const _columns = ref([]); const flatColumns = ref([]); const sortColumn = () => { _columns.value.sort((a, b) => { var _a, _b; return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0); }); }; const insertColumn = (column2, parent) => { var _a; const array4 = unref(_columns); let newColumns = []; if (!parent) { array4.push(column2); newColumns = array4; } else { if (parent && !parent.children) { parent.children = []; } (_a = parent == null ? void 0 : parent.children) == null ? void 0 : _a.push(column2); newColumns = replaceColumn(array4, parent); } sortColumn(); _columns.value = newColumns; }; const removeColumn = (column2) => { const i = _columns.value.findIndex((v) => v === column2); if (i === -1) { return; } _columns.value.splice(i, 1); }; const updateColumns = () => { flatColumns.value = [].concat(doFlattenColumns(_columns.value)); }; return { _columns, flatColumns, insertColumn, removeColumn, sortColumn, updateColumns }; } function doFlattenRows(dataList, level, rowKey, rowLevelMap, hiddenRowKeys) { const result = []; dataList.forEach((data) => { result.push(data); if (level > 0) { const key = getRowIdentity(data, rowKey); rowLevelMap.value[key] = level; hiddenRowKeys.value.push(key); } if (data.children) { rowLevelMap.value[getRowIdentity(data, rowKey)] = level; result.push.apply(result, doFlattenRows(data.children, level + 1, rowKey, rowLevelMap, hiddenRowKeys)); } }); return result; } function createRowGenerator(dataSource, rowKey, flatColumns) { const flatRows = ref([]); const hiddenRowKeys = ref([]); const rowLevelMap = ref({}); const firstDefaultColumn = ref(""); const updateRows = () => { const hasExpand = flatColumns.value.some((column2) => column2.type === "expand"); const result = hasExpand ? dataSource.value : doFlattenRows(dataSource.value, 0, rowKey, rowLevelMap, hiddenRowKeys); flatRows.value = [].concat(result); }; const updateFirstDefaultColumn = () => { const index2 = flatColumns.value.findIndex((column2) => column2.type === ""); firstDefaultColumn.value = index2 !== -1 ? flatColumns.value[index2].id : ""; }; return { flatRows, hiddenRowKeys, rowLevelMap, updateRows, firstDefaultColumn, updateFirstDefaultColumn }; } function createSelection(dataSource, rowKey, flatRows) { const _checkSet = ref(/* @__PURE__ */ new Set()); const checkRow = (toggle, row, index2) => { const key = getRowIdentity(row, rowKey, index2); if (toggle) { _checkSet.value.add(key); } else { _checkSet.value.delete(key); } }; const toggleRowSelection = (row, checked, index2) => { const key = getRowIdentity(row, rowKey, index2); const isIncluded = _checkSet.value.has(key); const addRow = () => { _checkSet.value.add(key); }; const deleteRow = () => { _checkSet.value.delete(key); }; if (isBoolean(checked)) { if (checked && !isIncluded) { addRow(); } else if (!checked && isIncluded) { deleteRow(); } } else { if (isIncluded) { deleteRow(); } else { addRow(); } } }; const isRowChecked = (row, index2) => { return _checkSet.value.has(getRowIdentity(row, rowKey, index2)); }; const getCheckedRows = () => { return flatRows.value.filter((item, index2) => isRowChecked(item, index2)); }; const _checkAllRecord = ref(false); const _checkAll = computed({ get: () => _checkAllRecord.value, set: (val) => { _checkAllRecord.value = val; dataSource.value.forEach((item, index2) => { checkRow(val, item, index2); }); } }); const _halfChecked = ref(false); watch( _checkSet, (set) => { if (set.size === 0) { return; } let allTrue = true; let allFalse = true; const items = flatRows.value; for (let i = 0; i < items.length; i++) { const checked = isRowChecked(items[i], i); allTrue && (allTrue = checked); allFalse && (allFalse = !checked); } _checkAllRecord.value = allTrue; _halfChecked.value = !(allFalse || allTrue); }, { immediate: true, deep: true } ); watch(dataSource, (value) => { _checkAllRecord.value = value.findIndex((item, index2) => !isRowChecked(item, index2)) === -1; }); return { _checkSet, _checkAll, _halfChecked, getCheckedRows, checkRow, isRowChecked, toggleRowSelection }; } function createFixedLogic(columns) { const isFixedLeft = computed(() => { return columns.value.reduce((prev, current) => prev || !!current.fixedLeft, false); }); return { isFixedLeft }; } function createStore(dataSource, table2, ctx) { const _data = ref([]); const { _columns, flatColumns, insertColumn, removeColumn, sortColumn, updateColumns } = createColumnGenerator(); const { flatRows, hiddenRowKeys, rowLevelMap, updateRows, firstDefaultColumn, updateFirstDefaultColumn } = createRowGenerator( dataSource, table2.props.rowKey, flatColumns ); const { _checkAll, _checkSet, _halfChecked, getCheckedRows, isRowChecked, checkRow, toggleRowSelection } = createSelection( _data, table2.props.rowKey, flatRows ); const { thList, collectTh, sortData } = useSort$1(dataSource, flatRows); const { isFixedLeft } = createFixedLogic(_columns); const { isRowExpanded, updateExpandRows, setExpandRows, toggleRowExpansion } = useExpand(_data, table2); const { tableCellModeMap, setCellMode, resetCellMode } = useEditTableCell(); const emitTableEvent = (eventName, ...params) => { ctx.emit.apply(ctx, [eventName, ...params]); }; watch( dataSource, (value) => { _data.value = [...value]; updateExpandRows(); }, { deep: true, immediate: true } ); return { states: { _data, flatRows, hiddenRowKeys, rowLevelMap, _columns, flatColumns, _checkSet, _checkAll, _halfChecked, isFixedLeft, thList, firstDefaultColumn, tableCellModeMap }, insertColumn, sortColumn, removeColumn, updateColumns, updateRows, getCheckedRows, collectTh, sortData, isRowChecked, checkRow, isRowExpanded, setExpandRows, toggleRowExpansion, toggleRowSelection, updateFirstDefaultColumn, setCellMode, resetCellMode, emitTableEvent }; } var ColGroup = defineComponent({ name: "DColGroup", setup() { const parent = inject(TABLE_TOKEN); const columns = parent == null ? void 0 : parent.store.states.flatColumns; const isFixed = computed(() => (parent == null ? void 0 : parent.props.tableLayout) === "fixed"); return () => createVNode("colgroup", null, [columns == null ? void 0 : columns.value.map((column2, index2) => { return createVNode("col", { "key": index2, "column-id": isFixed.value ? column2.id : "", "width": column2.type === "expand" ? 60 : isFixed.value ? column2.realWidth : column2.width || "" }, null); })]); } }); const sortProps = { sortDirection: { type: String, default: "" } }; var sort = ""; const XLINK_HREF = { "xlink:href": "#sort-svg-path-1" }; var Sort = defineComponent({ props: sortProps, emits: ["sort"], setup(props, ctx) { const directionMap = { ASC: "DESC", DESC: "", default: "ASC" }; const changeDirection = () => { ctx.emit("sort", directionMap[props.sortDirection || "default"]); }; const ns2 = useNamespace$1("table"); return () => createVNode("span", { "onClick": changeDirection, "class": ns2.e("sort-clickable") }, [createVNode("i", { "class": [{ [ns2.e("sort-default")]: !props.sortDirection, [ns2.e("sort-asc")]: props.sortDirection === "ASC", [ns2.e("sort-desc")]: props.sortDirection === "DESC" }] }, [createVNode("svg", { "width": "16px", "height": "16px", "viewBox": "0 0 16 16", "version": "1.1", "xmlns": "http://www.w3.org/2000/svg" }, [createVNode("defs", null, [createVNode("circle", { "id": "sort-svg-path-1", "cx": "8", "cy": "8", "r": "8" }, null), createVNode("filter", { "x": "-34.4%", "y": "-21.9%", "width": "168.8%", "height": "168.8%", "filterUnits": "objectBoundingBox", "id": "filter-2" }, [createVNode("feOffset", { "dx": "0", "dy": "2", "in": "SourceAlpha", "result": "shadowOffsetOuter1" }, null), createVNode("feGaussianBlur", { "stdDeviation": "1.5", "in": "shadowOffsetOuter1", "result": "shadowBlurOuter1" }, null), createVNode("feColorMatrix", { "values": "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.085309222 0", "type": "matrix", "in": "shadowBlurOuter1" }, null)])]), createVNode("g", { "stroke": "none", "stroke-width": "1", "fill": "none", "fill-rule": "evenodd" }, [createVNode("use", mergeProps({ "fill-rule": "evenodd" }, XLINK_HREF), null), createVNode("polygon", { "points": "8 4 11 7 5 7" }, null), createVNode("polygon", { "points": "8 12 5 9 11 9" }, null)])])])]); } }); const filterProps = { filterList: { type: Array, default: () => [] }, multiple: { type: Boolean, default: true } }; const dropdownProps = { visible: { type: Boolean, default: false }, trigger: { type: String, default: "click" }, closeScope: { type: String, default: "all" }, position: { type: Array, default: () => ["bottom", "top", "left", "right"] }, offset: { type: [Number, Object], default: 4 }, shiftOffset: { type: Number }, closeOnMouseLeaveMenu: { type: Boolean, default: false }, showAnimation: { type: Boolean, default: true }, overlayClass: { type: String, default: "" }, destroyOnHide: { type: Boolean, default: true }, teleport: { type: [String, Object], default: "body" } }; const POPPER_TRIGGER_TOKEN = Symbol("popper-trigger"); const dropdownMap = /* @__PURE__ */ new Map(); function subscribeEvent(dom, type4, callback) { dom == null ? void 0 : dom.addEventListener(type4, callback); return () => { dom == null ? void 0 : dom.removeEventListener(type4, callback); }; } const useDropdownEvent = ({ id, isOpen, origin, dropdownRef, props, emit }) => { let overlayEnter = false; let originEnter = false; const { trigger, closeScope, closeOnMouseLeaveMenu } = toRefs(props); const toggle = (status) => { isOpen.value = status; emit("toggle", isOpen.value); }; const handleLeave = async (elementType, closeAll) => { await new Promise((resolve) => setTimeout(resolve, 50)); if (elementType === "origin" && overlayEnter || elementType === "dropdown" && originEnter) { return; } if (closeAll) { [...dropdownMap.values()].reverse().forEach((item) => { setTimeout(() => { var _a; (_a = item.toggle) == null ? void 0 : _a.call(item); }, 0); }); } toggle(false); }; watch([trigger, origin, dropdownRef], ([triggerVal, originVal, dropdownEl], ov, onInvalidate) => { const originEl = getElement(originVal); const subscriptions = []; setTimeout(() => { subscriptions.push( subscribeEvent(document, "click", (e) => { e.stopPropagation(); const dropdownValues = [...dropdownMap.values()]; if (!isOpen.value || closeScope.value === "none" || (dropdownEl == null ? void 0 : dropdownEl.contains(e.target)) && closeScope.value === "blank" || dropdownValues.some((item) => { var _a; return (_a = item.toggleEl) == null ? void 0 : _a.contains(e.target); }) && dropdownValues.some((item) => { var _a; return (_a = item.menuEl) == null ? void 0 : _a.contains(e.target); })) { return; } [...dropdownMap.values()].reverse().forEach((item) => { setTimeout(() => { var _a, _b; if (!((_a = item.toggleEl) == null ? void 0 : _a.contains(e.target))) { (_b = item.toggle) == null ? void 0 : _b.call(item); } }, 0); }); overlayEnter = false; }) ); }, 0); if (triggerVal === "click") { subscriptions.push( subscribeEvent(originEl, "click", () => toggle(!isOpen.value)), subscribeEvent(dropdownEl, "mouseleave", (e) => { var _a; if (closeOnMouseLeaveMenu.value && !((_a = dropdownMap.get(id).child) == null ? void 0 : _a.contains(e.relatedTarget))) { handleLeave("dropdown", true); } }) ); } else if (triggerVal === "hover") { subscriptions.push( subscribeEvent(originEl, "mouseenter", () => { originEnter = true; toggle(true); }), subscribeEvent(originEl, "mouseleave", () => { originEnter = false; handleLeave("origin"); }), subscribeEvent(dropdownEl, "mouseenter", () => { overlayEnter = true; isOpen.value = true; }), subscribeEvent(dropdownEl, "mouseleave", (e) => { var _a; overlayEnter = false; if (e.relatedTarget && ((originEl == null ? void 0 : originEl.contains(e.relatedTarget)) || ((_a = dropdownMap.get(id).child) == null ? void 0 : _a.contains(e.relatedTarget)))) { return; } handleLeave("dropdown", true); }) ); } onInvalidate(() => subscriptions.forEach((v) => v())); }); }; function useDropdown(id, visible, isOpen, origin, dropdownRef, emit) { watch( visible, (newVal, oldVal) => { if (oldVal === void 0) { return; } isOpen.value = newVal; emit("toggle", isOpen.value); }, { immediate: true } ); watch([isOpen, dropdownRef], ([isOpenVal, dropdownEl]) => { var _a; if (isOpenVal) { dropdownMap.set(id, { ...dropdownMap.get(id), menuEl: dropdownEl, toggle: () => { isOpen.value = false; emit("toggle", isOpen.value); } }); for (const value of dropdownMap.values()) { if ((_a = value.menuEl) == null ? void 0 : _a.contains(origin.value)) { value.child = dropdownEl; } } } }); onMounted(() => { dropdownMap.set(id, { toggleEl: origin.value }); }); onUnmounted(() => { dropdownMap.delete(id); }); } function useOverlayProps(props, currentPosition, isOpen) { const { showAnimation, overlayClass, destroyOnHide } = toRefs(props); const overlayModelValue = ref(false); const overlayShowValue = ref(false); const styles = computed(() => ({ transformOrigin: currentPosition.value === "top" ? "0% 100%" : "0% 0%", zIndex: "var(--devui-z-index-dropdown, 1052)" })); const classes = computed(() => ({ "fade-in-bottom": showAnimation.value && isOpen.value && currentPosition.value === "bottom", "fade-in-top": showAnimation.value && isOpen.value && currentPosition.value === "top", [`${overlayClass.value}`]: true })); const handlePositionChange = (pos) => { currentPosition.value = pos.includes("top") || pos.includes("right-end") || pos.includes("left-end") ? "top" : "bottom"; }; watch(isOpen, (isOpenVal) => { overlayModelValue.value = destroyOnHide.value ? isOpenVal : true; overlayShowValue.value = isOpenVal; }); return { overlayModelValue, overlayShowValue, styles, classes, handlePositionChange }; } const fixedOverlayProps = { modelValue: { type: Boolean, default: false }, lockScroll: { type: Boolean, default: true }, closeOnClickOverlay: { type: Boolean, default: true } }; function useFixedOverlay(props, ctx) { let lockScrollCb; const onClick = (event) => { event.preventDefault(); ctx.emit("click", event); if (props.closeOnClickOverlay) { ctx.emit("update:modelValue", false); } }; const removeBodyAdditions = () => { lockScrollCb == null ? void 0 : lockScrollCb(); }; watch( () => props.modelValue, (val) => { if (val) { props.lockScroll && (lockScrollCb = lockScroll()); } else { removeBodyAdditions(); } } ); onUnmounted(removeBodyAdditions); return { onClick }; } var fixedOverlay = ""; defineComponent({ name: "DFixedOverlay", inheritAttrs: false, props: fixedOverlayProps, emits: ["update:modelValue", "click"], setup(props, ctx) { const { modelValue } = toRefs(props); const ns2 = useNamespace$1("fixed-overlay"); const { onClick } = useFixedOverlay(props, ctx); return () => createVNode(Transition, { "name": ns2.m("fade") }, { default: () => { var _a, _b; return [modelValue.value && createVNode("div", mergeProps({ "class": ns2.b() }, ctx.attrs, { "onClick": onClick }), [(_b = (_a = ctx.slots).default) == null ? void 0 : _b.call(_a)])]; } }); } }); const flexibleOverlayProps = { modelValue: { type: Boolean, default: false }, origin: { type: Object, require: true }, position: { type: Array, default: ["bottom"] }, offset: { type: [Number, Object], default: 8 }, shiftOffset: { type: Number }, align: { type: String, default: null }, showArrow: { type: Boolean, default: false }, isArrowCenter: { type: Boolean, default: true }, clickEventBubble: { type: Boolean, default: false }, fitOriginWidth: { type: Boolean, default: false } }; function adjustArrowPosition(isArrowCenter, point, placement, originRect) { let { x, y } = point; if (!isArrowCenter) { const { width, height } = originRect; if (x && placement.includes("start")) { x = 12; } if (x && placement.includes("end")) { x = Math.round(width - 24); } if (y && placement.includes("start")) { y = 10; } if (y && placement.includes("end")) { y = height - 14; } } return { x, y }; } function useOverlay(props, emit) { const { fitOriginWidth, position, showArrow } = toRefs(props); const overlayRef = ref(); const arrowRef = ref(); const overlayWidth = ref(0); let originObserver; const styles = computed(() => { if (fitOriginWidth.value) { return { width: overlayWidth.value + "px" }; } else { return {}; } }); const updateArrowPosition = (arrowEl, placement, point, overlayEl) => { const { x, y } = adjustArrowPosition(props.isArrowCenter, point, placement, overlayEl.getBoundingClientRect()); const staticSide = { top: "bottom", right: "left", bottom: "top", left: "right" }[placement.split("-")[0]]; Object.assign(arrowEl.style, { left: x ? `${x}px` : "", top: y ? `${y}px` : "", right: "", bottom: "", [staticSide]: "-4px" }); }; const updatePosition = async () => { const hostEl = props.origin; const overlayEl = unref(overlayRef.value); const arrowEl = unref(arrowRef.value); const [mainPosition, ...fallbackPosition] = position.value; const middleware = [offset(props.offset)]; middleware.push(fallbackPosition.length ? flip({ fallbackPlacements: fallbackPosition }) : flip()); if (showArrow.value) { middleware.push(arrow({ element: arrowRef.value })); } const { x, y, placement, middlewareData } = await computePosition(hostEl, overlayEl, { strategy: "fixed", placement: mainPosition, middleware }); let applyX = x; let applyY = y; emit("positionChange", placement); Object.assign(overlayEl.style, { top: `${applyY}px`, left: `${applyX}px` }); props.showArrow && updateArrowPosition(arrowEl, placement, middlewareData.arrow, overlayEl); }; const scrollCallback = (e) => { var _a, _b; const scrollElement = e.target; if (scrollElement == null ? void 0 : scrollElement.contains((_b = (_a = props.origin) == null ? void 0 : _a.$el) != null ? _b : props.origin)) { updatePosition(); } }; const updateWidth = (originEl) => { overlayWidth.value = originEl.getBoundingClientRect().width; updatePosition(); }; const observeOrigin = () => { var _a, _b; if (fitOriginWidth.value && typeof window !== "undefined") { const originEl = (_b = (_a = props.origin) == null ? void 0 : _a.$el) != null ? _b : props.origin; if (originEl) { originObserver = new window.ResizeObserver(() => updateWidth(originEl)); originObserver.observe(originEl); } } }; const unobserveOrigin = () => { var _a, _b; const originEl = (_b = (_a = props.origin) == null ? void 0 : _a.$el) != null ? _b : props.origin; originEl && (originObserver == null ? void 0 : originObserver.unobserve(originEl)); }; watch( () => props.modelValue, () => { if (props.modelValue && props.origin) { nextTick(updatePosition); window.addEventListener("scroll", scrollCallback, true); window.addEventListener("resize", updatePosition); observeOrigin(); } else { window.removeEventListener("scroll", scrollCallback, true); window.removeEventListener("resize", updatePosition); unobserveOrigin(); } } ); onUnmounted(() => { window.removeEventListener("scroll", scrollCallback, true); window.removeEventListener("resize", updatePosition); unobserveOrigin(); }); return { arrowRef, overlayRef, styles, updatePosition }; } var flexibleOverlay = ""; const FlexibleOverlay = defineComponent({ name: "DFlexibleOverlay", inheritAttrs: false, props: flexibleOverlayProps, emits: ["update:modelValue", "positionChange"], setup(props, { slots, attrs, emit, expose }) { const ns2 = useNamespace$1("flexible-overlay"); const { clickEventBubble } = toRefs(props); const { arrowRef, overlayRef, styles, updatePosition } = useOverlay(props, emit); expose({ updatePosition }); return () => { var _a; return props.modelValue && createVNode("div", mergeProps({ "ref": overlayRef, "class": ns2.b(), "style": styles.value }, attrs, { "onClick": withModifiers(() => ({}), [clickEventBubble.value ? "" : "stop"]), "onPointerup": withModifiers(() => ({}), ["stop"]) }), [(_a = slots.default) == null ? void 0 : _a.call(slots), props.showArrow && createVNode("div", { "ref": arrowRef, "class": ns2.e("arrow") }, null)]); }; } }); /** * @vue/shared v3.4.27 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT **/ const isObject = (val) => val !== null && typeof val === "object"; const ns$3 = useNamespace$1("popper-trigger"); function wrapContent(content) { return h("span", { class: ns$3.b() }, content); } function getFirstValidChild(nodes) { for (const child of nodes) { if (isObject(child)) { if (child.type === Comment) { continue; } if (child.type === "svg" || child.type === Text) { return wrapContent(child); } if (child.type === Fragment) { return getFirstValidChild(child.children); } return child; } return wrapContent(child); } return null; } var PopperTrigger = defineComponent({ name: "DPopperTrigger", setup(_, ctx) { const { slots, attrs } = ctx; return () => { var _a; const defaultSlot = (_a = slots.default) == null ? void 0 : _a.call(slots, attrs); const triggerRef = inject(POPPER_TRIGGER_TOKEN); if (!defaultSlot) { return null; } const firstValidChild = getFirstValidChild(defaultSlot); if (!firstValidChild) { return null; } return withDirectives(cloneVNode(firstValidChild, attrs), [[{ mounted(el) { triggerRef.value = el; }, updated(el) { triggerRef.value = el; }, unmounted() { triggerRef.value = null; } }]]); }; } }); var dropdown = ""; let dropdownId = 1; var Dropdown = defineComponent({ name: "DDropdown", inheritAttrs: false, props: dropdownProps, emits: ["toggle"], setup(props, { slots, attrs, emit, expose }) { const { visible, position, offset: offset2, destroyOnHide, shiftOffset, showAnimation, teleport } = toRefs(props); const origin = ref(); const dropdownRef = ref(); const overlayRef = ref(); const id = `dropdown_${dropdownId++}`; const isOpen = ref(false); const currentPosition = ref("bottom"); const ns2 = useNamespace$1("dropdown"); provide(POPPER_TRIGGER_TOKEN, origin); useDropdownEvent({ id, isOpen, origin, dropdownRef, props, emit }); useDropdown(id, visible, isOpen, origin, dropdownRef, emit); const { overlayModelValue, overlayShowValue, styles, classes, handlePositionChange } = useOverlayProps(props, currentPosition, isOpen); watch(overlayShowValue, (overlayShowValueVal) => { nextTick(() => { if (!destroyOnHide.value && overlayShowValueVal) { overlayRef.value.updatePosition(); } }); }); expose({ updatePosition: () => overlayRef.value.updatePosition() }); return () => createVNode(Fragment, null, [createVNode(PopperTrigger, null, { default: () => { var _a; return [(_a = slots.default) == null ? void 0 : _a.call(slots)]; } }), createVNode(Teleport, { "to": teleport.value }, { default: () => [createVNode(Transition, { "name": showAnimation.value ? ns2.m(`fade-${currentPosition.value}`) : "" }, { default: () => [withDirectives(createVNode(FlexibleOverlay, { "modelValue": overlayModelValue.value, "onUpdate:modelValue": ($event) => overlayModelValue.value = $event, "ref": overlayRef, "origin": origin.value, "position": position.value, "offset": offset2.value, "shiftOffset": shiftOffset == null ? void 0 : shiftOffset.value, "onPositionChange": handlePositionChange, "click-event-bubble": true, "class": classes.value, "style": styles.value }, { default: () => { var _a; return [createVNode("div", mergeProps({ "ref": dropdownRef, "class": ns2.e("menu-wrap") }, attrs), [(_a = slots.menu) == null ? void 0 : _a.call(slots)])]; } }), [[vShow, overlayShowValue.value]])] })] })]); } }); const dropdownMenuProps = { modelValue: { type: Boolean, default: false }, origin: { type: Object, require: true }, position: { type: Array, default: ["bottom"] }, align: { type: String, default: null }, offset: { type: [Number, Object], default: 4 }, clickOutside: { type: Function, default: () => true }, showAnimation: { type: Boolean, default: true }, overlayClass: { type: String, default: "" } }; defineComponent({ name: "DDropdownMenu", inheritAttrs: false, props: dropdownMenuProps, emits: ["update:modelValue"], setup(props, { slots, attrs, emit }) { const { modelValue, origin, position, align, offset: offset2, clickOutside, showAnimation, overlayClass } = toRefs(props); const dropdownMenuRef = ref(null); const ns2 = useNamespace$1("dropdown"); onClickOutside(dropdownMenuRef, (value) => { var _a, _b; if (((_a = clickOutside.value) == null ? void 0 : _a.call(clickOutside)) && !((_b = origin == null ? void 0 : origin.value) == null ? void 0 : _b.contains(value.target))) { emit("update:modelValue", false); } }); const currentPosition = ref("bottom"); const handlePositionChange = (pos) => { currentPosition.value = pos.split("-")[0] === "top" ? "top" : "bottom"; }; const styles = computed(() => ({ transformOrigin: currentPosition.value === "top" ? "0% 100%" : "0% 0%" })); return () => createVNode(Teleport, { "to": "body" }, { default: () => [createVNode(Transition, { "name": showAnimation.value ? ns2.m(`fade-${currentPosition.value}`) : "" }, { default: () => [createVNode(FlexibleOverlay, { "modelValue": modelValue.value, "onUpdate:modelValue": ($event) => modelValue.value = $event, "origin": origin == null ? void 0 : origin.value, "position": position.value, "align": align.value, "offset": offset2.value, "onPositionChange": handlePositionChange, "class": overlayClass.value, "style": styles.value }, { default: () => { var _a; return [createVNode("div", mergeProps({ "ref": dropdownMenuRef, "class": ns2.e("menu-wrap") }, attrs), [(_a = slots.default) == null ? void 0 : _a.call(slots)])]; } })] })] }); } }); const DEFAULT_PREFIX = "icon"; const iconProps = { name: { type: String, default: "" }, size: { type: [Number, String], default: "inherit" }, color: { type: String, default: "inherit" }, component: { type: Object, default: null }, classPrefix: { type: String, default: DEFAULT_PREFIX }, operable: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, rotate: { type: [Number, String] } }; const svgIconProps = { name: { type: String, default: "", required: true }, color: { type: String, default: "inherit" }, size: { type: [Number, String], default: "inherit" } }; var icon = ""; var svgIcon = defineComponent({ name: "DSvgIcon", props: svgIconProps, setup(props) { const { name, color, size } = toRefs(props); const ns2 = useNamespace$1("svg-icon"); const iconName = computed(() => `#icon-${name.value}`); const iconSize = computed(() => { return typeof size.value === "number" ? `${size.value}px` : size.value; }); const styles = { width: iconSize.value, height: iconSize.value }; return () => { return createVNode("svg", { "class": ns2.b(), "style": styles }, [createVNode("use", { "xlink:href": iconName.value, "fill": color.value }, null)]); }; } }); function useIconDom(props, ctx) { const { component, name, size, color, classPrefix, rotate } = toRefs(props); const ns2 = useNamespace$1("icon"); const iconSize = computed(() => { return typeof size.value === "number" ? `${size.value}px` : size.value; }); const IconComponent = component.value ? resolveDynamicComponent(component.value) : resolveDynamicComponent(svgIcon); const imgIconDom = () => { return createVNode("img", mergeProps({ "src": name.value, "alt": name.value.split("/")[name.value.split("/").length - 1], "class": [(rotate == null ? void 0 : rotate.value) === "infinite" && ns2.m("spin")], "style": { width: iconSize.value || "", transform: `rotate(${rotate == null ? void 0 : rotate.value}deg)`, verticalAlign: "middle" } }, ctx.attrs), null); }; const svgIconDom = () => { return createVNode(IconComponent, mergeProps({ "name": name.value, "color": color.value, "size": iconSize.value, "class": [(rotate == null ? void 0 : rotate.value) === "infinite" && ns2.m("spin")], "style": { transform: `rotate(${rotate == null ? void 0 : rotate.value}deg)` } }, ctx.attrs), null); }; const fontIconDom = () => { const fontIconClass = /^icon-/.test(name.value) ? name.value : `${classPrefix.value}-${name.value}`; return createVNode("i", mergeProps({ "class": [classPrefix.value, fontIconClass, (rotate == null ? void 0 : rotate.value) === "infinite" && ns2.m("spin")], "style": { fontSize: iconSize.value, color: color.value, transform: `rotate(${rotate == null ? void 0 : rotate.value}deg)` } }, ctx.attrs), null); }; const iconDom = () => { return component.value ? svgIconDom() : isUrl(name.value) ? imgIconDom() : fontIconDom(); }; return { iconDom }; } var Icon = defineComponent({ name: "DIcon", props: iconProps, emits: ["click"], setup(props, ctx) { const { disabled, operable } = toRefs(props); const { iconDom } = useIconDom(props, ctx); const ns2 = useNamespace$1("icon"); const wrapClassed = computed(() => ({ [ns2.e("container")]: true, [ns2.m("disabled")]: disabled.value, [ns2.m("operable")]: operable.value, [ns2.m("no-slots")]: !Object.keys(ctx.slots).length })); const onClick = (e) => { if (disabled.value) { return; } ctx.emit("click", e); }; return () => { var _a, _b, _c, _d; return createVNode("div", { "class": wrapClassed.value, "onClick": onClick }, [(_b = (_a = ctx.slots).prefix) == null ? void 0 : _b.call(_a), iconDom(), (_d = (_c = ctx.slots).suffix) == null ? void 0 : _d.ca