75743d7011097cc6a5d7a9b7005dd16f8bec7f7e5444fa052e34c289fb00e718684e7f2d7cc4804699941a3447ff68301ae7a9ad52a897111582edfc7ee4db 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { ref, provide } from 'vue';
  2. import { useNamespace } from '../../../../hooks/use-namespace/index.mjs';
  3. import { isFunction } from '@vue/shared';
  4. import { removeClass, addClass } from '../../../../utils/dom/style.mjs';
  5. const dragEventsKey = Symbol("dragEvents");
  6. function useDragNodeHandler({
  7. props,
  8. ctx,
  9. el$,
  10. dropIndicator$,
  11. store
  12. }) {
  13. const ns = useNamespace("tree");
  14. const dragState = ref({
  15. showDropIndicator: false,
  16. draggingNode: null,
  17. dropNode: null,
  18. allowDrop: true,
  19. dropType: null
  20. });
  21. const treeNodeDragStart = ({ event, treeNode }) => {
  22. if (!event.dataTransfer)
  23. return;
  24. if (isFunction(props.allowDrag) && !props.allowDrag(treeNode.node)) {
  25. event.preventDefault();
  26. return false;
  27. }
  28. event.dataTransfer.effectAllowed = "move";
  29. try {
  30. event.dataTransfer.setData("text/plain", "");
  31. } catch (e) {
  32. }
  33. dragState.value.draggingNode = treeNode;
  34. ctx.emit("node-drag-start", treeNode.node, event);
  35. };
  36. const treeNodeDragOver = ({ event, treeNode }) => {
  37. if (!event.dataTransfer)
  38. return;
  39. const dropNode = treeNode;
  40. const oldDropNode = dragState.value.dropNode;
  41. if (oldDropNode && oldDropNode.node.id !== dropNode.node.id) {
  42. removeClass(oldDropNode.$el, ns.is("drop-inner"));
  43. }
  44. const draggingNode = dragState.value.draggingNode;
  45. if (!draggingNode || !dropNode)
  46. return;
  47. let dropPrev = true;
  48. let dropInner = true;
  49. let dropNext = true;
  50. let userAllowDropInner = true;
  51. if (isFunction(props.allowDrop)) {
  52. dropPrev = props.allowDrop(draggingNode.node, dropNode.node, "prev");
  53. userAllowDropInner = dropInner = props.allowDrop(draggingNode.node, dropNode.node, "inner");
  54. dropNext = props.allowDrop(draggingNode.node, dropNode.node, "next");
  55. }
  56. event.dataTransfer.dropEffect = dropInner || dropPrev || dropNext ? "move" : "none";
  57. if ((dropPrev || dropInner || dropNext) && (oldDropNode == null ? void 0 : oldDropNode.node.id) !== dropNode.node.id) {
  58. if (oldDropNode) {
  59. ctx.emit("node-drag-leave", draggingNode.node, oldDropNode.node, event);
  60. }
  61. ctx.emit("node-drag-enter", draggingNode.node, dropNode.node, event);
  62. }
  63. if (dropPrev || dropInner || dropNext) {
  64. dragState.value.dropNode = dropNode;
  65. } else {
  66. dragState.value.dropNode = null;
  67. }
  68. if (dropNode.node.nextSibling === draggingNode.node) {
  69. dropNext = false;
  70. }
  71. if (dropNode.node.previousSibling === draggingNode.node) {
  72. dropPrev = false;
  73. }
  74. if (dropNode.node.contains(draggingNode.node, false)) {
  75. dropInner = false;
  76. }
  77. if (draggingNode.node === dropNode.node || draggingNode.node.contains(dropNode.node)) {
  78. dropPrev = false;
  79. dropInner = false;
  80. dropNext = false;
  81. }
  82. const dropEl = dropNode.$el;
  83. const targetPosition = dropEl.querySelector(`.${ns.be("node", "content")}`).getBoundingClientRect();
  84. const treePosition = el$.value.getBoundingClientRect();
  85. let dropType;
  86. const prevPercent = dropPrev ? dropInner ? 0.25 : dropNext ? 0.45 : 1 : Number.NEGATIVE_INFINITY;
  87. const nextPercent = dropNext ? dropInner ? 0.75 : dropPrev ? 0.55 : 0 : Number.POSITIVE_INFINITY;
  88. let indicatorTop = -9999;
  89. const distance = event.clientY - targetPosition.top;
  90. if (distance < targetPosition.height * prevPercent) {
  91. dropType = "before";
  92. } else if (distance > targetPosition.height * nextPercent) {
  93. dropType = "after";
  94. } else if (dropInner) {
  95. dropType = "inner";
  96. } else {
  97. dropType = "none";
  98. }
  99. const iconPosition = dropEl.querySelector(`.${ns.be("node", "expand-icon")}`).getBoundingClientRect();
  100. const dropIndicator = dropIndicator$.value;
  101. if (dropType === "before") {
  102. indicatorTop = iconPosition.top - treePosition.top;
  103. } else if (dropType === "after") {
  104. indicatorTop = iconPosition.bottom - treePosition.top;
  105. }
  106. dropIndicator.style.top = `${indicatorTop}px`;
  107. dropIndicator.style.left = `${iconPosition.right - treePosition.left}px`;
  108. if (dropType === "inner") {
  109. addClass(dropEl, ns.is("drop-inner"));
  110. } else {
  111. removeClass(dropEl, ns.is("drop-inner"));
  112. }
  113. dragState.value.showDropIndicator = dropType === "before" || dropType === "after";
  114. dragState.value.allowDrop = dragState.value.showDropIndicator || userAllowDropInner;
  115. dragState.value.dropType = dropType;
  116. ctx.emit("node-drag-over", draggingNode.node, dropNode.node, event);
  117. };
  118. const treeNodeDragEnd = (event) => {
  119. var _a, _b;
  120. const { draggingNode, dropType, dropNode } = dragState.value;
  121. event.preventDefault();
  122. if (event.dataTransfer) {
  123. event.dataTransfer.dropEffect = "move";
  124. }
  125. if ((draggingNode == null ? void 0 : draggingNode.node.data) && dropNode) {
  126. const draggingNodeCopy = { data: draggingNode.node.data };
  127. if (dropType !== "none") {
  128. draggingNode.node.remove();
  129. }
  130. if (dropType === "before") {
  131. (_a = dropNode.node.parent) == null ? void 0 : _a.insertBefore(draggingNodeCopy, dropNode.node);
  132. } else if (dropType === "after") {
  133. (_b = dropNode.node.parent) == null ? void 0 : _b.insertAfter(draggingNodeCopy, dropNode.node);
  134. } else if (dropType === "inner") {
  135. dropNode.node.insertChild(draggingNodeCopy);
  136. }
  137. if (dropType !== "none") {
  138. store.value.registerNode(draggingNodeCopy);
  139. if (store.value.key) {
  140. draggingNode.node.eachNode((node) => {
  141. var _a2;
  142. (_a2 = store.value.nodesMap[node.data[store.value.key]]) == null ? void 0 : _a2.setChecked(node.checked, !store.value.checkStrictly);
  143. });
  144. }
  145. }
  146. removeClass(dropNode.$el, ns.is("drop-inner"));
  147. ctx.emit("node-drag-end", draggingNode.node, dropNode.node, dropType, event);
  148. if (dropType !== "none") {
  149. ctx.emit("node-drop", draggingNode.node, dropNode.node, dropType, event);
  150. }
  151. }
  152. if (draggingNode && !dropNode) {
  153. ctx.emit("node-drag-end", draggingNode.node, null, dropType, event);
  154. }
  155. dragState.value.showDropIndicator = false;
  156. dragState.value.draggingNode = null;
  157. dragState.value.dropNode = null;
  158. dragState.value.allowDrop = true;
  159. };
  160. provide(dragEventsKey, {
  161. treeNodeDragStart,
  162. treeNodeDragOver,
  163. treeNodeDragEnd
  164. });
  165. return {
  166. dragState
  167. };
  168. }
  169. export { dragEventsKey, useDragNodeHandler };
  170. //# sourceMappingURL=useDragNode.mjs.map