2025-02-28 19:43:11 +08:00

395 lines
18 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const vooks_1 = require("vooks");
const seemly_1 = require("seemly");
const _utils_1 = require("../../_utils");
const TreeNodeSwitcher_1 = __importDefault(require("./TreeNodeSwitcher"));
const TreeNodeCheckbox_1 = __importDefault(require("./TreeNodeCheckbox"));
const TreeNodeContent_1 = __importDefault(require("./TreeNodeContent"));
const interface_1 = require("./interface");
const dnd_1 = require("./dnd");
const utils_1 = require("./utils");
const TreeNode = (0, vue_1.defineComponent)({
name: 'TreeNode',
props: {
clsPrefix: {
type: String,
required: true
},
tmNode: {
type: Object,
required: true
}
},
setup(props) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const NTree = (0, vue_1.inject)(interface_1.treeInjectionKey);
const { droppingNodeParentRef, droppingMouseNodeRef, draggingNodeRef, droppingPositionRef, droppingOffsetLevelRef, nodePropsRef, indentRef, blockLineRef, checkboxPlacementRef, checkOnClickRef, disabledFieldRef, showLineRef, renderSwitcherIconRef, overrideDefaultNodeClickBehaviorRef } = NTree;
const checkboxDisabledRef = (0, vooks_1.useMemo)(() => !!props.tmNode.rawNode.checkboxDisabled);
const nodeIsDisabledRef = (0, vooks_1.useMemo)(() => {
return (0, utils_1.isNodeDisabled)(props.tmNode, disabledFieldRef.value);
});
const disabledRef = (0, vooks_1.useMemo)(() => NTree.disabledRef.value || nodeIsDisabledRef.value);
const resolvedNodePropsRef = (0, vue_1.computed)(() => {
const { value: nodeProps } = nodePropsRef;
if (!nodeProps)
return undefined;
return nodeProps({
option: props.tmNode.rawNode
});
});
// used for drag and drop
const contentInstRef = (0, vue_1.ref)(null);
// must be non-reactive
const contentElRef = { value: null };
(0, vue_1.onMounted)(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
contentElRef.value = contentInstRef.value.$el;
});
function handleSwitcherClick() {
const callback = () => {
const { tmNode } = props;
if (!tmNode.isLeaf && !tmNode.shallowLoaded) {
if (!NTree.loadingKeysRef.value.has(tmNode.key)) {
NTree.loadingKeysRef.value.add(tmNode.key);
}
else {
return;
}
const { onLoadRef: { value: onLoad } } = NTree;
if (onLoad) {
void onLoad(tmNode.rawNode)
.then((value) => {
if (value !== false) {
NTree.handleSwitcherClick(tmNode);
}
})
.finally(() => {
NTree.loadingKeysRef.value.delete(tmNode.key);
});
}
}
else {
NTree.handleSwitcherClick(tmNode);
}
};
if (renderSwitcherIconRef.value) {
// if renderSwitcherIcon is set, icon dom may be altered before event
// bubbles to parent dom, so that target check fails. Call it in next
// event loop so that event bubble phase is finishes.
setTimeout(callback, 0);
}
else {
callback();
}
}
const selectableRef = (0, vooks_1.useMemo)(() => !nodeIsDisabledRef.value &&
NTree.selectableRef.value &&
(NTree.internalTreeSelect
? NTree.mergedCheckStrategyRef.value !== 'child' ||
(NTree.multipleRef.value && NTree.cascadeRef.value) ||
props.tmNode.isLeaf
: true));
const checkableRef = (0, vooks_1.useMemo)(() => NTree.checkableRef.value &&
(NTree.cascadeRef.value ||
NTree.mergedCheckStrategyRef.value !== 'child' ||
props.tmNode.isLeaf));
const checkedRef = (0, vooks_1.useMemo)(() => NTree.displayedCheckedKeysRef.value.includes(props.tmNode.key));
const mergedCheckOnClickRef = (0, vooks_1.useMemo)(() => {
const { value: checkable } = checkableRef;
if (!checkable)
return false;
const { value: checkOnClick } = checkOnClickRef;
const { tmNode } = props;
if (typeof checkOnClick === 'boolean') {
return !tmNode.disabled && checkOnClick;
}
return checkOnClick(props.tmNode.rawNode);
});
function _handleClick(e) {
const { value: expandOnClick } = NTree.expandOnClickRef;
const { value: selectable } = selectableRef;
const { value: mergedCheckOnClick } = mergedCheckOnClickRef;
if (!selectable && !expandOnClick && !mergedCheckOnClick)
return;
if ((0, seemly_1.happensIn)(e, 'checkbox') || (0, seemly_1.happensIn)(e, 'switcher'))
return;
const { tmNode } = props;
if (selectable) {
NTree.handleSelect(tmNode);
}
if (expandOnClick && !tmNode.isLeaf) {
handleSwitcherClick();
}
if (mergedCheckOnClick) {
handleCheck(!checkedRef.value);
}
}
function handleNodeClick(e) {
var _a, _b;
if (!disabledRef.value) {
const overrideDefaultNodeClickBehavior = overrideDefaultNodeClickBehaviorRef.value;
let shouldOverride = false;
if (overrideDefaultNodeClickBehavior) {
switch (overrideDefaultNodeClickBehavior({ option: props.tmNode.rawNode })) {
case 'toggleCheck':
shouldOverride = true;
handleCheck(!checkedRef.value);
break;
case 'toggleSelect':
shouldOverride = true;
NTree.handleSelect(props.tmNode);
break;
case 'toggleExpand':
shouldOverride = true;
handleSwitcherClick();
shouldOverride = true;
break;
case 'none':
shouldOverride = true;
shouldOverride = true;
return;
case 'default':
default:
break;
}
}
if (!shouldOverride) {
_handleClick(e);
}
}
(_b = (_a = resolvedNodePropsRef.value) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
}
function handleContentClick(e) {
if (blockLineRef.value)
return;
handleNodeClick(e);
}
function handleLineClick(e) {
if (!blockLineRef.value)
return;
handleNodeClick(e);
}
function handleCheck(checked) {
NTree.handleCheck(props.tmNode, checked);
}
// Dnd
function handleDragStart(e) {
NTree.handleDragStart({
event: e,
node: props.tmNode
});
}
function handleDragEnter(e) {
if (e.currentTarget !== e.target) {
return;
}
NTree.handleDragEnter({
event: e,
node: props.tmNode
});
}
function handleDragOver(e) {
e.preventDefault(); // if not prevent, drop event won't be fired...
NTree.handleDragOver({
event: e,
node: props.tmNode
});
}
function handleDragEnd(e) {
NTree.handleDragEnd({
event: e,
node: props.tmNode
});
}
function handleDragLeave(e) {
if (e.currentTarget !== e.target) {
return;
}
NTree.handleDragLeave({
event: e,
node: props.tmNode
});
}
function handleDrop(e) {
e.preventDefault();
if (droppingPositionRef.value !== null) {
NTree.handleDrop({
event: e,
node: props.tmNode,
dropPosition: droppingPositionRef.value
});
}
}
const indentNodes = (0, vue_1.computed)(() => {
const { clsPrefix } = props;
const { value: indent } = indentRef;
if (showLineRef.value) {
const indentNodes = [];
let cursor = props.tmNode.parent;
while (cursor) {
if (cursor.isLastChild) {
indentNodes.push((0, vue_1.h)("div", { class: `${clsPrefix}-tree-node-indent` },
(0, vue_1.h)("div", { style: { width: `${indent}px` } })));
}
else {
indentNodes.push((0, vue_1.h)("div", { class: [
`${clsPrefix}-tree-node-indent`,
`${clsPrefix}-tree-node-indent--show-line`
] },
(0, vue_1.h)("div", { style: { width: `${indent}px` } })));
}
cursor = cursor.parent;
}
return indentNodes.reverse();
}
else {
return (0, seemly_1.repeat)(props.tmNode.level, (0, vue_1.h)("div", { class: `${props.clsPrefix}-tree-node-indent` },
(0, vue_1.h)("div", { style: { width: `${indent}px` } })));
}
});
return {
showDropMark: (0, vooks_1.useMemo)(() => {
const { value: draggingNode } = draggingNodeRef;
if (!draggingNode)
return;
const { value: droppingPosition } = droppingPositionRef;
if (!droppingPosition)
return;
const { value: droppingMouseNode } = droppingMouseNodeRef;
if (!droppingMouseNode) {
return;
}
const { tmNode } = props;
if (tmNode.key === droppingMouseNode.key)
return true;
return false;
}),
showDropMarkAsParent: (0, vooks_1.useMemo)(() => {
const { value: droppingNodeParent } = droppingNodeParentRef;
if (!droppingNodeParent)
return false;
const { tmNode } = props;
const { value: droppingPosition } = droppingPositionRef;
if (droppingPosition === 'before' || droppingPosition === 'after') {
return droppingNodeParent.key === tmNode.key;
}
return false;
}),
pending: (0, vooks_1.useMemo)(() => NTree.pendingNodeKeyRef.value === props.tmNode.key),
loading: (0, vooks_1.useMemo)(() => NTree.loadingKeysRef.value.has(props.tmNode.key)),
highlight: (0, vooks_1.useMemo)(() => {
var _a;
return (_a = NTree.highlightKeySetRef.value) === null || _a === void 0 ? void 0 : _a.has(props.tmNode.key);
}),
checked: checkedRef,
indeterminate: (0, vooks_1.useMemo)(() => NTree.displayedIndeterminateKeysRef.value.includes(props.tmNode.key)),
selected: (0, vooks_1.useMemo)(() => NTree.mergedSelectedKeysRef.value.includes(props.tmNode.key)),
expanded: (0, vooks_1.useMemo)(() => NTree.mergedExpandedKeysRef.value.includes(props.tmNode.key)),
disabled: disabledRef,
checkable: checkableRef,
mergedCheckOnClick: mergedCheckOnClickRef,
checkboxDisabled: checkboxDisabledRef,
selectable: selectableRef,
expandOnClick: NTree.expandOnClickRef,
internalScrollable: NTree.internalScrollableRef,
draggable: NTree.draggableRef,
blockLine: blockLineRef,
nodeProps: resolvedNodePropsRef,
checkboxFocusable: NTree.internalCheckboxFocusableRef,
droppingPosition: droppingPositionRef,
droppingOffsetLevel: droppingOffsetLevelRef,
indent: indentRef,
checkboxPlacement: checkboxPlacementRef,
showLine: showLineRef,
contentInstRef,
contentElRef,
indentNodes,
handleCheck,
handleDrop,
handleDragStart,
handleDragEnter,
handleDragOver,
handleDragEnd,
handleDragLeave,
handleLineClick,
handleContentClick,
handleSwitcherClick
};
},
render() {
const { tmNode, clsPrefix, checkable, expandOnClick, selectable, selected, checked, highlight, draggable, blockLine, indent, indentNodes, disabled, pending, internalScrollable, nodeProps, checkboxPlacement } = this;
// drag start not inside
// it need to be append to node itself, not wrapper
const dragEventHandlers = draggable && !disabled
? {
onDragenter: this.handleDragEnter,
onDragleave: this.handleDragLeave,
onDragend: this.handleDragEnd,
onDrop: this.handleDrop,
onDragover: this.handleDragOver
}
: undefined;
// In non virtual mode, there's no evidence that which element should be
// scrolled to, so we need data-key to query the target element.
const dataKey = internalScrollable ? (0, _utils_1.createDataKey)(tmNode.key) : undefined;
const checkboxOnRight = checkboxPlacement === 'right';
const checkboxNode = checkable ? ((0, vue_1.h)(TreeNodeCheckbox_1.default, { indent: indent, right: checkboxOnRight, focusable: this.checkboxFocusable, disabled: disabled || this.checkboxDisabled, clsPrefix: clsPrefix, checked: this.checked, indeterminate: this.indeterminate, onCheck: this.handleCheck })) : null;
return ((0, vue_1.h)("div", Object.assign({ class: `${clsPrefix}-tree-node-wrapper` }, dragEventHandlers),
(0, vue_1.h)("div", Object.assign({}, (blockLine ? nodeProps : undefined), { class: [
`${clsPrefix}-tree-node`,
{
[`${clsPrefix}-tree-node--selected`]: selected,
[`${clsPrefix}-tree-node--checkable`]: checkable,
[`${clsPrefix}-tree-node--highlight`]: highlight,
[`${clsPrefix}-tree-node--pending`]: pending,
[`${clsPrefix}-tree-node--disabled`]: disabled,
[`${clsPrefix}-tree-node--selectable`]: selectable,
[`${clsPrefix}-tree-node--clickable`]: selectable || expandOnClick || this.mergedCheckOnClick
},
nodeProps === null || nodeProps === void 0 ? void 0 : nodeProps.class
], "data-key": dataKey, draggable: draggable && blockLine, onClick: this.handleLineClick, onDragstart: draggable && blockLine && !disabled
? this.handleDragStart
: undefined }),
indentNodes,
tmNode.isLeaf && this.showLine ? ((0, vue_1.h)("div", { class: [
`${clsPrefix}-tree-node-indent`,
`${clsPrefix}-tree-node-indent--show-line`,
tmNode.isLeaf && `${clsPrefix}-tree-node-indent--is-leaf`,
tmNode.isLastChild &&
`${clsPrefix}-tree-node-indent--last-child`
] },
(0, vue_1.h)("div", { style: { width: `${indent}px` } }))) : ((0, vue_1.h)(TreeNodeSwitcher_1.default, { clsPrefix: clsPrefix, expanded: this.expanded, selected: selected, loading: this.loading, hide: tmNode.isLeaf, tmNode: this.tmNode, indent: indent, onClick: this.handleSwitcherClick })),
!checkboxOnRight ? checkboxNode : null,
(0, vue_1.h)(TreeNodeContent_1.default, { ref: "contentInstRef", clsPrefix: clsPrefix, checked: checked, selected: selected, onClick: this.handleContentClick, nodeProps: blockLine ? undefined : nodeProps, onDragstart: draggable && !blockLine && !disabled
? this.handleDragStart
: undefined, tmNode: tmNode }),
draggable
? this.showDropMark
? (0, dnd_1.renderDropMark)({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
el: this.contentElRef.value,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
position: this.droppingPosition,
offsetLevel: this.droppingOffsetLevel,
indent
})
: this.showDropMarkAsParent
? (0, dnd_1.renderDropMark)({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
el: this.contentElRef.value,
position: 'inside',
offsetLevel: this.droppingOffsetLevel,
indent
})
: null
: null,
checkboxOnRight ? checkboxNode : null)));
}
});
exports.default = TreeNode;