UNPKG

splitpanes-ts

Version:

TypeScript version of A Vue.js reliable, simple and touch-ready panes splitter / resizer

2 lines (1 loc) 10.3 kB
(function(x,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],l):(x=typeof globalThis<"u"?globalThis:x||self,l(x.splitpanes={},x.Vue))})(this,function(x,l){"use strict";const T=l.defineComponent({__name:"splitpanes",props:{horizontal:{type:Boolean,default:!1},pushOtherPanes:{type:Boolean,default:!0},maximizePanes:{type:Boolean,default:!0},rtl:{type:Boolean,default:!1},firstSplitter:{type:Boolean,default:!1}},emits:["ready","resize","resized","pane-click","pane-maximize","pane-add","pane-remove","splitter-click","splitter-dblclick"],setup(B,{emit:S}){const M=S,u=B,o=l.ref([]),w=l.computed(()=>o.value.reduce((e,n)=>(e[n.id]=n,e),{})),h=l.computed(()=>o.value.length),m=l.ref(null),P=l.ref(!1),d=l.ref({mouseDown:!1,dragging:!1,activeSplitter:null,cursorOffset:0}),z=l.ref({splitter:null,timeoutId:null}),k=l.computed(()=>({[`splitpanes splitpanes--${u.horizontal?"horizontal":"vertical"}`]:!0,"splitpanes--dragging":d.value.dragging})),E=()=>{document.addEventListener("mousemove",g,{passive:!1}),document.addEventListener("mouseup",r),"ontouchstart"in window&&(document.addEventListener("touchmove",g,{passive:!1}),document.addEventListener("touchend",r))},y=()=>{document.removeEventListener("mousemove",g),document.removeEventListener("mouseup",r),"ontouchstart"in window&&(document.removeEventListener("touchmove",g),document.removeEventListener("touchend",r))},R=(e,n)=>{var i;const t=(i=e.target)==null?void 0:i.closest(".splitpanes__splitter");if(t){const{left:a,top:s}=t.getBoundingClientRect(),{clientX:c,clientY:f}="ontouchstart"in window&&"touches"in e?e.touches[0]:e;d.value.cursorOffset=u.horizontal?f-s:c-a}E(),d.value.mouseDown=!0,d.value.activeSplitter=n},g=e=>{d.value.mouseDown&&(e.preventDefault(),d.value.dragging=!0,requestAnimationFrame(()=>{G(F(e)),p("resize",{event:e},!0)}))},r=e=>{var n;d.value.dragging&&((n=window.getSelection())==null||n.removeAllRanges(),p("resized",{event:e},!0)),d.value.mouseDown=!1,d.value.activeSplitter=null,setTimeout(()=>{d.value.dragging=!1,y()},100)},b=(e,n)=>{"ontouchstart"in window&&(e.preventDefault(),z.value.splitter===n?(clearTimeout(z.value.timeoutId),z.value.timeoutId=null,C(e,n),z.value.splitter=null):(z.value.splitter=n,z.value.timeoutId=setTimeout(()=>z.value.splitter=null,500))),d.value.dragging||p("splitter-click",{event:e,index:n},!0)},C=(e,n)=>{if(p("splitter-dblclick",{event:e,index:n},!0),u.maximizePanes){let t=0;o.value=o.value.map((i,a)=>(i.size=a===n?i.max:i.min,a!==n&&(t+=i.min),i)),o.value[n].size-=t,p("pane-maximize",{event:e,index:n,pane:o.value[n]}),p("resized",{event:e,index:n},!0)}},$=(e,n)=>{const t=w.value[n];t&&p("pane-click",{event:e,index:t.index,pane:t})},F=e=>{const n=m.value.getBoundingClientRect(),{clientX:t,clientY:i}="ontouchstart"in window&&"touches"in e?e.touches[0]:e;return{x:t-(u.horizontal?0:d.value.cursorOffset)-n.left,y:i-(u.horizontal?d.value.cursorOffset:0)-n.top}},H=e=>{const n=e[u.horizontal?"y":"x"],t=m.value[u.horizontal?"clientHeight":"clientWidth"];return(u.rtl&&!u.horizontal?t-n:n)*100/t},G=e=>{const n=d.value.activeSplitter;if(n===null)return;let t={prevPanesSize:A(n),nextPanesSize:_(n),prevReachedMinPanes:0,nextReachedMinPanes:0};const i=0+(u.pushOtherPanes?0:t.prevPanesSize),a=100-(u.pushOtherPanes?0:t.nextPanesSize),s=Math.max(Math.min(H(e),a),i);let c=[n,n+1],f=o.value[c[0]]||null,v=o.value[c[1]]||null;const q=f.max<100&&s>=f.max+t.prevPanesSize,te=v.max<100&&s<=100-(v.max+_(n+1));if(q||te){q?(f.size=f.max,v.size=Math.max(100-f.max-t.prevPanesSize-t.nextPanesSize,0)):(f.size=Math.max(100-v.max-t.prevPanesSize-_(n+1),0),v.size=v.max);return}if(u.pushOtherPanes){const L=V(t,s);if(!L)return;({sums:t,panesToResize:c}=L),f=o.value[c[0]]||null,v=o.value[c[1]]||null}f!==null&&(f.size=Math.min(Math.max(s-t.prevPanesSize-t.prevReachedMinPanes,f.min),f.max)),v!==null&&(v.size=Math.min(Math.max(100-s-t.nextPanesSize-t.nextReachedMinPanes,v.min),v.max))},V=(e,n)=>{const t=d.value.activeSplitter;if(t===null)return null;const i=[t,t+1];return n<e.prevPanesSize+o.value[i[0]].min&&(i[0]=X(t).index||0,e.prevReachedMinPanes=0,i[0]<t&&o.value.forEach((a,s)=>{s>i[0]&&s<=t&&(a.size=a.min,e.prevReachedMinPanes+=a.min)}),e.prevPanesSize=A(i[0]),i[0]===void 0)?(e.prevReachedMinPanes=0,o.value[0].size=o.value[0].min,o.value.forEach((a,s)=>{s>0&&s<=t&&(a.size=a.min,e.prevReachedMinPanes+=a.min)}),o.value[i[1]].size=100-e.prevReachedMinPanes-o.value[0].min-e.prevPanesSize-e.nextPanesSize,null):n>100-e.nextPanesSize-o.value[i[1]].min&&(i[1]=Y(t).index||o.value.length-1,e.nextReachedMinPanes=0,i[1]>t+1&&o.value.forEach((a,s)=>{s>t&&s<i[1]&&(a.size=a.min,e.nextReachedMinPanes+=a.min)}),e.nextPanesSize=_(i[1]-1),i[1]===void 0)?(e.nextReachedMinPanes=0,o.value.forEach((a,s)=>{s<h.value-1&&s>=t+1&&(a.size=a.min,e.nextReachedMinPanes+=a.min)}),o.value[i[0]].size=100-e.prevPanesSize-_(i[0]-1),null):{sums:e,panesToResize:i}},A=e=>o.value.reduce((n,t,i)=>n+(i<e?t.size:0),0),_=e=>o.value.reduce((n,t,i)=>n+(i>e+1?t.size:0),0),X=e=>[...o.value].reverse().find(t=>t.index<e&&t.size>t.min)||{},Y=e=>o.value.find(t=>t.index>e+1&&t.size>t.min)||{},I=()=>{var n;const e=Array.from(((n=m.value)==null?void 0:n.children)||[]);for(const t of e){const i=t.classList.contains("splitpanes__pane"),a=t.classList.contains("splitpanes__splitter");!i&&!a&&(t.remove(),console.warn("Splitpanes: Only <pane> elements are allowed at the root of <splitpanes>. One of your DOM nodes was removed."))}},j=(e,n,t=!1)=>{var s;const i=e-1,a=document.createElement("div");a.classList.add("splitpanes__splitter"),t||(a.onmousedown=c=>R(c,i),typeof window<"u"&&"ontouchstart"in window&&(a.ontouchstart=c=>R(c,i)),a.onclick=c=>b(c,i+1)),a.ondblclick=c=>C(c,i+1),(s=n.parentNode)==null||s.insertBefore(a,n)},W=e=>{e.onmousedown=null,e.onclick=null,e.ondblclick=null,e.remove()},N=()=>{var t;const e=Array.from(((t=m.value)==null?void 0:t.children)||[]);for(const i of e)i.className.includes("splitpanes__splitter")&&W(i);let n=0;for(const i of e)i.className.includes("splitpanes__pane")&&(!n&&u.firstSplitter?j(n,i,!0):n&&j(n,i),n++)},J=({uid:e,...n})=>{const t=w.value[e];for(const[i,a]of Object.entries(n))t[i]=a},K=e=>{var t;let n=-1;Array.from(((t=m.value)==null?void 0:t.children)||[]).some(i=>(i.className.includes("splitpanes__pane")&&n++,i.isSameNode(e.el))),o.value.splice(n,0,{...e,index:n}),o.value.forEach((i,a)=>i.index=a),P.value&&l.nextTick(()=>{N(),D({addedPane:o.value[n]}),p("pane-add",{pane:o.value[n]})})},Q=e=>{const n=o.value.findIndex(i=>i.id===e);o.value[n].el=null;const t=o.value.splice(n,1)[0];o.value.forEach((i,a)=>i.index=a),l.nextTick(()=>{N(),p("pane-remove",{pane:t}),D({removedPane:{...t}})})},D=(e={})=>{!e.addedPane&&!e.removedPane?ee():o.value.some(n=>n.givenSize!==null||n.min||n.max<100)?ne(e):Z(),P.value&&p("resized")},Z=()=>{const e=100/h.value;let n=0;const t=[],i=[];for(const a of o.value)a.size=Math.max(Math.min(e,a.max),a.min),n-=a.size,a.size>=a.max&&t.push(a.id),a.size<=a.min&&i.push(a.id);n>.1&&O(n,t,i)},ee=()=>{let e=100;const n=[],t=[];let i=0;for(const s of o.value)e-=s.size,s.givenSize!==null&&i++,s.size>=s.max&&n.push(s.id),s.size<=s.min&&t.push(s.id);let a=100;if(e>.1){for(const s of o.value)s.givenSize===null&&(s.size=Math.max(Math.min(e/(h.value-i),s.max),s.min)),a-=s.size;a>.1&&O(a,n,t)}},ne=({addedPane:e}={})=>{let n=100/h.value,t=0;const i=[],a=[];e&&e.givenSize!==null&&(n=(100-e.givenSize)/(h.value-1));for(const s of o.value)t-=s.size,s.size>=s.max&&i.push(s.id),s.size<=s.min&&a.push(s.id);if(!(Math.abs(t)<.1)){for(const s of o.value)(e==null?void 0:e.givenSize)!==null&&(e==null?void 0:e.id)===s.id||(s.size=Math.max(Math.min(n,s.max),s.min)),t-=s.size,s.size>=s.max&&i.push(s.id),s.size<=s.min&&a.push(s.id);t>.1&&O(t,i,a)}},O=(e,n,t)=>{let i;e>0?i=e/(h.value-n.length):i=e/(h.value-t.length),o.value.forEach(a=>{if(e>0&&!n.includes(a.id)){const s=Math.max(Math.min(a.size+i,a.max),a.min),c=s-a.size;e-=c,a.size=s}else if(!t.includes(a.id)){const s=Math.max(Math.min(a.size+i,a.max),a.min),c=s-a.size;e-=c,a.size=s}}),Math.abs(e)>.1&&l.nextTick(()=>{P.value&&console.warn("Splitpanes: Could not resize panes correctly due to their constraints.")})},p=(e,n=void 0,t=!1)=>{const i=(n==null?void 0:n.index)??d.value.activeSplitter??null;M(e,{...n,...i!==null&&{index:i},...t&&i!==null&&{prevPane:o.value[i-(u.firstSplitter?1:0)],nextPane:o.value[i+(u.firstSplitter?0:1)]},panes:o.value.map(a=>({min:a.min,max:a.max,size:a.size}))})};return l.watch(()=>u.firstSplitter,()=>N()),l.onMounted(()=>{I(),N(),D(),p("ready"),P.value=!0}),l.onBeforeUnmount(()=>P.value=!1),l.provide("panes",o),l.provide("indexedPanes",w),l.provide("horizontal",l.computed(()=>u.horizontal)),l.provide("requestUpdate",J),l.provide("onPaneAdd",K),l.provide("onPaneRemove",Q),l.provide("onPaneClick",$),(e,n)=>(l.openBlock(),l.createElementBlock("div",{ref_key:"containerEl",ref:m,class:l.normalizeClass(k.value)},[l.renderSlot(e.$slots,"default")],2))}}),U=l.defineComponent({__name:"pane",props:{size:{},minSize:{default:0},maxSize:{default:100}},setup(B){var g;const S=B,M=l.inject("requestUpdate"),u=l.inject("onPaneAdd"),o=l.inject("horizontal"),w=l.inject("onPaneRemove"),h=l.inject("onPaneClick"),m=(g=l.getCurrentInstance())==null?void 0:g.uid,P=l.inject("indexedPanes"),d=l.computed(()=>P.value[m]),z=l.ref(null),k=l.computed(()=>{const r=isNaN(Number(S.size))||S.size===void 0?0:parseFloat(String(S.size));return Math.max(Math.min(r,y.value),E.value)}),E=l.computed(()=>{const r=parseFloat(String(S.minSize));return isNaN(r)?0:r}),y=l.computed(()=>{const r=parseFloat(String(S.maxSize));return isNaN(r)?100:r}),R=l.computed(()=>{var r;return`${o.value?"height":"width"}: ${(r=d.value)==null?void 0:r.size}%`});return l.watch(()=>k.value,r=>M({uid:m,size:r})),l.watch(()=>E.value,r=>M({uid:m,min:r})),l.watch(()=>y.value,r=>M({uid:m,max:r})),l.onMounted(()=>{u({id:m,el:z.value,min:E.value,max:y.value,givenSize:S.size===void 0?null:k.value,size:k.value})}),l.onBeforeUnmount(()=>w(m)),(r,b)=>(l.openBlock(),l.createElementBlock("div",{ref_key:"paneEl",ref:z,class:"splitpanes__pane",onClick:b[0]||(b[0]=C=>l.unref(h)(C,l.unref(m))),style:l.normalizeStyle(R.value)},[l.renderSlot(r.$slots,"default")],4))}});x.Pane=U,x.Splitpanes=T,Object.defineProperty(x,Symbol.toStringTag,{value:"Module"})});