UNPKG

@fesjs/fes-design

Version:
257 lines (254 loc) 8.04 kB
import { defineComponent, computed, ref, createVNode } from 'vue'; import { isUndefined, isFunction } from 'lodash-es'; import { useElementHover } from '@vueuse/core'; import getPrefixCls from '../_util/getPrefixCls'; import CaretDownOutlined from '../icon/CaretDownOutlined'; import LoadingOutlined from '../icon/LoadingOutlined'; import Checkbox from '../checkbox'; import FEllipsis from '../ellipsis'; import TextHightlight from '../text-highlight'; import { COMPONENT_NAME, INDENT } from './const'; import useTreeNode from './useTreeNode'; const prefixCls = getPrefixCls('tree-node'); const treeNodeProps = { value: { type: [String, Number], required: true }, label: { type: [String, Function], required: true }, disabled: { type: Boolean }, selectable: { type: Boolean }, checkable: { type: Boolean }, isLeaf: { type: Boolean, default: false }, level: { type: Number, default: 0 }, draggable: { type: Boolean, default: false }, noExpand: { type: Boolean, default: false } }; var treeNode = defineComponent({ name: COMPONENT_NAME.TREE_NODE, props: treeNodeProps, setup(props, _ref) { let { slots } = _ref; const { root, isExpanded, isSelected, isChecked, isIndeterminate, isInline, isFirst } = useTreeNode(props); const disabled = computed(() => props.disabled); const selectable = computed(() => isUndefined(props.selectable) ? root.props.selectable : props.selectable); const checkable = computed(() => isUndefined(props.checkable) ? root.props.checkable : props.checkable); const classList = computed(() => { var _root$dragHighlightNo; return [prefixCls, disabled.value && 'is-disabled', isSelected.value && 'is-selected', isInline.value && 'is-inline', isFirst.value && 'is-inline-first', ((_root$dragHighlightNo = root.dragHighlightNode.value) === null || _root$dragHighlightNo === void 0 ? void 0 : _root$dragHighlightNo.value) === props.value && 'is-highlight'].filter(Boolean); }); const style = computed(() => { if (isInline.value && !isFirst.value) { return {}; } return { paddingLeft: `${(props.level - 1) * INDENT}px` }; }); let isLoaded = false; const isLoading = ref(false); const handleClickSwitcher = async event => { const node = root.nodeList.get(props.value); if (!isLoaded && root.props.loadData && (!node.children || node.children.length === 0)) { isLoading.value = true; try { await root.props.loadData(node.origin); isLoaded = true; root.expandNode(props.value, event); } catch (e) { console.error(e); } isLoading.value = false; } else { root.expandNode(props.value, event); } }; const handleClickContent = event => { if (disabled.value) { return; } // 默认 select 行为 if (selectable.value) { return root.selectNode(props.value, event); } // 再 check 行为 if (checkable.value) { return root.checkNode(props.value, event); } // 再展开行为 if (!props.isLeaf) { handleClickSwitcher(event); } }; const handleClickCheckbox = event => { if (disabled.value) { return; } if (checkable.value) { return root.checkNode(props.value, event); } }; const handleStopClickPrefix = event => { event.stopPropagation(); }; const renderDragTag = () => { const dragOverInfo = root.dragOverInfo.value; if (!dragOverInfo) { return; } if (dragOverInfo.position === 'inside') { return; } if ((dragOverInfo === null || dragOverInfo === void 0 ? void 0 : dragOverInfo.node.value) === props.value) { const style = {}; style.left = `${props.level * INDENT + 9}px`; return createVNode("div", { "class": [`${prefixCls}-drag-over`, `is-${dragOverInfo === null || dragOverInfo === void 0 ? void 0 : dragOverInfo.position}`], "style": style }, null); } return null; }; const renderSwitcher = () => { if (props.isLeaf) { const leafClass = [`${prefixCls}-switcher`]; if (props.noExpand) { leafClass.push('no-expand'); } return createVNode("span", { "class": leafClass }, null); } const icon = isLoading.value ? createVNode(LoadingOutlined, null, null) : createVNode(CaretDownOutlined, { "class": [`${prefixCls}-switcher-icon`, isExpanded.value ? 'is-expanded' : ''] }, null); return createVNode("span", { "class": `${prefixCls}-switcher`, "onClick": handleClickSwitcher }, [icon]); }; const renderCheckbox = () => { if (!checkable.value) { return null; } return createVNode("span", { "class": `${prefixCls}-checkbox` }, [createVNode(Checkbox, { "indeterminate": isIndeterminate.value, "modelValue": isChecked.value, "onChange": handleClickCheckbox, "disabled": props.disabled }, null)]); }; const treeNodeElement = ref(); const isHovered = useElementHover(treeNodeElement); const slotParams = computed(() => { return { isHovered: isHovered.value, value: props.value }; }); const renderPrefix = () => { var _slots$prefix; if (!slots.prefix) { return null; } return createVNode("span", { "class": `${prefixCls}-content-prefix`, "onClick": handleStopClickPrefix }, [(_slots$prefix = slots.prefix) === null || _slots$prefix === void 0 ? void 0 : _slots$prefix.call(slots, slotParams.value)]); }; const renderSuffix = () => { var _slots$suffix; if (!slots.suffix) { return null; } return createVNode("span", { "class": `${prefixCls}-content-suffix`, "onClick": handleStopClickPrefix }, [(_slots$suffix = slots.suffix) === null || _slots$suffix === void 0 ? void 0 : _slots$suffix.call(slots, slotParams.value)]); }; const renderLabel = () => { const node = root.nodeList.get(props.value); if (isFunction(props.label)) { return createVNode("span", { "class": `${prefixCls}-content-label` }, [props.label(node)]); } else if (isFunction(root.slots.label)) { return createVNode("span", { "class": `${prefixCls}-content-label` }, [root.slots.label(node)]); } return createVNode(FEllipsis, { "class": `${prefixCls}-content-label` }, { default: () => [root.props.filterTextHighlight && root.props.filterText ? createVNode(TextHightlight, { "strict": true, "searchValues": [root.props.filterText] }, { default: () => [props.label] }) : props.label] }); }; return () => createVNode("div", { "ref": treeNodeElement, "class": classList.value, "style": style.value, "data-value": props.value, "draggable": props.draggable, "onDragstart": event => { root.handleDragstart(props.value, event); }, "onDragenter": event => { root.handleDragenter(props.value, event); }, "onDragover": event => { root.handleDragover(props.value, event); }, "onDragleave": event => { root.handleDragleave(props.value, event); }, "onDragend": event => { root.handleDragend(props.value, event); }, "onDrop": event => { root.handleDrop(props.value, event); } }, [renderDragTag(), renderSwitcher(), renderCheckbox(), createVNode("span", { "class": `${prefixCls}-content`, "onClick": handleClickContent }, [renderPrefix(), renderLabel(), renderSuffix()])]); } }); export { treeNode as default };