UNPKG

@kong/splitpanes

Version:

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

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