UNPKG

vue3-drag-directive

Version:

🪶 Lightweight Vue3 drag directive

2 lines (1 loc) 6.4 kB
const t=function(){let t="dragging";class e{dom;durationTime;firstPosition;lastPosition;isPlaying;constructor(t,e=.5){this.dom=t,this.durationTime="number"==typeof e?e+"s":e,this.firstPosition=this.getDomPosition(),this.lastPosition={x:0,y:0},this.isPlaying=!1}getDomPosition(){const t=this.dom.getBoundingClientRect();return{x:t.left,y:t.top}}recordFirst(){const t=this.getDomPosition();this.firstPosition.x=t.x,this.firstPosition.y=t.y}recordLast(){const t=this.getDomPosition();this.lastPosition.x=t.x,this.lastPosition.y=t.y}invert(){const e=this.firstPosition.x-this.lastPosition.x,n=this.firstPosition.y-this.lastPosition.y;return(0!==e||0!==n)&&(this.dom.style.transition="none",this.dom.style.transform=`translate(${e}px, ${n}px)`,this.dom.classList.contains(t)||(this.dom.style.pointerEvents="none"),!0)}play(){return new Promise((t=>{if(this.isPlaying)return void t();let e;this.isPlaying=!0;let n=!1;if(this.recordLast(),!1===this.invert())return this.reset(),void t();var i;i=()=>{this.dom.style.transition="transform "+this.durationTime,this.dom.style.transform="none";const i=()=>{n||(n=!0,clearTimeout(e),this.reset(),this.recordFirst(),t())};this.dom.addEventListener("transitionend",i,{once:!0}),e=setTimeout(i,1e3*parseFloat(this.durationTime)+50)},requestAnimationFrame((()=>{requestAnimationFrame(i)}))}))}reset(){this.dom.style.pointerEvents="",this.dom.style.transition="",this.dom.style.transform="",this.isPlaying=!1}}return class{flipDoms;isAnimating;constructor(n,i=.5,r){this.flipDoms=new Set([...n].map((t=>new e(t,i)))),r&&(t=r),this.isAnimating=!1}async play(){this.isAnimating=!0;const t=[...this.flipDoms].map((t=>t.play()));await Promise.all(t),this.isAnimating=!1}}}(),e=(t,n)=>{if(Object.is(t,n))return!0;if(t instanceof Date&&n instanceof Date)return t.getTime()===n.getTime();if(t instanceof RegExp&&n instanceof RegExp)return""+t==""+n;if("object"!=typeof t||null===t||"object"!=typeof n||null===n)return!1;const i=Reflect.ownKeys(t),r=Reflect.ownKeys(n);if(i.length!==r.length)return!1;for(let r=0;i.length>r;r++){if(!Reflect.has(n,i[r]))return!1;if(!e(t[i[r]],n[i[r]]))return!1}return!0},n="vue-drag-list-directive__dragging",i={count:0,preventDefault(t){t.preventDefault()},add(){0===this.count&&(window.addEventListener("dragenter",this.preventDefault,!1),window.addEventListener("dragover",this.preventDefault,!1),window.addEventListener("dragend",this.preventDefault,!1)),this.count++},remove(){this.count--,0===this.count&&(window.removeEventListener("dragenter",this.preventDefault),window.removeEventListener("dragover",this.preventDefault),window.removeEventListener("dragend",this.preventDefault))}};let r=null;const s={mounted(t,e){!function(){const t=`\n /* 被拖拽元素的样式 */\n .${n} {\n opacity: 0;\n background-color: transparent;\n } \n `;if(document.getElementById("drag-list-styles"))return;const e=document.createElement("style");e.id="drag-list-styles",e.textContent=t,document.head.appendChild(e)}();const{list:i,canDrag:r=!0,dragItemClass:s="app-item",dragHandleClass:o}=e.value;r&&(l(t,!0),d(t),a(t,i,s,o))},async updated(t,n){if(t._isDragging)return;d(t);const{list:i,canDrag:r,dragItemClass:s="app-item",dragHandleClass:c}=n.value;e(n.value,n.oldValue)||(o(t),r?(l(t,!0),a(t,i,s,c)):l(t,!1))},unmounted(t){o(t)}};function a(e,s,a,o){e.currentDragNode=null;const d=e;let l;d._isDragAllowed=!1;const c=`drag-list-${Date.now()}-${Math.floor(1e3*Math.random())}`;function f(i){const s=i.target;if(!u(i,c))return;if(function(t,e){return!1===t&&g(e)}(e._isDragAllowed,o))return void i.preventDefault();!function(){const t=window.getSelection&&window.getSelection();t&&t.removeAllRanges&&t.removeAllRanges()}(),e.dispatchEvent(new CustomEvent("drag-mode-start",{detail:{isDragging:!0}})),r=c,e._isDragging=!0,l=new t(e.children,.5,n);const d=s.closest("."+a);setTimeout((()=>{e._isDragging&&d.classList.add(n)})),i.dataTransfer.effectAllowed="move",e.currentDragNode=d}function m(t){if(D(t),function(t){return r&&r!==t}(c))return;const n=t.target.closest("."+a);if(!n||n===e.currentDragNode||n===e)return;const i=Array.from(e.children),s=i.indexOf(e.currentDragNode),o=i.indexOf(n);d.insertBefore(e.currentDragNode,o>s?n.nextElementSibling:n),l.play()}function h(t){if(D(t),e.currentDragNode){e.currentDragNode.classList.remove(n);const t=Array.from(e.children).filter((t=>!!t&&!!t.dataset&&!!t.dataset.id)).map((t=>s.find((e=>e.id+""==t.dataset.id+"")))).filter((t=>!!t));e.dispatchEvent(new CustomEvent("drag-mode-end",{detail:{updatedData:t,draggedItemData:t.find((t=>t.id===e.currentDragNode.dataset.id))||null}}))}e._isDragging=!1,e._actualClickTarget=null,e._isDragAllowed=!1}function v(t){if(u(t,c)&&(e._actualClickTarget=t.target,g(o)&&!function(t,e,n){const i=t&&t.closest("."+n);return t===e||!i}(t.target,e,a))){const n=function(t,e){return null!==t.closest("."+e)}(t.target,o);e._isDragAllowed=n}}function D(t){t.preventDefault()}e.dataset.dragListId=c,e.addEventListener("dragstart",f),e.addEventListener("dragenter",m),e.addEventListener("dragend",h),e.addEventListener("dragover",D),e.addEventListener("drop",D),e.addEventListener("mousedown",v),i.add(),e._dragListHandlers={handleDragStart:f,handleDragEnter:m,handleDragEnd:h,preventDefault:D,handleMouseDown:v}}function o(t){if(!t._dragListHandlers||t._isDragging)return;const{handleDragStart:e,handleDragEnter:n,handleDragEnd:r,preventDefault:s,handleMouseDown:a}=t._dragListHandlers;a&&t.removeEventListener("mousedown",a),t.removeEventListener("dragstart",e),t.removeEventListener("dragenter",n),t.removeEventListener("dragend",r),t.removeEventListener("dragover",s),t.removeEventListener("drop",s),i.remove(),d(t),l(t,!1),t._isDragging=!1,delete t._dragListHandlers,delete t._actualClickTarget,delete t._isDragAllowed}function d(t){t.children&&Array.from(t.children).forEach((t=>{t.classList&&t.classList.contains(n)&&t.classList.remove(n)}))}function l(t,e){t&&t.children&&Array.from(t.children).forEach((t=>{t.hasAttribute("data-id")&&(e?t.setAttribute("draggable","true"):t.removeAttribute("draggable"))}))}function c(t){t.directive("drag-list",s)}function g(t){return void 0!==t}function u(t,e){if(!t.target)return!1;const n=t.target.closest("[data-drag-list-id]");return!!n&&n.dataset.dragListId===e}const f={install(t,e={}){t.directive(e.name||"drag-list",s)}};export{f as default,s as dragListDirective,c as registerDragList,s as vDragList};