UNPKG

@neodrag/solid

Version:

SolidJS library to add dragging to your apps 😉

1 lines • 5.07 kB
import{onCleanup as t,createEffect as e}from"solid-js";var n={dragStart:!0},r={delay:0,distance:3};function o(t,e={}){let o,f,{bounds:g,axis:h="both",gpuAcceleration:p=!0,legacyTranslate:m=!1,transform:y,applyUserSelectHack:w=!0,disabled:b=!1,ignoreMultitouch:v=!1,recomputeBounds:x=n,grid:E,threshold:S=r,position:A,cancel:C,handle:D,defaultClass:N="neodrag",defaultClassDragging:M="neodrag-dragging",defaultClassDragged:B="neodrag-dragged",defaultPosition:R={x:0,y:0},onDragStart:$,onDrag:X,onDragEnd:Y}=e,q=!1,H=!1,P=0,T=!1,k=!1,L=0,j=0,z=0,I=0,U=0,W=0,{x:F,y:G}=A?{x:A?.x??0,y:A?.y??0}:R;ot(F,G);let J,K,O,Q,V,Z="",_=!!A;x={...n,...x},S={...r,...S??{}};let tt=new Set;function et(t){q&&!H&&k&&T&&V&&(H=!0,function(t){at("neodrag:start",$,t)}(t),rt.add(M),w&&(Z=nt.userSelect,nt.userSelect="none"))}const nt=document.body.style,rt=t.classList;function ot(e=L,n=j){if(!y){if(m){let r=`${+e}px, ${+n}px`;return c(t,"transform",p?`translate3d(${r}, 0)`:`translate(${r})`)}return c(t,"translate",`${+e}px ${+n}px`)}const r=y({offsetX:e,offsetY:n,rootNode:t});i(r)&&c(t,"transform",r)}function at(e,n,r){const o=function(e){return{offsetX:L,offsetY:j,rootNode:t,currentNode:V,event:e}}(r);t.dispatchEvent(new CustomEvent(e,{detail:o})),n?.(o)}const it=addEventListener,st=new AbortController,dt={signal:st.signal,capture:!1};function lt(){let e=t.offsetWidth/K.width;return isNaN(e)&&(e=1),e}return c(t,"touch-action","none"),it("pointerdown",(e=>{if(b)return;if(2===e.button)return;if(tt.add(e.pointerId),v&&tt.size>1)return e.preventDefault();if(x.dragStart&&(J=l(g,t)),i(D)&&i(C)&&D===C)throw new Error("`handle` selector can't be same as `cancel` selector");if(rt.add(N),O=function(t,e){if(!t)return[e];if(u(t))return[t];if(Array.isArray(t))return t;const n=e.querySelectorAll(t);if(null===n)throw new Error("Selector passed for `handle` option should be child of the element on which the action is applied");return Array.from(n.values())}(D,t),Q=function(t,e){if(!t)return[];if(u(t))return[t];if(Array.isArray(t))return t;const n=e.querySelectorAll(t);if(null===n)throw new Error("Selector passed for `cancel` option should be child of the element on which the action is applied");return Array.from(n.values())}(C,t),o=/(both|x)/.test(h),f=/(both|y)/.test(h),d(Q,O))throw new Error("Element being dragged can't be a child of the element on which `cancel` is applied");const n=e.composedPath()[0];if(!O.some((t=>t.contains(n)||t.shadowRoot?.contains(n)))||d(Q,[n]))return;V=1===O.length?t:O.find((t=>t.contains(n))),q=!0,P=Date.now(),S.delay||(T=!0),K=t.getBoundingClientRect();const{clientX:r,clientY:a}=e,s=lt();o&&(z=r-F/s),f&&(I=a-G/s),J&&(U=r-K.left,W=a-K.top)}),dt),it("pointermove",(e=>{if(!q||v&&tt.size>1)return;if(!H){if(!T){Date.now()-P>=S.delay&&(T=!0,et(e))}if(!k){const t=e.clientX-z,n=e.clientY-I;Math.sqrt(t**2+n**2)>=S.distance&&(k=!0,et(e))}if(!H)return}x.drag&&(J=l(g,t)),e.preventDefault(),K=t.getBoundingClientRect();let n=e.clientX,r=e.clientY;const i=lt();if(J){const t={left:J.left+U,top:J.top+W,right:J.right+U-K.width,bottom:J.bottom+W-K.height};n=a(n,t.left,t.right),r=a(r,t.top,t.bottom)}if(Array.isArray(E)){let[t,e]=E;if(isNaN(+t)||t<0)throw new Error("1st argument of `grid` must be a valid positive number");if(isNaN(+e)||e<0)throw new Error("2nd argument of `grid` must be a valid positive number");let o=n-z,a=r-I;[o,a]=s([t/i,e/i],o,a),n=z+o,r=I+a}o&&(L=Math.round((n-z)*i)),f&&(j=Math.round((r-I)*i)),F=L,G=j,at("neodrag",X,e),ot()}),dt),it("pointerup",(e=>{(tt.delete(e.pointerId),q)&&(H&&(it("click",(t=>t.stopPropagation()),{once:!0,signal:st.signal,capture:!0}),x.dragEnd&&(J=l(g,t)),rt.remove(M),rt.add(B),w&&(nt.userSelect=Z),at("neodrag:end",Y,e),o&&(z=L),f&&(I=j)),q=!1,H=!1,T=!1,k=!1)}),dt),{destroy:()=>st.abort(),update:t=>{h=t.axis||"both",b=t.disabled??!1,v=t.ignoreMultitouch??!1,D=t.handle,g=t.bounds,x=t.recomputeBounds??n,C=t.cancel,w=t.applyUserSelectHack??!0,E=t.grid,p=t.gpuAcceleration??!0,m=t.legacyTranslate??!1,y=t.transform,S={...r,...t.threshold??{}};const e=rt.contains(B);rt.remove(N,B),N=t.defaultClass??"neodrag",M=t.defaultClassDragging??"neodrag-dragging",B=t.defaultClassDragged??"neodrag-dragged",rt.add(N),e&&rt.add(B),_&&(F=L=t.position?.x??L,G=j=t.position?.y??j,ot())}}}var a=(t,e,n)=>Math.min(Math.max(t,e),n),i=t=>"string"==typeof t,s=([t,e],n,r)=>{const o=(t,e)=>0===e?0:Math.ceil(t/e)*e;return[o(n,t),o(r,e)]};var d=(t,e)=>t.some((t=>e.some((e=>t.contains(e)))));function l(t,e){if(void 0===t)return;if(u(t))return t.getBoundingClientRect();if("object"==typeof t){const{top:e=0,left:n=0,right:r=0,bottom:o=0}=t;return{top:e,right:window.innerWidth-r,bottom:window.innerHeight-o,left:n}}if("parent"===t)return e.parentNode.getBoundingClientRect();const n=document.querySelector(t);if(null===n)throw new Error("The selector provided for bound doesn't exists in the document.");return n.getBoundingClientRect()}var c=(t,e,n)=>t.style.setProperty(e,n),u=t=>t instanceof HTMLElement,f=()=>({draggable:(n,r)=>{const{update:a,destroy:i}=o(n,r());t(i),e((()=>a(r())))}});export{f as createDraggable};