@fesjs/fes-design
Version:
fes-design for PC
257 lines (254 loc) • 8.04 kB
JavaScript
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 };