d0da132261427c67632db2319f53c06fcdeaca8d709ce539d8b73f77de0dfc50ce9d0c23d03f12259938591f5f335a1c409e1adb1b8269d12f500af287a051 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import { ref, shallowRef, computed, watch } from 'vue';
  2. import { TreeOptionsEnum, NODE_CLICK, NODE_DROP, CURRENT_CHANGE, NODE_EXPAND, NODE_COLLAPSE } from '../virtual-tree.mjs';
  3. import { useCheck } from './useCheck.mjs';
  4. import { useFilter } from './useFilter.mjs';
  5. import { isObject } from '@vue/shared';
  6. function useTree(props, emit) {
  7. const expandedKeySet = ref(/* @__PURE__ */ new Set());
  8. const currentKey = ref();
  9. const tree = shallowRef();
  10. const listRef = ref();
  11. const {
  12. isIndeterminate,
  13. isChecked,
  14. toggleCheckbox,
  15. getCheckedKeys,
  16. getCheckedNodes,
  17. getHalfCheckedKeys,
  18. getHalfCheckedNodes,
  19. setChecked,
  20. setCheckedKeys
  21. } = useCheck(props, tree);
  22. const { doFilter, hiddenNodeKeySet, isForceHiddenExpandIcon } = useFilter(props, tree);
  23. const valueKey = computed(() => {
  24. var _a;
  25. return ((_a = props.props) == null ? void 0 : _a.value) || TreeOptionsEnum.KEY;
  26. });
  27. const childrenKey = computed(() => {
  28. var _a;
  29. return ((_a = props.props) == null ? void 0 : _a.children) || TreeOptionsEnum.CHILDREN;
  30. });
  31. const disabledKey = computed(() => {
  32. var _a;
  33. return ((_a = props.props) == null ? void 0 : _a.disabled) || TreeOptionsEnum.DISABLED;
  34. });
  35. const labelKey = computed(() => {
  36. var _a;
  37. return ((_a = props.props) == null ? void 0 : _a.label) || TreeOptionsEnum.LABEL;
  38. });
  39. const flattenTree = computed(() => {
  40. var _a;
  41. const expandedKeys = expandedKeySet.value;
  42. const hiddenKeys = hiddenNodeKeySet.value;
  43. const flattenNodes = [];
  44. const nodes = ((_a = tree.value) == null ? void 0 : _a.treeNodes) || [];
  45. const stack = [];
  46. for (let i = nodes.length - 1; i >= 0; --i) {
  47. stack.push(nodes[i]);
  48. }
  49. while (stack.length) {
  50. const node = stack.pop();
  51. if (hiddenKeys.has(node.key))
  52. continue;
  53. flattenNodes.push(node);
  54. if (node.children && expandedKeys.has(node.key)) {
  55. for (let i = node.children.length - 1; i >= 0; --i) {
  56. stack.push(node.children[i]);
  57. }
  58. }
  59. }
  60. return flattenNodes;
  61. });
  62. const isNotEmpty = computed(() => {
  63. return flattenTree.value.length > 0;
  64. });
  65. function createTree(data) {
  66. const treeNodeMap = /* @__PURE__ */ new Map();
  67. const levelTreeNodeMap = /* @__PURE__ */ new Map();
  68. let maxLevel = 1;
  69. function traverse(nodes, level = 1, parent = void 0) {
  70. var _a;
  71. const siblings = [];
  72. for (const rawNode of nodes) {
  73. const value = getKey(rawNode);
  74. const node = {
  75. level,
  76. key: value,
  77. data: rawNode
  78. };
  79. node.label = getLabel(rawNode);
  80. node.parent = parent;
  81. const children = getChildren(rawNode);
  82. node.disabled = getDisabled(rawNode);
  83. node.isLeaf = !children || children.length === 0;
  84. node.expanded = expandedKeySet.value.has(value);
  85. if (children && children.length) {
  86. node.children = traverse(children, level + 1, node);
  87. }
  88. siblings.push(node);
  89. treeNodeMap.set(value, node);
  90. if (!levelTreeNodeMap.has(level)) {
  91. levelTreeNodeMap.set(level, []);
  92. }
  93. (_a = levelTreeNodeMap.get(level)) == null ? void 0 : _a.push(node);
  94. }
  95. if (level > maxLevel) {
  96. maxLevel = level;
  97. }
  98. return siblings;
  99. }
  100. const treeNodes = traverse(data);
  101. return {
  102. treeNodeMap,
  103. levelTreeNodeMap,
  104. maxLevel,
  105. treeNodes
  106. };
  107. }
  108. function filter(query) {
  109. const keys = doFilter(query);
  110. if (keys) {
  111. expandedKeySet.value = keys;
  112. }
  113. }
  114. function getChildren(node) {
  115. return node[childrenKey.value];
  116. }
  117. function getKey(node) {
  118. if (!node) {
  119. return "";
  120. }
  121. return node[valueKey.value];
  122. }
  123. function getDisabled(node) {
  124. return node[disabledKey.value];
  125. }
  126. function getLabel(node) {
  127. return node[labelKey.value];
  128. }
  129. function toggleExpand(node) {
  130. const expandedKeys = expandedKeySet.value;
  131. if (expandedKeys.has(node.key)) {
  132. collapseNode(node);
  133. } else {
  134. expandNode(node);
  135. }
  136. }
  137. function setExpandedKeys(keys) {
  138. const expandedKeys = /* @__PURE__ */ new Set();
  139. const nodeMap = tree.value.treeNodeMap;
  140. expandedKeySet.value.forEach((key) => {
  141. const node = nodeMap.get(key);
  142. expandedKeySet.value.delete(node.key);
  143. node.expanded = false;
  144. });
  145. keys.forEach((k) => {
  146. let node = nodeMap.get(k);
  147. while (node && !expandedKeys.has(node.key)) {
  148. expandedKeys.add(node.key);
  149. node.expanded = true;
  150. node = node.parent;
  151. }
  152. });
  153. expandedKeySet.value = expandedKeys;
  154. }
  155. function handleNodeClick(node, e) {
  156. emit(NODE_CLICK, node.data, node, e);
  157. handleCurrentChange(node);
  158. if (props.expandOnClickNode) {
  159. toggleExpand(node);
  160. }
  161. if (props.showCheckbox && (props.checkOnClickNode || node.isLeaf && props.checkOnClickLeaf) && !node.disabled) {
  162. toggleCheckbox(node, !isChecked(node), true);
  163. }
  164. }
  165. function handleNodeDrop(node, e) {
  166. emit(NODE_DROP, node.data, node, e);
  167. }
  168. function handleCurrentChange(node) {
  169. if (!isCurrent(node)) {
  170. currentKey.value = node.key;
  171. emit(CURRENT_CHANGE, node.data, node);
  172. }
  173. }
  174. function handleNodeCheck(node, checked) {
  175. toggleCheckbox(node, checked);
  176. }
  177. function expandNode(node) {
  178. const keySet = expandedKeySet.value;
  179. if (tree.value && props.accordion) {
  180. const { treeNodeMap } = tree.value;
  181. keySet.forEach((key) => {
  182. const treeNode = treeNodeMap.get(key);
  183. if (node && node.level === (treeNode == null ? void 0 : treeNode.level)) {
  184. keySet.delete(key);
  185. treeNode.expanded = false;
  186. }
  187. });
  188. }
  189. keySet.add(node.key);
  190. node.expanded = true;
  191. emit(NODE_EXPAND, node.data, node);
  192. }
  193. function collapseNode(node) {
  194. expandedKeySet.value.delete(node.key);
  195. node.expanded = false;
  196. emit(NODE_COLLAPSE, node.data, node);
  197. }
  198. function isDisabled(node) {
  199. return !!node.disabled;
  200. }
  201. function isCurrent(node) {
  202. const current = currentKey.value;
  203. return current !== void 0 && current === node.key;
  204. }
  205. function getCurrentNode() {
  206. var _a, _b;
  207. if (!currentKey.value)
  208. return void 0;
  209. return (_b = (_a = tree.value) == null ? void 0 : _a.treeNodeMap.get(currentKey.value)) == null ? void 0 : _b.data;
  210. }
  211. function getCurrentKey() {
  212. return currentKey.value;
  213. }
  214. function setCurrentKey(key) {
  215. currentKey.value = key;
  216. }
  217. function setData(data) {
  218. tree.value = createTree(data);
  219. }
  220. function getNode(data) {
  221. var _a;
  222. const key = isObject(data) ? getKey(data) : data;
  223. return (_a = tree.value) == null ? void 0 : _a.treeNodeMap.get(key);
  224. }
  225. function scrollToNode(key, strategy = "auto") {
  226. const node = getNode(key);
  227. if (node && listRef.value) {
  228. listRef.value.scrollToItem(flattenTree.value.indexOf(node), strategy);
  229. }
  230. }
  231. function scrollTo(offset) {
  232. var _a;
  233. (_a = listRef.value) == null ? void 0 : _a.scrollTo(offset);
  234. }
  235. watch(() => props.currentNodeKey, (key) => {
  236. currentKey.value = key;
  237. }, {
  238. immediate: true
  239. });
  240. watch(() => props.defaultExpandedKeys, (key) => {
  241. expandedKeySet.value = new Set(key);
  242. }, {
  243. immediate: true
  244. });
  245. watch(() => props.data, (data) => {
  246. setData(data);
  247. }, {
  248. immediate: true
  249. });
  250. return {
  251. tree,
  252. flattenTree,
  253. isNotEmpty,
  254. listRef,
  255. getKey,
  256. getChildren,
  257. toggleExpand,
  258. toggleCheckbox,
  259. isChecked,
  260. isIndeterminate,
  261. isDisabled,
  262. isCurrent,
  263. isForceHiddenExpandIcon,
  264. handleNodeClick,
  265. handleNodeDrop,
  266. handleNodeCheck,
  267. getCurrentNode,
  268. getCurrentKey,
  269. setCurrentKey,
  270. getCheckedKeys,
  271. getCheckedNodes,
  272. getHalfCheckedKeys,
  273. getHalfCheckedNodes,
  274. setChecked,
  275. setCheckedKeys,
  276. filter,
  277. setData,
  278. getNode,
  279. expandNode,
  280. collapseNode,
  281. setExpandedKeys,
  282. scrollToNode,
  283. scrollTo
  284. };
  285. }
  286. export { useTree };
  287. //# sourceMappingURL=useTree.mjs.map