Tree.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. import _typeof from "@babel/runtime/helpers/esm/typeof";
  2. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  3. import _extends from "@babel/runtime/helpers/esm/extends";
  4. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  5. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  6. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  7. import { createVNode as _createVNode } from "vue";
  8. import { useProvideKeysState, TreeContext } from './contextTypes';
  9. import { getDragChildrenKeys, parseCheckedKeys, conductExpandParent, calcSelectedKeys, calcDropPosition, arrAdd, arrDel, posToArr } from './util';
  10. import { flattenTreeData, convertTreeToData, convertDataToEntities, convertNodePropsToEventData, getTreeNodeProps, fillFieldNames } from './utils/treeUtil';
  11. import NodeList, { MOTION_KEY, MotionEntity } from './NodeList';
  12. import { conductCheck } from './utils/conductUtil';
  13. import DropIndicator from './DropIndicator';
  14. import { computed, defineComponent, onUnmounted, reactive, ref, shallowRef, watch, watchEffect, nextTick, toRaw } from 'vue';
  15. import initDefaultProps from '../_util/props-util/initDefaultProps';
  16. import { treeProps } from './props';
  17. import { warning } from '../vc-util/warning';
  18. import KeyCode from '../_util/KeyCode';
  19. import classNames from '../_util/classNames';
  20. import pickAttrs from '../_util/pickAttrs';
  21. import useMaxLevel from './useMaxLevel';
  22. var MAX_RETRY_TIMES = 10;
  23. export default defineComponent({
  24. compatConfig: {
  25. MODE: 3
  26. },
  27. name: 'Tree',
  28. inheritAttrs: false,
  29. slots: ['checkable', 'title', 'icon', 'titleRender'],
  30. props: initDefaultProps(treeProps(), {
  31. prefixCls: 'vc-tree',
  32. showLine: false,
  33. showIcon: true,
  34. selectable: true,
  35. multiple: false,
  36. checkable: false,
  37. disabled: false,
  38. checkStrictly: false,
  39. draggable: false,
  40. defaultExpandParent: true,
  41. autoExpandParent: false,
  42. defaultExpandAll: false,
  43. defaultExpandedKeys: [],
  44. defaultCheckedKeys: [],
  45. defaultSelectedKeys: [],
  46. dropIndicatorRender: DropIndicator,
  47. allowDrop: function allowDrop() {
  48. return true;
  49. }
  50. }),
  51. setup: function setup(props, _ref) {
  52. var attrs = _ref.attrs,
  53. slots = _ref.slots,
  54. expose = _ref.expose;
  55. var destroyed = ref(false);
  56. var delayedDragEnterLogic = {};
  57. var indent = ref();
  58. var selectedKeys = shallowRef([]);
  59. var checkedKeys = shallowRef([]);
  60. var halfCheckedKeys = shallowRef([]);
  61. var loadedKeys = shallowRef([]);
  62. var loadingKeys = shallowRef([]);
  63. var expandedKeys = shallowRef([]);
  64. var loadingRetryTimes = {};
  65. var dragState = reactive({
  66. draggingNodeKey: null,
  67. dragChildrenKeys: [],
  68. // dropTargetKey is the key of abstract-drop-node
  69. // the abstract-drop-node is the real drop node when drag and drop
  70. // not the DOM drag over node
  71. dropTargetKey: null,
  72. dropPosition: null,
  73. dropContainerKey: null,
  74. dropLevelOffset: null,
  75. dropTargetPos: null,
  76. dropAllowed: true,
  77. // the abstract-drag-over-node
  78. // if mouse is on the bottom of top dom node or no the top of the bottom dom node
  79. // abstract-drag-over-node is the top node
  80. dragOverNodeKey: null
  81. });
  82. var treeData = shallowRef([]);
  83. watch([function () {
  84. return props.treeData;
  85. }, function () {
  86. return props.children;
  87. }], function () {
  88. treeData.value = props.treeData !== undefined ? toRaw(props.treeData).slice() : convertTreeToData(toRaw(props.children));
  89. }, {
  90. immediate: true,
  91. deep: true
  92. });
  93. var keyEntities = shallowRef({});
  94. var focused = ref(false);
  95. var activeKey = ref(null);
  96. var listChanging = ref(false);
  97. var fieldNames = computed(function () {
  98. return fillFieldNames(props.fieldNames);
  99. });
  100. var listRef = ref();
  101. var dragStartMousePosition = null;
  102. var dragNode = null;
  103. var currentMouseOverDroppableNodeKey = null;
  104. var treeNodeRequiredProps = computed(function () {
  105. return {
  106. expandedKeysSet: expandedKeysSet.value,
  107. selectedKeysSet: selectedKeysSet.value,
  108. loadedKeysSet: loadedKeysSet.value,
  109. loadingKeysSet: loadingKeysSet.value,
  110. checkedKeysSet: checkedKeysSet.value,
  111. halfCheckedKeysSet: halfCheckedKeysSet.value,
  112. dragOverNodeKey: dragState.dragOverNodeKey,
  113. dropPosition: dragState.dropPosition,
  114. keyEntities: keyEntities.value
  115. };
  116. });
  117. var expandedKeysSet = computed(function () {
  118. return new Set(expandedKeys.value);
  119. });
  120. var selectedKeysSet = computed(function () {
  121. return new Set(selectedKeys.value);
  122. });
  123. var loadedKeysSet = computed(function () {
  124. return new Set(loadedKeys.value);
  125. });
  126. var loadingKeysSet = computed(function () {
  127. return new Set(loadingKeys.value);
  128. });
  129. var checkedKeysSet = computed(function () {
  130. return new Set(checkedKeys.value);
  131. });
  132. var halfCheckedKeysSet = computed(function () {
  133. return new Set(halfCheckedKeys.value);
  134. });
  135. watchEffect(function () {
  136. if (treeData.value) {
  137. var entitiesMap = convertDataToEntities(treeData.value, {
  138. fieldNames: fieldNames.value
  139. });
  140. keyEntities.value = _objectSpread(_defineProperty({}, MOTION_KEY, MotionEntity), entitiesMap.keyEntities);
  141. }
  142. });
  143. var init = false; // 处理 defaultXxxx api, 仅仅首次有效
  144. watch([function () {
  145. return props.expandedKeys;
  146. }, function () {
  147. return props.autoExpandParent;
  148. }, keyEntities],
  149. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  150. function (_ref2, _ref3) {
  151. var _ref4 = _slicedToArray(_ref2, 2),
  152. _newKeys = _ref4[0],
  153. newAutoExpandParent = _ref4[1];
  154. var _ref5 = _slicedToArray(_ref3, 2),
  155. _oldKeys = _ref5[0],
  156. oldAutoExpandParent = _ref5[1];
  157. var keys = expandedKeys.value;
  158. // ================ expandedKeys =================
  159. if (props.expandedKeys !== undefined || init && newAutoExpandParent !== oldAutoExpandParent) {
  160. keys = props.autoExpandParent || !init && props.defaultExpandParent ? conductExpandParent(props.expandedKeys, keyEntities.value) : props.expandedKeys;
  161. } else if (!init && props.defaultExpandAll) {
  162. var cloneKeyEntities = _objectSpread({}, keyEntities.value);
  163. delete cloneKeyEntities[MOTION_KEY];
  164. keys = Object.keys(cloneKeyEntities).map(function (key) {
  165. return cloneKeyEntities[key].key;
  166. });
  167. } else if (!init && props.defaultExpandedKeys) {
  168. keys = props.autoExpandParent || props.defaultExpandParent ? conductExpandParent(props.defaultExpandedKeys, keyEntities.value) : props.defaultExpandedKeys;
  169. }
  170. if (keys) {
  171. expandedKeys.value = keys;
  172. }
  173. init = true;
  174. }, {
  175. immediate: true
  176. });
  177. // ================ flattenNodes =================
  178. var flattenNodes = shallowRef([]);
  179. watchEffect(function () {
  180. flattenNodes.value = flattenTreeData(treeData.value, expandedKeys.value, fieldNames.value);
  181. });
  182. // ================ selectedKeys =================
  183. watchEffect(function () {
  184. if (props.selectable) {
  185. if (props.selectedKeys !== undefined) {
  186. selectedKeys.value = calcSelectedKeys(props.selectedKeys, props);
  187. } else if (!init && props.defaultSelectedKeys) {
  188. selectedKeys.value = calcSelectedKeys(props.defaultSelectedKeys, props);
  189. }
  190. }
  191. });
  192. var _useMaxLevel = useMaxLevel(keyEntities),
  193. maxLevel = _useMaxLevel.maxLevel,
  194. levelEntities = _useMaxLevel.levelEntities;
  195. // ================= checkedKeys =================
  196. watchEffect(function () {
  197. if (props.checkable) {
  198. var checkedKeyEntity;
  199. if (props.checkedKeys !== undefined) {
  200. checkedKeyEntity = parseCheckedKeys(props.checkedKeys) || {};
  201. } else if (!init && props.defaultCheckedKeys) {
  202. checkedKeyEntity = parseCheckedKeys(props.defaultCheckedKeys) || {};
  203. } else if (treeData.value) {
  204. // If `treeData` changed, we also need check it
  205. checkedKeyEntity = parseCheckedKeys(props.checkedKeys) || {
  206. checkedKeys: checkedKeys.value,
  207. halfCheckedKeys: halfCheckedKeys.value
  208. };
  209. }
  210. if (checkedKeyEntity) {
  211. var _checkedKeyEntity = checkedKeyEntity,
  212. _checkedKeyEntity$che = _checkedKeyEntity.checkedKeys,
  213. newCheckedKeys = _checkedKeyEntity$che === void 0 ? [] : _checkedKeyEntity$che,
  214. _checkedKeyEntity$hal = _checkedKeyEntity.halfCheckedKeys,
  215. newHalfCheckedKeys = _checkedKeyEntity$hal === void 0 ? [] : _checkedKeyEntity$hal;
  216. if (!props.checkStrictly) {
  217. var conductKeys = conductCheck(newCheckedKeys, true, keyEntities.value, maxLevel.value, levelEntities.value);
  218. newCheckedKeys = conductKeys.checkedKeys;
  219. newHalfCheckedKeys = conductKeys.halfCheckedKeys;
  220. }
  221. checkedKeys.value = newCheckedKeys;
  222. halfCheckedKeys.value = newHalfCheckedKeys;
  223. }
  224. }
  225. });
  226. // ================= loadedKeys ==================
  227. watchEffect(function () {
  228. if (props.loadedKeys) {
  229. loadedKeys.value = props.loadedKeys;
  230. }
  231. });
  232. var resetDragState = function resetDragState() {
  233. _extends(dragState, {
  234. dragOverNodeKey: null,
  235. dropPosition: null,
  236. dropLevelOffset: null,
  237. dropTargetKey: null,
  238. dropContainerKey: null,
  239. dropTargetPos: null,
  240. dropAllowed: false
  241. });
  242. };
  243. var scrollTo = function scrollTo(scroll) {
  244. listRef.value.scrollTo(scroll);
  245. };
  246. watch(function () {
  247. return props.activeKey;
  248. }, function () {
  249. if (props.activeKey !== undefined) {
  250. activeKey.value = props.activeKey;
  251. }
  252. }, {
  253. immediate: true
  254. });
  255. watch(activeKey, function (val) {
  256. nextTick(function () {
  257. if (val !== null) {
  258. scrollTo({
  259. key: val
  260. });
  261. }
  262. });
  263. }, {
  264. immediate: true,
  265. flush: 'post'
  266. });
  267. // =========================== Expanded ===========================
  268. /** Set uncontrolled `expandedKeys`. This will also auto update `flattenNodes`. */
  269. var setExpandedKeys = function setExpandedKeys(keys) {
  270. if (props.expandedKeys === undefined) {
  271. expandedKeys.value = keys;
  272. }
  273. };
  274. var cleanDragState = function cleanDragState() {
  275. if (dragState.draggingNodeKey !== null) {
  276. _extends(dragState, {
  277. draggingNodeKey: null,
  278. dropPosition: null,
  279. dropContainerKey: null,
  280. dropTargetKey: null,
  281. dropLevelOffset: null,
  282. dropAllowed: true,
  283. dragOverNodeKey: null
  284. });
  285. }
  286. dragStartMousePosition = null;
  287. currentMouseOverDroppableNodeKey = null;
  288. };
  289. // if onNodeDragEnd is called, onWindowDragEnd won't be called since stopPropagation() is called
  290. var onNodeDragEnd = function onNodeDragEnd(event, node) {
  291. var onDragend = props.onDragend;
  292. dragState.dragOverNodeKey = null;
  293. cleanDragState();
  294. onDragend === null || onDragend === void 0 ? void 0 : onDragend({
  295. event: event,
  296. node: node.eventData
  297. });
  298. dragNode = null;
  299. };
  300. // since stopPropagation() is called in treeNode
  301. // if onWindowDrag is called, whice means state is keeped, drag state should be cleared
  302. var onWindowDragEnd = function onWindowDragEnd(event) {
  303. onNodeDragEnd(event, null, true);
  304. window.removeEventListener('dragend', onWindowDragEnd);
  305. };
  306. var onNodeDragStart = function onNodeDragStart(event, node) {
  307. var onDragstart = props.onDragstart;
  308. var eventKey = node.eventKey,
  309. eventData = node.eventData;
  310. dragNode = node;
  311. dragStartMousePosition = {
  312. x: event.clientX,
  313. y: event.clientY
  314. };
  315. var newExpandedKeys = arrDel(expandedKeys.value, eventKey);
  316. dragState.draggingNodeKey = eventKey;
  317. dragState.dragChildrenKeys = getDragChildrenKeys(eventKey, keyEntities.value);
  318. indent.value = listRef.value.getIndentWidth();
  319. setExpandedKeys(newExpandedKeys);
  320. window.addEventListener('dragend', onWindowDragEnd);
  321. if (onDragstart) {
  322. onDragstart({
  323. event: event,
  324. node: eventData
  325. });
  326. }
  327. };
  328. /**
  329. * [Legacy] Select handler is smaller than node,
  330. * so that this will trigger when drag enter node or select handler.
  331. * This is a little tricky if customize css without padding.
  332. * Better for use mouse move event to refresh drag state.
  333. * But let's just keep it to avoid event trigger logic change.
  334. */
  335. var onNodeDragEnter = function onNodeDragEnter(event, node) {
  336. var onDragenter = props.onDragenter,
  337. onExpand = props.onExpand,
  338. allowDrop = props.allowDrop,
  339. direction = props.direction;
  340. var pos = node.pos,
  341. eventKey = node.eventKey;
  342. // record the key of node which is latest entered, used in dragleave event.
  343. if (currentMouseOverDroppableNodeKey !== eventKey) {
  344. currentMouseOverDroppableNodeKey = eventKey;
  345. }
  346. if (!dragNode) {
  347. resetDragState();
  348. return;
  349. }
  350. var _calcDropPosition = calcDropPosition(event, dragNode, node, indent.value, dragStartMousePosition, allowDrop, flattenNodes.value, keyEntities.value, expandedKeysSet.value, direction),
  351. dropPosition = _calcDropPosition.dropPosition,
  352. dropLevelOffset = _calcDropPosition.dropLevelOffset,
  353. dropTargetKey = _calcDropPosition.dropTargetKey,
  354. dropContainerKey = _calcDropPosition.dropContainerKey,
  355. dropTargetPos = _calcDropPosition.dropTargetPos,
  356. dropAllowed = _calcDropPosition.dropAllowed,
  357. dragOverNodeKey = _calcDropPosition.dragOverNodeKey;
  358. if (
  359. // don't allow drop inside its children
  360. dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 ||
  361. // don't allow drop when drop is not allowed caculated by calcDropPosition
  362. !dropAllowed) {
  363. resetDragState();
  364. return;
  365. }
  366. // Side effect for delay drag
  367. if (!delayedDragEnterLogic) {
  368. delayedDragEnterLogic = {};
  369. }
  370. Object.keys(delayedDragEnterLogic).forEach(function (key) {
  371. clearTimeout(delayedDragEnterLogic[key]);
  372. });
  373. if (dragNode.eventKey !== node.eventKey) {
  374. // hoist expand logic here
  375. // since if logic is on the bottom
  376. // it will be blocked by abstract dragover node check
  377. // => if you dragenter from top, you mouse will still be consider as in the top node
  378. delayedDragEnterLogic[pos] = window.setTimeout(function () {
  379. if (dragState.draggingNodeKey === null) return;
  380. var newExpandedKeys = expandedKeys.value.slice();
  381. var entity = keyEntities.value[node.eventKey];
  382. if (entity && (entity.children || []).length) {
  383. newExpandedKeys = arrAdd(expandedKeys.value, node.eventKey);
  384. }
  385. setExpandedKeys(newExpandedKeys);
  386. if (onExpand) {
  387. onExpand(newExpandedKeys, {
  388. node: node.eventData,
  389. expanded: true,
  390. nativeEvent: event
  391. });
  392. }
  393. }, 800);
  394. }
  395. // Skip if drag node is self
  396. if (dragNode.eventKey === dropTargetKey && dropLevelOffset === 0) {
  397. resetDragState();
  398. return;
  399. }
  400. // Update drag over node and drag state
  401. _extends(dragState, {
  402. dragOverNodeKey: dragOverNodeKey,
  403. dropPosition: dropPosition,
  404. dropLevelOffset: dropLevelOffset,
  405. dropTargetKey: dropTargetKey,
  406. dropContainerKey: dropContainerKey,
  407. dropTargetPos: dropTargetPos,
  408. dropAllowed: dropAllowed
  409. });
  410. if (onDragenter) {
  411. onDragenter({
  412. event: event,
  413. node: node.eventData,
  414. expandedKeys: expandedKeys.value
  415. });
  416. }
  417. };
  418. var onNodeDragOver = function onNodeDragOver(event, node) {
  419. var onDragover = props.onDragover,
  420. allowDrop = props.allowDrop,
  421. direction = props.direction;
  422. if (!dragNode) {
  423. return;
  424. }
  425. var _calcDropPosition2 = calcDropPosition(event, dragNode, node, indent.value, dragStartMousePosition, allowDrop, flattenNodes.value, keyEntities.value, expandedKeysSet.value, direction),
  426. dropPosition = _calcDropPosition2.dropPosition,
  427. dropLevelOffset = _calcDropPosition2.dropLevelOffset,
  428. dropTargetKey = _calcDropPosition2.dropTargetKey,
  429. dropContainerKey = _calcDropPosition2.dropContainerKey,
  430. dropAllowed = _calcDropPosition2.dropAllowed,
  431. dropTargetPos = _calcDropPosition2.dropTargetPos,
  432. dragOverNodeKey = _calcDropPosition2.dragOverNodeKey;
  433. if (dragState.dragChildrenKeys.indexOf(dropTargetKey) !== -1 || !dropAllowed) {
  434. // don't allow drop inside its children
  435. // don't allow drop when drop is not allowed caculated by calcDropPosition
  436. return;
  437. }
  438. // Update drag position
  439. if (dragNode.eventKey === dropTargetKey && dropLevelOffset === 0) {
  440. if (!(dragState.dropPosition === null && dragState.dropLevelOffset === null && dragState.dropTargetKey === null && dragState.dropContainerKey === null && dragState.dropTargetPos === null && dragState.dropAllowed === false && dragState.dragOverNodeKey === null)) {
  441. resetDragState();
  442. }
  443. } else if (!(dropPosition === dragState.dropPosition && dropLevelOffset === dragState.dropLevelOffset && dropTargetKey === dragState.dropTargetKey && dropContainerKey === dragState.dropContainerKey && dropTargetPos === dragState.dropTargetPos && dropAllowed === dragState.dropAllowed && dragOverNodeKey === dragState.dragOverNodeKey)) {
  444. _extends(dragState, {
  445. dropPosition: dropPosition,
  446. dropLevelOffset: dropLevelOffset,
  447. dropTargetKey: dropTargetKey,
  448. dropContainerKey: dropContainerKey,
  449. dropTargetPos: dropTargetPos,
  450. dropAllowed: dropAllowed,
  451. dragOverNodeKey: dragOverNodeKey
  452. });
  453. }
  454. if (onDragover) {
  455. onDragover({
  456. event: event,
  457. node: node.eventData
  458. });
  459. }
  460. };
  461. var onNodeDragLeave = function onNodeDragLeave(event, node) {
  462. // if it is outside the droppable area
  463. // currentMouseOverDroppableNodeKey will be updated in dragenter event when into another droppable receiver.
  464. if (currentMouseOverDroppableNodeKey === node.eventKey && !event.currentTarget.contains(event.relatedTarget)) {
  465. resetDragState();
  466. currentMouseOverDroppableNodeKey = null;
  467. }
  468. var onDragleave = props.onDragleave;
  469. if (onDragleave) {
  470. onDragleave({
  471. event: event,
  472. node: node.eventData
  473. });
  474. }
  475. };
  476. var onNodeDrop = function onNodeDrop(event, _node) {
  477. var _activeItem$value;
  478. var outsideTree = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  479. var dragChildrenKeys = dragState.dragChildrenKeys,
  480. dropPosition = dragState.dropPosition,
  481. dropTargetKey = dragState.dropTargetKey,
  482. dropTargetPos = dragState.dropTargetPos,
  483. dropAllowed = dragState.dropAllowed;
  484. if (!dropAllowed) return;
  485. var onDrop = props.onDrop;
  486. dragState.dragOverNodeKey = null;
  487. cleanDragState();
  488. if (dropTargetKey === null) return;
  489. var abstractDropNodeProps = _objectSpread(_objectSpread({}, getTreeNodeProps(dropTargetKey, toRaw(treeNodeRequiredProps.value))), {}, {
  490. active: ((_activeItem$value = activeItem.value) === null || _activeItem$value === void 0 ? void 0 : _activeItem$value.key) === dropTargetKey,
  491. data: keyEntities.value[dropTargetKey].node
  492. });
  493. var dropToChild = dragChildrenKeys.indexOf(dropTargetKey) !== -1;
  494. warning(!dropToChild, "Can not drop to dragNode's children node. Maybe this is a bug of ant-design-vue. Please report an issue.");
  495. var posArr = posToArr(dropTargetPos);
  496. var dropResult = {
  497. event: event,
  498. node: convertNodePropsToEventData(abstractDropNodeProps),
  499. dragNode: dragNode ? dragNode.eventData : null,
  500. dragNodesKeys: [dragNode.eventKey].concat(dragChildrenKeys),
  501. dropToGap: dropPosition !== 0,
  502. dropPosition: dropPosition + Number(posArr[posArr.length - 1])
  503. };
  504. if (!outsideTree) {
  505. onDrop === null || onDrop === void 0 ? void 0 : onDrop(dropResult);
  506. }
  507. dragNode = null;
  508. };
  509. var onNodeClick = function onNodeClick(e, treeNode) {
  510. var onClick = props.onClick;
  511. if (onClick) {
  512. onClick(e, treeNode);
  513. }
  514. };
  515. var onNodeDoubleClick = function onNodeDoubleClick(e, treeNode) {
  516. var onDblclick = props.onDblclick;
  517. if (onDblclick) {
  518. onDblclick(e, treeNode);
  519. }
  520. };
  521. var onNodeSelect = function onNodeSelect(e, treeNode) {
  522. var newSelectedKeys = selectedKeys.value;
  523. var onSelect = props.onSelect,
  524. multiple = props.multiple;
  525. var selected = treeNode.selected;
  526. var key = treeNode[fieldNames.value.key];
  527. var targetSelected = !selected;
  528. // Update selected keys
  529. if (!targetSelected) {
  530. newSelectedKeys = arrDel(newSelectedKeys, key);
  531. } else if (!multiple) {
  532. newSelectedKeys = [key];
  533. } else {
  534. newSelectedKeys = arrAdd(newSelectedKeys, key);
  535. }
  536. // [Legacy] Not found related usage in doc or upper libs
  537. var keyEntitiesValue = keyEntities.value;
  538. var selectedNodes = newSelectedKeys.map(function (selectedKey) {
  539. var entity = keyEntitiesValue[selectedKey];
  540. if (!entity) return null;
  541. return entity.node;
  542. }).filter(function (node) {
  543. return node;
  544. });
  545. if (props.selectedKeys === undefined) {
  546. selectedKeys.value = newSelectedKeys;
  547. }
  548. if (onSelect) {
  549. onSelect(newSelectedKeys, {
  550. event: 'select',
  551. selected: targetSelected,
  552. node: treeNode,
  553. selectedNodes: selectedNodes,
  554. nativeEvent: e
  555. });
  556. }
  557. };
  558. var onNodeCheck = function onNodeCheck(e, treeNode, checked) {
  559. var checkStrictly = props.checkStrictly,
  560. onCheck = props.onCheck;
  561. var key = treeNode[fieldNames.value.key];
  562. // Prepare trigger arguments
  563. var checkedObj;
  564. var eventObj = {
  565. event: 'check',
  566. node: treeNode,
  567. checked: checked,
  568. nativeEvent: e
  569. };
  570. var keyEntitiesValue = keyEntities.value;
  571. if (checkStrictly) {
  572. var newCheckedKeys = checked ? arrAdd(checkedKeys.value, key) : arrDel(checkedKeys.value, key);
  573. var newHalfCheckedKeys = arrDel(halfCheckedKeys.value, key);
  574. checkedObj = {
  575. checked: newCheckedKeys,
  576. halfChecked: newHalfCheckedKeys
  577. };
  578. eventObj.checkedNodes = newCheckedKeys.map(function (checkedKey) {
  579. return keyEntitiesValue[checkedKey];
  580. }).filter(function (entity) {
  581. return entity;
  582. }).map(function (entity) {
  583. return entity.node;
  584. });
  585. if (props.checkedKeys === undefined) {
  586. checkedKeys.value = newCheckedKeys;
  587. }
  588. } else {
  589. // Always fill first
  590. var _conductCheck = conductCheck([].concat(_toConsumableArray(checkedKeys.value), [key]), true, keyEntitiesValue, maxLevel.value, levelEntities.value),
  591. _newCheckedKeys = _conductCheck.checkedKeys,
  592. _newHalfCheckedKeys = _conductCheck.halfCheckedKeys;
  593. // If remove, we do it again to correction
  594. if (!checked) {
  595. var keySet = new Set(_newCheckedKeys);
  596. keySet.delete(key);
  597. var _conductCheck2 = conductCheck(Array.from(keySet), {
  598. checked: false,
  599. halfCheckedKeys: _newHalfCheckedKeys
  600. }, keyEntitiesValue, maxLevel.value, levelEntities.value);
  601. _newCheckedKeys = _conductCheck2.checkedKeys;
  602. _newHalfCheckedKeys = _conductCheck2.halfCheckedKeys;
  603. }
  604. checkedObj = _newCheckedKeys;
  605. // [Legacy] This is used for vc-tree-select`
  606. eventObj.checkedNodes = [];
  607. eventObj.checkedNodesPositions = [];
  608. eventObj.halfCheckedKeys = _newHalfCheckedKeys;
  609. _newCheckedKeys.forEach(function (checkedKey) {
  610. var entity = keyEntitiesValue[checkedKey];
  611. if (!entity) return;
  612. var node = entity.node,
  613. pos = entity.pos;
  614. eventObj.checkedNodes.push(node);
  615. eventObj.checkedNodesPositions.push({
  616. node: node,
  617. pos: pos
  618. });
  619. });
  620. if (props.checkedKeys === undefined) {
  621. checkedKeys.value = _newCheckedKeys;
  622. halfCheckedKeys.value = _newHalfCheckedKeys;
  623. }
  624. }
  625. if (onCheck) {
  626. onCheck(checkedObj, eventObj);
  627. }
  628. };
  629. var onNodeLoad = function onNodeLoad(treeNode) {
  630. var key = treeNode[fieldNames.value.key];
  631. var loadPromise = new Promise(function (resolve, reject) {
  632. // We need to get the latest state of loading/loaded keys
  633. var loadData = props.loadData,
  634. onLoad = props.onLoad;
  635. if (!loadData || loadedKeysSet.value.has(key) || loadingKeysSet.value.has(key)) {
  636. return null;
  637. }
  638. // Process load data
  639. var promise = loadData(treeNode);
  640. promise.then(function () {
  641. var newLoadedKeys = arrAdd(loadedKeys.value, key);
  642. var newLoadingKeys = arrDel(loadingKeys.value, key);
  643. // onLoad should trigger before internal setState to avoid `loadData` trigger twice.
  644. // https://github.com/ant-design/ant-design/issues/12464
  645. if (onLoad) {
  646. onLoad(newLoadedKeys, {
  647. event: 'load',
  648. node: treeNode
  649. });
  650. }
  651. if (props.loadedKeys === undefined) {
  652. loadedKeys.value = newLoadedKeys;
  653. }
  654. loadingKeys.value = newLoadingKeys;
  655. resolve();
  656. }).catch(function (e) {
  657. var newLoadingKeys = arrDel(loadingKeys.value, key);
  658. loadingKeys.value = newLoadingKeys;
  659. // If exceed max retry times, we give up retry
  660. loadingRetryTimes[key] = (loadingRetryTimes[key] || 0) + 1;
  661. if (loadingRetryTimes[key] >= MAX_RETRY_TIMES) {
  662. warning(false, 'Retry for `loadData` many times but still failed. No more retry.');
  663. var newLoadedKeys = arrAdd(loadedKeys.value, key);
  664. if (props.loadedKeys === undefined) {
  665. loadedKeys.value = newLoadedKeys;
  666. }
  667. resolve();
  668. }
  669. reject(e);
  670. });
  671. loadingKeys.value = arrAdd(loadingKeys.value, key);
  672. });
  673. // Not care warning if we ignore this
  674. loadPromise.catch(function () {});
  675. return loadPromise;
  676. };
  677. var onNodeMouseEnter = function onNodeMouseEnter(event, node) {
  678. var onMouseenter = props.onMouseenter;
  679. if (onMouseenter) {
  680. onMouseenter({
  681. event: event,
  682. node: node
  683. });
  684. }
  685. };
  686. var onNodeMouseLeave = function onNodeMouseLeave(event, node) {
  687. var onMouseleave = props.onMouseleave;
  688. if (onMouseleave) {
  689. onMouseleave({
  690. event: event,
  691. node: node
  692. });
  693. }
  694. };
  695. var onNodeContextMenu = function onNodeContextMenu(event, node) {
  696. var onRightClick = props.onRightClick;
  697. if (onRightClick) {
  698. event.preventDefault();
  699. onRightClick({
  700. event: event,
  701. node: node
  702. });
  703. }
  704. };
  705. var onFocus = function onFocus(e) {
  706. var onFocus = props.onFocus;
  707. focused.value = true;
  708. if (onFocus) {
  709. onFocus(e);
  710. }
  711. };
  712. var onBlur = function onBlur(e) {
  713. var onBlur = props.onBlur;
  714. focused.value = false;
  715. onActiveChange(null);
  716. if (onBlur) {
  717. onBlur(e);
  718. }
  719. };
  720. var onNodeExpand = function onNodeExpand(e, treeNode) {
  721. var newExpandedKeys = expandedKeys.value;
  722. var onExpand = props.onExpand,
  723. loadData = props.loadData;
  724. var expanded = treeNode.expanded;
  725. var key = treeNode[fieldNames.value.key];
  726. // Do nothing when motion is in progress
  727. if (listChanging.value) {
  728. return;
  729. }
  730. // Update selected keys
  731. var index = newExpandedKeys.indexOf(key);
  732. var targetExpanded = !expanded;
  733. warning(expanded && index !== -1 || !expanded && index === -1, 'Expand state not sync with index check');
  734. if (targetExpanded) {
  735. newExpandedKeys = arrAdd(newExpandedKeys, key);
  736. } else {
  737. newExpandedKeys = arrDel(newExpandedKeys, key);
  738. }
  739. setExpandedKeys(newExpandedKeys);
  740. if (onExpand) {
  741. onExpand(newExpandedKeys, {
  742. node: treeNode,
  743. expanded: targetExpanded,
  744. nativeEvent: e
  745. });
  746. }
  747. // Async Load data
  748. if (targetExpanded && loadData) {
  749. var loadPromise = onNodeLoad(treeNode);
  750. if (loadPromise) {
  751. loadPromise.then(function () {
  752. // [Legacy] Refresh logic
  753. // const newFlattenTreeData = flattenTreeData(
  754. // treeData.value,
  755. // newExpandedKeys,
  756. // fieldNames.value,
  757. // );
  758. // flattenNodes.value = newFlattenTreeData;
  759. }).catch(function (e) {
  760. var expandedKeysToRestore = arrDel(expandedKeys.value, key);
  761. setExpandedKeys(expandedKeysToRestore);
  762. Promise.reject(e);
  763. });
  764. }
  765. }
  766. };
  767. var onListChangeStart = function onListChangeStart() {
  768. listChanging.value = true;
  769. };
  770. var onListChangeEnd = function onListChangeEnd() {
  771. setTimeout(function () {
  772. listChanging.value = false;
  773. });
  774. };
  775. // =========================== Keyboard ===========================
  776. var onActiveChange = function onActiveChange(newActiveKey) {
  777. var onActiveChange = props.onActiveChange;
  778. if (activeKey.value === newActiveKey) {
  779. return;
  780. }
  781. if (props.activeKey !== undefined) {
  782. activeKey.value = newActiveKey;
  783. }
  784. if (newActiveKey !== null) {
  785. scrollTo({
  786. key: newActiveKey
  787. });
  788. }
  789. if (onActiveChange) {
  790. onActiveChange(newActiveKey);
  791. }
  792. };
  793. var activeItem = computed(function () {
  794. if (activeKey.value === null) {
  795. return null;
  796. }
  797. return flattenNodes.value.find(function (_ref6) {
  798. var key = _ref6.key;
  799. return key === activeKey.value;
  800. }) || null;
  801. });
  802. var offsetActiveKey = function offsetActiveKey(offset) {
  803. var index = flattenNodes.value.findIndex(function (_ref7) {
  804. var key = _ref7.key;
  805. return key === activeKey.value;
  806. });
  807. // Align with index
  808. if (index === -1 && offset < 0) {
  809. index = flattenNodes.value.length;
  810. }
  811. index = (index + offset + flattenNodes.value.length) % flattenNodes.value.length;
  812. var item = flattenNodes.value[index];
  813. if (item) {
  814. var key = item.key;
  815. onActiveChange(key);
  816. } else {
  817. onActiveChange(null);
  818. }
  819. };
  820. var activeItemEventNode = computed(function () {
  821. return convertNodePropsToEventData(_objectSpread(_objectSpread({}, getTreeNodeProps(activeKey.value, treeNodeRequiredProps.value)), {}, {
  822. data: activeItem.value.data,
  823. active: true
  824. }));
  825. });
  826. var onKeydown = function onKeydown(event) {
  827. var onKeydown = props.onKeydown,
  828. checkable = props.checkable,
  829. selectable = props.selectable;
  830. // >>>>>>>>>> Direction
  831. switch (event.which) {
  832. case KeyCode.UP:
  833. {
  834. offsetActiveKey(-1);
  835. event.preventDefault();
  836. break;
  837. }
  838. case KeyCode.DOWN:
  839. {
  840. offsetActiveKey(1);
  841. event.preventDefault();
  842. break;
  843. }
  844. }
  845. // >>>>>>>>>> Expand & Selection
  846. var item = activeItem.value;
  847. if (item && item.data) {
  848. var expandable = item.data.isLeaf === false || !!(item.data.children || []).length;
  849. var eventNode = activeItemEventNode.value;
  850. switch (event.which) {
  851. // >>> Expand
  852. case KeyCode.LEFT:
  853. {
  854. // Collapse if possible
  855. if (expandable && expandedKeysSet.value.has(activeKey.value)) {
  856. onNodeExpand({}, eventNode);
  857. } else if (item.parent) {
  858. onActiveChange(item.parent.key);
  859. }
  860. event.preventDefault();
  861. break;
  862. }
  863. case KeyCode.RIGHT:
  864. {
  865. // Expand if possible
  866. if (expandable && !expandedKeysSet.value.has(activeKey.value)) {
  867. onNodeExpand({}, eventNode);
  868. } else if (item.children && item.children.length) {
  869. onActiveChange(item.children[0].key);
  870. }
  871. event.preventDefault();
  872. break;
  873. }
  874. // Selection
  875. case KeyCode.ENTER:
  876. case KeyCode.SPACE:
  877. {
  878. if (checkable && !eventNode.disabled && eventNode.checkable !== false && !eventNode.disableCheckbox) {
  879. onNodeCheck({}, eventNode, !checkedKeysSet.value.has(activeKey.value));
  880. } else if (!checkable && selectable && !eventNode.disabled && eventNode.selectable !== false) {
  881. onNodeSelect({}, eventNode);
  882. }
  883. break;
  884. }
  885. }
  886. }
  887. if (onKeydown) {
  888. onKeydown(event);
  889. }
  890. };
  891. expose({
  892. onNodeExpand: onNodeExpand,
  893. scrollTo: scrollTo,
  894. onKeydown: onKeydown,
  895. selectedKeys: computed(function () {
  896. return selectedKeys.value;
  897. }),
  898. checkedKeys: computed(function () {
  899. return checkedKeys.value;
  900. }),
  901. halfCheckedKeys: computed(function () {
  902. return halfCheckedKeys.value;
  903. }),
  904. loadedKeys: computed(function () {
  905. return loadedKeys.value;
  906. }),
  907. loadingKeys: computed(function () {
  908. return loadingKeys.value;
  909. }),
  910. expandedKeys: computed(function () {
  911. return expandedKeys.value;
  912. })
  913. });
  914. onUnmounted(function () {
  915. window.removeEventListener('dragend', onWindowDragEnd);
  916. destroyed.value = true;
  917. });
  918. useProvideKeysState({
  919. expandedKeys: expandedKeys,
  920. selectedKeys: selectedKeys,
  921. loadedKeys: loadedKeys,
  922. loadingKeys: loadingKeys,
  923. checkedKeys: checkedKeys,
  924. halfCheckedKeys: halfCheckedKeys,
  925. expandedKeysSet: expandedKeysSet,
  926. selectedKeysSet: selectedKeysSet,
  927. loadedKeysSet: loadedKeysSet,
  928. loadingKeysSet: loadingKeysSet,
  929. checkedKeysSet: checkedKeysSet,
  930. halfCheckedKeysSet: halfCheckedKeysSet,
  931. flattenNodes: flattenNodes
  932. });
  933. return function () {
  934. var _classNames;
  935. var draggingNodeKey = dragState.draggingNodeKey,
  936. dropLevelOffset = dragState.dropLevelOffset,
  937. dropContainerKey = dragState.dropContainerKey,
  938. dropTargetKey = dragState.dropTargetKey,
  939. dropPosition = dragState.dropPosition,
  940. dragOverNodeKey = dragState.dragOverNodeKey;
  941. var prefixCls = props.prefixCls,
  942. showLine = props.showLine,
  943. focusable = props.focusable,
  944. _props$tabindex = props.tabindex,
  945. tabindex = _props$tabindex === void 0 ? 0 : _props$tabindex,
  946. selectable = props.selectable,
  947. showIcon = props.showIcon,
  948. _props$icon = props.icon,
  949. icon = _props$icon === void 0 ? slots.icon : _props$icon,
  950. switcherIcon = props.switcherIcon,
  951. draggable = props.draggable,
  952. checkable = props.checkable,
  953. checkStrictly = props.checkStrictly,
  954. disabled = props.disabled,
  955. motion = props.motion,
  956. loadData = props.loadData,
  957. filterTreeNode = props.filterTreeNode,
  958. height = props.height,
  959. itemHeight = props.itemHeight,
  960. virtual = props.virtual,
  961. dropIndicatorRender = props.dropIndicatorRender,
  962. onContextmenu = props.onContextmenu,
  963. onScroll = props.onScroll,
  964. direction = props.direction;
  965. var className = attrs.class,
  966. style = attrs.style;
  967. var domProps = pickAttrs(_objectSpread(_objectSpread({}, props), attrs), {
  968. aria: true,
  969. data: true
  970. });
  971. // It's better move to hooks but we just simply keep here
  972. var draggableConfig;
  973. if (draggable) {
  974. if (_typeof(draggable) === 'object') {
  975. draggableConfig = draggable;
  976. } else if (typeof draggable === 'function') {
  977. draggableConfig = {
  978. nodeDraggable: draggable
  979. };
  980. } else {
  981. draggableConfig = {};
  982. }
  983. }
  984. return _createVNode(TreeContext, {
  985. "value": {
  986. prefixCls: prefixCls,
  987. selectable: selectable,
  988. showIcon: showIcon,
  989. icon: icon,
  990. switcherIcon: switcherIcon,
  991. draggable: draggableConfig,
  992. draggingNodeKey: draggingNodeKey,
  993. checkable: checkable,
  994. customCheckable: slots.checkable,
  995. checkStrictly: checkStrictly,
  996. disabled: disabled,
  997. keyEntities: keyEntities.value,
  998. dropLevelOffset: dropLevelOffset,
  999. dropContainerKey: dropContainerKey,
  1000. dropTargetKey: dropTargetKey,
  1001. dropPosition: dropPosition,
  1002. dragOverNodeKey: dragOverNodeKey,
  1003. dragging: draggingNodeKey !== null,
  1004. indent: indent.value,
  1005. direction: direction,
  1006. dropIndicatorRender: dropIndicatorRender,
  1007. loadData: loadData,
  1008. filterTreeNode: filterTreeNode,
  1009. onNodeClick: onNodeClick,
  1010. onNodeDoubleClick: onNodeDoubleClick,
  1011. onNodeExpand: onNodeExpand,
  1012. onNodeSelect: onNodeSelect,
  1013. onNodeCheck: onNodeCheck,
  1014. onNodeLoad: onNodeLoad,
  1015. onNodeMouseEnter: onNodeMouseEnter,
  1016. onNodeMouseLeave: onNodeMouseLeave,
  1017. onNodeContextMenu: onNodeContextMenu,
  1018. onNodeDragStart: onNodeDragStart,
  1019. onNodeDragEnter: onNodeDragEnter,
  1020. onNodeDragOver: onNodeDragOver,
  1021. onNodeDragLeave: onNodeDragLeave,
  1022. onNodeDragEnd: onNodeDragEnd,
  1023. onNodeDrop: onNodeDrop,
  1024. slots: slots
  1025. }
  1026. }, {
  1027. default: function _default() {
  1028. return [_createVNode("div", {
  1029. "role": "tree",
  1030. "class": classNames(prefixCls, className, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-show-line"), showLine), _defineProperty(_classNames, "".concat(prefixCls, "-focused"), focused.value), _defineProperty(_classNames, "".concat(prefixCls, "-active-focused"), activeKey.value !== null), _classNames))
  1031. }, [_createVNode(NodeList, _objectSpread({
  1032. "ref": listRef,
  1033. "prefixCls": prefixCls,
  1034. "style": style,
  1035. "disabled": disabled,
  1036. "selectable": selectable,
  1037. "checkable": !!checkable,
  1038. "motion": motion,
  1039. "height": height,
  1040. "itemHeight": itemHeight,
  1041. "virtual": virtual,
  1042. "focusable": focusable,
  1043. "focused": focused.value,
  1044. "tabindex": tabindex,
  1045. "activeItem": activeItem.value,
  1046. "onFocus": onFocus,
  1047. "onBlur": onBlur,
  1048. "onKeydown": onKeydown,
  1049. "onActiveChange": onActiveChange,
  1050. "onListChangeStart": onListChangeStart,
  1051. "onListChangeEnd": onListChangeEnd,
  1052. "onContextmenu": onContextmenu,
  1053. "onScroll": onScroll
  1054. }, domProps), null)])];
  1055. }
  1056. });
  1057. };
  1058. }
  1059. });