3ec7318728f49d6bb8c19dac05277cc7bf677ae2779198de0e9440f8db95737264aa240020d60ce0d8ed22b330cc47cbc1550872feb893dd5ad583101c5608 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import { defineComponent, inject, ref, getCurrentInstance, provide, watch, nextTick, resolveComponent, withDirectives, openBlock, createElementBlock, normalizeClass, withModifiers, createElementVNode, normalizeStyle, createBlock, withCtx, resolveDynamicComponent, createCommentVNode, createVNode, Fragment, renderList, vShow } from 'vue';
  2. import { ElCollapseTransition } from '../../collapse-transition/index.mjs';
  3. import { ElCheckbox } from '../../checkbox/index.mjs';
  4. import { ElIcon } from '../../icon/index.mjs';
  5. import { Loading, CaretRight } from '@element-plus/icons-vue';
  6. import NodeContent from './tree-node-content.mjs';
  7. import { getNodeKey, handleCurrentChange } from './model/util.mjs';
  8. import { useNodeExpandEventBroadcast } from './model/useNodeExpandEventBroadcast.mjs';
  9. import { dragEventsKey } from './model/useDragNode.mjs';
  10. import Node from './model/node.mjs';
  11. import { ROOT_TREE_INJECTION_KEY, NODE_INSTANCE_INJECTION_KEY } from './tokens.mjs';
  12. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  13. import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
  14. import { isFunction, isString } from '@vue/shared';
  15. const _sfc_main = defineComponent({
  16. name: "ElTreeNode",
  17. components: {
  18. ElCollapseTransition,
  19. ElCheckbox,
  20. NodeContent,
  21. ElIcon,
  22. Loading
  23. },
  24. props: {
  25. node: {
  26. type: Node,
  27. default: () => ({})
  28. },
  29. props: {
  30. type: Object,
  31. default: () => ({})
  32. },
  33. accordion: Boolean,
  34. renderContent: Function,
  35. renderAfterExpand: Boolean,
  36. showCheckbox: Boolean
  37. },
  38. emits: ["node-expand"],
  39. setup(props, ctx) {
  40. const ns = useNamespace("tree");
  41. const { broadcastExpanded } = useNodeExpandEventBroadcast(props);
  42. const tree = inject(ROOT_TREE_INJECTION_KEY);
  43. const expanded = ref(false);
  44. const childNodeRendered = ref(false);
  45. const oldChecked = ref();
  46. const oldIndeterminate = ref();
  47. const node$ = ref();
  48. const dragEvents = inject(dragEventsKey);
  49. const instance = getCurrentInstance();
  50. provide(NODE_INSTANCE_INJECTION_KEY, instance);
  51. if (props.node.expanded) {
  52. expanded.value = true;
  53. childNodeRendered.value = true;
  54. }
  55. const childrenKey = tree.props.props["children"] || "children";
  56. watch(() => {
  57. var _a;
  58. const children = (_a = props.node.data) == null ? void 0 : _a[childrenKey];
  59. return children && [...children];
  60. }, () => {
  61. props.node.updateChildren();
  62. });
  63. watch(() => props.node.indeterminate, (val) => {
  64. handleSelectChange(props.node.checked, val);
  65. });
  66. watch(() => props.node.checked, (val) => {
  67. handleSelectChange(val, props.node.indeterminate);
  68. });
  69. watch(() => props.node.childNodes.length, () => props.node.reInitChecked());
  70. watch(() => props.node.expanded, (val) => {
  71. nextTick(() => expanded.value = val);
  72. if (val) {
  73. childNodeRendered.value = true;
  74. }
  75. });
  76. const getNodeKey$1 = (node) => {
  77. return getNodeKey(tree.props.nodeKey, node.data);
  78. };
  79. const getNodeClass = (node) => {
  80. const nodeClassFunc = props.props.class;
  81. if (!nodeClassFunc) {
  82. return {};
  83. }
  84. let className;
  85. if (isFunction(nodeClassFunc)) {
  86. const { data } = node;
  87. className = nodeClassFunc(data, node);
  88. } else {
  89. className = nodeClassFunc;
  90. }
  91. if (isString(className)) {
  92. return { [className]: true };
  93. } else {
  94. return className;
  95. }
  96. };
  97. const handleSelectChange = (checked, indeterminate) => {
  98. if (oldChecked.value !== checked || oldIndeterminate.value !== indeterminate) {
  99. tree.ctx.emit("check-change", props.node.data, checked, indeterminate);
  100. }
  101. oldChecked.value = checked;
  102. oldIndeterminate.value = indeterminate;
  103. };
  104. const handleClick = (e) => {
  105. handleCurrentChange(tree.store, tree.ctx.emit, () => {
  106. var _a;
  107. const nodeKeyProp = (_a = tree == null ? void 0 : tree.props) == null ? void 0 : _a.nodeKey;
  108. if (nodeKeyProp) {
  109. const curNodeKey = getNodeKey$1(props.node);
  110. tree.store.value.setCurrentNodeKey(curNodeKey);
  111. } else {
  112. tree.store.value.setCurrentNode(props.node);
  113. }
  114. });
  115. tree.currentNode.value = props.node;
  116. if (tree.props.expandOnClickNode) {
  117. handleExpandIconClick();
  118. }
  119. if ((tree.props.checkOnClickNode || props.node.isLeaf && tree.props.checkOnClickLeaf && props.showCheckbox) && !props.node.disabled) {
  120. handleCheckChange(!props.node.checked);
  121. }
  122. tree.ctx.emit("node-click", props.node.data, props.node, instance, e);
  123. };
  124. const handleContextMenu = (event) => {
  125. var _a;
  126. if ((_a = tree.instance.vnode.props) == null ? void 0 : _a["onNodeContextmenu"]) {
  127. event.stopPropagation();
  128. event.preventDefault();
  129. }
  130. tree.ctx.emit("node-contextmenu", event, props.node.data, props.node, instance);
  131. };
  132. const handleExpandIconClick = () => {
  133. if (props.node.isLeaf)
  134. return;
  135. if (expanded.value) {
  136. tree.ctx.emit("node-collapse", props.node.data, props.node, instance);
  137. props.node.collapse();
  138. } else {
  139. props.node.expand(() => {
  140. ctx.emit("node-expand", props.node.data, props.node, instance);
  141. });
  142. }
  143. };
  144. const handleCheckChange = (value) => {
  145. props.node.setChecked(value, !(tree == null ? void 0 : tree.props.checkStrictly));
  146. nextTick(() => {
  147. const store = tree.store.value;
  148. tree.ctx.emit("check", props.node.data, {
  149. checkedNodes: store.getCheckedNodes(),
  150. checkedKeys: store.getCheckedKeys(),
  151. halfCheckedNodes: store.getHalfCheckedNodes(),
  152. halfCheckedKeys: store.getHalfCheckedKeys()
  153. });
  154. });
  155. };
  156. const handleChildNodeExpand = (nodeData, node, instance2) => {
  157. broadcastExpanded(node);
  158. tree.ctx.emit("node-expand", nodeData, node, instance2);
  159. };
  160. const handleDragStart = (event) => {
  161. if (!tree.props.draggable)
  162. return;
  163. dragEvents.treeNodeDragStart({ event, treeNode: props });
  164. };
  165. const handleDragOver = (event) => {
  166. event.preventDefault();
  167. if (!tree.props.draggable)
  168. return;
  169. dragEvents.treeNodeDragOver({
  170. event,
  171. treeNode: { $el: node$.value, node: props.node }
  172. });
  173. };
  174. const handleDrop = (event) => {
  175. event.preventDefault();
  176. };
  177. const handleDragEnd = (event) => {
  178. if (!tree.props.draggable)
  179. return;
  180. dragEvents.treeNodeDragEnd(event);
  181. };
  182. return {
  183. ns,
  184. node$,
  185. tree,
  186. expanded,
  187. childNodeRendered,
  188. oldChecked,
  189. oldIndeterminate,
  190. getNodeKey: getNodeKey$1,
  191. getNodeClass,
  192. handleSelectChange,
  193. handleClick,
  194. handleContextMenu,
  195. handleExpandIconClick,
  196. handleCheckChange,
  197. handleChildNodeExpand,
  198. handleDragStart,
  199. handleDragOver,
  200. handleDrop,
  201. handleDragEnd,
  202. CaretRight
  203. };
  204. }
  205. });
  206. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  207. const _component_el_icon = resolveComponent("el-icon");
  208. const _component_el_checkbox = resolveComponent("el-checkbox");
  209. const _component_loading = resolveComponent("loading");
  210. const _component_node_content = resolveComponent("node-content");
  211. const _component_el_tree_node = resolveComponent("el-tree-node");
  212. const _component_el_collapse_transition = resolveComponent("el-collapse-transition");
  213. return withDirectives((openBlock(), createElementBlock("div", {
  214. ref: "node$",
  215. class: normalizeClass([
  216. _ctx.ns.b("node"),
  217. _ctx.ns.is("expanded", _ctx.expanded),
  218. _ctx.ns.is("current", _ctx.node.isCurrent),
  219. _ctx.ns.is("hidden", !_ctx.node.visible),
  220. _ctx.ns.is("focusable", !_ctx.node.disabled),
  221. _ctx.ns.is("checked", !_ctx.node.disabled && _ctx.node.checked),
  222. _ctx.getNodeClass(_ctx.node)
  223. ]),
  224. role: "treeitem",
  225. tabindex: "-1",
  226. "aria-expanded": _ctx.expanded,
  227. "aria-disabled": _ctx.node.disabled,
  228. "aria-checked": _ctx.node.checked,
  229. draggable: _ctx.tree.props.draggable,
  230. "data-key": _ctx.getNodeKey(_ctx.node),
  231. onClick: withModifiers(_ctx.handleClick, ["stop"]),
  232. onContextmenu: _ctx.handleContextMenu,
  233. onDragstart: withModifiers(_ctx.handleDragStart, ["stop"]),
  234. onDragover: withModifiers(_ctx.handleDragOver, ["stop"]),
  235. onDragend: withModifiers(_ctx.handleDragEnd, ["stop"]),
  236. onDrop: withModifiers(_ctx.handleDrop, ["stop"])
  237. }, [
  238. createElementVNode("div", {
  239. class: normalizeClass(_ctx.ns.be("node", "content")),
  240. style: normalizeStyle({ paddingLeft: (_ctx.node.level - 1) * _ctx.tree.props.indent + "px" })
  241. }, [
  242. _ctx.tree.props.icon || _ctx.CaretRight ? (openBlock(), createBlock(_component_el_icon, {
  243. key: 0,
  244. class: normalizeClass([
  245. _ctx.ns.be("node", "expand-icon"),
  246. _ctx.ns.is("leaf", _ctx.node.isLeaf),
  247. {
  248. expanded: !_ctx.node.isLeaf && _ctx.expanded
  249. }
  250. ]),
  251. onClick: withModifiers(_ctx.handleExpandIconClick, ["stop"])
  252. }, {
  253. default: withCtx(() => [
  254. (openBlock(), createBlock(resolveDynamicComponent(_ctx.tree.props.icon || _ctx.CaretRight)))
  255. ]),
  256. _: 1
  257. }, 8, ["class", "onClick"])) : createCommentVNode("v-if", true),
  258. _ctx.showCheckbox ? (openBlock(), createBlock(_component_el_checkbox, {
  259. key: 1,
  260. "model-value": _ctx.node.checked,
  261. indeterminate: _ctx.node.indeterminate,
  262. disabled: !!_ctx.node.disabled,
  263. onClick: withModifiers(() => {
  264. }, ["stop"]),
  265. onChange: _ctx.handleCheckChange
  266. }, null, 8, ["model-value", "indeterminate", "disabled", "onClick", "onChange"])) : createCommentVNode("v-if", true),
  267. _ctx.node.loading ? (openBlock(), createBlock(_component_el_icon, {
  268. key: 2,
  269. class: normalizeClass([_ctx.ns.be("node", "loading-icon"), _ctx.ns.is("loading")])
  270. }, {
  271. default: withCtx(() => [
  272. createVNode(_component_loading)
  273. ]),
  274. _: 1
  275. }, 8, ["class"])) : createCommentVNode("v-if", true),
  276. createVNode(_component_node_content, {
  277. node: _ctx.node,
  278. "render-content": _ctx.renderContent
  279. }, null, 8, ["node", "render-content"])
  280. ], 6),
  281. createVNode(_component_el_collapse_transition, null, {
  282. default: withCtx(() => [
  283. !_ctx.renderAfterExpand || _ctx.childNodeRendered ? withDirectives((openBlock(), createElementBlock("div", {
  284. key: 0,
  285. class: normalizeClass(_ctx.ns.be("node", "children")),
  286. role: "group",
  287. "aria-expanded": _ctx.expanded,
  288. onClick: withModifiers(() => {
  289. }, ["stop"])
  290. }, [
  291. (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.node.childNodes, (child) => {
  292. return openBlock(), createBlock(_component_el_tree_node, {
  293. key: _ctx.getNodeKey(child),
  294. "render-content": _ctx.renderContent,
  295. "render-after-expand": _ctx.renderAfterExpand,
  296. "show-checkbox": _ctx.showCheckbox,
  297. node: child,
  298. accordion: _ctx.accordion,
  299. props: _ctx.props,
  300. onNodeExpand: _ctx.handleChildNodeExpand
  301. }, null, 8, ["render-content", "render-after-expand", "show-checkbox", "node", "accordion", "props", "onNodeExpand"]);
  302. }), 128))
  303. ], 10, ["aria-expanded", "onClick"])), [
  304. [vShow, _ctx.expanded]
  305. ]) : createCommentVNode("v-if", true)
  306. ]),
  307. _: 1
  308. })
  309. ], 42, ["aria-expanded", "aria-disabled", "aria-checked", "draggable", "data-key", "onClick", "onContextmenu", "onDragstart", "onDragover", "onDragend", "onDrop"])), [
  310. [vShow, _ctx.node.visible]
  311. ]);
  312. }
  313. var ElTreeNode = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "tree-node.vue"]]);
  314. export { ElTreeNode as default };
  315. //# sourceMappingURL=tree-node.mjs.map