layui/package/component/es/tree/index.js
2022-12-30 16:13:19 +08:00

458 lines
21 KiB
JavaScript

import { w as withInstall } from "../badge/index2.js";
import { defineComponent, useSlots, computed, resolveComponent, openBlock, createElementBlock, Fragment, renderList, normalizeClass, createElementVNode, createVNode, unref, withModifiers, createBlock, createCommentVNode, renderSlot, createTextVNode, toDisplayString, withCtx, createSlots, ref, watch, onMounted, nextTick } from "vue";
import { _ as _sfc_main$2E, a as _sfc_main$2 } from "../checkbox/index2.js";
import { _ as _sfc_main$3 } from "../transition/index2.js";
const _hoisted_1 = ["onClick"];
const _hoisted_2 = { class: "layui-tree-main" };
const _hoisted_3 = ["onClick"];
const _hoisted_4 = {
key: 0,
class: "layui-tree-pack layui-tree-showLine",
style: { "display": "block" }
};
const __default__$1 = {
name: "TreeNode"
};
const _sfc_main$1 = defineComponent({
...__default__$1,
props: {
tree: null,
nodeList: null,
showCheckbox: { type: Boolean },
showLine: { type: Boolean },
selectedKey: null,
checkStrictly: { type: [Boolean, String] },
collapseTransition: { type: Boolean },
onlyIconControl: { type: Boolean }
},
emits: ["node-click"],
setup(__props, { emit }) {
const props = __props;
useSlots();
function renderLineShort(node) {
return !node.hasNextSibling && node.parentNode && (!node.parentNode.hasNextSibling || node.parentNode.hasNextSibling && !node.parentNode.children);
}
const nodeIconType = (node) => {
if (!props.showLine) {
if (node.children.length > 0) {
return "layui-tree-iconArrow ";
}
return "";
}
if (node.children.length !== 0) {
return !node.isLeaf ? "layui-icon-addition" : "layui-icon-subtraction";
}
return "layui-icon-file";
};
function recursiveNodeClick(node) {
emit("node-click", node);
}
function handleChange(checked, node) {
props.tree.setCheckedKeys(checked, props.checkStrictly, node);
}
function handleIconClick(node) {
node.isLeaf = !node.isLeaf;
}
function handleTitleClick(node) {
if (!props.onlyIconControl) {
handleIconClick(node);
}
if (!node.isDisabled) {
emit("node-click", node);
}
}
function handleRowClick(node) {
if (!props.showLine) {
handleTitleClick(node);
}
}
const isChildAllSelected = computed(() => {
function _isChildAllSelected(node) {
if (!props.showCheckbox) {
return false;
}
let childSelectNum = 0;
let res = false;
for (const item of node.children) {
if (item.isChecked)
childSelectNum++;
}
if (childSelectNum > 0)
node.isChecked = true;
if (childSelectNum == node.children.length) {
for (const item of node.children) {
res = _isChildAllSelected(item);
if (res)
break;
}
} else {
res = true;
}
return res;
}
return (node) => {
if (props.checkStrictly) {
return false;
} else {
let res = _isChildAllSelected(node);
return res;
}
};
});
return (_ctx, _cache) => {
const _component_tree_node = resolveComponent("tree-node", true);
return openBlock(true), createElementBlock(Fragment, null, renderList(__props.nodeList, (node, nodeIndex) => {
return openBlock(), createElementBlock("div", {
key: nodeIndex,
class: normalizeClass({
"layui-tree-set": true,
"layui-tree-setLineShort": renderLineShort(node),
"layui-tree-setHide": node.isRoot
})
}, [
createElementVNode("div", {
class: "layui-tree-entry",
onClick: ($event) => handleRowClick(node)
}, [
createElementVNode("div", _hoisted_2, [
createElementVNode("span", {
class: normalizeClass([
__props.showLine && node.children.length > 0 ? "layui-tree-icon" : "",
{ "layui-tree-iconClick": true }
])
}, [
createVNode(unref(_sfc_main$2E), {
type: nodeIconType(node),
onClick: withModifiers(($event) => handleIconClick(node), ["stop"])
}, null, 8, ["type", "onClick"])
], 2),
__props.showCheckbox ? (openBlock(), createBlock(_sfc_main$2, {
key: 0,
value: "",
skin: "primary",
modelValue: node.isChecked,
disabled: node.isDisabled,
isIndeterminate: unref(isChildAllSelected)(node),
onChange: (checked) => handleChange(checked, node)
}, null, 8, ["modelValue", "disabled", "isIndeterminate", "onChange"])) : createCommentVNode("", true),
createElementVNode("span", {
class: normalizeClass({
"layui-tree-txt": true,
"layui-disabled": node.isDisabled,
"layui-this": __props.selectedKey === node.id
}),
onClick: withModifiers(($event) => handleTitleClick(node), ["stop"])
}, [
renderSlot(_ctx.$slots, "title", { data: node }, () => [
createTextVNode(toDisplayString(node.title), 1)
])
], 10, _hoisted_3)
])
], 8, _hoisted_1),
createVNode(_sfc_main$3, { enable: __props.collapseTransition }, {
default: withCtx(() => [
node.isLeaf ? (openBlock(), createElementBlock("div", _hoisted_4, [
createVNode(_component_tree_node, {
tree: __props.tree,
"node-list": node.children,
"show-checkbox": __props.showCheckbox,
"show-line": __props.showLine,
"selected-key": __props.selectedKey,
"collapse-transition": __props.collapseTransition,
checkStrictly: __props.checkStrictly,
"only-icon-control": __props.onlyIconControl,
onNodeClick: recursiveNodeClick
}, createSlots({ _: 2 }, [
_ctx.$slots.title ? {
name: "title",
fn: withCtx((slotProp) => [
renderSlot(_ctx.$slots, "title", {
data: slotProp.data
})
]),
key: "0"
} : void 0
]), 1032, ["tree", "node-list", "show-checkbox", "show-line", "selected-key", "collapse-transition", "checkStrictly", "only-icon-control"])
])) : createCommentVNode("", true)
]),
_: 2
}, 1032, ["enable"])
], 2);
}), 128);
};
}
});
class Tree {
constructor(config, origin) {
this.config = config;
this.treeData = [];
this.init(origin);
}
init(origin) {
const tree = this.createTree(origin);
this.treeData = tree;
}
createTree(origin, parentKey = "") {
let data;
if (!Array.isArray(origin)) {
data = Array.of(Object.assign({}, origin));
} else {
data = origin;
}
const nodeList = [];
const { children } = this.config.replaceFields;
const len = data.length;
for (let i = 0; i < len; i++) {
const node = this.getNode(data[i], parentKey, i < len - 1);
const nodeChildren = Reflect.get(node, children);
const nodeHasChildren = !!Reflect.get(node, children);
if (nodeHasChildren) {
Reflect.set(node, children, this.createTree(nodeChildren, node.id));
}
nodeList.push(node);
}
return nodeList;
}
getNode(origin, parentKey, hasNextSibling) {
const {
nodeMap,
originMap,
checkedKeys,
expandKeys,
checkStrictly,
replaceFields: { children, id, title }
} = this.config;
const nodeKey = Reflect.get(origin, id);
const nodeTitle = Reflect.get(origin, title);
const nodeChildren = Reflect.get(origin, children);
const nodeDisabled = !!Reflect.get(origin, "disabled");
const nodeIsLeaf = !!Reflect.get(origin, "spread");
const parentNode = nodeMap.get(parentKey);
const node = Object.assign({}, origin, {
id: nodeKey,
title: nodeTitle,
children: nodeChildren ? nodeChildren : [],
parentKey,
isRoot: parentKey === "",
isDisabled: false,
isChecked: false,
isLeaf: false,
hasNextSibling,
parentNode: parentNode || null
});
node.isDisabled = nodeDisabled;
node.isChecked = checkedKeys.includes(nodeKey);
node.isLeaf = parentNode ? parentNode.isLeaf : expandKeys.includes(nodeKey);
node.isLeaf = nodeIsLeaf;
if (!nodeMap.has(nodeKey)) {
nodeMap.set(nodeKey, node);
}
if (!originMap.has(nodeKey)) {
originMap.set(nodeKey, origin);
}
return node;
}
treeForeach(tree, func) {
tree.forEach((data) => {
data.children && this.treeForeach(data.children, func);
func(data);
});
}
setChildrenChecked(checked, nodes) {
var ableCount = 0;
var checkCount = 0;
const len = nodes.length;
this.treeForeach(nodes, (node) => {
if (!node.isDisabled) {
ableCount = ableCount + 1;
if (node.isChecked) {
checkCount = checkCount + 1;
}
}
});
checkCount < ableCount ? checked = true : checked = false;
for (let i = 0; i < len; i++) {
if (!nodes[i].isDisabled || nodes[i].isDisabled && nodes[i].children.length > 0) {
nodes[i].isChecked = checked;
}
nodes[i].children && nodes[i].children.length > 0 && this.setChildrenChecked(checked, nodes[i].children);
}
}
setParentChecked(checked, parent) {
if (!parent) {
return;
}
parent.isChecked = checked;
const pChild = parent.children;
const pChildChecked = pChild.some((c) => c.isChecked);
if (pChildChecked) {
parent.isChecked = true;
}
if (parent.parentNode) {
this.setParentChecked(checked, parent.parentNode);
}
}
setCheckedKeys(checked, checkStrictly, node) {
node.isChecked = checked;
if (!checkStrictly) {
if (node.parentNode) {
this.setParentChecked(checked, node.parentNode);
}
if (node.children) {
this.setChildrenChecked(checked, node.children);
}
}
}
getData() {
return this.treeData;
}
getKeys() {
const checkedKeys = [];
const expandKeys = [];
const iterator = this.config.nodeMap[Symbol.iterator]();
let next = iterator.next();
while (!next.done) {
const [, node] = next.value;
const id = Reflect.get(node, this.config.replaceFields.id);
if (node.isChecked) {
checkedKeys.push(id);
}
if (node.isLeaf) {
expandKeys.push(id);
}
next = iterator.next();
}
return { checkedKeys, expandKeys };
}
getOriginData(key) {
return this.config.originMap.get(key);
}
}
const useTree = (props, emit) => {
var _a, _b, _c, _d;
const tree = new Tree({
nodeMap: /* @__PURE__ */ new Map(),
originMap: /* @__PURE__ */ new Map(),
replaceFields: {
id: "id",
title: "title",
children: "children"
},
showCheckbox: (_a = props.showCheckbox) != null ? _a : false,
checkedKeys: (_b = props.checkedKeys) != null ? _b : [],
expandKeys: (_c = props.expandKeys) != null ? _c : [],
checkStrictly: (_d = props.checkStrictly) != null ? _d : false
}, props.data);
const nodeList = computed(() => {
const nodes = tree.getData();
return nodes;
});
return {
tree,
nodeList
};
};
var index = /* @__PURE__ */ (() => '.layui-checkbox[size=lg]{height:18px;line-height:18px}.layui-checkbox[size=lg] .layui-form-checkbox[lay-skin=primary] .layui-icon{width:18px;height:18px;font-size:16px}.layui-checkbox[size=lg] .layui-form-checkbox[lay-skin=primary] .layui-checkbox-label{height:18px;line-height:18px;font-size:16px}.layui-checkbox[size=md]{height:16px;line-height:16px}.layui-checkbox[size=md] .layui-form-checkbox[lay-skin=primary] .layui-icon{width:16px;height:16px;font-size:14px}.layui-checkbox[size=md] .layui-form-checkbox[lay-skin=primary] .layui-checkbox-label{height:16px;line-height:16px;font-size:14px}.layui-checkbox[size=sm]{height:14px;line-height:14px}.layui-checkbox[size=sm] .layui-form-checkbox[lay-skin=primary] .layui-icon{width:14px;height:14px;font-size:12px}.layui-checkbox[size=sm] .layui-form-checkbox[lay-skin=primary] .layui-checkbox-label{height:14px;line-height:14px;font-size:12px}.layui-checkbox[size=xs]{height:12px;line-height:12px}.layui-checkbox[size=xs] .layui-form-checkbox[lay-skin=primary] .layui-icon{width:12px;height:12px;font-size:10px}.layui-checkbox[size=xs] .layui-form-checkbox[lay-skin=primary] .layui-checkbox-label{height:12px;line-height:12px;font-size:10px}.layui-checkbox input[type=checkbox]{display:none}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:var(--global-neutral-color-6);color:#fff;overflow:hidden}.layui-form-checkbox:hover span{background-color:var(--global-neutral-color-8)}.layui-form-checkbox i{top:0;right:0;width:29px;height:28px;position:absolute;border-top:1px solid var(--global-neutral-color-6);border-bottom:1px solid var(--global-neutral-color-6);border-right:1px solid var(--global-neutral-color-6);border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:var(--global-neutral-color-8);color:var(--global-neutral-color-8)}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:28px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{right:auto;left:0;width:16px;height:16px;line-height:16px;border:1px solid var(--global-neutral-color-6);font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:var(--global-checked-color);color:#fff}.layui-form-checked,.layui-form-checked:hover{border-color:var(--global-checked-color)}.layui-form-checked i,.layui-form-checked:hover i{color:var(--global-checked-color)}.layui-form-checked span,.layui-form-checked:hover span{background-color:var(--global-checked-color)}.layui-form-checked[lay-skin=primary] i{border-color:var(--global-checked-color);background-color:var(--global-checked-color);color:#fff}.layui-form-checked[lay-skin=primary] span{background:0 0!important}.layui-checkbox-disabled[lay-skin=primary] span{background:0 0!important;color:var(--global-neutral-color-8)!important}.layui-checkbox-disabled[lay-skin=primary]:hover i{border-color:var(--global-neutral-color-6)}.layui-checkbox-disabled,.layui-checkbox-disabled i{border-color:var(--global-neutral-color-3)!important}.layui-checkbox-disabled span{background-color:var(--global-neutral-color-3)!important}.layui-checkbox-disabled em{color:var(--global-neutral-color-6)!important}.layui-checkbox-disabled:hover i{color:#fff!important}.layui-checkbox-disabled .layui-icon-ok,.layui-checkbox-disabled .layui-icon-subtraction{background-color:var(--global-neutral-color-3)!important;border-color:var(--global-neutral-color-3)!important}.layui-tree{line-height:22px}.layui-tree .layui-form-checkbox{margin:0!important}.layui-tree-set{width:100%;position:relative}.layui-tree-txt.layui-this{color:var(--global-checked-color)!important}.layui-tree-pack{display:none;padding-left:20px;position:relative}.layui-tree-iconClick,.layui-tree-main{display:inline-block;vertical-align:middle}.layui-tree-line .layui-tree-pack{padding-left:27px}.layui-tree-line .layui-tree-set .layui-tree-set:after{content:"";position:absolute;top:14px;left:-9px;width:17px;height:0;border-top:1px dotted #c0c4cc}.layui-tree-entry{position:relative;padding:3px 0;height:20px;white-space:nowrap}.layui-tree-entry:hover{background-color:#eee}.layui-tree-line .layui-tree-entry:hover{background-color:#0000}.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color:#999;text-decoration:underline;transition:.3s}.layui-tree-main{cursor:pointer;padding-right:10px}.layui-tree-line .layui-tree-set:before{content:"";position:absolute;top:0;left:-9px;width:0;height:100%;border-left:1px dotted #c0c4cc}.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height:13px}.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height:0}.layui-tree-iconClick{position:relative;height:20px;line-height:20px;margin:0 10px;color:#c0c4cc}.layui-tree-icon{height:12px;line-height:12px;width:12px;text-align:center;border:1px solid #c0c4cc}.layui-tree-iconClick .layui-icon{font-size:18px}.layui-tree-icon .layui-icon{font-size:12px;color:#666}.layui-tree-iconArrow{padding:0 5px}.layui-tree-iconArrow:after{content:"";position:absolute;left:4px;top:3px;z-index:100;width:0;height:0;border-width:5px;border-style:solid;border-color:transparent transparent transparent #c0c4cc;transition:.5s}.layui-tree-btnGroup,.layui-tree-editInput{position:relative;vertical-align:middle;display:inline-block}.layui-tree-spread>.layui-tree-entry>.layui-tree-iconClick>.layui-tree-iconArrow:after{transform:rotate(90deg) translate(3px,4px)}.layui-tree-txt{display:inline-block;vertical-align:middle;color:#555}.layui-tree-search{margin-bottom:15px;color:#666}.layui-tree-btnGroup .layui-icon{display:inline-block;vertical-align:middle;padding:0 2px;cursor:pointer}.layui-tree-btnGroup .layui-icon:hover{color:#999;transition:.3s}.layui-tree-entry:hover .layui-tree-btnGroup{visibility:visible}.layui-tree-editInput{height:20px;line-height:20px;padding:0 3px;border:none;background-color:#0000000d}.layui-tree-emptyText{text-align:center;color:#999}\n')();
const __default__ = {
name: "LayTree"
};
const _sfc_main = defineComponent({
...__default__,
props: {
data: null,
disabled: { type: Boolean, default: false },
edit: { default: false },
checkedKeys: { default: () => {
return [];
} },
checkStrictly: { type: [Boolean, String], default: false },
collapseTransition: { type: Boolean, default: true },
onlyIconControl: { type: Boolean, default: false },
selectedKey: null,
showLine: { type: Boolean, default: true },
showCheckbox: { type: Boolean, default: false },
replaceFields: { default: () => {
return {
id: "id",
children: "children",
title: "title"
};
} }
},
emits: ["update:checkedKeys", "update:expandKeys", "node-click"],
setup(__props, { emit }) {
const props = __props;
useSlots();
const className = computed(() => {
return {
"layui-tree": true,
"layui-form": props.showCheckbox,
"layui-tree-line": props.showLine
};
});
let tree = ref();
let nodeList = ref();
const unWatch = ref(false);
const initStatus = ref(false);
const loadNodeList = () => {
let { tree: _tree, nodeList: _nodeList } = useTree(props);
tree.value = _tree;
nodeList.value = _nodeList.value;
};
watch(() => props.data, () => {
loadNodeList();
}, { deep: true, immediate: true });
watch(() => props.checkedKeys, () => {
if (!unWatch.value) {
loadNodeList();
}
});
watch(tree, () => {
if (initStatus.value) {
const { checkedKeys } = tree.value.getKeys();
unWatch.value = true;
emit("update:checkedKeys", checkedKeys);
setTimeout(() => {
unWatch.value = false;
}, 0);
}
}, { deep: true });
onMounted(() => {
nextTick(() => {
initStatus.value = true;
});
});
function handleClick(node) {
const originNode = tree.value.getOriginData(node.id);
emit("node-click", originNode);
}
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass(unref(className))
}, [
createVNode(_sfc_main$1, {
tree: unref(tree),
"node-list": unref(nodeList),
"show-checkbox": __props.showCheckbox,
"show-line": __props.showLine,
selectedKey: __props.selectedKey,
"check-strictly": __props.checkStrictly,
"collapse-transition": __props.collapseTransition,
"only-icon-control": __props.onlyIconControl,
onNodeClick: handleClick
}, createSlots({ _: 2 }, [
_ctx.$slots.title ? {
name: "title",
fn: withCtx(({ data }) => [
renderSlot(_ctx.$slots, "title", { data })
]),
key: "0"
} : void 0
]), 1032, ["tree", "node-list", "show-checkbox", "show-line", "selectedKey", "check-strictly", "collapse-transition", "only-icon-control"])
], 2);
};
}
});
const component = withInstall(_sfc_main);
export { component as default };