UNPKG

tav-ui

Version:
434 lines (431 loc) 14 kB
import { isVNode, defineComponent, reactive, ref, computed, unref, toRaw, watch, shallowRef, nextTick, watchEffect, onMounted, createVNode, mergeProps, Fragment, withDirectives, vShow } from 'vue'; import { Tree as Tree$1, Empty } from 'ant-design-vue'; import { omit, difference, get } from 'lodash-es'; import { useContextMenu } from '../../../hooks/web/useContextMenu2.mjs'; import { filter, treeToList } from '../../../utils/helper/treeHelper2.mjs'; import { extendSlots, getSlot } from '../../../utils/helper/tsxHelper2.mjs'; import { isArray, isFunction, isBoolean, isEmpty } from '../../../utils/is2.mjs'; import { TaContainerScroll } from '../../container-scroll/index2.mjs'; import { treeProps } from './props2.mjs'; import TreeHeader from './TreeHeader2.mjs'; import { TreeIcon } from './TreeIcon2.mjs'; import { useTree } from './useTree2.mjs'; function _isSlot(s) { return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s); } var Tree = defineComponent({ name: "TaTree", inheritAttrs: false, props: treeProps, emits: ["update:expandedKeys", "update:selectedKeys", "update:checkedKeys", "change", "check", "update:searchValue"], setup(props, { attrs, slots, emit, expose }) { const state = reactive({ checkStrictly: props.checkStrictly, expandedKeys: props.expandedKeys || [], selectedKeys: props.selectedKeys || [], checkedKeys: props.checkedKeys || [] }); const searchState = reactive({ startSearch: false, searchText: "", searchData: [], prevCheckedKeys: [] }); const treeDataRef = ref([]); const [createContextMenu] = useContextMenu(); const prefixCls = "ta-basic-tree"; const getFieldNames = computed(() => { const { fieldNames } = props; return { children: "children", title: "title", key: fieldNames?.id ? fieldNames?.id : fieldNames?.key ? fieldNames?.key : "key", id: fieldNames?.id ?? "id", pid: fieldNames?.pid ?? "pid", ...omit(fieldNames, ["key", "id", "pid"]) }; }); const getBindValues = computed(() => { const propsData = { blockNode: true, ...attrs, ...props, expandedKeys: state.expandedKeys, selectedKeys: state.selectedKeys, checkedKeys: state.checkedKeys, checkStrictly: state.checkStrictly, fieldNames: unref(getFieldNames), "onUpdate:expandedKeys": (v) => { state.expandedKeys = v; emit("update:expandedKeys", v); }, "onUpdate:selectedKeys": (v) => { state.selectedKeys = v; emit("update:selectedKeys", v); }, onCheck: (v, e) => { let currentValue = toRaw(state.checkedKeys); if (isArray(currentValue) && searchState.startSearch) { currentValue = [...currentValue, ...searchState.prevCheckedKeys]; const { key: keyField } = unref(getFieldNames); const target = e.node.$attrs ? e.node.$attrs : e.node; currentValue = difference(currentValue, getChildrenKeys(target[keyField])); if (e.checked && Array.isArray(currentValue)) { currentValue.push(target[keyField]); } state.checkedKeys = [.../* @__PURE__ */ new Set([...currentValue])]; } else { state.checkedKeys = v; } const rawVal = toRaw(state.checkedKeys); emit("update:checkedKeys", rawVal); emit("check", rawVal, e); }, onRightClick: handleRightClick }; return omit(propsData, "treeData", "class"); }); const getTreeData = computed(() => searchState.startSearch ? searchState.searchData : unref(treeDataRef)); const getNotFound = computed(() => { return !getTreeData.value || getTreeData.value.length === 0; }); const { deleteNodeByKey, insertNodeByKey, insertNodesByKey, filterByLevel, updateNodeByKey, getAllKeys, getChildrenKeys, getEnabledKeys } = useTree(treeDataRef, getFieldNames); function getIcon(params, icon) { if (!icon) { if (props.renderIcon && isFunction(props.renderIcon)) { return props.renderIcon(params); } } return icon; } async function handleRightClick({ event, node }) { const { rightMenuList, beforeRightClick } = props; const contextMenuOptions = { event, items: [] }; if (beforeRightClick && isFunction(beforeRightClick)) { const result = await beforeRightClick(node, event); if (Array.isArray(result)) { contextMenuOptions.items = result; } else { Object.assign(contextMenuOptions, result); } } else { contextMenuOptions["items"] = rightMenuList; } if (!contextMenuOptions.items?.length) return; createContextMenu(contextMenuOptions); } function setExpandedKeys(keys) { state.expandedKeys = keys; } function getExpandedKeys() { return state.expandedKeys; } function setSelectedKeys(keys) { state.selectedKeys = keys; } function getSelectedKeys() { return state.selectedKeys; } function setCheckedKeys(keys) { state.checkedKeys = keys; } function getCheckedKeys() { return state.checkedKeys; } function checkAll(checkAll2) { state.checkedKeys = checkAll2 ? getEnabledKeys() : []; } function expandAll(expandAll2) { state.expandedKeys = expandAll2 ? getAllKeys() : []; } function onStrictlyChange(strictly) { state.checkStrictly = strictly; } watch(() => props.searchValue, (val) => { if (val !== searchState.searchText) { searchState.searchText = val; } }, { immediate: true }); watch(() => props.treeData, (val) => { if (val) { handleSearch(searchState.searchText); } }); const searchedKeys = shallowRef([]); async function handleSearch(searchValue) { if (searchValue !== searchState.searchText) searchState.searchText = searchValue; emit("update:searchValue", searchValue); if (searchValue) { searchState.prevCheckedKeys = [...state.checkedKeys]; const { filterFn } = unref(props); searchState.startSearch = true; await nextTick(); const { title: titleField, key: keyField, pid: pidField } = unref(getFieldNames); const matchedKeys = []; searchState.searchData = filter(unref(treeDataRef), (node) => { let result = false; if (filterFn) { result = filterFn(searchValue, node, unref(getFieldNames)); } else { result = node[titleField]?.includes(searchValue); } if (result) { matchedKeys.push(node[keyField]); } return result; }, { id: keyField, pid: pidField }); searchedKeys.value = treeToList(searchState.searchData).map((val) => { return val[keyField]; }); if (searchedKeys.value.length) { setExpandedKeys([.../* @__PURE__ */ new Set([...state.expandedKeys, ...searchedKeys.value])]); } } else { searchState.startSearch = false; await nextTick(); if (searchedKeys.value.length) { setExpandedKeys([.../* @__PURE__ */ new Set([...state.expandedKeys, ...searchedKeys.value])]); } searchedKeys.value = []; searchState.prevCheckedKeys = []; return; } } function handleClickNode(key, children) { if (!props.clickRowToExpand || !children || children.length === 0) return; if (!state.expandedKeys.includes(key)) { setExpandedKeys([...state.expandedKeys, key]); } else { const keys = [...state.expandedKeys]; const index = keys.findIndex((item) => item === key); if (index !== -1) { keys.splice(index, 1); } setExpandedKeys(keys); } } watchEffect(() => { treeDataRef.value = props.treeData; }); onMounted(() => { const level = parseInt(props.defaultExpandLevel.toString()); if (level > 0) { state.expandedKeys = filterByLevel(level); } else if (props.defaultExpandAll) { expandAll(true); } }); watchEffect(() => { state.expandedKeys = props.expandedKeys; }); watchEffect(() => { state.selectedKeys = props.selectedKeys; }); watchEffect(() => { state.checkedKeys = props.checkedKeys; }); watchEffect(() => { state.checkStrictly = props.checkStrictly; }); const instance = { setExpandedKeys, getExpandedKeys, setSelectedKeys, getSelectedKeys, setCheckedKeys, getCheckedKeys, insertNodeByKey, insertNodesByKey, deleteNodeByKey, updateNodeByKey, checkAll, expandAll, filterByLevel: (level) => { state.expandedKeys = filterByLevel(level); }, setSearchValue: (value) => { handleSearch(value); }, getSearchValue: () => { return searchState.searchText; } }; expose(instance); function renderAction(node) { const { actionList } = props; if (!actionList || actionList.length === 0) return; return actionList.map((item, index) => { let nodeShow = true; if (isFunction(item.show)) { nodeShow = item.show?.(node); } else if (isBoolean(item.show)) { nodeShow = item.show; } if (!nodeShow) return null; return createVNode("span", { "key": index, "class": `${prefixCls}__action` }, [item.render(node)]); }); } function renderTreeNode({ data, level }) { return data && data.length > 0 ? data.map((item) => { const { key: keyField, children: childrenField } = unref(getFieldNames); const propsData = omit(item, "title"); const children = get(item, childrenField) || []; return createVNode(Tree$1.TreeNode, mergeProps(propsData, { "node": toRaw(item), "key": get(item, keyField), "class": `${!item[childrenField] || item[childrenField].length === 0 ? "level---1" : `level--${level}`}` }), { default: () => renderTreeNode({ data: children, level: level + 1 }) }); }) : []; } function renderTreeNodeTitle({ data }) { if (!data) { return null; } const searchText = searchState.searchText; const { highlight } = unref(props); const { title: titleField, key: keyField, children: childrenField } = unref(getFieldNames); const icon = getIcon({ ...data }, data.icon); const title = get(data, titleField); const searchIdx = searchText ? title.indexOf(searchText) : -1; const isHighlight = searchState.startSearch && !isEmpty(searchText) && highlight && searchIdx !== -1; const titleDom = createVNode("span", { "class": `${prefixCls}-title__content ${prefixCls}-title__content--highlight` }, [isHighlight ? createVNode(Fragment, null, [createVNode("span", null, [title.substr(0, searchIdx)]), createVNode("span", { "class": "highlight-keyword" }, [searchText]), createVNode("span", null, [title.substr(searchIdx + searchText.length)])]) : title]); return createVNode("span", { "class": `${prefixCls}-title pl-2`, "onClick": handleClickNode.bind(null, data[keyField], data[childrenField]) }, [icon && TreeIcon({ icon }), titleDom, createVNode("span", { "class": `${prefixCls}-title__actions` }, [renderAction({ ...data })])]); } return () => { let _slot; const { title, helpMessage, toolbar, search, checkable } = props; const showTitle = title || toolbar || search || slots.headerTitle; const scrollStyle = { height: "calc(100% - 38px)" }; return createVNode("div", { "class": [prefixCls, "h-full", attrs.class, unref(getBindValues)?.inlineLayoutLevel !== void 0 ? `inline-layout-level` : ""] }, [showTitle && createVNode(TreeHeader, { "checkable": checkable, "checkAll": checkAll, "expandAll": expandAll, "title": title, "search": search, "toolbar": toolbar, "helpMessage": helpMessage, "onStrictlyChange": onStrictlyChange, "onSearch": handleSearch, "searchText": searchState.searchText }, _isSlot(_slot = extendSlots(slots)) ? _slot : { default: () => [_slot] }), withDirectives(createVNode(TaContainerScroll, { "style": scrollStyle }, { default: () => [createVNode(Tree$1, mergeProps(unref(getBindValues), { "showIcon": false }), { default: () => renderTreeNode({ data: unref(getTreeData), level: 1 }), title: ({ data }) => { return slots?.title && typeof slots?.title === "string" ? getSlot(slots, slots?.title, data) : renderTreeNodeTitle({ data }); }, ...extendSlots(slots, ["title"]) })] }), [[vShow, !unref(getNotFound)]]), withDirectives(createVNode(Empty, { "image": Empty.PRESENTED_IMAGE_SIMPLE, "class": "!mt-4" }, null), [[vShow, unref(getNotFound)]])]); }; } }); export { Tree as default }; //# sourceMappingURL=tree2.mjs.map