UNPKG

splitpanes

Version:

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

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