react-zeugma 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
- 'use strict';var react=require('react'),core=require('@dnd-kit/core'),jsxRuntime=require('react/jsx-runtime');var G=react.createContext(void 0);var w=()=>{let e=react.useContext(G);if(!e)throw new Error("useDashboard must be used within a DashboardProvider");return e};function _(e,t){if(e===null)return null;if(e.type==="pane")return e.paneId===t?null:e;let n=_(e.first,t),o=_(e.second,t);return n===null?o:o===null?n:{...e,first:n,second:o}}function $(e,t,n,o,r){if(e===null)return {type:"pane",paneId:r};if(e.type==="pane"){if(e.paneId===t){let a={type:"pane",paneId:r},p={type:"pane",paneId:t},d=o==="left"||o==="top";return {type:"split",direction:n,first:d?a:p,second:d?p:a,splitPercentage:50}}return e}return {...e,first:$(e.first,t,n,o,r)||e.first,second:$(e.second,t,n,o,r)||e.second}}function U(e,t,n){return e===null?null:e.type==="pane"?e.paneId===t?{...e,paneId:n}:e.paneId===n?{...e,paneId:t}:e:{...e,first:U(e.first,t,n)||e.first,second:U(e.second,t,n)||e.second}}function te(e,t){if(e===null)return {type:"pane",paneId:t};function n(o,r){return o.type==="pane"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:o,second:{type:"pane",paneId:t}}:{...o,second:n(o.second,o.direction)}}return n(e,null)}function L(e,t,n){return e===null?null:e===t?{...e,splitPercentage:n}:e.type==="split"?{...e,first:L(e.first,t,n)||e.first,second:L(e.second,t,n)||e.second}:e}var ae=8,de=8,Xe=4;var Pe=({activeId:e,render:t,className:n})=>{let o=react.useRef(null);return react.useEffect(()=>{let r=a=>{o.current&&(o.current.style.transform=`translate(${a.clientX+12}px, ${a.clientY+12}px)`);};return document.addEventListener("pointermove",r),()=>document.removeEventListener("pointermove",r)},[]),jsxRuntime.jsx("div",{ref:o,className:n,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})},be=({layout:e,onChange:t,renderPane:n,renderDragOverlay:o,classNames:r={},fullscreenPaneId:a=null,onFullscreenChange:p,onRemove:d,dragActivationDistance:b=8,snapThreshold:c=8,onDragStart:h,onDragEnd:i,onResizeStart:v,onResize:R,onResizeEnd:S,renderResizer:u,minSplitPercentage:m=5,maxSplitPercentage:N=95,children:D})=>{let[f,k]=react.useState(null),q=core.useSensors(core.useSensor(core.PointerSensor,{activationConstraint:{distance:b}})),X=s=>{let l=s.active.id.toString();k(l),h&&h(l);},A=s=>{k(null);let{active:l,over:x}=s,g=l.id.toString();if(!x){i&&i(g,null,null);return}let I=x.id.toString(),Z=I.match(/^drop-center-(.+)$/);if(Z){let[,J]=Z;g!==J&&t(U(e,g,J)),i&&i(g,J,{type:"swap",position:"center"});return}let y=I.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!y){i&&i(g,null,null);return}let[,E,T]=y;if(g===T){i&&i(g,null,null);return}let C=E==="left"||E==="right"?"row":"column",oe=_(e,g),re=$(oe,T,C,E,g);t(re),i&&i(g,T,{type:"split",direction:C,position:E});},B=react.useCallback(s=>{let l=_(e,s);t(l);},[e,t]),Y=react.useCallback(s=>{let l=te(e,s);t(l);},[e,t]),F=react.useCallback((s,l)=>{let x=U(e,s,l);t(x);},[e,t]),H=react.useCallback((s,l,x,g)=>{let I=$(e,s,l,x,g);t(I);},[e,t]),M=react.useCallback((s,l)=>{let x=L(e,s,l);t(x);},[e,t]),P=react.useMemo(()=>({layout:e,onLayoutChange:t,renderPane:n,activeId:f,fullscreenPaneId:a,classNames:r,onRemove:d,onFullscreenChange:p,snapThreshold:c,onResizeStart:v,onResize:R,onResizeEnd:S,renderResizer:u,minSplitPercentage:m,maxSplitPercentage:N,removePane:B,addPane:Y,swapPanes:F,splitPane:H,updateSplitPercentage:M}),[e,t,n,f,a,r,d,p,c,v,R,S,u,m,N,B,Y,F,H,M]);return jsxRuntime.jsxs(G.Provider,{value:P,children:[jsxRuntime.jsx(core.DndContext,{sensors:q,collisionDetection:core.pointerWithin,onDragStart:X,onDragEnd:A,children:D}),f&&o&&jsxRuntime.jsx(Pe,{activeId:f,render:o,className:r.dragOverlay})]})};function Q({containerRef:e,isRow:t,direction:n,splitPercentage:o,resizerSize:r,snapThreshold:a,layout:p,currentNode:d,onLayoutChange:b,onResizeStart:c,onResizeEnd:h}){let{onResizeStart:i,onResize:v,onResizeEnd:R,minSplitPercentage:S=5,maxSplitPercentage:u=95}=w();return react.useCallback(m=>{m.preventDefault();let N=e.current;if(!N)return;document.body.classList.add("zeugma-resizing");let D=document.createElement("style");D.id="zeugma-global-cursor-style",D.textContent=`
1
+ 'use strict';var react=require('react'),core=require('@dnd-kit/core'),jsxRuntime=require('react/jsx-runtime');var G=react.createContext(void 0);var y=()=>{let e=react.useContext(G);if(!e)throw new Error("useDashboard must be used within a DashboardProvider");return e};function C(e,t){if(e===null)return null;if(e.type==="pane")return e.paneId===t?null:e;let o=C(e.first,t),n=C(e.second,t);return o===null?n:n===null?o:{...e,first:o,second:n}}function O(e,t,o,n,r){if(e===null)return {type:"pane",paneId:r};if(e.type==="pane"){if(e.paneId===t){let i={type:"pane",paneId:r},a={type:"pane",paneId:t},p=n==="left"||n==="top";return {type:"split",direction:o,first:p?i:a,second:p?a:i,splitPercentage:50}}return e}return {...e,first:O(e.first,t,o,n,r)||e.first,second:O(e.second,t,o,n,r)||e.second}}function _(e,t,o){return e===null?null:e.type==="pane"?e.paneId===t?{...e,paneId:o}:e.paneId===o?{...e,paneId:t}:e:{...e,first:_(e.first,t,o)||e.first,second:_(e.second,t,o)||e.second}}function re(e,t){if(e===null)return {type:"pane",paneId:t};function o(n,r){return n.type==="pane"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:n,second:{type:"pane",paneId:t}}:{...n,second:o(n.second,n.direction)}}return o(e,null)}function F(e,t,o){return e===null?null:e===t?{...e,splitPercentage:o}:e.type==="split"?{...e,first:F(e.first,t,o)||e.first,second:F(e.second,t,o)||e.second}:e}function ie(e,t,o){let n=C(e,t);if(n===null)return {type:"pane",paneId:t};let r=o==="left"||o==="right"?"row":"column",i=o==="left"||o==="top",a={type:"pane",paneId:t};return {type:"split",direction:r,first:i?a:n,second:i?n:a,splitPercentage:50}}var ge=8,he=8,nt=4;var be={top:{position:"absolute",top:0,left:0,right:0,height:"32px",zIndex:30,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"32px",zIndex:30,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"32px",zIndex:30,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"32px",zIndex:30,pointerEvents:"auto"}},Pe={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"}},Re=({id:e,position:t,activeClassName:o})=>{let{setNodeRef:n,isOver:r}=core.useDroppable({id:e});return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{ref:n,style:be[t]}),r&&jsxRuntime.jsx("div",{className:o,style:Pe[t]})]})},se=({activeId:e,hasOtherPanes:t,dropPreviewClassName:o})=>!e||!t?null:jsxRuntime.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:30,pointerEvents:"none"},children:["top","bottom","left","right"].map(n=>jsxRuntime.jsx(Re,{id:`drop-root-${n}`,position:n,activeClassName:o},n))});var Ce=({activeId:e,render:t,className:o})=>{let n=react.useRef(null);return react.useEffect(()=>{let r=i=>{n.current&&(n.current.style.transform=`translate(${i.clientX+12}px, ${i.clientY+12}px)`);};return document.addEventListener("pointermove",r),()=>document.removeEventListener("pointermove",r)},[]),jsxRuntime.jsx("div",{ref:n,className:o,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})},Le=({layout:e,onChange:t,renderPane:o,renderDragOverlay:n,classNames:r={},fullscreenPaneId:i=null,onFullscreenChange:a,onRemove:p,dragActivationDistance:R=8,snapThreshold:u=8,onDragStart:v,onDragEnd:s,onResizeStart:h,onResize:x,onResizeEnd:S,renderResizer:f,minSplitPercentage:g=5,maxSplitPercentage:N=95,children:D})=>{let[l,k]=react.useState(null),K=core.useSensors(core.useSensor(core.PointerSensor,{activationConstraint:{distance:R}})),X=c=>{let m=c.active.id.toString();k(m),v&&v(m);},A=c=>{k(null);let{active:m,over:P}=c,d=m.id.toString();if(!P){s&&s(d,null,null);return}let I=P.id.toString(),L=I.match(/^drop-root-(left|right|top|bottom)$/);if(L){let[,E]=L,ue=ie(e,d,E);t(ue),s&&s(d,"root",{type:"split",direction:E==="left"||E==="right"?"row":"column",position:E});return}let W=I.match(/^drop-center-(.+)$/);if(W){let[,E]=W;d!==E&&t(_(e,d,E)),s&&s(d,E,{type:"swap",position:"center"});return}let $=I.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!$){s&&s(d,null,null);return}let[,w,j]=$;if(d===j){s&&s(d,null,null);return}let ne=w==="left"||w==="right"?"row":"column",pe=C(e,d),ce=O(pe,j,ne,w,d);t(ce),s&&s(d,j,{type:"split",direction:ne,position:w});},Q=react.useCallback(c=>{let m=C(e,c);t(m);},[e,t]),Y=react.useCallback(c=>{let m=re(e,c);t(m);},[e,t]),Z=react.useCallback((c,m)=>{let P=_(e,c,m);t(P);},[e,t]),H=react.useCallback((c,m,P,d)=>{let I=O(e,c,m,P,d);t(I);},[e,t]),M=react.useCallback((c,m)=>{let P=F(e,c,m);t(P);},[e,t]),b=react.useMemo(()=>({layout:e,onLayoutChange:t,renderPane:o,activeId:l,fullscreenPaneId:i,classNames:r,onRemove:p,onFullscreenChange:a,snapThreshold:u,onResizeStart:h,onResize:x,onResizeEnd:S,renderResizer:f,minSplitPercentage:g,maxSplitPercentage:N,removePane:Q,addPane:Y,swapPanes:Z,splitPane:H,updateSplitPercentage:M}),[e,t,o,l,i,r,p,a,u,h,x,S,f,g,N,Q,Y,Z,H,M]),z=react.useMemo(()=>l?C(e,l)!==null:false,[e,l]);return jsxRuntime.jsxs(G.Provider,{value:b,children:[jsxRuntime.jsx(core.DndContext,{id:"zeugma-dnd-context",sensors:K,collisionDetection:core.pointerWithin,onDragStart:X,onDragEnd:A,children:jsxRuntime.jsxs("div",{className:"zeugma-dashboard-root",style:{position:"relative",width:"100%",height:"100%"},children:[D,jsxRuntime.jsx(se,{activeId:l,hasOtherPanes:z,dropPreviewClassName:r.dropPreview})]})}),l&&n&&jsxRuntime.jsx(Ce,{activeId:l,render:n,className:r.dragOverlay})]})};function ee({containerRef:e,isRow:t,direction:o,splitPercentage:n,resizerSize:r,snapThreshold:i,layout:a,currentNode:p,onLayoutChange:R,onResizeStart:u,onResizeEnd:v}){let{onResizeStart:s,onResize:h,onResizeEnd:x,minSplitPercentage:S=5,maxSplitPercentage:f=95}=y();return react.useCallback(g=>{g.preventDefault();let N=e.current;if(!N)return;document.body.classList.add("zeugma-resizing");let D=document.createElement("style");D.id="zeugma-global-cursor-style",D.textContent=`
2
2
  * {
3
3
  cursor: ${t?"col-resize":"row-resize"} !important;
4
4
  user-select: none !important;
5
5
  }
6
- `,document.head.appendChild(D),c&&c(),i&&i(d);let f=N.getBoundingClientRect(),k=m.clientX,q=m.clientY,X=o,A=m.currentTarget;A.setAttribute("data-resizing","true");let Y=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(P=>P!==A&&P.getAttribute("data-direction")===n).map(P=>{let s=P.getBoundingClientRect();return t?s.left+s.width/2:s.top+s.height/2}),F=X,H=P=>{let s=t?(P.clientX-k)/f.width*100:(P.clientY-q)/f.height*100,l=X+s,x=t?f.left+(f.width-r)*(l/100)+r/2:f.top+(f.height-r)*(l/100)+r/2,g=1/0,I=null;for(let T of Y){let C=Math.abs(x-T);C<a&&C<g&&(g=C,I=T);}let Z=l;I!==null&&(Z=t?(I-r/2-f.left)/(f.width-r)*100:(I-r/2-f.top)/(f.height-r)*100);let y=Math.max(S,Math.min(u,Z));F=y;let E=L(p,d,y);b(E),v&&v(d,y);},M=()=>{document.body.classList.remove("zeugma-resizing"),A.removeAttribute("data-resizing");let P=document.getElementById("zeugma-global-cursor-style");P&&P.remove(),document.removeEventListener("pointermove",H),document.removeEventListener("pointerup",M),h&&h(),R&&R(d,F);};document.addEventListener("pointermove",H),document.addEventListener("pointerup",M);},[e,t,n,o,r,a,p,d,b,c,h,i,v,R,S,u])}var De=({currentNode:e,resizerSize:t,snapThreshold:n,renderResizer:o})=>{let{layout:r,onLayoutChange:a,classNames:p,renderResizer:d}=w(),[b,c]=react.useState(false),h=o||d,i=react.useRef(null),{direction:v,first:R,second:S,splitPercentage:u}=e,m=v==="row",N=Q({containerRef:i,isRow:m,direction:v,splitPercentage:u,resizerSize:t,snapThreshold:n??8,layout:r,currentNode:e,onLayoutChange:a,onResizeStart:()=>c(true),onResizeEnd:()=>c(false)});return jsxRuntime.jsxs("div",{ref:i,style:{display:"flex",flexDirection:m?"row":"column",width:"100%",height:"100%",overflow:"hidden"},children:[jsxRuntime.jsx("div",{style:{flex:`${u} 1 0%`,overflow:"hidden"},children:jsxRuntime.jsx(j,{tree:R,resizerSize:t,snapThreshold:n,renderResizer:o})}),h?h({direction:v,splitPercentage:u,resizerSize:t,isResizing:b,onPointerDown:N}):jsxRuntime.jsx("div",{className:p.resizer,"data-direction":v,style:{width:m?`${t}px`:"100%",height:m?"100%":`${t}px`,cursor:m?"col-resize":"row-resize",position:"relative",zIndex:10,userSelect:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:N,role:"separator","aria-valuenow":u,"aria-valuemin":5,"aria-valuemax":95}),jsxRuntime.jsx("div",{style:{flex:`${100-u} 1 0%`,overflow:"hidden"},children:jsxRuntime.jsx(j,{tree:S,resizerSize:t,snapThreshold:n,renderResizer:o})})]})},j=({tree:e,resizerSize:t=4,snapThreshold:n,renderResizer:o})=>{let{layout:r,renderPane:a,fullscreenPaneId:p,snapThreshold:d}=w(),b=n!==void 0?n:d;if(p&&!e)return jsxRuntime.jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:a(p)});let c=e!==void 0?e:r;return c?c.type==="pane"?jsxRuntime.jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:a(c.paneId)}):jsxRuntime.jsx(De,{currentNode:c,resizerSize:t,snapThreshold:b,renderResizer:o}):null};var W=react.createContext(null);var Te={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"}},Ce={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},ne=({id:e,position:t,activeClassName:n})=>{let{setNodeRef:o,isOver:r}=core.useDroppable({id:e});return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{ref:o,style:Te[t]}),r&&jsxRuntime.jsx("div",{className:n,style:Ce[t]})]})},Le=({id:e,children:t,style:n})=>{let{activeId:o,classNames:r,fullscreenPaneId:a,onRemove:p,onFullscreenChange:d,removePane:b}=w(),c=o!==null&&o!==e,{attributes:h,listeners:i,setNodeRef:v,isDragging:R}=core.useDraggable({id:e}),S=o===e||R,u=a===e,m={isDragging:S,isFullscreen:u,toggleFullscreen:()=>d?.(u?null:e),remove:()=>{u&&d?.(null),p?p(e):b(e);}},N=react.useMemo(()=>({...i,...h}),[i,h]);return jsxRuntime.jsx(W.Provider,{value:N,children:jsxRuntime.jsxs("div",{ref:v,className:r.pane,style:{position:"relative",width:"100%",height:"100%",...n},children:[t(m),c&&jsxRuntime.jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(D=>jsxRuntime.jsx(ne,{id:`drop-${D}-${e}`,position:D,activeClassName:r.dropPreview},D)),jsxRuntime.jsx(ne,{id:`drop-center-${e}`,position:"center",activeClassName:r.swapPreview})]})]})})};var He=({children:e,className:t,style:n})=>{let o=react.useContext(W);if(!o)throw new Error("<DragHandle> must be used inside a <Pane>");return jsxRuntime.jsx("div",{className:t,style:{cursor:"grab",userSelect:"none",...n},...o,children:e})};exports.DEFAULT_DRAG_ACTIVATION_DISTANCE=de;exports.DEFAULT_RESIZER_SIZE=Xe;exports.DEFAULT_SNAP_THRESHOLD=ae;exports.DashboardProvider=be;exports.DragHandle=He;exports.Pane=Le;exports.PaneTree=j;exports.addPane=te;exports.removePane=_;exports.splitPane=$;exports.swapPanes=U;exports.updateSplitPercentage=L;exports.useDashboard=w;exports.useResizer=Q;//# sourceMappingURL=index.cjs.map
6
+ `,document.head.appendChild(D),u&&u(),s&&s(p);let l=N.getBoundingClientRect(),k=g.clientX,K=g.clientY,X=n,A=g.currentTarget;A.setAttribute("data-resizing","true");let Y=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(b=>b!==A&&b.getAttribute("data-direction")===o).map(b=>{let z=b.getBoundingClientRect();return t?z.left+z.width/2:z.top+z.height/2}),Z=X,H=b=>{let z=t?(b.clientX-k)/l.width*100:(b.clientY-K)/l.height*100,c=X+z,m=t?l.left+(l.width-r)*(c/100)+r/2:l.top+(l.height-r)*(c/100)+r/2,P=1/0,d=null;for(let $ of Y){let w=Math.abs(m-$);w<i&&w<P&&(P=w,d=$);}let I=c;d!==null&&(I=t?(d-r/2-l.left)/(l.width-r)*100:(d-r/2-l.top)/(l.height-r)*100);let L=Math.max(S,Math.min(f,I));Z=L;let W=F(a,p,L);R(W),h&&h(p,L);},M=()=>{document.body.classList.remove("zeugma-resizing"),A.removeAttribute("data-resizing");let b=document.getElementById("zeugma-global-cursor-style");b&&b.remove(),document.removeEventListener("pointermove",H),document.removeEventListener("pointerup",M),v&&v(),x&&x(p,Z);};document.addEventListener("pointermove",H),document.addEventListener("pointerup",M);},[e,t,o,n,r,i,a,p,R,u,v,s,h,x,S,f])}var He=({currentNode:e,resizerSize:t,snapThreshold:o,renderResizer:n})=>{let{layout:r,onLayoutChange:i,classNames:a,renderResizer:p}=y(),[R,u]=react.useState(false),v=n||p,s=react.useRef(null),{direction:h,first:x,second:S,splitPercentage:f}=e,g=h==="row",N=ee({containerRef:s,isRow:g,direction:h,splitPercentage:f,resizerSize:t,snapThreshold:o??8,layout:r,currentNode:e,onLayoutChange:i,onResizeStart:()=>u(true),onResizeEnd:()=>u(false)});return jsxRuntime.jsxs("div",{ref:s,style:{display:"flex",flexDirection:g?"row":"column",width:"100%",height:"100%",overflow:"hidden"},children:[jsxRuntime.jsx("div",{style:{flex:`${f} 1 0%`,overflow:"hidden"},children:jsxRuntime.jsx(te,{tree:x,resizerSize:t,snapThreshold:o,renderResizer:n})}),v?v({direction:h,splitPercentage:f,resizerSize:t,isResizing:R,onPointerDown:N}):jsxRuntime.jsx("div",{className:a.resizer,"data-direction":h,style:{width:g?`${t}px`:"100%",height:g?"100%":`${t}px`,cursor:g?"col-resize":"row-resize",position:"relative",zIndex:10,userSelect:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:N,role:"separator","aria-valuenow":f,"aria-valuemin":5,"aria-valuemax":95}),jsxRuntime.jsx("div",{style:{flex:`${100-f} 1 0%`,overflow:"hidden"},children:jsxRuntime.jsx(te,{tree:S,resizerSize:t,snapThreshold:o,renderResizer:n})})]})},te=({tree:e,resizerSize:t=4,snapThreshold:o,renderResizer:n})=>{let{layout:r,renderPane:i,fullscreenPaneId:a,snapThreshold:p}=y(),R=o!==void 0?o:p;if(a&&!e)return jsxRuntime.jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:i(a)});let u=e!==void 0?e:r;return u?u.type==="pane"?jsxRuntime.jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:i(u.paneId)}):jsxRuntime.jsx(He,{currentNode:u,resizerSize:t,snapThreshold:R,renderResizer:n}):null};var J=react.createContext(null);var Ve={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"}},ke={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},de=({id:e,position:t,activeClassName:o})=>{let{setNodeRef:n,isOver:r}=core.useDroppable({id:e});return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{ref:n,style:Ve[t]}),r&&jsxRuntime.jsx("div",{className:o,style:ke[t]})]})},Xe=({id:e,children:t,style:o})=>{let{activeId:n,classNames:r,fullscreenPaneId:i,onRemove:a,onFullscreenChange:p,removePane:R}=y(),u=n!==null&&n!==e,{attributes:v,listeners:s,setNodeRef:h,isDragging:x}=core.useDraggable({id:e}),S=n===e||x,f=i===e,g={isDragging:S,isFullscreen:f,toggleFullscreen:()=>p?.(f?null:e),remove:()=>{f&&p?.(null),a?a(e):R(e);}},N=react.useMemo(()=>({...s,...v}),[s,v]);return jsxRuntime.jsx(J.Provider,{value:N,children:jsxRuntime.jsxs("div",{ref:h,className:r.pane,style:{position:"relative",width:"100%",height:"100%",...o},children:[t(g),u&&jsxRuntime.jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(D=>jsxRuntime.jsx(de,{id:`drop-${D}-${e}`,position:D,activeClassName:r.dropPreview},D)),jsxRuntime.jsx(de,{id:`drop-center-${e}`,position:"center",activeClassName:r.swapPreview})]})]})})};var Ge=({children:e,className:t,style:o})=>{let n=react.useContext(J);if(!n)throw new Error("<DragHandle> must be used inside a <Pane>");return jsxRuntime.jsx("div",{className:t,style:{cursor:"grab",userSelect:"none",...o},...n,children:e})};exports.DEFAULT_DRAG_ACTIVATION_DISTANCE=he;exports.DEFAULT_RESIZER_SIZE=nt;exports.DEFAULT_SNAP_THRESHOLD=ge;exports.DashboardProvider=Le;exports.DragHandle=Ge;exports.Pane=Xe;exports.PaneTree=te;exports.addPane=re;exports.removePane=C;exports.splitPane=O;exports.splitRoot=ie;exports.swapPanes=_;exports.updateSplitPercentage=F;exports.useDashboard=y;exports.useResizer=ee;//# sourceMappingURL=index.cjs.map
7
7
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entities/dashboard/model/context.ts","../src/entities/dashboard/model/hooks.ts","../src/shared/lib/tree/tree-helpers.ts","../src/shared/config/constants.ts","../src/entities/dashboard/ui/DashboardProvider.tsx","../src/features/resize-pane/hooks/useResizer.ts","../src/widgets/pane-tree/ui/PaneTree.tsx","../src/entities/pane/model/context.ts","../src/entities/pane/ui/Pane.tsx","../src/entities/pane/ui/DragHandle.tsx"],"names":["DashboardContext","createContext","useDashboard","context","useContext","removePane","tree","idToRemove","newFirst","newSecond","splitPane","targetId","direction","splitType","paneToAdd","addedNode","originalNode","isFirst","swapPanes","idA","idB","addPane","insert","node","parentDirection","updateSplitPercentage","target","newPercentage","DEFAULT_SNAP_THRESHOLD","DEFAULT_DRAG_ACTIVATION_DISTANCE","DEFAULT_RESIZER_SIZE","CursorOverlay","activeId","render","className","ref","useRef","useEffect","handleMove","e","jsx","DashboardProvider","layout","onChange","renderPane","renderDragOverlay","classNames","fullscreenPaneId","onFullscreenChange","onRemove","dragActivationDistance","snapThreshold","onDragStart","onDragEnd","onResizeStart","onResize","onResizeEnd","renderResizer","minSplitPercentage","maxSplitPercentage","children","setActiveId","useState","sensors","useSensors","useSensor","PointerSensor","handleDragStart","event","draggingId","handleDragEnd","active","over","overIdStr","swapMatch","match","dropZone","treeWithoutDragging","newLayout","handleRemovePane","useCallback","paneId","handleAddPane","handleSwapPanes","paneIdA","paneIdB","handleSplitPane","handleUpdateSplitPercentage","currentNode","percentage","contextValue","useMemo","jsxs","DndContext","pointerWithin","useResizer","containerRef","isRow","splitPercentage","resizerSize","onLayoutChange","localOnResizeStart","localOnResizeEnd","globalOnResizeStart","globalOnResize","globalOnResizeEnd","container","styleEl","rect","startX","startY","startPercentage","resizerEl","otherPositions","el","r","currentPercentage","handlePointerMove","moveEvent","delta","proposedPercentage","proposedPos","closestDistance","bestTarget","pos","dist","snappedPercentage","finalPercentage","handlePointerUp","globalStyle","PaneSplit","propRenderResizer","contextRenderResizer","isResizing","setIsResizing","first","second","handlePointerDown","PaneTree","propSnapThreshold","contextSnapThreshold","DragListenersCtx","activationPositions","previewPositions","DropZone","id","position","activeClassName","setNodeRef","isOver","useDroppable","Fragment","Pane","style","showDropZones","attributes","listeners","isDragging","useDraggable","dragging","isFullscreen","renderProps","DragHandle","dragProps"],"mappings":"8GA+CO,IAAMA,CAAAA,CAAmBC,mBAAAA,CAAiD,MAAS,CAAA,CC5CnF,IAAMC,EAAe,IAAM,CAChC,IAAMC,CAAAA,CAAUC,gBAAAA,CAAWJ,CAAgB,CAAA,CAC3C,GAAI,CAACG,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,sDAAsD,EAExE,OAAOA,CACT,ECJO,SAASE,CAAAA,CAAWC,CAAAA,CAAuBC,EAAqC,CACrF,GAAID,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAC1B,GAAIA,CAAAA,CAAK,IAAA,GAAS,MAAA,CAChB,OAAOA,CAAAA,CAAK,MAAA,GAAWC,CAAAA,CAAa,IAAA,CAAOD,CAAAA,CAE7C,IAAME,CAAAA,CAAWH,CAAAA,CAAWC,CAAAA,CAAK,KAAA,CAAOC,CAAU,CAAA,CAC5CE,CAAAA,CAAYJ,CAAAA,CAAWC,CAAAA,CAAK,MAAA,CAAQC,CAAU,CAAA,CACpD,OAAIC,IAAa,IAAA,CAAaC,CAAAA,CAC1BA,CAAAA,GAAc,IAAA,CAAaD,CAAAA,CACxB,CAAE,GAAGF,CAAAA,CAAM,KAAA,CAAOE,CAAAA,CAAU,MAAA,CAAQC,CAAU,CACvD,CAKO,SAASC,CAAAA,CACdJ,CAAAA,CACAK,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAIR,CAAAA,GAAS,IAAA,CAAM,OAAO,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQQ,CAAU,CAAA,CAC5D,GAAIR,CAAAA,CAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,CAAAA,CAAK,MAAA,GAAWK,CAAAA,CAAU,CAC5B,IAAMI,CAAAA,CAAsB,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQD,CAAU,CAAA,CACxDE,CAAAA,CAAyB,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQL,CAAS,CAAA,CAC1DM,CAAAA,CAAUJ,CAAAA,GAAc,MAAA,EAAUA,CAAAA,GAAc,MACtD,OAAO,CACL,IAAA,CAAM,OAAA,CACN,SAAA,CAAAD,CAAAA,CACA,KAAA,CAAOK,CAAAA,CAAUF,CAAAA,CAAYC,CAAAA,CAC7B,MAAA,CAAQC,CAAAA,CAAUD,CAAAA,CAAeD,CAAAA,CACjC,eAAA,CAAiB,EACnB,CACF,CACA,OAAOT,CACT,CACA,OAAO,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOI,CAAAA,CAAUJ,CAAAA,CAAK,KAAA,CAAOK,CAAAA,CAAUC,EAAWC,CAAAA,CAAWC,CAAS,CAAA,EAAKR,CAAAA,CAAK,KAAA,CAChF,MAAA,CAAQI,CAAAA,CAAUJ,CAAAA,CAAK,MAAA,CAAQK,CAAAA,CAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,CAAA,EAAKR,CAAAA,CAAK,MACpF,CACF,CAKO,SAASY,CAAAA,CAAUZ,CAAAA,CAAuBa,CAAAA,CAAaC,CAAAA,CAA8B,CAC1F,OAAId,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,CAAK,IAAA,GAAS,OACZA,CAAAA,CAAK,MAAA,GAAWa,CAAAA,CAAY,CAAE,GAAGb,CAAAA,CAAM,MAAA,CAAQc,CAAI,CAAA,CACnDd,CAAAA,CAAK,MAAA,GAAWc,CAAAA,CAAY,CAAE,GAAGd,CAAAA,CAAM,MAAA,CAAQa,CAAI,CAAA,CAChDb,CAAAA,CAEF,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOY,CAAAA,CAAUZ,CAAAA,CAAK,KAAA,CAAOa,CAAAA,CAAKC,CAAG,CAAA,EAAKd,CAAAA,CAAK,MAC/C,MAAA,CAAQY,CAAAA,CAAUZ,CAAAA,CAAK,MAAA,CAAQa,CAAAA,CAAKC,CAAG,CAAA,EAAKd,CAAAA,CAAK,MACnD,CACF,CAKO,SAASe,EAAAA,CAAQf,CAAAA,CAAuBQ,CAAAA,CAA6B,CAC1E,GAAIR,CAAAA,GAAS,IAAA,CACX,OAAO,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQQ,CAAU,CAAA,CAG3C,SAASQ,CAAAA,CAAOC,CAAAA,CAAgBC,CAAAA,CAAkD,CAChF,OAAID,CAAAA,CAAK,IAAA,GAAS,MAAA,CAET,CACL,IAAA,CAAM,OAAA,CACN,SAAA,CAHgCC,CAAAA,GAAoB,KAAA,CAAQ,QAAA,CAAW,KAAA,CAIvE,eAAA,CAAiB,EAAA,CACjB,KAAA,CAAOD,CAAAA,CACP,MAAA,CAAQ,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQT,CAAU,CAC5C,CAAA,CAGK,CACL,GAAGS,CAAAA,CACH,MAAA,CAAQD,CAAAA,CAAOC,CAAAA,CAAK,OAAQA,CAAAA,CAAK,SAAS,CAC5C,CACF,CAEA,OAAOD,CAAAA,CAAOhB,CAAAA,CAAM,IAAI,CAC1B,CAKO,SAASmB,CAAAA,CACdnB,CAAAA,CACAoB,CAAAA,CACAC,CAAAA,CACiB,CACjB,OAAIrB,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,GAASoB,CAAAA,CACJ,CAAE,GAAGpB,CAAAA,CAAM,eAAA,CAAiBqB,CAAc,CAAA,CAE/CrB,CAAAA,CAAK,OAAS,OAAA,CACT,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOmB,CAAAA,CAAsBnB,CAAAA,CAAK,KAAA,CAAOoB,CAAAA,CAAQC,CAAa,CAAA,EAAKrB,CAAAA,CAAK,KAAA,CACxE,MAAA,CAAQmB,CAAAA,CAAsBnB,CAAAA,CAAK,MAAA,CAAQoB,CAAAA,CAAQC,CAAa,CAAA,EAAKrB,CAAAA,CAAK,MAC5E,CAAA,CAEKA,CACT,CCpHO,IAAMsB,EAAAA,CAAyB,CAAA,CACzBC,EAAAA,CAAmC,CAAA,CACnCC,GAAuB,ECoBpC,IAAMC,EAAAA,CAID,CAAC,CAAE,QAAA,CAAAC,CAAAA,CAAU,MAAA,CAAAC,CAAAA,CAAQ,SAAA,CAAAC,CAAU,CAAA,GAAM,CACxC,IAAMC,CAAAA,CAAMC,YAAAA,CAAuB,IAAI,CAAA,CAEvC,OAAAC,eAAAA,CAAU,IAAM,CACd,IAAMC,CAAAA,CAAcC,CAAAA,EAAoB,CAClCJ,CAAAA,CAAI,OAAA,GACNA,CAAAA,CAAI,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAY,CAAA,UAAA,EAAaI,CAAAA,CAAE,OAAA,CAAU,EAAE,CAAA,IAAA,EAAOA,CAAAA,CAAE,OAAA,CAAU,EAAE,CAAA,GAAA,CAAA,EAElF,CAAA,CACA,OAAA,QAAA,CAAS,gBAAA,CAAiB,aAAA,CAAeD,CAAU,CAAA,CAC5C,IAAM,QAAA,CAAS,mBAAA,CAAoB,aAAA,CAAeA,CAAU,CACrE,CAAA,CAAG,EAAE,EAGHE,cAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKL,CAAAA,CACL,SAAA,CAAWD,CAAAA,CACX,KAAA,CAAO,CACL,QAAA,CAAU,OAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,MAAA,CAAQ,IAAA,CACR,aAAA,CAAe,MACjB,CAAA,CAEC,QAAA,CAAAD,CAAAA,CAAOD,CAAQ,CAAA,CAClB,CAEJ,CAAA,CAgCaS,EAAAA,CAAsD,CAAC,CAClE,MAAA,CAAAC,CAAAA,CACA,SAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CAAa,EAAC,CACd,gBAAA,CAAAC,CAAAA,CAAmB,IAAA,CACnB,kBAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,sBAAA,CAAAC,CAAAA,CAAyB,CAAA,CACzB,aAAA,CAAAC,CAAAA,CAAgB,CAAA,CAChB,WAAA,CAAAC,CAAAA,CACA,SAAA,CAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,YAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,CAAAA,CAAqB,CAAA,CACrB,kBAAA,CAAAC,CAAAA,CAAqB,EAAA,CACrB,QAAA,CAAAC,CACF,CAAA,GAAM,CACJ,GAAM,CAAC5B,CAAAA,CAAU6B,CAAW,CAAA,CAAIC,cAAAA,CAAwB,IAAI,CAAA,CAEtDC,CAAAA,CAAUC,eAAAA,CACdC,cAAAA,CAAUC,kBAAAA,CAAe,CACvB,oBAAA,CAAsB,CAAE,QAAA,CAAUhB,CAAuB,CAC3D,CAAC,CACH,CAAA,CAEMiB,CAAAA,CAAmBC,CAAAA,EAA0B,CACjD,IAAMC,CAAAA,CAAaD,CAAAA,CAAM,MAAA,CAAO,EAAA,CAAG,QAAA,EAAS,CAC5CP,CAAAA,CAAYQ,CAAU,CAAA,CAClBjB,CAAAA,EACFA,CAAAA,CAAYiB,CAAU,EAE1B,CAAA,CAEMC,CAAAA,CAAiBF,CAAAA,EAAwB,CAC7CP,CAAAA,CAAY,IAAI,CAAA,CAChB,GAAM,CAAE,OAAAU,CAAAA,CAAQ,IAAA,CAAAC,CAAK,CAAA,CAAIJ,CAAAA,CACnBC,CAAAA,CAAaE,CAAAA,CAAO,EAAA,CAAG,QAAA,EAAS,CAEtC,GAAI,CAACC,CAAAA,CAAM,CACLnB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,IAAMI,CAAAA,CAAYD,CAAAA,CAAK,EAAA,CAAG,QAAA,EAAS,CAG7BE,CAAAA,CAAYD,CAAAA,CAAU,MAAM,oBAAoB,CAAA,CACtD,GAAIC,CAAAA,CAAW,CACb,GAAM,EAAG/D,CAAQ,CAAA,CAAI+D,CAAAA,CACjBL,CAAAA,GAAe1D,CAAAA,EACjBgC,CAAAA,CAASzB,CAAAA,CAAUwB,CAAAA,CAAQ2B,CAAAA,CAAY1D,CAAQ,CAAC,CAAA,CAE9C0C,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY1D,CAAAA,CAAU,CAAE,IAAA,CAAM,MAAA,CAAQ,QAAA,CAAU,QAAS,CAAC,EAEtE,MACF,CAGA,IAAMgE,CAAAA,CAAQF,CAAAA,CAAU,KAAA,CAAM,qCAAqC,CAAA,CACnE,GAAI,CAACE,CAAAA,CAAO,CACNtB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,GAAM,EAAGO,CAAAA,CAAUjE,CAAQ,CAAA,CAAIgE,CAAAA,CAC/B,GAAIN,CAAAA,GAAe1D,CAAAA,CAAU,CACvB0C,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,IAAMzD,CAAAA,CAA4BgE,CAAAA,GAAa,MAAA,EAAUA,CAAAA,GAAa,OAAA,CAAU,KAAA,CAAQ,QAAA,CAClFC,EAAAA,CAAsBxE,CAAAA,CAAWqC,CAAAA,CAAQ2B,CAAU,CAAA,CAEnDS,EAAAA,CAAYpE,CAAAA,CAChBmE,EAAAA,CACAlE,CAAAA,CACAC,CAAAA,CACAgE,CAAAA,CACAP,CACF,CAAA,CACA1B,CAAAA,CAASmC,EAAS,CAAA,CACdzB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY1D,CAAAA,CAAU,CAC9B,IAAA,CAAM,OAAA,CACN,SAAA,CAAAC,CAAAA,CACA,QAAA,CAAUgE,CACZ,CAAC,EAEL,CAAA,CAEMG,CAAAA,CAAmBC,iBAAAA,CACtBC,CAAAA,EAAmB,CAClB,IAAMH,CAAAA,CAAYzE,CAAAA,CAAWqC,CAAAA,CAAQuC,CAAM,CAAA,CAC3CtC,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,EAAQC,CAAQ,CACnB,CAAA,CAEMuC,CAAAA,CAAgBF,iBAAAA,CACnBC,CAAAA,EAAmB,CAClB,IAAMH,CAAAA,CAAYzD,EAAAA,CAAQqB,CAAAA,CAAQuC,CAAM,CAAA,CACxCtC,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEMwC,CAAAA,CAAkBH,iBAAAA,CACtB,CAACI,CAAAA,CAAiBC,CAAAA,GAAoB,CACpC,IAAMP,CAAAA,CAAY5D,EAAUwB,CAAAA,CAAQ0C,CAAAA,CAASC,CAAO,CAAA,CACpD1C,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEM2C,CAAAA,CAAkBN,iBAAAA,CACtB,CACErE,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,GACG,CACH,IAAMgE,CAAAA,CAAYpE,CAAAA,CAAUgC,CAAAA,CAAQ/B,CAAAA,CAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,CAAA,CAC7E6B,EAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEM4C,CAAAA,CAA8BP,iBAAAA,CAClC,CAACQ,CAAAA,CAAwBC,CAAAA,GAAuB,CAC9C,IAAMX,CAAAA,CAAYrD,CAAAA,CAAsBiB,CAAAA,CAAQ8C,CAAAA,CAAaC,CAAU,CAAA,CACvE9C,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAGM+C,EAAeC,aAAAA,CACnB,KAAO,CACL,MAAA,CAAAjD,CAAAA,CACA,cAAA,CAAgBC,CAAAA,CAChB,UAAA,CAAAC,CAAAA,CACA,QAAA,CAAAZ,CAAAA,CACA,gBAAA,CAAAe,CAAAA,CACA,UAAA,CAAAD,CAAAA,CACA,QAAA,CAAAG,CAAAA,CACA,kBAAA,CAAAD,CAAAA,CACA,aAAA,CAAAG,CAAAA,CACA,aAAA,CAAAG,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,EACA,kBAAA,CAAAC,CAAAA,CACA,UAAA,CAAYoB,CAAAA,CACZ,OAAA,CAASG,CAAAA,CACT,SAAA,CAAWC,CAAAA,CACX,SAAA,CAAWG,CAAAA,CACX,qBAAA,CAAuBC,CACzB,CAAA,CAAA,CACA,CACE7C,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAZ,CAAAA,CACAe,CAAAA,CACAD,CAAAA,CACAG,CAAAA,CACAD,CAAAA,CACAG,CAAAA,CACAG,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAoB,CAAAA,CACAG,EACAC,CAAAA,CACAG,CAAAA,CACAC,CACF,CACF,CAAA,CAEA,OACEK,eAAAA,CAAC5F,CAAAA,CAAiB,QAAA,CAAjB,CAA0B,KAAA,CAAO0F,CAAAA,CAChC,QAAA,CAAA,CAAAlD,cAAAA,CAACqD,eAAAA,CAAA,CACC,OAAA,CAAS9B,CAAAA,CACT,kBAAA,CAAoB+B,kBAAAA,CACpB,WAAA,CAAa3B,CAAAA,CACb,SAAA,CAAWG,CAAAA,CAEV,QAAA,CAAAV,CAAAA,CACH,CAAA,CACC5B,CAAAA,EAAYa,CAAAA,EACXL,cAAAA,CAACT,GAAA,CACC,QAAA,CAAUC,CAAAA,CACV,MAAA,CAAQa,CAAAA,CACR,SAAA,CAAWC,CAAAA,CAAW,WAAA,CACxB,CAAA,CAAA,CAEJ,CAEJ,ECxRO,SAASiD,CAAAA,CAAW,CACzB,YAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,SAAA,CAAArF,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAAhD,CAAAA,CACA,OAAAT,CAAAA,CACA,WAAA,CAAA8C,CAAAA,CACA,cAAA,CAAAY,CAAAA,CACA,aAAA,CAAeC,CAAAA,CACf,WAAA,CAAaC,CACf,CAAA,CAAoB,CAClB,GAAM,CACJ,aAAA,CAAeC,CAAAA,CACf,QAAA,CAAUC,CAAAA,CACV,WAAA,CAAaC,CAAAA,CACb,kBAAA,CAAA/C,CAAAA,CAAqB,CAAA,CACrB,kBAAA,CAAAC,CAAAA,CAAqB,EACvB,CAAA,CAAIzD,CAAAA,EAAa,CAEjB,OAAO8E,iBAAAA,CACJzC,GAA0C,CACzCA,CAAAA,CAAE,cAAA,EAAe,CACjB,IAAMmE,CAAAA,CAAYV,CAAAA,CAAa,OAAA,CAC/B,GAAI,CAACU,CAAAA,CAAW,OAEhB,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,iBAAiB,CAAA,CAG7C,IAAMC,CAAAA,CAAU,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA,CAC9CA,CAAAA,CAAQ,EAAA,CAAK,4BAAA,CACbA,CAAAA,CAAQ,WAAA,CAAc;AAAA;AAAA,gBAAA,EAEVV,CAAAA,CAAQ,aAAe,YAAY,CAAA;AAAA;AAAA;AAAA,IAAA,CAAA,CAI/C,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYU,CAAO,CAAA,CAE7BN,CAAAA,EACFA,CAAAA,EAAmB,CAEjBE,CAAAA,EACFA,CAAAA,CAAoBf,CAAW,CAAA,CAGjC,IAAMoB,CAAAA,CAAOF,CAAAA,CAAU,qBAAA,EAAsB,CACvCG,CAAAA,CAAStE,CAAAA,CAAE,OAAA,CACXuE,CAAAA,CAASvE,CAAAA,CAAE,OAAA,CACXwE,CAAAA,CAAkBb,CAAAA,CAGlBc,CAAAA,CAAYzE,CAAAA,CAAE,aAAA,CACpByE,CAAAA,CAAU,aAAa,eAAA,CAAiB,MAAM,CAAA,CAM9C,IAAMC,CAAAA,CAJgB,KAAA,CAAM,IAAA,CAC1B,QAAA,CAAS,gBAAA,CAAiB,uCAAuC,CACnE,CAAA,CAAE,MAAA,CAAQC,CAAAA,EAAOA,CAAAA,GAAOF,CAAAA,EAAaE,EAAG,YAAA,CAAa,gBAAgB,CAAA,GAAMtG,CAAS,CAAA,CAE/C,GAAA,CAAKsG,CAAAA,EAAO,CAC/C,IAAMC,CAAAA,CAAID,CAAAA,CAAG,qBAAA,EAAsB,CACnC,OAAOjB,CAAAA,CAAQkB,CAAAA,CAAE,IAAA,CAAOA,EAAE,KAAA,CAAQ,CAAA,CAAIA,CAAAA,CAAE,GAAA,CAAMA,CAAAA,CAAE,MAAA,CAAS,CAC3D,CAAC,CAAA,CAEGC,CAAAA,CAAoBL,CAAAA,CAElBM,CAAAA,CAAqBC,CAAAA,EAA4B,CACrD,IAAMC,CAAAA,CAAQtB,GACRqB,CAAAA,CAAU,OAAA,CAAUT,CAAAA,EAAUD,CAAAA,CAAK,KAAA,CAAS,GAAA,CAAA,CAC5CU,CAAAA,CAAU,OAAA,CAAUR,GAAUF,CAAAA,CAAK,MAAA,CAAU,GAAA,CAC7CY,CAAAA,CAAqBT,CAAAA,CAAkBQ,CAAAA,CAGvCE,CAAAA,CAAcxB,CAAAA,CAChBW,EAAK,IAAA,CAAA,CAAQA,CAAAA,CAAK,KAAA,CAAQT,CAAAA,GAAgBqB,CAAAA,CAAqB,GAAA,CAAA,CAAOrB,CAAAA,CAAc,CAAA,CACpFS,CAAAA,CAAK,GAAA,CAAA,CAAOA,CAAAA,CAAK,MAAA,CAAST,CAAAA,GAAgBqB,CAAAA,CAAqB,GAAA,CAAA,CAAOrB,CAAAA,CAAc,EAEpFuB,CAAAA,CAAkB,CAAA,CAAA,CAAA,CAClBC,CAAAA,CAA4B,IAAA,CAEhC,IAAA,IAAWC,CAAAA,IAAOX,CAAAA,CAAgB,CAChC,IAAMY,CAAAA,CAAO,IAAA,CAAK,GAAA,CAAIJ,CAAAA,CAAcG,CAAG,CAAA,CACnCC,CAAAA,CAAO1E,CAAAA,EAAiB0E,EAAOH,CAAAA,GACjCA,CAAAA,CAAkBG,CAAAA,CAClBF,CAAAA,CAAaC,CAAAA,EAEjB,CAEA,IAAIE,CAAAA,CAAoBN,CAAAA,CACpBG,CAAAA,GAAe,IAAA,GACjBG,CAAAA,CAAoB7B,CAAAA,CAAAA,CACd0B,CAAAA,CAAaxB,CAAAA,CAAc,CAAA,CAAIS,EAAK,IAAA,GAASA,CAAAA,CAAK,KAAA,CAAQT,CAAAA,CAAAA,CAAgB,GAAA,CAAA,CAC1EwB,CAAAA,CAAaxB,CAAAA,CAAc,CAAA,CAAIS,CAAAA,CAAK,GAAA,GAAQA,CAAAA,CAAK,MAAA,CAAST,CAAAA,CAAAA,CAAgB,GAAA,CAAA,CAGlF,IAAM4B,CAAAA,CAAkB,KAAK,GAAA,CAC3BrE,CAAAA,CACA,IAAA,CAAK,GAAA,CAAIC,CAAAA,CAAoBmE,CAAiB,CAChD,CAAA,CACAV,CAAAA,CAAoBW,CAAAA,CACpB,IAAMjD,CAAAA,CAAYrD,CAAAA,CAAsBiB,CAAAA,CAAQ8C,CAAAA,CAAauC,CAAe,EAC5E3B,CAAAA,CAAetB,CAAS,CAAA,CACpB0B,CAAAA,EACFA,CAAAA,CAAehB,CAAAA,CAAauC,CAAe,EAE/C,EAEMC,CAAAA,CAAkB,IAAM,CAC5B,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,iBAAiB,EAChDhB,CAAAA,CAAU,eAAA,CAAgB,eAAe,CAAA,CAEzC,IAAMiB,CAAAA,CAAc,QAAA,CAAS,cAAA,CAAe,4BAA4B,CAAA,CACpEA,CAAAA,EACFA,CAAAA,CAAY,MAAA,EAAO,CAGrB,QAAA,CAAS,mBAAA,CAAoB,cAAeZ,CAAiB,CAAA,CAC7D,QAAA,CAAS,mBAAA,CAAoB,WAAA,CAAaW,CAAe,CAAA,CAErD1B,CAAAA,EACFA,GAAiB,CAEfG,CAAAA,EACFA,CAAAA,CAAkBjB,CAAAA,CAAa4B,CAAiB,EAEpD,CAAA,CAEA,QAAA,CAAS,iBAAiB,aAAA,CAAeC,CAAiB,CAAA,CAC1D,QAAA,CAAS,gBAAA,CAAiB,WAAA,CAAaW,CAAe,EACxD,CAAA,CACA,CACEhC,CAAAA,CACAC,CAAAA,CACArF,CAAAA,CACAsF,CAAAA,CACAC,CAAAA,CACAhD,CAAAA,CACAT,EACA8C,CAAAA,CACAY,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACA/C,CAAAA,CACAC,CACF,CACF,CACF,CCnJA,IAAMuE,EAAAA,CAAsC,CAAC,CAC3C,WAAA,CAAA1C,CAAAA,CACA,WAAA,CAAAW,CAAAA,CACA,aAAA,CAAAhD,CAAAA,CACA,cAAegF,CACjB,CAAA,GAAM,CACJ,GAAM,CAAE,MAAA,CAAAzF,CAAAA,CAAQ,cAAA,CAAA0D,CAAAA,CAAgB,UAAA,CAAAtD,CAAAA,CAAY,aAAA,CAAesF,CAAqB,CAAA,CAAIlI,CAAAA,EAAa,CAC3F,CAACmI,CAAAA,CAAYC,CAAa,CAAA,CAAIxE,cAAAA,CAAS,KAAK,CAAA,CAE5CL,CAAAA,CAAgB0E,CAAAA,EAAqBC,CAAAA,CAErCpC,CAAAA,CAAe5D,YAAAA,CAAuB,IAAI,CAAA,CAC1C,CAAE,SAAA,CAAAxB,CAAAA,CAAW,MAAA2H,CAAAA,CAAO,MAAA,CAAAC,CAAAA,CAAQ,eAAA,CAAAtC,CAAgB,CAAA,CAAIV,CAAAA,CAChDS,CAAAA,CAAQrF,IAAc,KAAA,CAEtB6H,CAAAA,CAAoB1C,CAAAA,CAAW,CACnC,YAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,UAAArF,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAehD,CAAAA,EAAiB,CAAA,CAChC,MAAA,CAAAT,CAAAA,CACA,WAAA,CAAA8C,CAAAA,CACA,cAAA,CAAAY,CAAAA,CACA,aAAA,CAAe,IAAMkC,EAAc,IAAI,CAAA,CACvC,WAAA,CAAa,IAAMA,CAAAA,CAAc,KAAK,CACxC,CAAC,EAED,OACE1C,eAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKI,CAAAA,CACL,KAAA,CAAO,CACL,OAAA,CAAS,OACT,aAAA,CAAeC,CAAAA,CAAQ,KAAA,CAAQ,QAAA,CAC/B,KAAA,CAAO,MAAA,CACP,MAAA,CAAQ,MAAA,CACR,QAAA,CAAU,QACZ,CAAA,CAEA,QAAA,CAAA,CAAAzD,cAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAM,CAAA,EAAG0D,CAAe,CAAA,KAAA,CAAA,CAAS,QAAA,CAAU,QAAS,CAAA,CAChE,QAAA,CAAA1D,cAAAA,CAACkG,EAAA,CACC,IAAA,CAAMH,CAAAA,CACN,WAAA,CAAapC,CAAAA,CACb,aAAA,CAAehD,CAAAA,CACf,aAAA,CAAegF,EACjB,CAAA,CACF,CAAA,CACC1E,CAAAA,CACCA,CAAAA,CAAc,CACZ,SAAA,CAAA7C,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,UAAA,CAAAkC,CAAAA,CACA,aAAA,CAAeI,CACjB,CAAC,EAEDjG,cAAAA,CAAC,KAAA,CAAA,CACC,SAAA,CAAWM,CAAAA,CAAW,OAAA,CACtB,gBAAA,CAAgBlC,CAAAA,CAChB,KAAA,CAAO,CACL,KAAA,CAAOqF,CAAAA,CAAQ,CAAA,EAAGE,CAAW,CAAA,EAAA,CAAA,CAAO,MAAA,CACpC,MAAA,CAAQF,EAAQ,MAAA,CAAS,CAAA,EAAGE,CAAW,CAAA,EAAA,CAAA,CACvC,MAAA,CAAQF,CAAAA,CAAQ,YAAA,CAAe,YAAA,CAC/B,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,EAAA,CACR,UAAA,CAAY,MAAA,CACZ,SAAA,CAAW,YAAA,CACX,WAAY,CACd,CAAA,CACA,aAAA,CAAewC,CAAAA,CACf,IAAA,CAAK,WAAA,CACL,eAAA,CAAevC,CAAAA,CACf,gBAAe,CAAA,CACf,eAAA,CAAe,EAAA,CACjB,CAAA,CAEF1D,cAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAM,CAAA,EAAG,GAAA,CAAM0D,CAAe,CAAA,KAAA,CAAA,CAAS,QAAA,CAAU,QAAS,CAAA,CACtE,QAAA,CAAA1D,cAAAA,CAACkG,CAAAA,CAAA,CACC,IAAA,CAAMF,CAAAA,CACN,WAAA,CAAarC,CAAAA,CACb,aAAA,CAAehD,EACf,aAAA,CAAegF,CAAAA,CACjB,CAAA,CACF,CAAA,CAAA,CACF,CAEJ,CAAA,CAEaO,CAAAA,CAAoC,CAAC,CAChD,IAAA,CAAApI,CAAAA,CACA,WAAA,CAAA6F,CAAAA,CAAc,CAAA,CACd,aAAA,CAAewC,CAAAA,CACf,aAAA,CAAAlF,CACF,CAAA,GAAM,CACJ,GAAM,CACJ,MAAA,CAAAf,CAAAA,CACA,UAAA,CAAAE,CAAAA,CACA,gBAAA,CAAAG,CAAAA,CACA,aAAA,CAAe6F,CACjB,CAAA,CAAI1I,CAAAA,EAAa,CAEXiD,CAAAA,CAAgBwF,IAAsB,MAAA,CAAYA,CAAAA,CAAoBC,CAAAA,CAG5E,GAAI7F,CAAAA,EAAoB,CAACzC,CAAAA,CACvB,OACEkC,eAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,QAAA,CAAU,UAAW,CAAA,CAC/D,QAAA,CAAAI,CAAAA,CAAWG,CAAgB,CAAA,CAC9B,CAAA,CAIJ,IAAMyC,CAAAA,CAAclF,CAAAA,GAAS,MAAA,CAAYA,CAAAA,CAAOoC,CAAAA,CAEhD,OAAK8C,CAAAA,CAEDA,CAAAA,CAAY,IAAA,GAAS,OAErBhD,cAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,QAAA,CAAU,UAAW,CAAA,CAC/D,QAAA,CAAAI,CAAAA,CAAW4C,CAAAA,CAAY,MAAM,CAAA,CAChC,EAKFhD,cAAAA,CAAC0F,EAAAA,CAAA,CACC,WAAA,CAAa1C,CAAAA,CACb,WAAA,CAAaW,CAAAA,CACb,aAAA,CAAehD,CAAAA,CACf,aAAA,CAAeM,CAAAA,CACjB,CAAA,CAhBuB,IAkB3B,ECzJO,IAAMoF,CAAAA,CAAmB5I,mBAAAA,CAA8C,IAAI,CAAA,CCUlF,IAAM6I,EAAAA,CAA2D,CAC/D,GAAA,CAAK,CACH,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,KAAA,CACN,MAAO,KAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,OAAQ,CACN,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,KAAA,CACN,KAAA,CAAO,MACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,IAAA,CAAM,CACJ,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,EACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,MAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,EACA,KAAA,CAAO,CACL,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,MAAO,CAAA,CACP,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,MAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,KAAA,CACL,KAAM,KAAA,CACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CACF,CAAA,CAEMC,EAAAA,CAAwD,CAC5D,GAAA,CAAK,CACH,QAAA,CAAU,WACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,OAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,KAAM,CACJ,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,KAAA,CAAO,CACL,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,EACR,KAAA,CAAO,CAAA,CACP,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,UAAW,YACb,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAAA,CACR,MAAA,CAAQ,EAAA,CACR,cAAe,MAAA,CACf,SAAA,CAAW,YACb,CACF,CAAA,CAEMC,EAAAA,CAAoC,CAAC,CAAE,GAAAC,CAAAA,CAAI,QAAA,CAAAC,CAAAA,CAAU,eAAA,CAAAC,CAAgB,CAAA,GAAM,CAC/E,GAAM,CAAE,UAAA,CAAAC,CAAAA,CAAY,MAAA,CAAAC,CAAO,CAAA,CAAIC,iBAAAA,CAAa,CAAE,EAAA,CAAAL,CAAG,CAAC,CAAA,CAClD,OACErD,eAAAA,CAAA2D,mBAAAA,CAAA,CACE,QAAA,CAAA,CAAA/G,eAAC,KAAA,CAAA,CAAI,GAAA,CAAK4G,CAAAA,CAAY,KAAA,CAAON,EAAAA,CAAoBI,CAAQ,CAAA,CAAG,CAAA,CAC3DG,CAAAA,EAAU7G,cAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAW2G,CAAAA,CAAiB,KAAA,CAAOJ,EAAAA,CAAiBG,CAAQ,EAAG,CAAA,CAAA,CACjF,CAEJ,CAAA,CAQaM,EAAAA,CAA4B,CAAC,CAAE,EAAA,CAAAP,CAAAA,CAAI,QAAA,CAAArF,CAAAA,CAAU,KAAA,CAAA6F,CAAM,CAAA,GAAM,CACpE,GAAM,CAAE,SAAAzH,CAAAA,CAAU,UAAA,CAAAc,CAAAA,CAAY,gBAAA,CAAAC,CAAAA,CAAkB,QAAA,CAAAE,CAAAA,CAAU,kBAAA,CAAAD,EAAoB,UAAA,CAAA3C,CAAW,CAAA,CACvFH,CAAAA,EAAa,CACTwJ,CAAAA,CAAgB1H,CAAAA,GAAa,IAAA,EAAQA,IAAaiH,CAAAA,CAElD,CAAE,UAAA,CAAAU,CAAAA,CAAY,SAAA,CAAAC,CAAAA,CAAW,UAAA,CAAAR,CAAAA,CAAY,UAAA,CAAAS,CAAW,CAAA,CAAIC,iBAAAA,CAAa,CAAE,EAAA,CAAAb,CAAG,CAAC,EACvEc,CAAAA,CAAW/H,CAAAA,GAAaiH,CAAAA,EAAMY,CAAAA,CAC9BG,CAAAA,CAAejH,CAAAA,GAAqBkG,CAAAA,CAEpCgB,CAAAA,CAA+B,CACnC,UAAA,CAAYF,CAAAA,CACZ,YAAA,CAAAC,CAAAA,CACA,gBAAA,CAAkB,IAAMhH,CAAAA,GAAqBgH,CAAAA,CAAe,KAAOf,CAAE,CAAA,CACrE,MAAA,CAAQ,IAAM,CACRe,CAAAA,EACFhH,CAAAA,GAAqB,IAAI,CAAA,CAEvBC,CAAAA,CACFA,CAAAA,CAASgG,CAAE,CAAA,CAEX5I,CAAAA,CAAW4I,CAAE,EAEjB,CACF,CAAA,CAGMvD,CAAAA,CAAeC,aAAAA,CACnB,KAAO,CACL,GAAGiE,CAAAA,CACH,GAAGD,CACL,CAAA,CAAA,CACA,CAACC,CAAAA,CAAWD,CAAU,CACxB,CAAA,CAEA,OACEnH,cAAAA,CAACqG,EAAiB,QAAA,CAAjB,CAA0B,KAAA,CAAOnD,CAAAA,CAChC,QAAA,CAAAE,eAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKwD,CAAAA,CACL,SAAA,CAAWtG,CAAAA,CAAW,IAAA,CACtB,KAAA,CAAO,CAAE,QAAA,CAAU,UAAA,CAAY,MAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,GAAG2G,CAAM,CAAA,CAEtE,QAAA,CAAA,CAAA7F,CAAAA,CAASqG,CAAW,CAAA,CAEpBP,CAAAA,EACC9D,eAAAA,CAAC,KAAA,CAAA,CACC,KAAA,CAAO,CACL,QAAA,CAAU,WACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CAEE,QAAA,CAAA,CAAA,CAAC,KAAA,CAAO,QAAA,CAAU,OAAQ,OAAO,CAAA,CAAY,GAAA,CAAKgC,CAAAA,EAClDpF,cAAAA,CAACwG,EAAAA,CAAA,CAEC,EAAA,CAAI,QAAQpB,CAAG,CAAA,CAAA,EAAIqB,CAAE,CAAA,CAAA,CACrB,QAAA,CAAUrB,CAAAA,CACV,eAAA,CAAiB9E,CAAAA,CAAW,aAHvB8E,CAIP,CACD,CAAA,CACDpF,cAAAA,CAACwG,EAAAA,CAAA,CACC,EAAA,CAAI,CAAA,YAAA,EAAeC,CAAE,CAAA,CAAA,CACrB,QAAA,CAAS,QAAA,CACT,eAAA,CAAiBnG,CAAAA,CAAW,WAAA,CAC9B,CAAA,CAAA,CACF,GAEJ,CAAA,CACF,CAEJ,ECnMO,IAAMoH,EAAAA,CAAwC,CAAC,CAAE,QAAA,CAAAtG,CAAAA,CAAU,SAAA,CAAA1B,EAAW,KAAA,CAAAuH,CAAM,CAAA,GAAM,CACvF,IAAMU,CAAAA,CAAY/J,gBAAAA,CAAWyI,CAAgB,CAAA,CAC7C,GAAI,CAACsB,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,2CAA2C,EAE7D,OACE3H,cAAAA,CAAC,KAAA,CAAA,CACC,SAAA,CAAWN,CAAAA,CACX,KAAA,CAAO,CAAE,MAAA,CAAQ,OAAQ,UAAA,CAAY,MAAA,CAAQ,GAAGuH,CAAM,CAAA,CACrD,GAAGU,CAAAA,CAEH,QAAA,CAAAvG,EACH,CAEJ","file":"index.cjs","sourcesContent":["import { createContext, ReactNode } from 'react'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\n\nexport interface ZeugmaClassNames {\n pane?: string\n dropPreview?: string\n swapPreview?: string\n dragOverlay?: string\n resizer?: string\n}\n\nexport interface ResizerRenderProps {\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n isResizing: boolean\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void\n}\n\nexport interface DashboardContextValue {\n layout: TreeNode | null\n onLayoutChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n activeId: string | null\n fullscreenPaneId: string | null\n classNames: ZeugmaClassNames\n onRemove?: (paneId: string) => void\n onFullscreenChange?: (paneId: string | null) => void\n snapThreshold?: number\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n removePane: (paneId: string) => void\n addPane: (paneId: string) => void\n swapPanes: (paneIdA: string, paneIdB: string) => void\n splitPane: (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => void\n updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void\n}\n\nexport const DashboardContext = createContext<DashboardContextValue | undefined>(undefined)\n","import { useContext } from 'react'\nimport { DashboardContext } from './context'\n\nexport const useDashboard = () => {\n const context = useContext(DashboardContext)\n if (!context) {\n throw new Error('useDashboard must be used within a DashboardProvider')\n }\n return context\n}\n","import { TreeNode, SplitNode, SplitDirection, PaneNode } from '../../model'\n\n/**\n * Tree Helper: Remove a pane and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, idToRemove: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.paneId === idToRemove ? null : tree\n }\n const newFirst = removePane(tree.first, idToRemove)\n const newSecond = removePane(tree.second, idToRemove)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n): TreeNode | null {\n if (tree === null) return { type: 'pane', paneId: paneToAdd }\n if (tree.type === 'pane') {\n if (tree.paneId === targetId) {\n const addedNode: PaneNode = { type: 'pane', paneId: paneToAdd }\n const originalNode: PaneNode = { type: 'pane', paneId: targetId }\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : originalNode,\n second: isFirst ? originalNode : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Swap the position of two panes in the tree structure.\n */\nexport function swapPanes(tree: TreeNode | null, idA: string, idB: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.paneId === idA) return { ...tree, paneId: idB }\n if (tree.paneId === idB) return { ...tree, paneId: idA }\n return tree\n }\n return {\n ...tree,\n first: swapPanes(tree.first, idA, idB) || tree.first,\n second: swapPanes(tree.second, idA, idB) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.\n */\nexport function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode {\n if (tree === null) {\n return { type: 'pane', paneId: paneToAdd }\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: { type: 'pane', paneId: paneToAdd },\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage } as SplitNode\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n","export const DEFAULT_SNAP_THRESHOLD = 8 // px\nexport const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8 // px\nexport const DEFAULT_RESIZER_SIZE = 4 // px\n","import React, { useState, useEffect, useRef, ReactNode, useMemo, useCallback } from 'react'\nimport {\n DndContext,\n useSensor,\n useSensors,\n PointerSensor,\n DragStartEvent,\n DragEndEvent,\n pointerWithin,\n} from '@dnd-kit/core'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\nimport {\n removePane,\n splitPane,\n swapPanes,\n addPane,\n updateSplitPercentage,\n} from '../../../shared/lib/tree'\nimport { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_SNAP_THRESHOLD } from '../../../shared/config'\nimport { DashboardContext, ZeugmaClassNames, ResizerRenderProps } from '../model/context'\n\n/** Cursor-following overlay rendered via portal */\nconst CursorOverlay: React.FC<{\n activeId: string\n render: (id: string) => ReactNode\n className?: string\n}> = ({ activeId, render, className }) => {\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const handleMove = (e: PointerEvent) => {\n if (ref.current) {\n ref.current.style.transform = `translate(${e.clientX + 12}px, ${e.clientY + 12}px)`\n }\n }\n document.addEventListener('pointermove', handleMove)\n return () => document.removeEventListener('pointermove', handleMove)\n }, [])\n\n return (\n <div\n ref={ref}\n className={className}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n zIndex: 9999,\n pointerEvents: 'none',\n }}\n >\n {render(activeId)}\n </div>\n )\n}\n\ninterface DashboardProviderProps {\n layout: TreeNode | null\n onChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n renderDragOverlay?: (activeId: string) => ReactNode\n classNames?: ZeugmaClassNames\n fullscreenPaneId?: string | null\n onFullscreenChange?: (paneId: string | null) => void\n onRemove?: (paneId: string) => void\n dragActivationDistance?: number\n snapThreshold?: number\n onDragStart?: (activeId: string) => void\n onDragEnd?: (\n activeId: string,\n overId: string | null,\n dropAction: {\n type: 'split' | 'swap'\n direction?: SplitDirection\n position?: 'top' | 'bottom' | 'left' | 'right' | 'center'\n } | null,\n ) => void\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n children: ReactNode\n}\n\nexport const DashboardProvider: React.FC<DashboardProviderProps> = ({\n layout,\n onChange,\n renderPane,\n renderDragOverlay,\n classNames = {},\n fullscreenPaneId = null,\n onFullscreenChange,\n onRemove,\n dragActivationDistance = DEFAULT_DRAG_ACTIVATION_DISTANCE,\n snapThreshold = DEFAULT_SNAP_THRESHOLD,\n onDragStart,\n onDragEnd,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n children,\n}) => {\n const [activeId, setActiveId] = useState<string | null>(null)\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: dragActivationDistance },\n }),\n )\n\n const handleDragStart = (event: DragStartEvent) => {\n const draggingId = event.active.id.toString()\n setActiveId(draggingId)\n if (onDragStart) {\n onDragStart(draggingId)\n }\n }\n\n const handleDragEnd = (event: DragEndEvent) => {\n setActiveId(null)\n const { active, over } = event\n const draggingId = active.id.toString()\n\n if (!over) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const overIdStr = over.id.toString()\n\n // Check for center (swap) drop\n const swapMatch = overIdStr.match(/^drop-center-(.+)$/)\n if (swapMatch) {\n const [, targetId] = swapMatch\n if (draggingId !== targetId) {\n onChange(swapPanes(layout, draggingId, targetId))\n }\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, { type: 'swap', position: 'center' })\n }\n return\n }\n\n // Check for edge (split) drop\n const match = overIdStr.match(/^drop-(left|right|top|bottom)-(.+)$/)\n if (!match) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const [, dropZone, targetId] = match\n if (draggingId === targetId) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const direction: SplitDirection = dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n const treeWithoutDragging = removePane(layout, draggingId)\n\n const newLayout = splitPane(\n treeWithoutDragging,\n targetId,\n direction,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n draggingId,\n )\n onChange(newLayout)\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n }\n\n const handleRemovePane = useCallback(\n (paneId: string) => {\n const newLayout = removePane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleAddPane = useCallback(\n (paneId: string) => {\n const newLayout = addPane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSwapPanes = useCallback(\n (paneIdA: string, paneIdB: string) => {\n const newLayout = swapPanes(layout, paneIdA, paneIdB)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSplitPane = useCallback(\n (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => {\n const newLayout = splitPane(layout, targetId, direction, splitType, paneToAdd)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleUpdateSplitPercentage = useCallback(\n (currentNode: SplitNode, percentage: number) => {\n const newLayout = updateSplitPercentage(layout, currentNode, percentage)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n // Best practice: Memoize context value to prevent unnecessary re-renders of context consumers.\n const contextValue = useMemo(\n () => ({\n layout,\n onLayoutChange: onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n removePane: handleRemovePane,\n addPane: handleAddPane,\n swapPanes: handleSwapPanes,\n splitPane: handleSplitPane,\n updateSplitPercentage: handleUpdateSplitPercentage,\n }),\n [\n layout,\n onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n handleRemovePane,\n handleAddPane,\n handleSwapPanes,\n handleSplitPane,\n handleUpdateSplitPercentage,\n ],\n )\n\n return (\n <DashboardContext.Provider value={contextValue}>\n <DndContext\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n {children}\n </DndContext>\n {activeId && renderDragOverlay && (\n <CursorOverlay\n activeId={activeId}\n render={renderDragOverlay}\n className={classNames.dragOverlay}\n />\n )}\n </DashboardContext.Provider>\n )\n}\n","import React, { useCallback } from 'react'\nimport { TreeNode, SplitNode, SplitDirection } from '../../../shared/model'\nimport { updateSplitPercentage } from '../../../shared/lib/tree'\nimport { useDashboard } from '../../../entities/dashboard'\n\ninterface UseResizerProps {\n containerRef: React.RefObject<HTMLDivElement | null>\n isRow: boolean\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n snapThreshold: number\n layout: TreeNode | null\n currentNode: SplitNode\n onLayoutChange: (newLayout: TreeNode | null) => void\n onResizeStart?: () => void\n onResizeEnd?: () => void\n}\n\nexport function useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: localOnResizeStart,\n onResizeEnd: localOnResizeEnd,\n}: UseResizerProps) {\n const {\n onResizeStart: globalOnResizeStart,\n onResize: globalOnResize,\n onResizeEnd: globalOnResizeEnd,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n } = useDashboard()\n\n return useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault()\n const container = containerRef.current\n if (!container) return\n\n document.body.classList.add('zeugma-resizing')\n\n // Inject global cursor style to keep resizing cursor active across the entire page during drag\n const styleEl = document.createElement('style')\n styleEl.id = 'zeugma-global-cursor-style'\n styleEl.textContent = `\n * {\n cursor: ${isRow ? 'col-resize' : 'row-resize'} !important;\n user-select: none !important;\n }\n `\n document.head.appendChild(styleEl)\n\n if (localOnResizeStart) {\n localOnResizeStart()\n }\n if (globalOnResizeStart) {\n globalOnResizeStart(currentNode)\n }\n\n const rect = container.getBoundingClientRect()\n const startX = e.clientX\n const startY = e.clientY\n const startPercentage = splitPercentage\n\n // Cache other resizers of the same direction once at drag-start to prevent layout thrashing on move\n const resizerEl = e.currentTarget\n resizerEl.setAttribute('data-resizing', 'true')\n\n const otherResizers = Array.from(\n document.querySelectorAll('div[role=\"separator\"][data-direction]'),\n ).filter((el) => el !== resizerEl && el.getAttribute('data-direction') === direction)\n\n const otherPositions = otherResizers.map((el) => {\n const r = el.getBoundingClientRect()\n return isRow ? r.left + r.width / 2 : r.top + r.height / 2\n })\n\n let currentPercentage = startPercentage\n\n const handlePointerMove = (moveEvent: PointerEvent) => {\n const delta = isRow\n ? ((moveEvent.clientX - startX) / rect.width) * 100\n : ((moveEvent.clientY - startY) / rect.height) * 100\n const proposedPercentage = startPercentage + delta\n\n // Find physical position corresponding to proposed percentage\n const proposedPos = isRow\n ? rect.left + (rect.width - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n : rect.top + (rect.height - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n\n let closestDistance = Infinity\n let bestTarget: number | null = null\n\n for (const pos of otherPositions) {\n const dist = Math.abs(proposedPos - pos)\n if (dist < snapThreshold && dist < closestDistance) {\n closestDistance = dist\n bestTarget = pos\n }\n }\n\n let snappedPercentage = proposedPercentage\n if (bestTarget !== null) {\n snappedPercentage = isRow\n ? ((bestTarget - resizerSize / 2 - rect.left) / (rect.width - resizerSize)) * 100\n : ((bestTarget - resizerSize / 2 - rect.top) / (rect.height - resizerSize)) * 100\n }\n\n const finalPercentage = Math.max(\n minSplitPercentage,\n Math.min(maxSplitPercentage, snappedPercentage),\n )\n currentPercentage = finalPercentage\n const newLayout = updateSplitPercentage(layout, currentNode, finalPercentage)\n onLayoutChange(newLayout)\n if (globalOnResize) {\n globalOnResize(currentNode, finalPercentage)\n }\n }\n\n const handlePointerUp = () => {\n document.body.classList.remove('zeugma-resizing')\n resizerEl.removeAttribute('data-resizing')\n\n const globalStyle = document.getElementById('zeugma-global-cursor-style')\n if (globalStyle) {\n globalStyle.remove()\n }\n\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n\n if (localOnResizeEnd) {\n localOnResizeEnd()\n }\n if (globalOnResizeEnd) {\n globalOnResizeEnd(currentNode, currentPercentage)\n }\n }\n\n document.addEventListener('pointermove', handlePointerMove)\n document.addEventListener('pointerup', handlePointerUp)\n },\n [\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n localOnResizeStart,\n localOnResizeEnd,\n globalOnResizeStart,\n globalOnResize,\n globalOnResizeEnd,\n minSplitPercentage,\n maxSplitPercentage,\n ],\n )\n}\n","import React, { useRef, useState } from 'react'\nimport { useDashboard, ResizerRenderProps } from '../../../entities/dashboard'\nimport { useResizer } from '../../../features/resize-pane'\nimport { TreeNode, SplitNode } from '../../../shared/model'\n\nexport interface PaneTreeProps {\n tree?: TreeNode | null\n /** Size of the resizer in pixels (default 4) */\n resizerSize?: number\n /** Threshold in pixels to snap to adjacent resizer edges (default 8) */\n snapThreshold?: number\n /** Custom resizer renderer to override context-level renderResizer */\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\ninterface PaneSplitProps {\n currentNode: SplitNode\n resizerSize: number\n snapThreshold?: number\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\nconst PaneSplit: React.FC<PaneSplitProps> = ({\n currentNode,\n resizerSize,\n snapThreshold,\n renderResizer: propRenderResizer,\n}) => {\n const { layout, onLayoutChange, classNames, renderResizer: contextRenderResizer } = useDashboard()\n const [isResizing, setIsResizing] = useState(false)\n\n const renderResizer = propRenderResizer || contextRenderResizer\n\n const containerRef = useRef<HTMLDivElement>(null)\n const { direction, first, second, splitPercentage } = currentNode\n const isRow = direction === 'row'\n\n const handlePointerDown = useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold: snapThreshold ?? 8,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: () => setIsResizing(true),\n onResizeEnd: () => setIsResizing(false),\n })\n\n return (\n <div\n ref={containerRef}\n style={{\n display: 'flex',\n flexDirection: isRow ? 'row' : 'column',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <div style={{ flex: `${splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={first}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n {renderResizer ? (\n renderResizer({\n direction,\n splitPercentage,\n resizerSize,\n isResizing,\n onPointerDown: handlePointerDown,\n })\n ) : (\n <div\n className={classNames.resizer}\n data-direction={direction}\n style={{\n width: isRow ? `${resizerSize}px` : '100%',\n height: isRow ? '100%' : `${resizerSize}px`,\n cursor: isRow ? 'col-resize' : 'row-resize',\n position: 'relative',\n zIndex: 10,\n userSelect: 'none',\n boxSizing: 'border-box',\n flexShrink: 0,\n }}\n onPointerDown={handlePointerDown}\n role=\"separator\"\n aria-valuenow={splitPercentage}\n aria-valuemin={5}\n aria-valuemax={95}\n />\n )}\n <div style={{ flex: `${100 - splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={second}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n </div>\n )\n}\n\nexport const PaneTree: React.FC<PaneTreeProps> = ({\n tree,\n resizerSize = 4,\n snapThreshold: propSnapThreshold,\n renderResizer,\n}) => {\n const {\n layout,\n renderPane,\n fullscreenPaneId,\n snapThreshold: contextSnapThreshold,\n } = useDashboard()\n\n const snapThreshold = propSnapThreshold !== undefined ? propSnapThreshold : contextSnapThreshold\n\n // Fullscreen bypass\n if (fullscreenPaneId && !tree) {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(fullscreenPaneId)}\n </div>\n )\n }\n\n const currentNode = tree !== undefined ? tree : layout\n\n if (!currentNode) return null\n\n if (currentNode.type === 'pane') {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(currentNode.paneId)}\n </div>\n )\n }\n\n return (\n <PaneSplit\n currentNode={currentNode}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={renderResizer}\n />\n )\n}\n","import { createContext } from 'react'\n\nexport const DragListenersCtx = createContext<Record<string, unknown> | null>(null)\n","import React, { useMemo } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport { useDashboard } from '../../dashboard'\nimport { DragListenersCtx } from '../model/context'\nimport { PaneRenderProps } from '../model/types'\n\ninterface DropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right' | 'center'\n activeClassName?: string\n}\n\nconst activationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n center: {\n position: 'absolute',\n top: '25%',\n left: '25%',\n width: '50%',\n height: '50%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n}\n\nconst previewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n center: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={activationPositions[position]} />\n {isOver && <div className={activeClassName} style={previewPositions[position]} />}\n </>\n )\n}\n\ninterface PaneProps {\n id: string\n children: (props: PaneRenderProps) => React.ReactNode\n style?: React.CSSProperties\n}\n\nexport const Pane: React.FC<PaneProps> = ({ id, children, style }) => {\n const { activeId, classNames, fullscreenPaneId, onRemove, onFullscreenChange, removePane } =\n useDashboard()\n const showDropZones = activeId !== null && activeId !== id\n\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id })\n const dragging = activeId === id || isDragging\n const isFullscreen = fullscreenPaneId === id\n\n const renderProps: PaneRenderProps = {\n isDragging: dragging,\n isFullscreen,\n toggleFullscreen: () => onFullscreenChange?.(isFullscreen ? null : id),\n remove: () => {\n if (isFullscreen) {\n onFullscreenChange?.(null)\n }\n if (onRemove) {\n onRemove(id)\n } else {\n removePane(id)\n }\n },\n }\n\n // Best practice: Memoize drag context value to prevent unnecessary re-renders of the drag handle.\n const contextValue = useMemo(\n () => ({\n ...listeners,\n ...attributes,\n }),\n [listeners, attributes],\n )\n\n return (\n <DragListenersCtx.Provider value={contextValue}>\n <div\n ref={setNodeRef}\n className={classNames.pane}\n style={{ position: 'relative', width: '100%', height: '100%', ...style }}\n >\n {children(renderProps)}\n\n {showDropZones && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 15,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <DropZone\n key={pos}\n id={`drop-${pos}-${id}`}\n position={pos}\n activeClassName={classNames.dropPreview}\n />\n ))}\n <DropZone\n id={`drop-center-${id}`}\n position=\"center\"\n activeClassName={classNames.swapPreview}\n />\n </div>\n )}\n </div>\n </DragListenersCtx.Provider>\n )\n}\n","import React, { useContext } from 'react'\nimport { DragListenersCtx } from '../model/context'\n\ninterface DragHandleProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\nexport const DragHandle: React.FC<DragHandleProps> = ({ children, className, style }) => {\n const dragProps = useContext(DragListenersCtx)\n if (!dragProps) {\n throw new Error('<DragHandle> must be used inside a <Pane>')\n }\n return (\n <div\n className={className}\n style={{ cursor: 'grab', userSelect: 'none', ...style }}\n {...dragProps}\n >\n {children}\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/entities/dashboard/model/context.ts","../src/entities/dashboard/model/hooks.ts","../src/shared/lib/tree/tree-helpers.ts","../src/shared/config/constants.ts","../src/entities/dashboard/ui/RootDropZone.tsx","../src/entities/dashboard/ui/DashboardProvider.tsx","../src/features/resize-pane/hooks/useResizer.ts","../src/widgets/pane-tree/ui/PaneTree.tsx","../src/entities/pane/model/context.ts","../src/entities/pane/ui/Pane.tsx","../src/entities/pane/ui/DragHandle.tsx"],"names":["DashboardContext","createContext","useDashboard","context","useContext","removePane","tree","idToRemove","newFirst","newSecond","splitPane","targetId","direction","splitType","paneToAdd","addedNode","originalNode","isFirst","swapPanes","idA","idB","addPane","insert","node","parentDirection","updateSplitPercentage","target","newPercentage","splitRoot","draggingId","treeWithoutDragging","draggedNode","DEFAULT_SNAP_THRESHOLD","DEFAULT_DRAG_ACTIVATION_DISTANCE","DEFAULT_RESIZER_SIZE","rootActivationPositions","rootPreviewPositions","RootDropZone","id","position","activeClassName","setNodeRef","isOver","useDroppable","jsxs","Fragment","jsx","RootDropZones","activeId","hasOtherPanes","dropPreviewClassName","pos","CursorOverlay","render","className","ref","useRef","useEffect","handleMove","e","DashboardProvider","layout","onChange","renderPane","renderDragOverlay","classNames","fullscreenPaneId","onFullscreenChange","onRemove","dragActivationDistance","snapThreshold","onDragStart","onDragEnd","onResizeStart","onResize","onResizeEnd","renderResizer","minSplitPercentage","maxSplitPercentage","children","setActiveId","useState","sensors","useSensors","useSensor","PointerSensor","handleDragStart","event","handleDragEnd","active","over","overIdStr","rootMatch","dropZone","newLayout","swapMatch","match","handleRemovePane","useCallback","paneId","handleAddPane","handleSwapPanes","paneIdA","paneIdB","handleSplitPane","handleUpdateSplitPercentage","currentNode","percentage","contextValue","useMemo","DndContext","pointerWithin","useResizer","containerRef","isRow","splitPercentage","resizerSize","onLayoutChange","localOnResizeStart","localOnResizeEnd","globalOnResizeStart","globalOnResize","globalOnResizeEnd","container","styleEl","rect","startX","startY","startPercentage","resizerEl","otherPositions","el","r","currentPercentage","handlePointerMove","moveEvent","delta","proposedPercentage","proposedPos","closestDistance","bestTarget","dist","snappedPercentage","finalPercentage","handlePointerUp","globalStyle","PaneSplit","propRenderResizer","contextRenderResizer","isResizing","setIsResizing","first","second","handlePointerDown","PaneTree","propSnapThreshold","contextSnapThreshold","DragListenersCtx","activationPositions","previewPositions","DropZone","Pane","style","showDropZones","attributes","listeners","isDragging","useDraggable","dragging","isFullscreen","renderProps","DragHandle","dragProps"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, ReactNode } from 'react'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\n\nexport interface ZeugmaClassNames {\n pane?: string\n dropPreview?: string\n swapPreview?: string\n dragOverlay?: string\n resizer?: string\n}\n\nexport interface ResizerRenderProps {\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n isResizing: boolean\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void\n}\n\nexport interface DashboardContextValue {\n layout: TreeNode | null\n onLayoutChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n activeId: string | null\n fullscreenPaneId: string | null\n classNames: ZeugmaClassNames\n onRemove?: (paneId: string) => void\n onFullscreenChange?: (paneId: string | null) => void\n snapThreshold?: number\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n removePane: (paneId: string) => void\n addPane: (paneId: string) => void\n swapPanes: (paneIdA: string, paneIdB: string) => void\n splitPane: (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => void\n updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void\n}\n\nexport const DashboardContext = createContext<DashboardContextValue | undefined>(undefined)\n","import { useContext } from 'react'\nimport { DashboardContext } from './context'\n\nexport const useDashboard = () => {\n const context = useContext(DashboardContext)\n if (!context) {\n throw new Error('useDashboard must be used within a DashboardProvider')\n }\n return context\n}\n","import { TreeNode, SplitNode, SplitDirection, PaneNode } from '../../model'\n\n/**\n * Tree Helper: Remove a pane and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, idToRemove: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.paneId === idToRemove ? null : tree\n }\n const newFirst = removePane(tree.first, idToRemove)\n const newSecond = removePane(tree.second, idToRemove)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n): TreeNode | null {\n if (tree === null) return { type: 'pane', paneId: paneToAdd }\n if (tree.type === 'pane') {\n if (tree.paneId === targetId) {\n const addedNode: PaneNode = { type: 'pane', paneId: paneToAdd }\n const originalNode: PaneNode = { type: 'pane', paneId: targetId }\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : originalNode,\n second: isFirst ? originalNode : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Swap the position of two panes in the tree structure.\n */\nexport function swapPanes(tree: TreeNode | null, idA: string, idB: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.paneId === idA) return { ...tree, paneId: idB }\n if (tree.paneId === idB) return { ...tree, paneId: idA }\n return tree\n }\n return {\n ...tree,\n first: swapPanes(tree.first, idA, idB) || tree.first,\n second: swapPanes(tree.second, idA, idB) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.\n */\nexport function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode {\n if (tree === null) {\n return { type: 'pane', paneId: paneToAdd }\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: { type: 'pane', paneId: paneToAdd },\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage } as SplitNode\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n\n/**\n * Tree Helper: Split the entire tree at the root using a dragged pane.\n */\nexport function splitRoot(\n tree: TreeNode | null,\n draggingId: string,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n): TreeNode | null {\n const treeWithoutDragging = removePane(tree, draggingId)\n if (treeWithoutDragging === null) {\n return { type: 'pane', paneId: draggingId }\n }\n\n const direction: SplitDirection = splitType === 'left' || splitType === 'right' ? 'row' : 'column'\n const isFirst = splitType === 'left' || splitType === 'top'\n const draggedNode: TreeNode = { type: 'pane', paneId: draggingId }\n\n return {\n type: 'split',\n direction,\n first: isFirst ? draggedNode : treeWithoutDragging,\n second: isFirst ? treeWithoutDragging : draggedNode,\n splitPercentage: 50,\n }\n}\n","export const DEFAULT_SNAP_THRESHOLD = 8 // px\nexport const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8 // px\nexport const DEFAULT_RESIZER_SIZE = 4 // px\n","import React from 'react'\nimport { useDroppable } from '@dnd-kit/core'\n\nconst rootActivationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n}\n\nconst rootPreviewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nexport interface RootDropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right'\n activeClassName?: string\n}\n\nexport const RootDropZone: React.FC<RootDropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={rootActivationPositions[position]} />\n {isOver && <div className={activeClassName} style={rootPreviewPositions[position]} />}\n </>\n )\n}\n\nexport interface RootDropZonesProps {\n activeId: string | null\n hasOtherPanes: boolean\n dropPreviewClassName?: string\n}\n\nexport const RootDropZones: React.FC<RootDropZonesProps> = ({\n activeId,\n hasOtherPanes,\n dropPreviewClassName,\n}) => {\n if (!activeId || !hasOtherPanes) return null\n\n return (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 30,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <RootDropZone\n key={pos}\n id={`drop-root-${pos}`}\n position={pos}\n activeClassName={dropPreviewClassName}\n />\n ))}\n </div>\n )\n}\n","import React, { useState, useEffect, useRef, ReactNode, useMemo, useCallback } from 'react'\nimport {\n DndContext,\n useSensor,\n useSensors,\n PointerSensor,\n DragStartEvent,\n DragEndEvent,\n pointerWithin,\n} from '@dnd-kit/core'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\nimport {\n removePane,\n splitPane,\n swapPanes,\n addPane,\n updateSplitPercentage,\n splitRoot,\n} from '../../../shared/lib/tree'\nimport { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_SNAP_THRESHOLD } from '../../../shared/config'\nimport { DashboardContext, ZeugmaClassNames, ResizerRenderProps } from '../model/context'\nimport { RootDropZones } from './RootDropZone'\n\n/** Cursor-following overlay rendered via portal */\nconst CursorOverlay: React.FC<{\n activeId: string\n render: (id: string) => ReactNode\n className?: string\n}> = ({ activeId, render, className }) => {\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const handleMove = (e: PointerEvent) => {\n if (ref.current) {\n ref.current.style.transform = `translate(${e.clientX + 12}px, ${e.clientY + 12}px)`\n }\n }\n document.addEventListener('pointermove', handleMove)\n return () => document.removeEventListener('pointermove', handleMove)\n }, [])\n\n return (\n <div\n ref={ref}\n className={className}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n zIndex: 9999,\n pointerEvents: 'none',\n }}\n >\n {render(activeId)}\n </div>\n )\n}\n\ninterface DashboardProviderProps {\n layout: TreeNode | null\n onChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n renderDragOverlay?: (activeId: string) => ReactNode\n classNames?: ZeugmaClassNames\n fullscreenPaneId?: string | null\n onFullscreenChange?: (paneId: string | null) => void\n onRemove?: (paneId: string) => void\n dragActivationDistance?: number\n snapThreshold?: number\n onDragStart?: (activeId: string) => void\n onDragEnd?: (\n activeId: string,\n overId: string | null,\n dropAction: {\n type: 'split' | 'swap'\n direction?: SplitDirection\n position?: 'top' | 'bottom' | 'left' | 'right' | 'center'\n } | null,\n ) => void\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n children: ReactNode\n}\n\nexport const DashboardProvider: React.FC<DashboardProviderProps> = ({\n layout,\n onChange,\n renderPane,\n renderDragOverlay,\n classNames = {},\n fullscreenPaneId = null,\n onFullscreenChange,\n onRemove,\n dragActivationDistance = DEFAULT_DRAG_ACTIVATION_DISTANCE,\n snapThreshold = DEFAULT_SNAP_THRESHOLD,\n onDragStart,\n onDragEnd,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n children,\n}) => {\n const [activeId, setActiveId] = useState<string | null>(null)\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: dragActivationDistance },\n }),\n )\n\n const handleDragStart = (event: DragStartEvent) => {\n const draggingId = event.active.id.toString()\n setActiveId(draggingId)\n if (onDragStart) {\n onDragStart(draggingId)\n }\n }\n\n const handleDragEnd = (event: DragEndEvent) => {\n setActiveId(null)\n const { active, over } = event\n const draggingId = active.id.toString()\n\n if (!over) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const overIdStr = over.id.toString()\n\n // Check for root drop (places pane like half of the root)\n const rootMatch = overIdStr.match(/^drop-root-(left|right|top|bottom)$/)\n if (rootMatch) {\n const [, dropZone] = rootMatch\n const newLayout = splitRoot(\n layout,\n draggingId,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n )\n onChange(newLayout)\n\n if (onDragEnd) {\n const direction: SplitDirection =\n dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n onDragEnd(draggingId, 'root', {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n return\n }\n\n // Check for center (swap) drop\n const swapMatch = overIdStr.match(/^drop-center-(.+)$/)\n if (swapMatch) {\n const [, targetId] = swapMatch\n if (draggingId !== targetId) {\n onChange(swapPanes(layout, draggingId, targetId))\n }\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, { type: 'swap', position: 'center' })\n }\n return\n }\n\n // Check for edge (split) drop\n const match = overIdStr.match(/^drop-(left|right|top|bottom)-(.+)$/)\n if (!match) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const [, dropZone, targetId] = match\n if (draggingId === targetId) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const direction: SplitDirection = dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n const treeWithoutDragging = removePane(layout, draggingId)\n\n const newLayout = splitPane(\n treeWithoutDragging,\n targetId,\n direction,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n draggingId,\n )\n onChange(newLayout)\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n }\n\n const handleRemovePane = useCallback(\n (paneId: string) => {\n const newLayout = removePane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleAddPane = useCallback(\n (paneId: string) => {\n const newLayout = addPane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSwapPanes = useCallback(\n (paneIdA: string, paneIdB: string) => {\n const newLayout = swapPanes(layout, paneIdA, paneIdB)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSplitPane = useCallback(\n (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => {\n const newLayout = splitPane(layout, targetId, direction, splitType, paneToAdd)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleUpdateSplitPercentage = useCallback(\n (currentNode: SplitNode, percentage: number) => {\n const newLayout = updateSplitPercentage(layout, currentNode, percentage)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n // Best practice: Memoize context value to prevent unnecessary re-renders of context consumers.\n const contextValue = useMemo(\n () => ({\n layout,\n onLayoutChange: onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n removePane: handleRemovePane,\n addPane: handleAddPane,\n swapPanes: handleSwapPanes,\n splitPane: handleSplitPane,\n updateSplitPercentage: handleUpdateSplitPercentage,\n }),\n [\n layout,\n onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n handleRemovePane,\n handleAddPane,\n handleSwapPanes,\n handleSplitPane,\n handleUpdateSplitPercentage,\n ],\n )\n\n const hasOtherPanes = useMemo(() => {\n if (!activeId) return false\n return removePane(layout, activeId) !== null\n }, [layout, activeId])\n\n return (\n <DashboardContext.Provider value={contextValue}>\n <DndContext\n id=\"zeugma-dnd-context\"\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div\n className=\"zeugma-dashboard-root\"\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n }}\n >\n {children}\n <RootDropZones\n activeId={activeId}\n hasOtherPanes={hasOtherPanes}\n dropPreviewClassName={classNames.dropPreview}\n />\n </div>\n </DndContext>\n {activeId && renderDragOverlay && (\n <CursorOverlay\n activeId={activeId}\n render={renderDragOverlay}\n className={classNames.dragOverlay}\n />\n )}\n </DashboardContext.Provider>\n )\n}\n","import React, { useCallback } from 'react'\nimport { TreeNode, SplitNode, SplitDirection } from '../../../shared/model'\nimport { updateSplitPercentage } from '../../../shared/lib/tree'\nimport { useDashboard } from '../../../entities/dashboard'\n\ninterface UseResizerProps {\n containerRef: React.RefObject<HTMLDivElement | null>\n isRow: boolean\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n snapThreshold: number\n layout: TreeNode | null\n currentNode: SplitNode\n onLayoutChange: (newLayout: TreeNode | null) => void\n onResizeStart?: () => void\n onResizeEnd?: () => void\n}\n\nexport function useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: localOnResizeStart,\n onResizeEnd: localOnResizeEnd,\n}: UseResizerProps) {\n const {\n onResizeStart: globalOnResizeStart,\n onResize: globalOnResize,\n onResizeEnd: globalOnResizeEnd,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n } = useDashboard()\n\n return useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault()\n const container = containerRef.current\n if (!container) return\n\n document.body.classList.add('zeugma-resizing')\n\n // Inject global cursor style to keep resizing cursor active across the entire page during drag\n const styleEl = document.createElement('style')\n styleEl.id = 'zeugma-global-cursor-style'\n styleEl.textContent = `\n * {\n cursor: ${isRow ? 'col-resize' : 'row-resize'} !important;\n user-select: none !important;\n }\n `\n document.head.appendChild(styleEl)\n\n if (localOnResizeStart) {\n localOnResizeStart()\n }\n if (globalOnResizeStart) {\n globalOnResizeStart(currentNode)\n }\n\n const rect = container.getBoundingClientRect()\n const startX = e.clientX\n const startY = e.clientY\n const startPercentage = splitPercentage\n\n // Cache other resizers of the same direction once at drag-start to prevent layout thrashing on move\n const resizerEl = e.currentTarget\n resizerEl.setAttribute('data-resizing', 'true')\n\n const otherResizers = Array.from(\n document.querySelectorAll('div[role=\"separator\"][data-direction]'),\n ).filter((el) => el !== resizerEl && el.getAttribute('data-direction') === direction)\n\n const otherPositions = otherResizers.map((el) => {\n const r = el.getBoundingClientRect()\n return isRow ? r.left + r.width / 2 : r.top + r.height / 2\n })\n\n let currentPercentage = startPercentage\n\n const handlePointerMove = (moveEvent: PointerEvent) => {\n const delta = isRow\n ? ((moveEvent.clientX - startX) / rect.width) * 100\n : ((moveEvent.clientY - startY) / rect.height) * 100\n const proposedPercentage = startPercentage + delta\n\n // Find physical position corresponding to proposed percentage\n const proposedPos = isRow\n ? rect.left + (rect.width - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n : rect.top + (rect.height - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n\n let closestDistance = Infinity\n let bestTarget: number | null = null\n\n for (const pos of otherPositions) {\n const dist = Math.abs(proposedPos - pos)\n if (dist < snapThreshold && dist < closestDistance) {\n closestDistance = dist\n bestTarget = pos\n }\n }\n\n let snappedPercentage = proposedPercentage\n if (bestTarget !== null) {\n snappedPercentage = isRow\n ? ((bestTarget - resizerSize / 2 - rect.left) / (rect.width - resizerSize)) * 100\n : ((bestTarget - resizerSize / 2 - rect.top) / (rect.height - resizerSize)) * 100\n }\n\n const finalPercentage = Math.max(\n minSplitPercentage,\n Math.min(maxSplitPercentage, snappedPercentage),\n )\n currentPercentage = finalPercentage\n const newLayout = updateSplitPercentage(layout, currentNode, finalPercentage)\n onLayoutChange(newLayout)\n if (globalOnResize) {\n globalOnResize(currentNode, finalPercentage)\n }\n }\n\n const handlePointerUp = () => {\n document.body.classList.remove('zeugma-resizing')\n resizerEl.removeAttribute('data-resizing')\n\n const globalStyle = document.getElementById('zeugma-global-cursor-style')\n if (globalStyle) {\n globalStyle.remove()\n }\n\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n\n if (localOnResizeEnd) {\n localOnResizeEnd()\n }\n if (globalOnResizeEnd) {\n globalOnResizeEnd(currentNode, currentPercentage)\n }\n }\n\n document.addEventListener('pointermove', handlePointerMove)\n document.addEventListener('pointerup', handlePointerUp)\n },\n [\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n localOnResizeStart,\n localOnResizeEnd,\n globalOnResizeStart,\n globalOnResize,\n globalOnResizeEnd,\n minSplitPercentage,\n maxSplitPercentage,\n ],\n )\n}\n","import React, { useRef, useState } from 'react'\nimport { useDashboard, ResizerRenderProps } from '../../../entities/dashboard'\nimport { useResizer } from '../../../features/resize-pane'\nimport { TreeNode, SplitNode } from '../../../shared/model'\n\nexport interface PaneTreeProps {\n tree?: TreeNode | null\n /** Size of the resizer in pixels (default 4) */\n resizerSize?: number\n /** Threshold in pixels to snap to adjacent resizer edges (default 8) */\n snapThreshold?: number\n /** Custom resizer renderer to override context-level renderResizer */\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\ninterface PaneSplitProps {\n currentNode: SplitNode\n resizerSize: number\n snapThreshold?: number\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\nconst PaneSplit: React.FC<PaneSplitProps> = ({\n currentNode,\n resizerSize,\n snapThreshold,\n renderResizer: propRenderResizer,\n}) => {\n const { layout, onLayoutChange, classNames, renderResizer: contextRenderResizer } = useDashboard()\n const [isResizing, setIsResizing] = useState(false)\n\n const renderResizer = propRenderResizer || contextRenderResizer\n\n const containerRef = useRef<HTMLDivElement>(null)\n const { direction, first, second, splitPercentage } = currentNode\n const isRow = direction === 'row'\n\n const handlePointerDown = useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold: snapThreshold ?? 8,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: () => setIsResizing(true),\n onResizeEnd: () => setIsResizing(false),\n })\n\n return (\n <div\n ref={containerRef}\n style={{\n display: 'flex',\n flexDirection: isRow ? 'row' : 'column',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <div style={{ flex: `${splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={first}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n {renderResizer ? (\n renderResizer({\n direction,\n splitPercentage,\n resizerSize,\n isResizing,\n onPointerDown: handlePointerDown,\n })\n ) : (\n <div\n className={classNames.resizer}\n data-direction={direction}\n style={{\n width: isRow ? `${resizerSize}px` : '100%',\n height: isRow ? '100%' : `${resizerSize}px`,\n cursor: isRow ? 'col-resize' : 'row-resize',\n position: 'relative',\n zIndex: 10,\n userSelect: 'none',\n boxSizing: 'border-box',\n flexShrink: 0,\n }}\n onPointerDown={handlePointerDown}\n role=\"separator\"\n aria-valuenow={splitPercentage}\n aria-valuemin={5}\n aria-valuemax={95}\n />\n )}\n <div style={{ flex: `${100 - splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={second}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n </div>\n )\n}\n\nexport const PaneTree: React.FC<PaneTreeProps> = ({\n tree,\n resizerSize = 4,\n snapThreshold: propSnapThreshold,\n renderResizer,\n}) => {\n const {\n layout,\n renderPane,\n fullscreenPaneId,\n snapThreshold: contextSnapThreshold,\n } = useDashboard()\n\n const snapThreshold = propSnapThreshold !== undefined ? propSnapThreshold : contextSnapThreshold\n\n // Fullscreen bypass\n if (fullscreenPaneId && !tree) {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(fullscreenPaneId)}\n </div>\n )\n }\n\n const currentNode = tree !== undefined ? tree : layout\n\n if (!currentNode) return null\n\n if (currentNode.type === 'pane') {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(currentNode.paneId)}\n </div>\n )\n }\n\n return (\n <PaneSplit\n currentNode={currentNode}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={renderResizer}\n />\n )\n}\n","import { createContext } from 'react'\n\nexport const DragListenersCtx = createContext<Record<string, unknown> | null>(null)\n","import React, { useMemo } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport { useDashboard } from '../../dashboard'\nimport { DragListenersCtx } from '../model/context'\nimport { PaneRenderProps } from '../model/types'\n\ninterface DropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right' | 'center'\n activeClassName?: string\n}\n\nconst activationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n center: {\n position: 'absolute',\n top: '25%',\n left: '25%',\n width: '50%',\n height: '50%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n}\n\nconst previewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n center: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={activationPositions[position]} />\n {isOver && <div className={activeClassName} style={previewPositions[position]} />}\n </>\n )\n}\n\ninterface PaneProps {\n id: string\n children: (props: PaneRenderProps) => React.ReactNode\n style?: React.CSSProperties\n}\n\nexport const Pane: React.FC<PaneProps> = ({ id, children, style }) => {\n const { activeId, classNames, fullscreenPaneId, onRemove, onFullscreenChange, removePane } =\n useDashboard()\n const showDropZones = activeId !== null && activeId !== id\n\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id })\n const dragging = activeId === id || isDragging\n const isFullscreen = fullscreenPaneId === id\n\n const renderProps: PaneRenderProps = {\n isDragging: dragging,\n isFullscreen,\n toggleFullscreen: () => onFullscreenChange?.(isFullscreen ? null : id),\n remove: () => {\n if (isFullscreen) {\n onFullscreenChange?.(null)\n }\n if (onRemove) {\n onRemove(id)\n } else {\n removePane(id)\n }\n },\n }\n\n // Best practice: Memoize drag context value to prevent unnecessary re-renders of the drag handle.\n const contextValue = useMemo(\n () => ({\n ...listeners,\n ...attributes,\n }),\n [listeners, attributes],\n )\n\n return (\n <DragListenersCtx.Provider value={contextValue}>\n <div\n ref={setNodeRef}\n className={classNames.pane}\n style={{ position: 'relative', width: '100%', height: '100%', ...style }}\n >\n {children(renderProps)}\n\n {showDropZones && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 15,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <DropZone\n key={pos}\n id={`drop-${pos}-${id}`}\n position={pos}\n activeClassName={classNames.dropPreview}\n />\n ))}\n <DropZone\n id={`drop-center-${id}`}\n position=\"center\"\n activeClassName={classNames.swapPreview}\n />\n </div>\n )}\n </div>\n </DragListenersCtx.Provider>\n )\n}\n","import React, { useContext } from 'react'\nimport { DragListenersCtx } from '../model/context'\n\ninterface DragHandleProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\nexport const DragHandle: React.FC<DragHandleProps> = ({ children, className, style }) => {\n const dragProps = useContext(DragListenersCtx)\n if (!dragProps) {\n throw new Error('<DragHandle> must be used inside a <Pane>')\n }\n return (\n <div\n className={className}\n style={{ cursor: 'grab', userSelect: 'none', ...style }}\n {...dragProps}\n >\n {children}\n </div>\n )\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -151,5 +151,9 @@ declare function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode;
151
151
  * Tree Helper: Update split percentage recursively.
152
152
  */
153
153
  declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
154
+ /**
155
+ * Tree Helper: Split the entire tree at the root using a dragged pane.
156
+ */
157
+ declare function splitRoot(tree: TreeNode | null, draggingId: string, splitType: 'left' | 'right' | 'top' | 'bottom'): TreeNode | null;
154
158
 
155
- export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, type DashboardContextValue, DashboardProvider, DragHandle, Pane, type PaneNode, type PaneRenderProps, PaneTree, type ResizerRenderProps, type SplitDirection, type SplitNode, type TreeNode, type ZeugmaClassNames, addPane, removePane, splitPane, swapPanes, updateSplitPercentage, useDashboard, useResizer };
159
+ export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, type DashboardContextValue, DashboardProvider, DragHandle, Pane, type PaneNode, type PaneRenderProps, PaneTree, type ResizerRenderProps, type SplitDirection, type SplitNode, type TreeNode, type ZeugmaClassNames, addPane, removePane, splitPane, splitRoot, swapPanes, updateSplitPercentage, useDashboard, useResizer };
package/dist/index.d.ts CHANGED
@@ -151,5 +151,9 @@ declare function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode;
151
151
  * Tree Helper: Update split percentage recursively.
152
152
  */
153
153
  declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
154
+ /**
155
+ * Tree Helper: Split the entire tree at the root using a dragged pane.
156
+ */
157
+ declare function splitRoot(tree: TreeNode | null, draggingId: string, splitType: 'left' | 'right' | 'top' | 'bottom'): TreeNode | null;
154
158
 
155
- export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, type DashboardContextValue, DashboardProvider, DragHandle, Pane, type PaneNode, type PaneRenderProps, PaneTree, type ResizerRenderProps, type SplitDirection, type SplitNode, type TreeNode, type ZeugmaClassNames, addPane, removePane, splitPane, swapPanes, updateSplitPercentage, useDashboard, useResizer };
159
+ export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, type DashboardContextValue, DashboardProvider, DragHandle, Pane, type PaneNode, type PaneRenderProps, PaneTree, type ResizerRenderProps, type SplitDirection, type SplitNode, type TreeNode, type ZeugmaClassNames, addPane, removePane, splitPane, splitRoot, swapPanes, updateSplitPercentage, useDashboard, useResizer };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import {createContext,useContext,useState,useCallback,useMemo,useRef,useEffect}from'react';import {useSensors,useSensor,PointerSensor,DndContext,pointerWithin,useDraggable,useDroppable}from'@dnd-kit/core';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var G=createContext(void 0);var w=()=>{let e=useContext(G);if(!e)throw new Error("useDashboard must be used within a DashboardProvider");return e};function _(e,t){if(e===null)return null;if(e.type==="pane")return e.paneId===t?null:e;let n=_(e.first,t),o=_(e.second,t);return n===null?o:o===null?n:{...e,first:n,second:o}}function $(e,t,n,o,r){if(e===null)return {type:"pane",paneId:r};if(e.type==="pane"){if(e.paneId===t){let a={type:"pane",paneId:r},p={type:"pane",paneId:t},d=o==="left"||o==="top";return {type:"split",direction:n,first:d?a:p,second:d?p:a,splitPercentage:50}}return e}return {...e,first:$(e.first,t,n,o,r)||e.first,second:$(e.second,t,n,o,r)||e.second}}function U(e,t,n){return e===null?null:e.type==="pane"?e.paneId===t?{...e,paneId:n}:e.paneId===n?{...e,paneId:t}:e:{...e,first:U(e.first,t,n)||e.first,second:U(e.second,t,n)||e.second}}function te(e,t){if(e===null)return {type:"pane",paneId:t};function n(o,r){return o.type==="pane"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:o,second:{type:"pane",paneId:t}}:{...o,second:n(o.second,o.direction)}}return n(e,null)}function L(e,t,n){return e===null?null:e===t?{...e,splitPercentage:n}:e.type==="split"?{...e,first:L(e.first,t,n)||e.first,second:L(e.second,t,n)||e.second}:e}var ae=8,de=8,Xe=4;var Pe=({activeId:e,render:t,className:n})=>{let o=useRef(null);return useEffect(()=>{let r=a=>{o.current&&(o.current.style.transform=`translate(${a.clientX+12}px, ${a.clientY+12}px)`);};return document.addEventListener("pointermove",r),()=>document.removeEventListener("pointermove",r)},[]),jsx("div",{ref:o,className:n,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})},be=({layout:e,onChange:t,renderPane:n,renderDragOverlay:o,classNames:r={},fullscreenPaneId:a=null,onFullscreenChange:p,onRemove:d,dragActivationDistance:b=8,snapThreshold:c=8,onDragStart:h,onDragEnd:i,onResizeStart:v,onResize:R,onResizeEnd:S,renderResizer:u,minSplitPercentage:m=5,maxSplitPercentage:N=95,children:D})=>{let[f,k]=useState(null),q=useSensors(useSensor(PointerSensor,{activationConstraint:{distance:b}})),X=s=>{let l=s.active.id.toString();k(l),h&&h(l);},A=s=>{k(null);let{active:l,over:x}=s,g=l.id.toString();if(!x){i&&i(g,null,null);return}let I=x.id.toString(),Z=I.match(/^drop-center-(.+)$/);if(Z){let[,J]=Z;g!==J&&t(U(e,g,J)),i&&i(g,J,{type:"swap",position:"center"});return}let y=I.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!y){i&&i(g,null,null);return}let[,E,T]=y;if(g===T){i&&i(g,null,null);return}let C=E==="left"||E==="right"?"row":"column",oe=_(e,g),re=$(oe,T,C,E,g);t(re),i&&i(g,T,{type:"split",direction:C,position:E});},B=useCallback(s=>{let l=_(e,s);t(l);},[e,t]),Y=useCallback(s=>{let l=te(e,s);t(l);},[e,t]),F=useCallback((s,l)=>{let x=U(e,s,l);t(x);},[e,t]),H=useCallback((s,l,x,g)=>{let I=$(e,s,l,x,g);t(I);},[e,t]),M=useCallback((s,l)=>{let x=L(e,s,l);t(x);},[e,t]),P=useMemo(()=>({layout:e,onLayoutChange:t,renderPane:n,activeId:f,fullscreenPaneId:a,classNames:r,onRemove:d,onFullscreenChange:p,snapThreshold:c,onResizeStart:v,onResize:R,onResizeEnd:S,renderResizer:u,minSplitPercentage:m,maxSplitPercentage:N,removePane:B,addPane:Y,swapPanes:F,splitPane:H,updateSplitPercentage:M}),[e,t,n,f,a,r,d,p,c,v,R,S,u,m,N,B,Y,F,H,M]);return jsxs(G.Provider,{value:P,children:[jsx(DndContext,{sensors:q,collisionDetection:pointerWithin,onDragStart:X,onDragEnd:A,children:D}),f&&o&&jsx(Pe,{activeId:f,render:o,className:r.dragOverlay})]})};function Q({containerRef:e,isRow:t,direction:n,splitPercentage:o,resizerSize:r,snapThreshold:a,layout:p,currentNode:d,onLayoutChange:b,onResizeStart:c,onResizeEnd:h}){let{onResizeStart:i,onResize:v,onResizeEnd:R,minSplitPercentage:S=5,maxSplitPercentage:u=95}=w();return useCallback(m=>{m.preventDefault();let N=e.current;if(!N)return;document.body.classList.add("zeugma-resizing");let D=document.createElement("style");D.id="zeugma-global-cursor-style",D.textContent=`
1
+ import {createContext,useContext,useState,useCallback,useMemo,useRef,useEffect}from'react';import {useSensors,useSensor,PointerSensor,DndContext,pointerWithin,useDraggable,useDroppable}from'@dnd-kit/core';import {jsxs,jsx,Fragment}from'react/jsx-runtime';var G=createContext(void 0);var y=()=>{let e=useContext(G);if(!e)throw new Error("useDashboard must be used within a DashboardProvider");return e};function C(e,t){if(e===null)return null;if(e.type==="pane")return e.paneId===t?null:e;let o=C(e.first,t),n=C(e.second,t);return o===null?n:n===null?o:{...e,first:o,second:n}}function O(e,t,o,n,r){if(e===null)return {type:"pane",paneId:r};if(e.type==="pane"){if(e.paneId===t){let i={type:"pane",paneId:r},a={type:"pane",paneId:t},p=n==="left"||n==="top";return {type:"split",direction:o,first:p?i:a,second:p?a:i,splitPercentage:50}}return e}return {...e,first:O(e.first,t,o,n,r)||e.first,second:O(e.second,t,o,n,r)||e.second}}function _(e,t,o){return e===null?null:e.type==="pane"?e.paneId===t?{...e,paneId:o}:e.paneId===o?{...e,paneId:t}:e:{...e,first:_(e.first,t,o)||e.first,second:_(e.second,t,o)||e.second}}function re(e,t){if(e===null)return {type:"pane",paneId:t};function o(n,r){return n.type==="pane"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:n,second:{type:"pane",paneId:t}}:{...n,second:o(n.second,n.direction)}}return o(e,null)}function F(e,t,o){return e===null?null:e===t?{...e,splitPercentage:o}:e.type==="split"?{...e,first:F(e.first,t,o)||e.first,second:F(e.second,t,o)||e.second}:e}function ie(e,t,o){let n=C(e,t);if(n===null)return {type:"pane",paneId:t};let r=o==="left"||o==="right"?"row":"column",i=o==="left"||o==="top",a={type:"pane",paneId:t};return {type:"split",direction:r,first:i?a:n,second:i?n:a,splitPercentage:50}}var ge=8,he=8,nt=4;var be={top:{position:"absolute",top:0,left:0,right:0,height:"32px",zIndex:30,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"32px",zIndex:30,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"32px",zIndex:30,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"32px",zIndex:30,pointerEvents:"auto"}},Pe={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:31,pointerEvents:"none",boxSizing:"border-box"}},Re=({id:e,position:t,activeClassName:o})=>{let{setNodeRef:n,isOver:r}=useDroppable({id:e});return jsxs(Fragment,{children:[jsx("div",{ref:n,style:be[t]}),r&&jsx("div",{className:o,style:Pe[t]})]})},se=({activeId:e,hasOtherPanes:t,dropPreviewClassName:o})=>!e||!t?null:jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:30,pointerEvents:"none"},children:["top","bottom","left","right"].map(n=>jsx(Re,{id:`drop-root-${n}`,position:n,activeClassName:o},n))});var Ce=({activeId:e,render:t,className:o})=>{let n=useRef(null);return useEffect(()=>{let r=i=>{n.current&&(n.current.style.transform=`translate(${i.clientX+12}px, ${i.clientY+12}px)`);};return document.addEventListener("pointermove",r),()=>document.removeEventListener("pointermove",r)},[]),jsx("div",{ref:n,className:o,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})},Le=({layout:e,onChange:t,renderPane:o,renderDragOverlay:n,classNames:r={},fullscreenPaneId:i=null,onFullscreenChange:a,onRemove:p,dragActivationDistance:R=8,snapThreshold:u=8,onDragStart:v,onDragEnd:s,onResizeStart:h,onResize:x,onResizeEnd:S,renderResizer:f,minSplitPercentage:g=5,maxSplitPercentage:N=95,children:D})=>{let[l,k]=useState(null),K=useSensors(useSensor(PointerSensor,{activationConstraint:{distance:R}})),X=c=>{let m=c.active.id.toString();k(m),v&&v(m);},A=c=>{k(null);let{active:m,over:P}=c,d=m.id.toString();if(!P){s&&s(d,null,null);return}let I=P.id.toString(),L=I.match(/^drop-root-(left|right|top|bottom)$/);if(L){let[,E]=L,ue=ie(e,d,E);t(ue),s&&s(d,"root",{type:"split",direction:E==="left"||E==="right"?"row":"column",position:E});return}let W=I.match(/^drop-center-(.+)$/);if(W){let[,E]=W;d!==E&&t(_(e,d,E)),s&&s(d,E,{type:"swap",position:"center"});return}let $=I.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!$){s&&s(d,null,null);return}let[,w,j]=$;if(d===j){s&&s(d,null,null);return}let ne=w==="left"||w==="right"?"row":"column",pe=C(e,d),ce=O(pe,j,ne,w,d);t(ce),s&&s(d,j,{type:"split",direction:ne,position:w});},Q=useCallback(c=>{let m=C(e,c);t(m);},[e,t]),Y=useCallback(c=>{let m=re(e,c);t(m);},[e,t]),Z=useCallback((c,m)=>{let P=_(e,c,m);t(P);},[e,t]),H=useCallback((c,m,P,d)=>{let I=O(e,c,m,P,d);t(I);},[e,t]),M=useCallback((c,m)=>{let P=F(e,c,m);t(P);},[e,t]),b=useMemo(()=>({layout:e,onLayoutChange:t,renderPane:o,activeId:l,fullscreenPaneId:i,classNames:r,onRemove:p,onFullscreenChange:a,snapThreshold:u,onResizeStart:h,onResize:x,onResizeEnd:S,renderResizer:f,minSplitPercentage:g,maxSplitPercentage:N,removePane:Q,addPane:Y,swapPanes:Z,splitPane:H,updateSplitPercentage:M}),[e,t,o,l,i,r,p,a,u,h,x,S,f,g,N,Q,Y,Z,H,M]),z=useMemo(()=>l?C(e,l)!==null:false,[e,l]);return jsxs(G.Provider,{value:b,children:[jsx(DndContext,{id:"zeugma-dnd-context",sensors:K,collisionDetection:pointerWithin,onDragStart:X,onDragEnd:A,children:jsxs("div",{className:"zeugma-dashboard-root",style:{position:"relative",width:"100%",height:"100%"},children:[D,jsx(se,{activeId:l,hasOtherPanes:z,dropPreviewClassName:r.dropPreview})]})}),l&&n&&jsx(Ce,{activeId:l,render:n,className:r.dragOverlay})]})};function ee({containerRef:e,isRow:t,direction:o,splitPercentage:n,resizerSize:r,snapThreshold:i,layout:a,currentNode:p,onLayoutChange:R,onResizeStart:u,onResizeEnd:v}){let{onResizeStart:s,onResize:h,onResizeEnd:x,minSplitPercentage:S=5,maxSplitPercentage:f=95}=y();return useCallback(g=>{g.preventDefault();let N=e.current;if(!N)return;document.body.classList.add("zeugma-resizing");let D=document.createElement("style");D.id="zeugma-global-cursor-style",D.textContent=`
2
2
  * {
3
3
  cursor: ${t?"col-resize":"row-resize"} !important;
4
4
  user-select: none !important;
5
5
  }
6
- `,document.head.appendChild(D),c&&c(),i&&i(d);let f=N.getBoundingClientRect(),k=m.clientX,q=m.clientY,X=o,A=m.currentTarget;A.setAttribute("data-resizing","true");let Y=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(P=>P!==A&&P.getAttribute("data-direction")===n).map(P=>{let s=P.getBoundingClientRect();return t?s.left+s.width/2:s.top+s.height/2}),F=X,H=P=>{let s=t?(P.clientX-k)/f.width*100:(P.clientY-q)/f.height*100,l=X+s,x=t?f.left+(f.width-r)*(l/100)+r/2:f.top+(f.height-r)*(l/100)+r/2,g=1/0,I=null;for(let T of Y){let C=Math.abs(x-T);C<a&&C<g&&(g=C,I=T);}let Z=l;I!==null&&(Z=t?(I-r/2-f.left)/(f.width-r)*100:(I-r/2-f.top)/(f.height-r)*100);let y=Math.max(S,Math.min(u,Z));F=y;let E=L(p,d,y);b(E),v&&v(d,y);},M=()=>{document.body.classList.remove("zeugma-resizing"),A.removeAttribute("data-resizing");let P=document.getElementById("zeugma-global-cursor-style");P&&P.remove(),document.removeEventListener("pointermove",H),document.removeEventListener("pointerup",M),h&&h(),R&&R(d,F);};document.addEventListener("pointermove",H),document.addEventListener("pointerup",M);},[e,t,n,o,r,a,p,d,b,c,h,i,v,R,S,u])}var De=({currentNode:e,resizerSize:t,snapThreshold:n,renderResizer:o})=>{let{layout:r,onLayoutChange:a,classNames:p,renderResizer:d}=w(),[b,c]=useState(false),h=o||d,i=useRef(null),{direction:v,first:R,second:S,splitPercentage:u}=e,m=v==="row",N=Q({containerRef:i,isRow:m,direction:v,splitPercentage:u,resizerSize:t,snapThreshold:n??8,layout:r,currentNode:e,onLayoutChange:a,onResizeStart:()=>c(true),onResizeEnd:()=>c(false)});return jsxs("div",{ref:i,style:{display:"flex",flexDirection:m?"row":"column",width:"100%",height:"100%",overflow:"hidden"},children:[jsx("div",{style:{flex:`${u} 1 0%`,overflow:"hidden"},children:jsx(j,{tree:R,resizerSize:t,snapThreshold:n,renderResizer:o})}),h?h({direction:v,splitPercentage:u,resizerSize:t,isResizing:b,onPointerDown:N}):jsx("div",{className:p.resizer,"data-direction":v,style:{width:m?`${t}px`:"100%",height:m?"100%":`${t}px`,cursor:m?"col-resize":"row-resize",position:"relative",zIndex:10,userSelect:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:N,role:"separator","aria-valuenow":u,"aria-valuemin":5,"aria-valuemax":95}),jsx("div",{style:{flex:`${100-u} 1 0%`,overflow:"hidden"},children:jsx(j,{tree:S,resizerSize:t,snapThreshold:n,renderResizer:o})})]})},j=({tree:e,resizerSize:t=4,snapThreshold:n,renderResizer:o})=>{let{layout:r,renderPane:a,fullscreenPaneId:p,snapThreshold:d}=w(),b=n!==void 0?n:d;if(p&&!e)return jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:a(p)});let c=e!==void 0?e:r;return c?c.type==="pane"?jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:a(c.paneId)}):jsx(De,{currentNode:c,resizerSize:t,snapThreshold:b,renderResizer:o}):null};var W=createContext(null);var Te={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"}},Ce={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},ne=({id:e,position:t,activeClassName:n})=>{let{setNodeRef:o,isOver:r}=useDroppable({id:e});return jsxs(Fragment,{children:[jsx("div",{ref:o,style:Te[t]}),r&&jsx("div",{className:n,style:Ce[t]})]})},Le=({id:e,children:t,style:n})=>{let{activeId:o,classNames:r,fullscreenPaneId:a,onRemove:p,onFullscreenChange:d,removePane:b}=w(),c=o!==null&&o!==e,{attributes:h,listeners:i,setNodeRef:v,isDragging:R}=useDraggable({id:e}),S=o===e||R,u=a===e,m={isDragging:S,isFullscreen:u,toggleFullscreen:()=>d?.(u?null:e),remove:()=>{u&&d?.(null),p?p(e):b(e);}},N=useMemo(()=>({...i,...h}),[i,h]);return jsx(W.Provider,{value:N,children:jsxs("div",{ref:v,className:r.pane,style:{position:"relative",width:"100%",height:"100%",...n},children:[t(m),c&&jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(D=>jsx(ne,{id:`drop-${D}-${e}`,position:D,activeClassName:r.dropPreview},D)),jsx(ne,{id:`drop-center-${e}`,position:"center",activeClassName:r.swapPreview})]})]})})};var He=({children:e,className:t,style:n})=>{let o=useContext(W);if(!o)throw new Error("<DragHandle> must be used inside a <Pane>");return jsx("div",{className:t,style:{cursor:"grab",userSelect:"none",...n},...o,children:e})};export{de as DEFAULT_DRAG_ACTIVATION_DISTANCE,Xe as DEFAULT_RESIZER_SIZE,ae as DEFAULT_SNAP_THRESHOLD,be as DashboardProvider,He as DragHandle,Le as Pane,j as PaneTree,te as addPane,_ as removePane,$ as splitPane,U as swapPanes,L as updateSplitPercentage,w as useDashboard,Q as useResizer};//# sourceMappingURL=index.js.map
6
+ `,document.head.appendChild(D),u&&u(),s&&s(p);let l=N.getBoundingClientRect(),k=g.clientX,K=g.clientY,X=n,A=g.currentTarget;A.setAttribute("data-resizing","true");let Y=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(b=>b!==A&&b.getAttribute("data-direction")===o).map(b=>{let z=b.getBoundingClientRect();return t?z.left+z.width/2:z.top+z.height/2}),Z=X,H=b=>{let z=t?(b.clientX-k)/l.width*100:(b.clientY-K)/l.height*100,c=X+z,m=t?l.left+(l.width-r)*(c/100)+r/2:l.top+(l.height-r)*(c/100)+r/2,P=1/0,d=null;for(let $ of Y){let w=Math.abs(m-$);w<i&&w<P&&(P=w,d=$);}let I=c;d!==null&&(I=t?(d-r/2-l.left)/(l.width-r)*100:(d-r/2-l.top)/(l.height-r)*100);let L=Math.max(S,Math.min(f,I));Z=L;let W=F(a,p,L);R(W),h&&h(p,L);},M=()=>{document.body.classList.remove("zeugma-resizing"),A.removeAttribute("data-resizing");let b=document.getElementById("zeugma-global-cursor-style");b&&b.remove(),document.removeEventListener("pointermove",H),document.removeEventListener("pointerup",M),v&&v(),x&&x(p,Z);};document.addEventListener("pointermove",H),document.addEventListener("pointerup",M);},[e,t,o,n,r,i,a,p,R,u,v,s,h,x,S,f])}var He=({currentNode:e,resizerSize:t,snapThreshold:o,renderResizer:n})=>{let{layout:r,onLayoutChange:i,classNames:a,renderResizer:p}=y(),[R,u]=useState(false),v=n||p,s=useRef(null),{direction:h,first:x,second:S,splitPercentage:f}=e,g=h==="row",N=ee({containerRef:s,isRow:g,direction:h,splitPercentage:f,resizerSize:t,snapThreshold:o??8,layout:r,currentNode:e,onLayoutChange:i,onResizeStart:()=>u(true),onResizeEnd:()=>u(false)});return jsxs("div",{ref:s,style:{display:"flex",flexDirection:g?"row":"column",width:"100%",height:"100%",overflow:"hidden"},children:[jsx("div",{style:{flex:`${f} 1 0%`,overflow:"hidden"},children:jsx(te,{tree:x,resizerSize:t,snapThreshold:o,renderResizer:n})}),v?v({direction:h,splitPercentage:f,resizerSize:t,isResizing:R,onPointerDown:N}):jsx("div",{className:a.resizer,"data-direction":h,style:{width:g?`${t}px`:"100%",height:g?"100%":`${t}px`,cursor:g?"col-resize":"row-resize",position:"relative",zIndex:10,userSelect:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:N,role:"separator","aria-valuenow":f,"aria-valuemin":5,"aria-valuemax":95}),jsx("div",{style:{flex:`${100-f} 1 0%`,overflow:"hidden"},children:jsx(te,{tree:S,resizerSize:t,snapThreshold:o,renderResizer:n})})]})},te=({tree:e,resizerSize:t=4,snapThreshold:o,renderResizer:n})=>{let{layout:r,renderPane:i,fullscreenPaneId:a,snapThreshold:p}=y(),R=o!==void 0?o:p;if(a&&!e)return jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:i(a)});let u=e!==void 0?e:r;return u?u.type==="pane"?jsx("div",{style:{width:"100%",height:"100%",position:"relative"},children:i(u.paneId)}):jsx(He,{currentNode:u,resizerSize:t,snapThreshold:R,renderResizer:n}):null};var J=createContext(null);var Ve={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:0,bottom:0,left:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:0,bottom:0,right:0,width:"25%",height:"100%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"}},ke={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},de=({id:e,position:t,activeClassName:o})=>{let{setNodeRef:n,isOver:r}=useDroppable({id:e});return jsxs(Fragment,{children:[jsx("div",{ref:n,style:Ve[t]}),r&&jsx("div",{className:o,style:ke[t]})]})},Xe=({id:e,children:t,style:o})=>{let{activeId:n,classNames:r,fullscreenPaneId:i,onRemove:a,onFullscreenChange:p,removePane:R}=y(),u=n!==null&&n!==e,{attributes:v,listeners:s,setNodeRef:h,isDragging:x}=useDraggable({id:e}),S=n===e||x,f=i===e,g={isDragging:S,isFullscreen:f,toggleFullscreen:()=>p?.(f?null:e),remove:()=>{f&&p?.(null),a?a(e):R(e);}},N=useMemo(()=>({...s,...v}),[s,v]);return jsx(J.Provider,{value:N,children:jsxs("div",{ref:h,className:r.pane,style:{position:"relative",width:"100%",height:"100%",...o},children:[t(g),u&&jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(D=>jsx(de,{id:`drop-${D}-${e}`,position:D,activeClassName:r.dropPreview},D)),jsx(de,{id:`drop-center-${e}`,position:"center",activeClassName:r.swapPreview})]})]})})};var Ge=({children:e,className:t,style:o})=>{let n=useContext(J);if(!n)throw new Error("<DragHandle> must be used inside a <Pane>");return jsx("div",{className:t,style:{cursor:"grab",userSelect:"none",...o},...n,children:e})};export{he as DEFAULT_DRAG_ACTIVATION_DISTANCE,nt as DEFAULT_RESIZER_SIZE,ge as DEFAULT_SNAP_THRESHOLD,Le as DashboardProvider,Ge as DragHandle,Xe as Pane,te as PaneTree,re as addPane,C as removePane,O as splitPane,ie as splitRoot,_ as swapPanes,F as updateSplitPercentage,y as useDashboard,ee as useResizer};//# sourceMappingURL=index.js.map
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entities/dashboard/model/context.ts","../src/entities/dashboard/model/hooks.ts","../src/shared/lib/tree/tree-helpers.ts","../src/shared/config/constants.ts","../src/entities/dashboard/ui/DashboardProvider.tsx","../src/features/resize-pane/hooks/useResizer.ts","../src/widgets/pane-tree/ui/PaneTree.tsx","../src/entities/pane/model/context.ts","../src/entities/pane/ui/Pane.tsx","../src/entities/pane/ui/DragHandle.tsx"],"names":["DashboardContext","createContext","useDashboard","context","useContext","removePane","tree","idToRemove","newFirst","newSecond","splitPane","targetId","direction","splitType","paneToAdd","addedNode","originalNode","isFirst","swapPanes","idA","idB","addPane","insert","node","parentDirection","updateSplitPercentage","target","newPercentage","DEFAULT_SNAP_THRESHOLD","DEFAULT_DRAG_ACTIVATION_DISTANCE","DEFAULT_RESIZER_SIZE","CursorOverlay","activeId","render","className","ref","useRef","useEffect","handleMove","e","jsx","DashboardProvider","layout","onChange","renderPane","renderDragOverlay","classNames","fullscreenPaneId","onFullscreenChange","onRemove","dragActivationDistance","snapThreshold","onDragStart","onDragEnd","onResizeStart","onResize","onResizeEnd","renderResizer","minSplitPercentage","maxSplitPercentage","children","setActiveId","useState","sensors","useSensors","useSensor","PointerSensor","handleDragStart","event","draggingId","handleDragEnd","active","over","overIdStr","swapMatch","match","dropZone","treeWithoutDragging","newLayout","handleRemovePane","useCallback","paneId","handleAddPane","handleSwapPanes","paneIdA","paneIdB","handleSplitPane","handleUpdateSplitPercentage","currentNode","percentage","contextValue","useMemo","jsxs","DndContext","pointerWithin","useResizer","containerRef","isRow","splitPercentage","resizerSize","onLayoutChange","localOnResizeStart","localOnResizeEnd","globalOnResizeStart","globalOnResize","globalOnResizeEnd","container","styleEl","rect","startX","startY","startPercentage","resizerEl","otherPositions","el","r","currentPercentage","handlePointerMove","moveEvent","delta","proposedPercentage","proposedPos","closestDistance","bestTarget","pos","dist","snappedPercentage","finalPercentage","handlePointerUp","globalStyle","PaneSplit","propRenderResizer","contextRenderResizer","isResizing","setIsResizing","first","second","handlePointerDown","PaneTree","propSnapThreshold","contextSnapThreshold","DragListenersCtx","activationPositions","previewPositions","DropZone","id","position","activeClassName","setNodeRef","isOver","useDroppable","Fragment","Pane","style","showDropZones","attributes","listeners","isDragging","useDraggable","dragging","isFullscreen","renderProps","DragHandle","dragProps"],"mappings":"+PA+CO,IAAMA,CAAAA,CAAmBC,aAAAA,CAAiD,MAAS,CAAA,CC5CnF,IAAMC,EAAe,IAAM,CAChC,IAAMC,CAAAA,CAAUC,UAAAA,CAAWJ,CAAgB,CAAA,CAC3C,GAAI,CAACG,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,sDAAsD,EAExE,OAAOA,CACT,ECJO,SAASE,CAAAA,CAAWC,CAAAA,CAAuBC,EAAqC,CACrF,GAAID,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAC1B,GAAIA,CAAAA,CAAK,IAAA,GAAS,MAAA,CAChB,OAAOA,CAAAA,CAAK,MAAA,GAAWC,CAAAA,CAAa,IAAA,CAAOD,CAAAA,CAE7C,IAAME,CAAAA,CAAWH,CAAAA,CAAWC,CAAAA,CAAK,KAAA,CAAOC,CAAU,CAAA,CAC5CE,CAAAA,CAAYJ,CAAAA,CAAWC,CAAAA,CAAK,MAAA,CAAQC,CAAU,CAAA,CACpD,OAAIC,IAAa,IAAA,CAAaC,CAAAA,CAC1BA,CAAAA,GAAc,IAAA,CAAaD,CAAAA,CACxB,CAAE,GAAGF,CAAAA,CAAM,KAAA,CAAOE,CAAAA,CAAU,MAAA,CAAQC,CAAU,CACvD,CAKO,SAASC,CAAAA,CACdJ,CAAAA,CACAK,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAIR,CAAAA,GAAS,IAAA,CAAM,OAAO,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQQ,CAAU,CAAA,CAC5D,GAAIR,CAAAA,CAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,CAAAA,CAAK,MAAA,GAAWK,CAAAA,CAAU,CAC5B,IAAMI,CAAAA,CAAsB,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQD,CAAU,CAAA,CACxDE,CAAAA,CAAyB,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQL,CAAS,CAAA,CAC1DM,CAAAA,CAAUJ,CAAAA,GAAc,MAAA,EAAUA,CAAAA,GAAc,MACtD,OAAO,CACL,IAAA,CAAM,OAAA,CACN,SAAA,CAAAD,CAAAA,CACA,KAAA,CAAOK,CAAAA,CAAUF,CAAAA,CAAYC,CAAAA,CAC7B,MAAA,CAAQC,CAAAA,CAAUD,CAAAA,CAAeD,CAAAA,CACjC,eAAA,CAAiB,EACnB,CACF,CACA,OAAOT,CACT,CACA,OAAO,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOI,CAAAA,CAAUJ,CAAAA,CAAK,KAAA,CAAOK,CAAAA,CAAUC,EAAWC,CAAAA,CAAWC,CAAS,CAAA,EAAKR,CAAAA,CAAK,KAAA,CAChF,MAAA,CAAQI,CAAAA,CAAUJ,CAAAA,CAAK,MAAA,CAAQK,CAAAA,CAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,CAAA,EAAKR,CAAAA,CAAK,MACpF,CACF,CAKO,SAASY,CAAAA,CAAUZ,CAAAA,CAAuBa,CAAAA,CAAaC,CAAAA,CAA8B,CAC1F,OAAId,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,CAAK,IAAA,GAAS,OACZA,CAAAA,CAAK,MAAA,GAAWa,CAAAA,CAAY,CAAE,GAAGb,CAAAA,CAAM,MAAA,CAAQc,CAAI,CAAA,CACnDd,CAAAA,CAAK,MAAA,GAAWc,CAAAA,CAAY,CAAE,GAAGd,CAAAA,CAAM,MAAA,CAAQa,CAAI,CAAA,CAChDb,CAAAA,CAEF,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOY,CAAAA,CAAUZ,CAAAA,CAAK,KAAA,CAAOa,CAAAA,CAAKC,CAAG,CAAA,EAAKd,CAAAA,CAAK,MAC/C,MAAA,CAAQY,CAAAA,CAAUZ,CAAAA,CAAK,MAAA,CAAQa,CAAAA,CAAKC,CAAG,CAAA,EAAKd,CAAAA,CAAK,MACnD,CACF,CAKO,SAASe,EAAAA,CAAQf,CAAAA,CAAuBQ,CAAAA,CAA6B,CAC1E,GAAIR,CAAAA,GAAS,IAAA,CACX,OAAO,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQQ,CAAU,CAAA,CAG3C,SAASQ,CAAAA,CAAOC,CAAAA,CAAgBC,CAAAA,CAAkD,CAChF,OAAID,CAAAA,CAAK,IAAA,GAAS,MAAA,CAET,CACL,IAAA,CAAM,OAAA,CACN,SAAA,CAHgCC,CAAAA,GAAoB,KAAA,CAAQ,QAAA,CAAW,KAAA,CAIvE,eAAA,CAAiB,EAAA,CACjB,KAAA,CAAOD,CAAAA,CACP,MAAA,CAAQ,CAAE,IAAA,CAAM,MAAA,CAAQ,MAAA,CAAQT,CAAU,CAC5C,CAAA,CAGK,CACL,GAAGS,CAAAA,CACH,MAAA,CAAQD,CAAAA,CAAOC,CAAAA,CAAK,OAAQA,CAAAA,CAAK,SAAS,CAC5C,CACF,CAEA,OAAOD,CAAAA,CAAOhB,CAAAA,CAAM,IAAI,CAC1B,CAKO,SAASmB,CAAAA,CACdnB,CAAAA,CACAoB,CAAAA,CACAC,CAAAA,CACiB,CACjB,OAAIrB,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,GAASoB,CAAAA,CACJ,CAAE,GAAGpB,CAAAA,CAAM,eAAA,CAAiBqB,CAAc,CAAA,CAE/CrB,CAAAA,CAAK,OAAS,OAAA,CACT,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOmB,CAAAA,CAAsBnB,CAAAA,CAAK,KAAA,CAAOoB,CAAAA,CAAQC,CAAa,CAAA,EAAKrB,CAAAA,CAAK,KAAA,CACxE,MAAA,CAAQmB,CAAAA,CAAsBnB,CAAAA,CAAK,MAAA,CAAQoB,CAAAA,CAAQC,CAAa,CAAA,EAAKrB,CAAAA,CAAK,MAC5E,CAAA,CAEKA,CACT,CCpHO,IAAMsB,EAAAA,CAAyB,CAAA,CACzBC,EAAAA,CAAmC,CAAA,CACnCC,GAAuB,ECoBpC,IAAMC,EAAAA,CAID,CAAC,CAAE,QAAA,CAAAC,CAAAA,CAAU,MAAA,CAAAC,CAAAA,CAAQ,SAAA,CAAAC,CAAU,CAAA,GAAM,CACxC,IAAMC,CAAAA,CAAMC,MAAAA,CAAuB,IAAI,CAAA,CAEvC,OAAAC,SAAAA,CAAU,IAAM,CACd,IAAMC,CAAAA,CAAcC,CAAAA,EAAoB,CAClCJ,CAAAA,CAAI,OAAA,GACNA,CAAAA,CAAI,OAAA,CAAQ,KAAA,CAAM,SAAA,CAAY,CAAA,UAAA,EAAaI,CAAAA,CAAE,OAAA,CAAU,EAAE,CAAA,IAAA,EAAOA,CAAAA,CAAE,OAAA,CAAU,EAAE,CAAA,GAAA,CAAA,EAElF,CAAA,CACA,OAAA,QAAA,CAAS,gBAAA,CAAiB,aAAA,CAAeD,CAAU,CAAA,CAC5C,IAAM,QAAA,CAAS,mBAAA,CAAoB,aAAA,CAAeA,CAAU,CACrE,CAAA,CAAG,EAAE,EAGHE,GAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKL,CAAAA,CACL,SAAA,CAAWD,CAAAA,CACX,KAAA,CAAO,CACL,QAAA,CAAU,OAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,MAAA,CAAQ,IAAA,CACR,aAAA,CAAe,MACjB,CAAA,CAEC,QAAA,CAAAD,CAAAA,CAAOD,CAAQ,CAAA,CAClB,CAEJ,CAAA,CAgCaS,EAAAA,CAAsD,CAAC,CAClE,MAAA,CAAAC,CAAAA,CACA,SAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CAAa,EAAC,CACd,gBAAA,CAAAC,CAAAA,CAAmB,IAAA,CACnB,kBAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,sBAAA,CAAAC,CAAAA,CAAyB,CAAA,CACzB,aAAA,CAAAC,CAAAA,CAAgB,CAAA,CAChB,WAAA,CAAAC,CAAAA,CACA,SAAA,CAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,YAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,CAAAA,CAAqB,CAAA,CACrB,kBAAA,CAAAC,CAAAA,CAAqB,EAAA,CACrB,QAAA,CAAAC,CACF,CAAA,GAAM,CACJ,GAAM,CAAC5B,CAAAA,CAAU6B,CAAW,CAAA,CAAIC,QAAAA,CAAwB,IAAI,CAAA,CAEtDC,CAAAA,CAAUC,UAAAA,CACdC,SAAAA,CAAUC,aAAAA,CAAe,CACvB,oBAAA,CAAsB,CAAE,QAAA,CAAUhB,CAAuB,CAC3D,CAAC,CACH,CAAA,CAEMiB,CAAAA,CAAmBC,CAAAA,EAA0B,CACjD,IAAMC,CAAAA,CAAaD,CAAAA,CAAM,MAAA,CAAO,EAAA,CAAG,QAAA,EAAS,CAC5CP,CAAAA,CAAYQ,CAAU,CAAA,CAClBjB,CAAAA,EACFA,CAAAA,CAAYiB,CAAU,EAE1B,CAAA,CAEMC,CAAAA,CAAiBF,CAAAA,EAAwB,CAC7CP,CAAAA,CAAY,IAAI,CAAA,CAChB,GAAM,CAAE,OAAAU,CAAAA,CAAQ,IAAA,CAAAC,CAAK,CAAA,CAAIJ,CAAAA,CACnBC,CAAAA,CAAaE,CAAAA,CAAO,EAAA,CAAG,QAAA,EAAS,CAEtC,GAAI,CAACC,CAAAA,CAAM,CACLnB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,IAAMI,CAAAA,CAAYD,CAAAA,CAAK,EAAA,CAAG,QAAA,EAAS,CAG7BE,CAAAA,CAAYD,CAAAA,CAAU,MAAM,oBAAoB,CAAA,CACtD,GAAIC,CAAAA,CAAW,CACb,GAAM,EAAG/D,CAAQ,CAAA,CAAI+D,CAAAA,CACjBL,CAAAA,GAAe1D,CAAAA,EACjBgC,CAAAA,CAASzB,CAAAA,CAAUwB,CAAAA,CAAQ2B,CAAAA,CAAY1D,CAAQ,CAAC,CAAA,CAE9C0C,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY1D,CAAAA,CAAU,CAAE,IAAA,CAAM,MAAA,CAAQ,QAAA,CAAU,QAAS,CAAC,EAEtE,MACF,CAGA,IAAMgE,CAAAA,CAAQF,CAAAA,CAAU,KAAA,CAAM,qCAAqC,CAAA,CACnE,GAAI,CAACE,CAAAA,CAAO,CACNtB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,GAAM,EAAGO,CAAAA,CAAUjE,CAAQ,CAAA,CAAIgE,CAAAA,CAC/B,GAAIN,CAAAA,GAAe1D,CAAAA,CAAU,CACvB0C,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY,IAAA,CAAM,IAAI,CAAA,CAElC,MACF,CAEA,IAAMzD,CAAAA,CAA4BgE,CAAAA,GAAa,MAAA,EAAUA,CAAAA,GAAa,OAAA,CAAU,KAAA,CAAQ,QAAA,CAClFC,EAAAA,CAAsBxE,CAAAA,CAAWqC,CAAAA,CAAQ2B,CAAU,CAAA,CAEnDS,EAAAA,CAAYpE,CAAAA,CAChBmE,EAAAA,CACAlE,CAAAA,CACAC,CAAAA,CACAgE,CAAAA,CACAP,CACF,CAAA,CACA1B,CAAAA,CAASmC,EAAS,CAAA,CACdzB,CAAAA,EACFA,CAAAA,CAAUgB,CAAAA,CAAY1D,CAAAA,CAAU,CAC9B,IAAA,CAAM,OAAA,CACN,SAAA,CAAAC,CAAAA,CACA,QAAA,CAAUgE,CACZ,CAAC,EAEL,CAAA,CAEMG,CAAAA,CAAmBC,WAAAA,CACtBC,CAAAA,EAAmB,CAClB,IAAMH,CAAAA,CAAYzE,CAAAA,CAAWqC,CAAAA,CAAQuC,CAAM,CAAA,CAC3CtC,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,EAAQC,CAAQ,CACnB,CAAA,CAEMuC,CAAAA,CAAgBF,WAAAA,CACnBC,CAAAA,EAAmB,CAClB,IAAMH,CAAAA,CAAYzD,EAAAA,CAAQqB,CAAAA,CAAQuC,CAAM,CAAA,CACxCtC,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEMwC,CAAAA,CAAkBH,WAAAA,CACtB,CAACI,CAAAA,CAAiBC,CAAAA,GAAoB,CACpC,IAAMP,CAAAA,CAAY5D,EAAUwB,CAAAA,CAAQ0C,CAAAA,CAASC,CAAO,CAAA,CACpD1C,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEM2C,CAAAA,CAAkBN,WAAAA,CACtB,CACErE,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,GACG,CACH,IAAMgE,CAAAA,CAAYpE,CAAAA,CAAUgC,CAAAA,CAAQ/B,CAAAA,CAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,CAAA,CAC7E6B,EAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAEM4C,CAAAA,CAA8BP,WAAAA,CAClC,CAACQ,CAAAA,CAAwBC,CAAAA,GAAuB,CAC9C,IAAMX,CAAAA,CAAYrD,CAAAA,CAAsBiB,CAAAA,CAAQ8C,CAAAA,CAAaC,CAAU,CAAA,CACvE9C,CAAAA,CAASmC,CAAS,EACpB,CAAA,CACA,CAACpC,CAAAA,CAAQC,CAAQ,CACnB,CAAA,CAGM+C,EAAeC,OAAAA,CACnB,KAAO,CACL,MAAA,CAAAjD,CAAAA,CACA,cAAA,CAAgBC,CAAAA,CAChB,UAAA,CAAAC,CAAAA,CACA,QAAA,CAAAZ,CAAAA,CACA,gBAAA,CAAAe,CAAAA,CACA,UAAA,CAAAD,CAAAA,CACA,QAAA,CAAAG,CAAAA,CACA,kBAAA,CAAAD,CAAAA,CACA,aAAA,CAAAG,CAAAA,CACA,aAAA,CAAAG,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,EACA,kBAAA,CAAAC,CAAAA,CACA,UAAA,CAAYoB,CAAAA,CACZ,OAAA,CAASG,CAAAA,CACT,SAAA,CAAWC,CAAAA,CACX,SAAA,CAAWG,CAAAA,CACX,qBAAA,CAAuBC,CACzB,CAAA,CAAA,CACA,CACE7C,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAZ,CAAAA,CACAe,CAAAA,CACAD,CAAAA,CACAG,CAAAA,CACAD,CAAAA,CACAG,CAAAA,CACAG,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAoB,CAAAA,CACAG,EACAC,CAAAA,CACAG,CAAAA,CACAC,CACF,CACF,CAAA,CAEA,OACEK,IAAAA,CAAC5F,CAAAA,CAAiB,QAAA,CAAjB,CAA0B,KAAA,CAAO0F,CAAAA,CAChC,QAAA,CAAA,CAAAlD,GAAAA,CAACqD,UAAAA,CAAA,CACC,OAAA,CAAS9B,CAAAA,CACT,kBAAA,CAAoB+B,aAAAA,CACpB,WAAA,CAAa3B,CAAAA,CACb,SAAA,CAAWG,CAAAA,CAEV,QAAA,CAAAV,CAAAA,CACH,CAAA,CACC5B,CAAAA,EAAYa,CAAAA,EACXL,GAAAA,CAACT,GAAA,CACC,QAAA,CAAUC,CAAAA,CACV,MAAA,CAAQa,CAAAA,CACR,SAAA,CAAWC,CAAAA,CAAW,WAAA,CACxB,CAAA,CAAA,CAEJ,CAEJ,ECxRO,SAASiD,CAAAA,CAAW,CACzB,YAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,SAAA,CAAArF,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAAhD,CAAAA,CACA,OAAAT,CAAAA,CACA,WAAA,CAAA8C,CAAAA,CACA,cAAA,CAAAY,CAAAA,CACA,aAAA,CAAeC,CAAAA,CACf,WAAA,CAAaC,CACf,CAAA,CAAoB,CAClB,GAAM,CACJ,aAAA,CAAeC,CAAAA,CACf,QAAA,CAAUC,CAAAA,CACV,WAAA,CAAaC,CAAAA,CACb,kBAAA,CAAA/C,CAAAA,CAAqB,CAAA,CACrB,kBAAA,CAAAC,CAAAA,CAAqB,EACvB,CAAA,CAAIzD,CAAAA,EAAa,CAEjB,OAAO8E,WAAAA,CACJzC,GAA0C,CACzCA,CAAAA,CAAE,cAAA,EAAe,CACjB,IAAMmE,CAAAA,CAAYV,CAAAA,CAAa,OAAA,CAC/B,GAAI,CAACU,CAAAA,CAAW,OAEhB,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,iBAAiB,CAAA,CAG7C,IAAMC,CAAAA,CAAU,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA,CAC9CA,CAAAA,CAAQ,EAAA,CAAK,4BAAA,CACbA,CAAAA,CAAQ,WAAA,CAAc;AAAA;AAAA,gBAAA,EAEVV,CAAAA,CAAQ,aAAe,YAAY,CAAA;AAAA;AAAA;AAAA,IAAA,CAAA,CAI/C,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYU,CAAO,CAAA,CAE7BN,CAAAA,EACFA,CAAAA,EAAmB,CAEjBE,CAAAA,EACFA,CAAAA,CAAoBf,CAAW,CAAA,CAGjC,IAAMoB,CAAAA,CAAOF,CAAAA,CAAU,qBAAA,EAAsB,CACvCG,CAAAA,CAAStE,CAAAA,CAAE,OAAA,CACXuE,CAAAA,CAASvE,CAAAA,CAAE,OAAA,CACXwE,CAAAA,CAAkBb,CAAAA,CAGlBc,CAAAA,CAAYzE,CAAAA,CAAE,aAAA,CACpByE,CAAAA,CAAU,aAAa,eAAA,CAAiB,MAAM,CAAA,CAM9C,IAAMC,CAAAA,CAJgB,KAAA,CAAM,IAAA,CAC1B,QAAA,CAAS,gBAAA,CAAiB,uCAAuC,CACnE,CAAA,CAAE,MAAA,CAAQC,CAAAA,EAAOA,CAAAA,GAAOF,CAAAA,EAAaE,EAAG,YAAA,CAAa,gBAAgB,CAAA,GAAMtG,CAAS,CAAA,CAE/C,GAAA,CAAKsG,CAAAA,EAAO,CAC/C,IAAMC,CAAAA,CAAID,CAAAA,CAAG,qBAAA,EAAsB,CACnC,OAAOjB,CAAAA,CAAQkB,CAAAA,CAAE,IAAA,CAAOA,EAAE,KAAA,CAAQ,CAAA,CAAIA,CAAAA,CAAE,GAAA,CAAMA,CAAAA,CAAE,MAAA,CAAS,CAC3D,CAAC,CAAA,CAEGC,CAAAA,CAAoBL,CAAAA,CAElBM,CAAAA,CAAqBC,CAAAA,EAA4B,CACrD,IAAMC,CAAAA,CAAQtB,GACRqB,CAAAA,CAAU,OAAA,CAAUT,CAAAA,EAAUD,CAAAA,CAAK,KAAA,CAAS,GAAA,CAAA,CAC5CU,CAAAA,CAAU,OAAA,CAAUR,GAAUF,CAAAA,CAAK,MAAA,CAAU,GAAA,CAC7CY,CAAAA,CAAqBT,CAAAA,CAAkBQ,CAAAA,CAGvCE,CAAAA,CAAcxB,CAAAA,CAChBW,EAAK,IAAA,CAAA,CAAQA,CAAAA,CAAK,KAAA,CAAQT,CAAAA,GAAgBqB,CAAAA,CAAqB,GAAA,CAAA,CAAOrB,CAAAA,CAAc,CAAA,CACpFS,CAAAA,CAAK,GAAA,CAAA,CAAOA,CAAAA,CAAK,MAAA,CAAST,CAAAA,GAAgBqB,CAAAA,CAAqB,GAAA,CAAA,CAAOrB,CAAAA,CAAc,EAEpFuB,CAAAA,CAAkB,CAAA,CAAA,CAAA,CAClBC,CAAAA,CAA4B,IAAA,CAEhC,IAAA,IAAWC,CAAAA,IAAOX,CAAAA,CAAgB,CAChC,IAAMY,CAAAA,CAAO,IAAA,CAAK,GAAA,CAAIJ,CAAAA,CAAcG,CAAG,CAAA,CACnCC,CAAAA,CAAO1E,CAAAA,EAAiB0E,EAAOH,CAAAA,GACjCA,CAAAA,CAAkBG,CAAAA,CAClBF,CAAAA,CAAaC,CAAAA,EAEjB,CAEA,IAAIE,CAAAA,CAAoBN,CAAAA,CACpBG,CAAAA,GAAe,IAAA,GACjBG,CAAAA,CAAoB7B,CAAAA,CAAAA,CACd0B,CAAAA,CAAaxB,CAAAA,CAAc,CAAA,CAAIS,EAAK,IAAA,GAASA,CAAAA,CAAK,KAAA,CAAQT,CAAAA,CAAAA,CAAgB,GAAA,CAAA,CAC1EwB,CAAAA,CAAaxB,CAAAA,CAAc,CAAA,CAAIS,CAAAA,CAAK,GAAA,GAAQA,CAAAA,CAAK,MAAA,CAAST,CAAAA,CAAAA,CAAgB,GAAA,CAAA,CAGlF,IAAM4B,CAAAA,CAAkB,KAAK,GAAA,CAC3BrE,CAAAA,CACA,IAAA,CAAK,GAAA,CAAIC,CAAAA,CAAoBmE,CAAiB,CAChD,CAAA,CACAV,CAAAA,CAAoBW,CAAAA,CACpB,IAAMjD,CAAAA,CAAYrD,CAAAA,CAAsBiB,CAAAA,CAAQ8C,CAAAA,CAAauC,CAAe,EAC5E3B,CAAAA,CAAetB,CAAS,CAAA,CACpB0B,CAAAA,EACFA,CAAAA,CAAehB,CAAAA,CAAauC,CAAe,EAE/C,EAEMC,CAAAA,CAAkB,IAAM,CAC5B,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,iBAAiB,EAChDhB,CAAAA,CAAU,eAAA,CAAgB,eAAe,CAAA,CAEzC,IAAMiB,CAAAA,CAAc,QAAA,CAAS,cAAA,CAAe,4BAA4B,CAAA,CACpEA,CAAAA,EACFA,CAAAA,CAAY,MAAA,EAAO,CAGrB,QAAA,CAAS,mBAAA,CAAoB,cAAeZ,CAAiB,CAAA,CAC7D,QAAA,CAAS,mBAAA,CAAoB,WAAA,CAAaW,CAAe,CAAA,CAErD1B,CAAAA,EACFA,GAAiB,CAEfG,CAAAA,EACFA,CAAAA,CAAkBjB,CAAAA,CAAa4B,CAAiB,EAEpD,CAAA,CAEA,QAAA,CAAS,iBAAiB,aAAA,CAAeC,CAAiB,CAAA,CAC1D,QAAA,CAAS,gBAAA,CAAiB,WAAA,CAAaW,CAAe,EACxD,CAAA,CACA,CACEhC,CAAAA,CACAC,CAAAA,CACArF,CAAAA,CACAsF,CAAAA,CACAC,CAAAA,CACAhD,CAAAA,CACAT,EACA8C,CAAAA,CACAY,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACA/C,CAAAA,CACAC,CACF,CACF,CACF,CCnJA,IAAMuE,EAAAA,CAAsC,CAAC,CAC3C,WAAA,CAAA1C,CAAAA,CACA,WAAA,CAAAW,CAAAA,CACA,aAAA,CAAAhD,CAAAA,CACA,cAAegF,CACjB,CAAA,GAAM,CACJ,GAAM,CAAE,MAAA,CAAAzF,CAAAA,CAAQ,cAAA,CAAA0D,CAAAA,CAAgB,UAAA,CAAAtD,CAAAA,CAAY,aAAA,CAAesF,CAAqB,CAAA,CAAIlI,CAAAA,EAAa,CAC3F,CAACmI,CAAAA,CAAYC,CAAa,CAAA,CAAIxE,QAAAA,CAAS,KAAK,CAAA,CAE5CL,CAAAA,CAAgB0E,CAAAA,EAAqBC,CAAAA,CAErCpC,CAAAA,CAAe5D,MAAAA,CAAuB,IAAI,CAAA,CAC1C,CAAE,SAAA,CAAAxB,CAAAA,CAAW,MAAA2H,CAAAA,CAAO,MAAA,CAAAC,CAAAA,CAAQ,eAAA,CAAAtC,CAAgB,CAAA,CAAIV,CAAAA,CAChDS,CAAAA,CAAQrF,IAAc,KAAA,CAEtB6H,CAAAA,CAAoB1C,CAAAA,CAAW,CACnC,YAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,UAAArF,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,aAAA,CAAehD,CAAAA,EAAiB,CAAA,CAChC,MAAA,CAAAT,CAAAA,CACA,WAAA,CAAA8C,CAAAA,CACA,cAAA,CAAAY,CAAAA,CACA,aAAA,CAAe,IAAMkC,EAAc,IAAI,CAAA,CACvC,WAAA,CAAa,IAAMA,CAAAA,CAAc,KAAK,CACxC,CAAC,EAED,OACE1C,IAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKI,CAAAA,CACL,KAAA,CAAO,CACL,OAAA,CAAS,OACT,aAAA,CAAeC,CAAAA,CAAQ,KAAA,CAAQ,QAAA,CAC/B,KAAA,CAAO,MAAA,CACP,MAAA,CAAQ,MAAA,CACR,QAAA,CAAU,QACZ,CAAA,CAEA,QAAA,CAAA,CAAAzD,GAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAM,CAAA,EAAG0D,CAAe,CAAA,KAAA,CAAA,CAAS,QAAA,CAAU,QAAS,CAAA,CAChE,QAAA,CAAA1D,GAAAA,CAACkG,EAAA,CACC,IAAA,CAAMH,CAAAA,CACN,WAAA,CAAapC,CAAAA,CACb,aAAA,CAAehD,CAAAA,CACf,aAAA,CAAegF,EACjB,CAAA,CACF,CAAA,CACC1E,CAAAA,CACCA,CAAAA,CAAc,CACZ,SAAA,CAAA7C,CAAAA,CACA,eAAA,CAAAsF,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,UAAA,CAAAkC,CAAAA,CACA,aAAA,CAAeI,CACjB,CAAC,EAEDjG,GAAAA,CAAC,KAAA,CAAA,CACC,SAAA,CAAWM,CAAAA,CAAW,OAAA,CACtB,gBAAA,CAAgBlC,CAAAA,CAChB,KAAA,CAAO,CACL,KAAA,CAAOqF,CAAAA,CAAQ,CAAA,EAAGE,CAAW,CAAA,EAAA,CAAA,CAAO,MAAA,CACpC,MAAA,CAAQF,EAAQ,MAAA,CAAS,CAAA,EAAGE,CAAW,CAAA,EAAA,CAAA,CACvC,MAAA,CAAQF,CAAAA,CAAQ,YAAA,CAAe,YAAA,CAC/B,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,EAAA,CACR,UAAA,CAAY,MAAA,CACZ,SAAA,CAAW,YAAA,CACX,WAAY,CACd,CAAA,CACA,aAAA,CAAewC,CAAAA,CACf,IAAA,CAAK,WAAA,CACL,eAAA,CAAevC,CAAAA,CACf,gBAAe,CAAA,CACf,eAAA,CAAe,EAAA,CACjB,CAAA,CAEF1D,GAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAM,CAAA,EAAG,GAAA,CAAM0D,CAAe,CAAA,KAAA,CAAA,CAAS,QAAA,CAAU,QAAS,CAAA,CACtE,QAAA,CAAA1D,GAAAA,CAACkG,CAAAA,CAAA,CACC,IAAA,CAAMF,CAAAA,CACN,WAAA,CAAarC,CAAAA,CACb,aAAA,CAAehD,EACf,aAAA,CAAegF,CAAAA,CACjB,CAAA,CACF,CAAA,CAAA,CACF,CAEJ,CAAA,CAEaO,CAAAA,CAAoC,CAAC,CAChD,IAAA,CAAApI,CAAAA,CACA,WAAA,CAAA6F,CAAAA,CAAc,CAAA,CACd,aAAA,CAAewC,CAAAA,CACf,aAAA,CAAAlF,CACF,CAAA,GAAM,CACJ,GAAM,CACJ,MAAA,CAAAf,CAAAA,CACA,UAAA,CAAAE,CAAAA,CACA,gBAAA,CAAAG,CAAAA,CACA,aAAA,CAAe6F,CACjB,CAAA,CAAI1I,CAAAA,EAAa,CAEXiD,CAAAA,CAAgBwF,IAAsB,MAAA,CAAYA,CAAAA,CAAoBC,CAAAA,CAG5E,GAAI7F,CAAAA,EAAoB,CAACzC,CAAAA,CACvB,OACEkC,IAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,QAAA,CAAU,UAAW,CAAA,CAC/D,QAAA,CAAAI,CAAAA,CAAWG,CAAgB,CAAA,CAC9B,CAAA,CAIJ,IAAMyC,CAAAA,CAAclF,CAAAA,GAAS,MAAA,CAAYA,CAAAA,CAAOoC,CAAAA,CAEhD,OAAK8C,CAAAA,CAEDA,CAAAA,CAAY,IAAA,GAAS,OAErBhD,GAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,QAAA,CAAU,UAAW,CAAA,CAC/D,QAAA,CAAAI,CAAAA,CAAW4C,CAAAA,CAAY,MAAM,CAAA,CAChC,EAKFhD,GAAAA,CAAC0F,EAAAA,CAAA,CACC,WAAA,CAAa1C,CAAAA,CACb,WAAA,CAAaW,CAAAA,CACb,aAAA,CAAehD,CAAAA,CACf,aAAA,CAAeM,CAAAA,CACjB,CAAA,CAhBuB,IAkB3B,ECzJO,IAAMoF,CAAAA,CAAmB5I,aAAAA,CAA8C,IAAI,CAAA,CCUlF,IAAM6I,EAAAA,CAA2D,CAC/D,GAAA,CAAK,CACH,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,KAAA,CACN,MAAO,KAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,OAAQ,CACN,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,KAAA,CACN,KAAA,CAAO,MACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,IAAA,CAAM,CACJ,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,EACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,MAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,EACA,KAAA,CAAO,CACL,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,MAAO,CAAA,CACP,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,MAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,KAAA,CACL,KAAM,KAAA,CACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CACF,CAAA,CAEMC,EAAAA,CAAwD,CAC5D,GAAA,CAAK,CACH,QAAA,CAAU,WACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,OAAQ,KAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,KAAM,CACJ,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,SAAA,CAAW,YACb,CAAA,CACA,KAAA,CAAO,CACL,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,EACR,KAAA,CAAO,CAAA,CACP,KAAA,CAAO,KAAA,CACP,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MAAA,CACf,UAAW,YACb,CAAA,CACA,MAAA,CAAQ,CACN,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAAA,CACR,MAAA,CAAQ,EAAA,CACR,cAAe,MAAA,CACf,SAAA,CAAW,YACb,CACF,CAAA,CAEMC,EAAAA,CAAoC,CAAC,CAAE,GAAAC,CAAAA,CAAI,QAAA,CAAAC,CAAAA,CAAU,eAAA,CAAAC,CAAgB,CAAA,GAAM,CAC/E,GAAM,CAAE,UAAA,CAAAC,CAAAA,CAAY,MAAA,CAAAC,CAAO,CAAA,CAAIC,YAAAA,CAAa,CAAE,EAAA,CAAAL,CAAG,CAAC,CAAA,CAClD,OACErD,IAAAA,CAAA2D,QAAAA,CAAA,CACE,QAAA,CAAA,CAAA/G,IAAC,KAAA,CAAA,CAAI,GAAA,CAAK4G,CAAAA,CAAY,KAAA,CAAON,EAAAA,CAAoBI,CAAQ,CAAA,CAAG,CAAA,CAC3DG,CAAAA,EAAU7G,GAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAW2G,CAAAA,CAAiB,KAAA,CAAOJ,EAAAA,CAAiBG,CAAQ,EAAG,CAAA,CAAA,CACjF,CAEJ,CAAA,CAQaM,EAAAA,CAA4B,CAAC,CAAE,EAAA,CAAAP,CAAAA,CAAI,QAAA,CAAArF,CAAAA,CAAU,KAAA,CAAA6F,CAAM,CAAA,GAAM,CACpE,GAAM,CAAE,SAAAzH,CAAAA,CAAU,UAAA,CAAAc,CAAAA,CAAY,gBAAA,CAAAC,CAAAA,CAAkB,QAAA,CAAAE,CAAAA,CAAU,kBAAA,CAAAD,EAAoB,UAAA,CAAA3C,CAAW,CAAA,CACvFH,CAAAA,EAAa,CACTwJ,CAAAA,CAAgB1H,CAAAA,GAAa,IAAA,EAAQA,IAAaiH,CAAAA,CAElD,CAAE,UAAA,CAAAU,CAAAA,CAAY,SAAA,CAAAC,CAAAA,CAAW,UAAA,CAAAR,CAAAA,CAAY,UAAA,CAAAS,CAAW,CAAA,CAAIC,YAAAA,CAAa,CAAE,EAAA,CAAAb,CAAG,CAAC,EACvEc,CAAAA,CAAW/H,CAAAA,GAAaiH,CAAAA,EAAMY,CAAAA,CAC9BG,CAAAA,CAAejH,CAAAA,GAAqBkG,CAAAA,CAEpCgB,CAAAA,CAA+B,CACnC,UAAA,CAAYF,CAAAA,CACZ,YAAA,CAAAC,CAAAA,CACA,gBAAA,CAAkB,IAAMhH,CAAAA,GAAqBgH,CAAAA,CAAe,KAAOf,CAAE,CAAA,CACrE,MAAA,CAAQ,IAAM,CACRe,CAAAA,EACFhH,CAAAA,GAAqB,IAAI,CAAA,CAEvBC,CAAAA,CACFA,CAAAA,CAASgG,CAAE,CAAA,CAEX5I,CAAAA,CAAW4I,CAAE,EAEjB,CACF,CAAA,CAGMvD,CAAAA,CAAeC,OAAAA,CACnB,KAAO,CACL,GAAGiE,CAAAA,CACH,GAAGD,CACL,CAAA,CAAA,CACA,CAACC,CAAAA,CAAWD,CAAU,CACxB,CAAA,CAEA,OACEnH,GAAAA,CAACqG,EAAiB,QAAA,CAAjB,CAA0B,KAAA,CAAOnD,CAAAA,CAChC,QAAA,CAAAE,IAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKwD,CAAAA,CACL,SAAA,CAAWtG,CAAAA,CAAW,IAAA,CACtB,KAAA,CAAO,CAAE,QAAA,CAAU,UAAA,CAAY,MAAO,MAAA,CAAQ,MAAA,CAAQ,MAAA,CAAQ,GAAG2G,CAAM,CAAA,CAEtE,QAAA,CAAA,CAAA7F,CAAAA,CAASqG,CAAW,CAAA,CAEpBP,CAAAA,EACC9D,IAAAA,CAAC,KAAA,CAAA,CACC,KAAA,CAAO,CACL,QAAA,CAAU,WACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAAA,CACR,MAAA,CAAQ,EAAA,CACR,aAAA,CAAe,MACjB,CAAA,CAEE,QAAA,CAAA,CAAA,CAAC,KAAA,CAAO,QAAA,CAAU,OAAQ,OAAO,CAAA,CAAY,GAAA,CAAKgC,CAAAA,EAClDpF,GAAAA,CAACwG,EAAAA,CAAA,CAEC,EAAA,CAAI,QAAQpB,CAAG,CAAA,CAAA,EAAIqB,CAAE,CAAA,CAAA,CACrB,QAAA,CAAUrB,CAAAA,CACV,eAAA,CAAiB9E,CAAAA,CAAW,aAHvB8E,CAIP,CACD,CAAA,CACDpF,GAAAA,CAACwG,EAAAA,CAAA,CACC,EAAA,CAAI,CAAA,YAAA,EAAeC,CAAE,CAAA,CAAA,CACrB,QAAA,CAAS,QAAA,CACT,eAAA,CAAiBnG,CAAAA,CAAW,WAAA,CAC9B,CAAA,CAAA,CACF,GAEJ,CAAA,CACF,CAEJ,ECnMO,IAAMoH,EAAAA,CAAwC,CAAC,CAAE,QAAA,CAAAtG,CAAAA,CAAU,SAAA,CAAA1B,EAAW,KAAA,CAAAuH,CAAM,CAAA,GAAM,CACvF,IAAMU,CAAAA,CAAY/J,UAAAA,CAAWyI,CAAgB,CAAA,CAC7C,GAAI,CAACsB,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,2CAA2C,EAE7D,OACE3H,GAAAA,CAAC,KAAA,CAAA,CACC,SAAA,CAAWN,CAAAA,CACX,KAAA,CAAO,CAAE,MAAA,CAAQ,OAAQ,UAAA,CAAY,MAAA,CAAQ,GAAGuH,CAAM,CAAA,CACrD,GAAGU,CAAAA,CAEH,QAAA,CAAAvG,EACH,CAEJ","file":"index.js","sourcesContent":["import { createContext, ReactNode } from 'react'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\n\nexport interface ZeugmaClassNames {\n pane?: string\n dropPreview?: string\n swapPreview?: string\n dragOverlay?: string\n resizer?: string\n}\n\nexport interface ResizerRenderProps {\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n isResizing: boolean\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void\n}\n\nexport interface DashboardContextValue {\n layout: TreeNode | null\n onLayoutChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n activeId: string | null\n fullscreenPaneId: string | null\n classNames: ZeugmaClassNames\n onRemove?: (paneId: string) => void\n onFullscreenChange?: (paneId: string | null) => void\n snapThreshold?: number\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n removePane: (paneId: string) => void\n addPane: (paneId: string) => void\n swapPanes: (paneIdA: string, paneIdB: string) => void\n splitPane: (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => void\n updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void\n}\n\nexport const DashboardContext = createContext<DashboardContextValue | undefined>(undefined)\n","import { useContext } from 'react'\nimport { DashboardContext } from './context'\n\nexport const useDashboard = () => {\n const context = useContext(DashboardContext)\n if (!context) {\n throw new Error('useDashboard must be used within a DashboardProvider')\n }\n return context\n}\n","import { TreeNode, SplitNode, SplitDirection, PaneNode } from '../../model'\n\n/**\n * Tree Helper: Remove a pane and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, idToRemove: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.paneId === idToRemove ? null : tree\n }\n const newFirst = removePane(tree.first, idToRemove)\n const newSecond = removePane(tree.second, idToRemove)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n): TreeNode | null {\n if (tree === null) return { type: 'pane', paneId: paneToAdd }\n if (tree.type === 'pane') {\n if (tree.paneId === targetId) {\n const addedNode: PaneNode = { type: 'pane', paneId: paneToAdd }\n const originalNode: PaneNode = { type: 'pane', paneId: targetId }\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : originalNode,\n second: isFirst ? originalNode : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Swap the position of two panes in the tree structure.\n */\nexport function swapPanes(tree: TreeNode | null, idA: string, idB: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.paneId === idA) return { ...tree, paneId: idB }\n if (tree.paneId === idB) return { ...tree, paneId: idA }\n return tree\n }\n return {\n ...tree,\n first: swapPanes(tree.first, idA, idB) || tree.first,\n second: swapPanes(tree.second, idA, idB) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.\n */\nexport function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode {\n if (tree === null) {\n return { type: 'pane', paneId: paneToAdd }\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: { type: 'pane', paneId: paneToAdd },\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage } as SplitNode\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n","export const DEFAULT_SNAP_THRESHOLD = 8 // px\nexport const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8 // px\nexport const DEFAULT_RESIZER_SIZE = 4 // px\n","import React, { useState, useEffect, useRef, ReactNode, useMemo, useCallback } from 'react'\nimport {\n DndContext,\n useSensor,\n useSensors,\n PointerSensor,\n DragStartEvent,\n DragEndEvent,\n pointerWithin,\n} from '@dnd-kit/core'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\nimport {\n removePane,\n splitPane,\n swapPanes,\n addPane,\n updateSplitPercentage,\n} from '../../../shared/lib/tree'\nimport { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_SNAP_THRESHOLD } from '../../../shared/config'\nimport { DashboardContext, ZeugmaClassNames, ResizerRenderProps } from '../model/context'\n\n/** Cursor-following overlay rendered via portal */\nconst CursorOverlay: React.FC<{\n activeId: string\n render: (id: string) => ReactNode\n className?: string\n}> = ({ activeId, render, className }) => {\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const handleMove = (e: PointerEvent) => {\n if (ref.current) {\n ref.current.style.transform = `translate(${e.clientX + 12}px, ${e.clientY + 12}px)`\n }\n }\n document.addEventListener('pointermove', handleMove)\n return () => document.removeEventListener('pointermove', handleMove)\n }, [])\n\n return (\n <div\n ref={ref}\n className={className}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n zIndex: 9999,\n pointerEvents: 'none',\n }}\n >\n {render(activeId)}\n </div>\n )\n}\n\ninterface DashboardProviderProps {\n layout: TreeNode | null\n onChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n renderDragOverlay?: (activeId: string) => ReactNode\n classNames?: ZeugmaClassNames\n fullscreenPaneId?: string | null\n onFullscreenChange?: (paneId: string | null) => void\n onRemove?: (paneId: string) => void\n dragActivationDistance?: number\n snapThreshold?: number\n onDragStart?: (activeId: string) => void\n onDragEnd?: (\n activeId: string,\n overId: string | null,\n dropAction: {\n type: 'split' | 'swap'\n direction?: SplitDirection\n position?: 'top' | 'bottom' | 'left' | 'right' | 'center'\n } | null,\n ) => void\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n children: ReactNode\n}\n\nexport const DashboardProvider: React.FC<DashboardProviderProps> = ({\n layout,\n onChange,\n renderPane,\n renderDragOverlay,\n classNames = {},\n fullscreenPaneId = null,\n onFullscreenChange,\n onRemove,\n dragActivationDistance = DEFAULT_DRAG_ACTIVATION_DISTANCE,\n snapThreshold = DEFAULT_SNAP_THRESHOLD,\n onDragStart,\n onDragEnd,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n children,\n}) => {\n const [activeId, setActiveId] = useState<string | null>(null)\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: dragActivationDistance },\n }),\n )\n\n const handleDragStart = (event: DragStartEvent) => {\n const draggingId = event.active.id.toString()\n setActiveId(draggingId)\n if (onDragStart) {\n onDragStart(draggingId)\n }\n }\n\n const handleDragEnd = (event: DragEndEvent) => {\n setActiveId(null)\n const { active, over } = event\n const draggingId = active.id.toString()\n\n if (!over) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const overIdStr = over.id.toString()\n\n // Check for center (swap) drop\n const swapMatch = overIdStr.match(/^drop-center-(.+)$/)\n if (swapMatch) {\n const [, targetId] = swapMatch\n if (draggingId !== targetId) {\n onChange(swapPanes(layout, draggingId, targetId))\n }\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, { type: 'swap', position: 'center' })\n }\n return\n }\n\n // Check for edge (split) drop\n const match = overIdStr.match(/^drop-(left|right|top|bottom)-(.+)$/)\n if (!match) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const [, dropZone, targetId] = match\n if (draggingId === targetId) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const direction: SplitDirection = dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n const treeWithoutDragging = removePane(layout, draggingId)\n\n const newLayout = splitPane(\n treeWithoutDragging,\n targetId,\n direction,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n draggingId,\n )\n onChange(newLayout)\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n }\n\n const handleRemovePane = useCallback(\n (paneId: string) => {\n const newLayout = removePane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleAddPane = useCallback(\n (paneId: string) => {\n const newLayout = addPane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSwapPanes = useCallback(\n (paneIdA: string, paneIdB: string) => {\n const newLayout = swapPanes(layout, paneIdA, paneIdB)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSplitPane = useCallback(\n (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => {\n const newLayout = splitPane(layout, targetId, direction, splitType, paneToAdd)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleUpdateSplitPercentage = useCallback(\n (currentNode: SplitNode, percentage: number) => {\n const newLayout = updateSplitPercentage(layout, currentNode, percentage)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n // Best practice: Memoize context value to prevent unnecessary re-renders of context consumers.\n const contextValue = useMemo(\n () => ({\n layout,\n onLayoutChange: onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n removePane: handleRemovePane,\n addPane: handleAddPane,\n swapPanes: handleSwapPanes,\n splitPane: handleSplitPane,\n updateSplitPercentage: handleUpdateSplitPercentage,\n }),\n [\n layout,\n onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n handleRemovePane,\n handleAddPane,\n handleSwapPanes,\n handleSplitPane,\n handleUpdateSplitPercentage,\n ],\n )\n\n return (\n <DashboardContext.Provider value={contextValue}>\n <DndContext\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n {children}\n </DndContext>\n {activeId && renderDragOverlay && (\n <CursorOverlay\n activeId={activeId}\n render={renderDragOverlay}\n className={classNames.dragOverlay}\n />\n )}\n </DashboardContext.Provider>\n )\n}\n","import React, { useCallback } from 'react'\nimport { TreeNode, SplitNode, SplitDirection } from '../../../shared/model'\nimport { updateSplitPercentage } from '../../../shared/lib/tree'\nimport { useDashboard } from '../../../entities/dashboard'\n\ninterface UseResizerProps {\n containerRef: React.RefObject<HTMLDivElement | null>\n isRow: boolean\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n snapThreshold: number\n layout: TreeNode | null\n currentNode: SplitNode\n onLayoutChange: (newLayout: TreeNode | null) => void\n onResizeStart?: () => void\n onResizeEnd?: () => void\n}\n\nexport function useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: localOnResizeStart,\n onResizeEnd: localOnResizeEnd,\n}: UseResizerProps) {\n const {\n onResizeStart: globalOnResizeStart,\n onResize: globalOnResize,\n onResizeEnd: globalOnResizeEnd,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n } = useDashboard()\n\n return useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault()\n const container = containerRef.current\n if (!container) return\n\n document.body.classList.add('zeugma-resizing')\n\n // Inject global cursor style to keep resizing cursor active across the entire page during drag\n const styleEl = document.createElement('style')\n styleEl.id = 'zeugma-global-cursor-style'\n styleEl.textContent = `\n * {\n cursor: ${isRow ? 'col-resize' : 'row-resize'} !important;\n user-select: none !important;\n }\n `\n document.head.appendChild(styleEl)\n\n if (localOnResizeStart) {\n localOnResizeStart()\n }\n if (globalOnResizeStart) {\n globalOnResizeStart(currentNode)\n }\n\n const rect = container.getBoundingClientRect()\n const startX = e.clientX\n const startY = e.clientY\n const startPercentage = splitPercentage\n\n // Cache other resizers of the same direction once at drag-start to prevent layout thrashing on move\n const resizerEl = e.currentTarget\n resizerEl.setAttribute('data-resizing', 'true')\n\n const otherResizers = Array.from(\n document.querySelectorAll('div[role=\"separator\"][data-direction]'),\n ).filter((el) => el !== resizerEl && el.getAttribute('data-direction') === direction)\n\n const otherPositions = otherResizers.map((el) => {\n const r = el.getBoundingClientRect()\n return isRow ? r.left + r.width / 2 : r.top + r.height / 2\n })\n\n let currentPercentage = startPercentage\n\n const handlePointerMove = (moveEvent: PointerEvent) => {\n const delta = isRow\n ? ((moveEvent.clientX - startX) / rect.width) * 100\n : ((moveEvent.clientY - startY) / rect.height) * 100\n const proposedPercentage = startPercentage + delta\n\n // Find physical position corresponding to proposed percentage\n const proposedPos = isRow\n ? rect.left + (rect.width - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n : rect.top + (rect.height - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n\n let closestDistance = Infinity\n let bestTarget: number | null = null\n\n for (const pos of otherPositions) {\n const dist = Math.abs(proposedPos - pos)\n if (dist < snapThreshold && dist < closestDistance) {\n closestDistance = dist\n bestTarget = pos\n }\n }\n\n let snappedPercentage = proposedPercentage\n if (bestTarget !== null) {\n snappedPercentage = isRow\n ? ((bestTarget - resizerSize / 2 - rect.left) / (rect.width - resizerSize)) * 100\n : ((bestTarget - resizerSize / 2 - rect.top) / (rect.height - resizerSize)) * 100\n }\n\n const finalPercentage = Math.max(\n minSplitPercentage,\n Math.min(maxSplitPercentage, snappedPercentage),\n )\n currentPercentage = finalPercentage\n const newLayout = updateSplitPercentage(layout, currentNode, finalPercentage)\n onLayoutChange(newLayout)\n if (globalOnResize) {\n globalOnResize(currentNode, finalPercentage)\n }\n }\n\n const handlePointerUp = () => {\n document.body.classList.remove('zeugma-resizing')\n resizerEl.removeAttribute('data-resizing')\n\n const globalStyle = document.getElementById('zeugma-global-cursor-style')\n if (globalStyle) {\n globalStyle.remove()\n }\n\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n\n if (localOnResizeEnd) {\n localOnResizeEnd()\n }\n if (globalOnResizeEnd) {\n globalOnResizeEnd(currentNode, currentPercentage)\n }\n }\n\n document.addEventListener('pointermove', handlePointerMove)\n document.addEventListener('pointerup', handlePointerUp)\n },\n [\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n localOnResizeStart,\n localOnResizeEnd,\n globalOnResizeStart,\n globalOnResize,\n globalOnResizeEnd,\n minSplitPercentage,\n maxSplitPercentage,\n ],\n )\n}\n","import React, { useRef, useState } from 'react'\nimport { useDashboard, ResizerRenderProps } from '../../../entities/dashboard'\nimport { useResizer } from '../../../features/resize-pane'\nimport { TreeNode, SplitNode } from '../../../shared/model'\n\nexport interface PaneTreeProps {\n tree?: TreeNode | null\n /** Size of the resizer in pixels (default 4) */\n resizerSize?: number\n /** Threshold in pixels to snap to adjacent resizer edges (default 8) */\n snapThreshold?: number\n /** Custom resizer renderer to override context-level renderResizer */\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\ninterface PaneSplitProps {\n currentNode: SplitNode\n resizerSize: number\n snapThreshold?: number\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\nconst PaneSplit: React.FC<PaneSplitProps> = ({\n currentNode,\n resizerSize,\n snapThreshold,\n renderResizer: propRenderResizer,\n}) => {\n const { layout, onLayoutChange, classNames, renderResizer: contextRenderResizer } = useDashboard()\n const [isResizing, setIsResizing] = useState(false)\n\n const renderResizer = propRenderResizer || contextRenderResizer\n\n const containerRef = useRef<HTMLDivElement>(null)\n const { direction, first, second, splitPercentage } = currentNode\n const isRow = direction === 'row'\n\n const handlePointerDown = useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold: snapThreshold ?? 8,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: () => setIsResizing(true),\n onResizeEnd: () => setIsResizing(false),\n })\n\n return (\n <div\n ref={containerRef}\n style={{\n display: 'flex',\n flexDirection: isRow ? 'row' : 'column',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <div style={{ flex: `${splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={first}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n {renderResizer ? (\n renderResizer({\n direction,\n splitPercentage,\n resizerSize,\n isResizing,\n onPointerDown: handlePointerDown,\n })\n ) : (\n <div\n className={classNames.resizer}\n data-direction={direction}\n style={{\n width: isRow ? `${resizerSize}px` : '100%',\n height: isRow ? '100%' : `${resizerSize}px`,\n cursor: isRow ? 'col-resize' : 'row-resize',\n position: 'relative',\n zIndex: 10,\n userSelect: 'none',\n boxSizing: 'border-box',\n flexShrink: 0,\n }}\n onPointerDown={handlePointerDown}\n role=\"separator\"\n aria-valuenow={splitPercentage}\n aria-valuemin={5}\n aria-valuemax={95}\n />\n )}\n <div style={{ flex: `${100 - splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={second}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n </div>\n )\n}\n\nexport const PaneTree: React.FC<PaneTreeProps> = ({\n tree,\n resizerSize = 4,\n snapThreshold: propSnapThreshold,\n renderResizer,\n}) => {\n const {\n layout,\n renderPane,\n fullscreenPaneId,\n snapThreshold: contextSnapThreshold,\n } = useDashboard()\n\n const snapThreshold = propSnapThreshold !== undefined ? propSnapThreshold : contextSnapThreshold\n\n // Fullscreen bypass\n if (fullscreenPaneId && !tree) {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(fullscreenPaneId)}\n </div>\n )\n }\n\n const currentNode = tree !== undefined ? tree : layout\n\n if (!currentNode) return null\n\n if (currentNode.type === 'pane') {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(currentNode.paneId)}\n </div>\n )\n }\n\n return (\n <PaneSplit\n currentNode={currentNode}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={renderResizer}\n />\n )\n}\n","import { createContext } from 'react'\n\nexport const DragListenersCtx = createContext<Record<string, unknown> | null>(null)\n","import React, { useMemo } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport { useDashboard } from '../../dashboard'\nimport { DragListenersCtx } from '../model/context'\nimport { PaneRenderProps } from '../model/types'\n\ninterface DropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right' | 'center'\n activeClassName?: string\n}\n\nconst activationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n center: {\n position: 'absolute',\n top: '25%',\n left: '25%',\n width: '50%',\n height: '50%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n}\n\nconst previewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n center: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={activationPositions[position]} />\n {isOver && <div className={activeClassName} style={previewPositions[position]} />}\n </>\n )\n}\n\ninterface PaneProps {\n id: string\n children: (props: PaneRenderProps) => React.ReactNode\n style?: React.CSSProperties\n}\n\nexport const Pane: React.FC<PaneProps> = ({ id, children, style }) => {\n const { activeId, classNames, fullscreenPaneId, onRemove, onFullscreenChange, removePane } =\n useDashboard()\n const showDropZones = activeId !== null && activeId !== id\n\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id })\n const dragging = activeId === id || isDragging\n const isFullscreen = fullscreenPaneId === id\n\n const renderProps: PaneRenderProps = {\n isDragging: dragging,\n isFullscreen,\n toggleFullscreen: () => onFullscreenChange?.(isFullscreen ? null : id),\n remove: () => {\n if (isFullscreen) {\n onFullscreenChange?.(null)\n }\n if (onRemove) {\n onRemove(id)\n } else {\n removePane(id)\n }\n },\n }\n\n // Best practice: Memoize drag context value to prevent unnecessary re-renders of the drag handle.\n const contextValue = useMemo(\n () => ({\n ...listeners,\n ...attributes,\n }),\n [listeners, attributes],\n )\n\n return (\n <DragListenersCtx.Provider value={contextValue}>\n <div\n ref={setNodeRef}\n className={classNames.pane}\n style={{ position: 'relative', width: '100%', height: '100%', ...style }}\n >\n {children(renderProps)}\n\n {showDropZones && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 15,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <DropZone\n key={pos}\n id={`drop-${pos}-${id}`}\n position={pos}\n activeClassName={classNames.dropPreview}\n />\n ))}\n <DropZone\n id={`drop-center-${id}`}\n position=\"center\"\n activeClassName={classNames.swapPreview}\n />\n </div>\n )}\n </div>\n </DragListenersCtx.Provider>\n )\n}\n","import React, { useContext } from 'react'\nimport { DragListenersCtx } from '../model/context'\n\ninterface DragHandleProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\nexport const DragHandle: React.FC<DragHandleProps> = ({ children, className, style }) => {\n const dragProps = useContext(DragListenersCtx)\n if (!dragProps) {\n throw new Error('<DragHandle> must be used inside a <Pane>')\n }\n return (\n <div\n className={className}\n style={{ cursor: 'grab', userSelect: 'none', ...style }}\n {...dragProps}\n >\n {children}\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/entities/dashboard/model/context.ts","../src/entities/dashboard/model/hooks.ts","../src/shared/lib/tree/tree-helpers.ts","../src/shared/config/constants.ts","../src/entities/dashboard/ui/RootDropZone.tsx","../src/entities/dashboard/ui/DashboardProvider.tsx","../src/features/resize-pane/hooks/useResizer.ts","../src/widgets/pane-tree/ui/PaneTree.tsx","../src/entities/pane/model/context.ts","../src/entities/pane/ui/Pane.tsx","../src/entities/pane/ui/DragHandle.tsx"],"names":["DashboardContext","createContext","useDashboard","context","useContext","removePane","tree","idToRemove","newFirst","newSecond","splitPane","targetId","direction","splitType","paneToAdd","addedNode","originalNode","isFirst","swapPanes","idA","idB","addPane","insert","node","parentDirection","updateSplitPercentage","target","newPercentage","splitRoot","draggingId","treeWithoutDragging","draggedNode","DEFAULT_SNAP_THRESHOLD","DEFAULT_DRAG_ACTIVATION_DISTANCE","DEFAULT_RESIZER_SIZE","rootActivationPositions","rootPreviewPositions","RootDropZone","id","position","activeClassName","setNodeRef","isOver","useDroppable","jsxs","Fragment","jsx","RootDropZones","activeId","hasOtherPanes","dropPreviewClassName","pos","CursorOverlay","render","className","ref","useRef","useEffect","handleMove","e","DashboardProvider","layout","onChange","renderPane","renderDragOverlay","classNames","fullscreenPaneId","onFullscreenChange","onRemove","dragActivationDistance","snapThreshold","onDragStart","onDragEnd","onResizeStart","onResize","onResizeEnd","renderResizer","minSplitPercentage","maxSplitPercentage","children","setActiveId","useState","sensors","useSensors","useSensor","PointerSensor","handleDragStart","event","handleDragEnd","active","over","overIdStr","rootMatch","dropZone","newLayout","swapMatch","match","handleRemovePane","useCallback","paneId","handleAddPane","handleSwapPanes","paneIdA","paneIdB","handleSplitPane","handleUpdateSplitPercentage","currentNode","percentage","contextValue","useMemo","DndContext","pointerWithin","useResizer","containerRef","isRow","splitPercentage","resizerSize","onLayoutChange","localOnResizeStart","localOnResizeEnd","globalOnResizeStart","globalOnResize","globalOnResizeEnd","container","styleEl","rect","startX","startY","startPercentage","resizerEl","otherPositions","el","r","currentPercentage","handlePointerMove","moveEvent","delta","proposedPercentage","proposedPos","closestDistance","bestTarget","dist","snappedPercentage","finalPercentage","handlePointerUp","globalStyle","PaneSplit","propRenderResizer","contextRenderResizer","isResizing","setIsResizing","first","second","handlePointerDown","PaneTree","propSnapThreshold","contextSnapThreshold","DragListenersCtx","activationPositions","previewPositions","DropZone","Pane","style","showDropZones","attributes","listeners","isDragging","useDraggable","dragging","isFullscreen","renderProps","DragHandle","dragProps"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, ReactNode } from 'react'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\n\nexport interface ZeugmaClassNames {\n pane?: string\n dropPreview?: string\n swapPreview?: string\n dragOverlay?: string\n resizer?: string\n}\n\nexport interface ResizerRenderProps {\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n isResizing: boolean\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void\n}\n\nexport interface DashboardContextValue {\n layout: TreeNode | null\n onLayoutChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n activeId: string | null\n fullscreenPaneId: string | null\n classNames: ZeugmaClassNames\n onRemove?: (paneId: string) => void\n onFullscreenChange?: (paneId: string | null) => void\n snapThreshold?: number\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n removePane: (paneId: string) => void\n addPane: (paneId: string) => void\n swapPanes: (paneIdA: string, paneIdB: string) => void\n splitPane: (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => void\n updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void\n}\n\nexport const DashboardContext = createContext<DashboardContextValue | undefined>(undefined)\n","import { useContext } from 'react'\nimport { DashboardContext } from './context'\n\nexport const useDashboard = () => {\n const context = useContext(DashboardContext)\n if (!context) {\n throw new Error('useDashboard must be used within a DashboardProvider')\n }\n return context\n}\n","import { TreeNode, SplitNode, SplitDirection, PaneNode } from '../../model'\n\n/**\n * Tree Helper: Remove a pane and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, idToRemove: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.paneId === idToRemove ? null : tree\n }\n const newFirst = removePane(tree.first, idToRemove)\n const newSecond = removePane(tree.second, idToRemove)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n): TreeNode | null {\n if (tree === null) return { type: 'pane', paneId: paneToAdd }\n if (tree.type === 'pane') {\n if (tree.paneId === targetId) {\n const addedNode: PaneNode = { type: 'pane', paneId: paneToAdd }\n const originalNode: PaneNode = { type: 'pane', paneId: targetId }\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : originalNode,\n second: isFirst ? originalNode : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Swap the position of two panes in the tree structure.\n */\nexport function swapPanes(tree: TreeNode | null, idA: string, idB: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.paneId === idA) return { ...tree, paneId: idB }\n if (tree.paneId === idB) return { ...tree, paneId: idA }\n return tree\n }\n return {\n ...tree,\n first: swapPanes(tree.first, idA, idB) || tree.first,\n second: swapPanes(tree.second, idA, idB) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.\n */\nexport function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode {\n if (tree === null) {\n return { type: 'pane', paneId: paneToAdd }\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: { type: 'pane', paneId: paneToAdd },\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage } as SplitNode\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n\n/**\n * Tree Helper: Split the entire tree at the root using a dragged pane.\n */\nexport function splitRoot(\n tree: TreeNode | null,\n draggingId: string,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n): TreeNode | null {\n const treeWithoutDragging = removePane(tree, draggingId)\n if (treeWithoutDragging === null) {\n return { type: 'pane', paneId: draggingId }\n }\n\n const direction: SplitDirection = splitType === 'left' || splitType === 'right' ? 'row' : 'column'\n const isFirst = splitType === 'left' || splitType === 'top'\n const draggedNode: TreeNode = { type: 'pane', paneId: draggingId }\n\n return {\n type: 'split',\n direction,\n first: isFirst ? draggedNode : treeWithoutDragging,\n second: isFirst ? treeWithoutDragging : draggedNode,\n splitPercentage: 50,\n }\n}\n","export const DEFAULT_SNAP_THRESHOLD = 8 // px\nexport const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8 // px\nexport const DEFAULT_RESIZER_SIZE = 4 // px\n","import React from 'react'\nimport { useDroppable } from '@dnd-kit/core'\n\nconst rootActivationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '32px',\n zIndex: 30,\n pointerEvents: 'auto',\n },\n}\n\nconst rootPreviewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 31,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nexport interface RootDropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right'\n activeClassName?: string\n}\n\nexport const RootDropZone: React.FC<RootDropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={rootActivationPositions[position]} />\n {isOver && <div className={activeClassName} style={rootPreviewPositions[position]} />}\n </>\n )\n}\n\nexport interface RootDropZonesProps {\n activeId: string | null\n hasOtherPanes: boolean\n dropPreviewClassName?: string\n}\n\nexport const RootDropZones: React.FC<RootDropZonesProps> = ({\n activeId,\n hasOtherPanes,\n dropPreviewClassName,\n}) => {\n if (!activeId || !hasOtherPanes) return null\n\n return (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 30,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <RootDropZone\n key={pos}\n id={`drop-root-${pos}`}\n position={pos}\n activeClassName={dropPreviewClassName}\n />\n ))}\n </div>\n )\n}\n","import React, { useState, useEffect, useRef, ReactNode, useMemo, useCallback } from 'react'\nimport {\n DndContext,\n useSensor,\n useSensors,\n PointerSensor,\n DragStartEvent,\n DragEndEvent,\n pointerWithin,\n} from '@dnd-kit/core'\nimport { TreeNode, SplitDirection, SplitNode } from '../../../shared/model'\nimport {\n removePane,\n splitPane,\n swapPanes,\n addPane,\n updateSplitPercentage,\n splitRoot,\n} from '../../../shared/lib/tree'\nimport { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_SNAP_THRESHOLD } from '../../../shared/config'\nimport { DashboardContext, ZeugmaClassNames, ResizerRenderProps } from '../model/context'\nimport { RootDropZones } from './RootDropZone'\n\n/** Cursor-following overlay rendered via portal */\nconst CursorOverlay: React.FC<{\n activeId: string\n render: (id: string) => ReactNode\n className?: string\n}> = ({ activeId, render, className }) => {\n const ref = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const handleMove = (e: PointerEvent) => {\n if (ref.current) {\n ref.current.style.transform = `translate(${e.clientX + 12}px, ${e.clientY + 12}px)`\n }\n }\n document.addEventListener('pointermove', handleMove)\n return () => document.removeEventListener('pointermove', handleMove)\n }, [])\n\n return (\n <div\n ref={ref}\n className={className}\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n zIndex: 9999,\n pointerEvents: 'none',\n }}\n >\n {render(activeId)}\n </div>\n )\n}\n\ninterface DashboardProviderProps {\n layout: TreeNode | null\n onChange: (newLayout: TreeNode | null) => void\n renderPane: (paneId: string) => ReactNode\n renderDragOverlay?: (activeId: string) => ReactNode\n classNames?: ZeugmaClassNames\n fullscreenPaneId?: string | null\n onFullscreenChange?: (paneId: string | null) => void\n onRemove?: (paneId: string) => void\n dragActivationDistance?: number\n snapThreshold?: number\n onDragStart?: (activeId: string) => void\n onDragEnd?: (\n activeId: string,\n overId: string | null,\n dropAction: {\n type: 'split' | 'swap'\n direction?: SplitDirection\n position?: 'top' | 'bottom' | 'left' | 'right' | 'center'\n } | null,\n ) => void\n onResizeStart?: (currentNode: SplitNode) => void\n onResize?: (currentNode: SplitNode, percentage: number) => void\n onResizeEnd?: (currentNode: SplitNode, percentage: number) => void\n renderResizer?: (props: ResizerRenderProps) => ReactNode\n minSplitPercentage?: number\n maxSplitPercentage?: number\n children: ReactNode\n}\n\nexport const DashboardProvider: React.FC<DashboardProviderProps> = ({\n layout,\n onChange,\n renderPane,\n renderDragOverlay,\n classNames = {},\n fullscreenPaneId = null,\n onFullscreenChange,\n onRemove,\n dragActivationDistance = DEFAULT_DRAG_ACTIVATION_DISTANCE,\n snapThreshold = DEFAULT_SNAP_THRESHOLD,\n onDragStart,\n onDragEnd,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n children,\n}) => {\n const [activeId, setActiveId] = useState<string | null>(null)\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: dragActivationDistance },\n }),\n )\n\n const handleDragStart = (event: DragStartEvent) => {\n const draggingId = event.active.id.toString()\n setActiveId(draggingId)\n if (onDragStart) {\n onDragStart(draggingId)\n }\n }\n\n const handleDragEnd = (event: DragEndEvent) => {\n setActiveId(null)\n const { active, over } = event\n const draggingId = active.id.toString()\n\n if (!over) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const overIdStr = over.id.toString()\n\n // Check for root drop (places pane like half of the root)\n const rootMatch = overIdStr.match(/^drop-root-(left|right|top|bottom)$/)\n if (rootMatch) {\n const [, dropZone] = rootMatch\n const newLayout = splitRoot(\n layout,\n draggingId,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n )\n onChange(newLayout)\n\n if (onDragEnd) {\n const direction: SplitDirection =\n dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n onDragEnd(draggingId, 'root', {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n return\n }\n\n // Check for center (swap) drop\n const swapMatch = overIdStr.match(/^drop-center-(.+)$/)\n if (swapMatch) {\n const [, targetId] = swapMatch\n if (draggingId !== targetId) {\n onChange(swapPanes(layout, draggingId, targetId))\n }\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, { type: 'swap', position: 'center' })\n }\n return\n }\n\n // Check for edge (split) drop\n const match = overIdStr.match(/^drop-(left|right|top|bottom)-(.+)$/)\n if (!match) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const [, dropZone, targetId] = match\n if (draggingId === targetId) {\n if (onDragEnd) {\n onDragEnd(draggingId, null, null)\n }\n return\n }\n\n const direction: SplitDirection = dropZone === 'left' || dropZone === 'right' ? 'row' : 'column'\n const treeWithoutDragging = removePane(layout, draggingId)\n\n const newLayout = splitPane(\n treeWithoutDragging,\n targetId,\n direction,\n dropZone as 'left' | 'right' | 'top' | 'bottom',\n draggingId,\n )\n onChange(newLayout)\n if (onDragEnd) {\n onDragEnd(draggingId, targetId, {\n type: 'split',\n direction,\n position: dropZone as 'left' | 'right' | 'top' | 'bottom',\n })\n }\n }\n\n const handleRemovePane = useCallback(\n (paneId: string) => {\n const newLayout = removePane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleAddPane = useCallback(\n (paneId: string) => {\n const newLayout = addPane(layout, paneId)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSwapPanes = useCallback(\n (paneIdA: string, paneIdB: string) => {\n const newLayout = swapPanes(layout, paneIdA, paneIdB)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleSplitPane = useCallback(\n (\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string,\n ) => {\n const newLayout = splitPane(layout, targetId, direction, splitType, paneToAdd)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n const handleUpdateSplitPercentage = useCallback(\n (currentNode: SplitNode, percentage: number) => {\n const newLayout = updateSplitPercentage(layout, currentNode, percentage)\n onChange(newLayout)\n },\n [layout, onChange],\n )\n\n // Best practice: Memoize context value to prevent unnecessary re-renders of context consumers.\n const contextValue = useMemo(\n () => ({\n layout,\n onLayoutChange: onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n removePane: handleRemovePane,\n addPane: handleAddPane,\n swapPanes: handleSwapPanes,\n splitPane: handleSplitPane,\n updateSplitPercentage: handleUpdateSplitPercentage,\n }),\n [\n layout,\n onChange,\n renderPane,\n activeId,\n fullscreenPaneId,\n classNames,\n onRemove,\n onFullscreenChange,\n snapThreshold,\n onResizeStart,\n onResize,\n onResizeEnd,\n renderResizer,\n minSplitPercentage,\n maxSplitPercentage,\n handleRemovePane,\n handleAddPane,\n handleSwapPanes,\n handleSplitPane,\n handleUpdateSplitPercentage,\n ],\n )\n\n const hasOtherPanes = useMemo(() => {\n if (!activeId) return false\n return removePane(layout, activeId) !== null\n }, [layout, activeId])\n\n return (\n <DashboardContext.Provider value={contextValue}>\n <DndContext\n id=\"zeugma-dnd-context\"\n sensors={sensors}\n collisionDetection={pointerWithin}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div\n className=\"zeugma-dashboard-root\"\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n }}\n >\n {children}\n <RootDropZones\n activeId={activeId}\n hasOtherPanes={hasOtherPanes}\n dropPreviewClassName={classNames.dropPreview}\n />\n </div>\n </DndContext>\n {activeId && renderDragOverlay && (\n <CursorOverlay\n activeId={activeId}\n render={renderDragOverlay}\n className={classNames.dragOverlay}\n />\n )}\n </DashboardContext.Provider>\n )\n}\n","import React, { useCallback } from 'react'\nimport { TreeNode, SplitNode, SplitDirection } from '../../../shared/model'\nimport { updateSplitPercentage } from '../../../shared/lib/tree'\nimport { useDashboard } from '../../../entities/dashboard'\n\ninterface UseResizerProps {\n containerRef: React.RefObject<HTMLDivElement | null>\n isRow: boolean\n direction: SplitDirection\n splitPercentage: number\n resizerSize: number\n snapThreshold: number\n layout: TreeNode | null\n currentNode: SplitNode\n onLayoutChange: (newLayout: TreeNode | null) => void\n onResizeStart?: () => void\n onResizeEnd?: () => void\n}\n\nexport function useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: localOnResizeStart,\n onResizeEnd: localOnResizeEnd,\n}: UseResizerProps) {\n const {\n onResizeStart: globalOnResizeStart,\n onResize: globalOnResize,\n onResizeEnd: globalOnResizeEnd,\n minSplitPercentage = 5,\n maxSplitPercentage = 95,\n } = useDashboard()\n\n return useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n e.preventDefault()\n const container = containerRef.current\n if (!container) return\n\n document.body.classList.add('zeugma-resizing')\n\n // Inject global cursor style to keep resizing cursor active across the entire page during drag\n const styleEl = document.createElement('style')\n styleEl.id = 'zeugma-global-cursor-style'\n styleEl.textContent = `\n * {\n cursor: ${isRow ? 'col-resize' : 'row-resize'} !important;\n user-select: none !important;\n }\n `\n document.head.appendChild(styleEl)\n\n if (localOnResizeStart) {\n localOnResizeStart()\n }\n if (globalOnResizeStart) {\n globalOnResizeStart(currentNode)\n }\n\n const rect = container.getBoundingClientRect()\n const startX = e.clientX\n const startY = e.clientY\n const startPercentage = splitPercentage\n\n // Cache other resizers of the same direction once at drag-start to prevent layout thrashing on move\n const resizerEl = e.currentTarget\n resizerEl.setAttribute('data-resizing', 'true')\n\n const otherResizers = Array.from(\n document.querySelectorAll('div[role=\"separator\"][data-direction]'),\n ).filter((el) => el !== resizerEl && el.getAttribute('data-direction') === direction)\n\n const otherPositions = otherResizers.map((el) => {\n const r = el.getBoundingClientRect()\n return isRow ? r.left + r.width / 2 : r.top + r.height / 2\n })\n\n let currentPercentage = startPercentage\n\n const handlePointerMove = (moveEvent: PointerEvent) => {\n const delta = isRow\n ? ((moveEvent.clientX - startX) / rect.width) * 100\n : ((moveEvent.clientY - startY) / rect.height) * 100\n const proposedPercentage = startPercentage + delta\n\n // Find physical position corresponding to proposed percentage\n const proposedPos = isRow\n ? rect.left + (rect.width - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n : rect.top + (rect.height - resizerSize) * (proposedPercentage / 100) + resizerSize / 2\n\n let closestDistance = Infinity\n let bestTarget: number | null = null\n\n for (const pos of otherPositions) {\n const dist = Math.abs(proposedPos - pos)\n if (dist < snapThreshold && dist < closestDistance) {\n closestDistance = dist\n bestTarget = pos\n }\n }\n\n let snappedPercentage = proposedPercentage\n if (bestTarget !== null) {\n snappedPercentage = isRow\n ? ((bestTarget - resizerSize / 2 - rect.left) / (rect.width - resizerSize)) * 100\n : ((bestTarget - resizerSize / 2 - rect.top) / (rect.height - resizerSize)) * 100\n }\n\n const finalPercentage = Math.max(\n minSplitPercentage,\n Math.min(maxSplitPercentage, snappedPercentage),\n )\n currentPercentage = finalPercentage\n const newLayout = updateSplitPercentage(layout, currentNode, finalPercentage)\n onLayoutChange(newLayout)\n if (globalOnResize) {\n globalOnResize(currentNode, finalPercentage)\n }\n }\n\n const handlePointerUp = () => {\n document.body.classList.remove('zeugma-resizing')\n resizerEl.removeAttribute('data-resizing')\n\n const globalStyle = document.getElementById('zeugma-global-cursor-style')\n if (globalStyle) {\n globalStyle.remove()\n }\n\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n\n if (localOnResizeEnd) {\n localOnResizeEnd()\n }\n if (globalOnResizeEnd) {\n globalOnResizeEnd(currentNode, currentPercentage)\n }\n }\n\n document.addEventListener('pointermove', handlePointerMove)\n document.addEventListener('pointerup', handlePointerUp)\n },\n [\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold,\n layout,\n currentNode,\n onLayoutChange,\n localOnResizeStart,\n localOnResizeEnd,\n globalOnResizeStart,\n globalOnResize,\n globalOnResizeEnd,\n minSplitPercentage,\n maxSplitPercentage,\n ],\n )\n}\n","import React, { useRef, useState } from 'react'\nimport { useDashboard, ResizerRenderProps } from '../../../entities/dashboard'\nimport { useResizer } from '../../../features/resize-pane'\nimport { TreeNode, SplitNode } from '../../../shared/model'\n\nexport interface PaneTreeProps {\n tree?: TreeNode | null\n /** Size of the resizer in pixels (default 4) */\n resizerSize?: number\n /** Threshold in pixels to snap to adjacent resizer edges (default 8) */\n snapThreshold?: number\n /** Custom resizer renderer to override context-level renderResizer */\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\ninterface PaneSplitProps {\n currentNode: SplitNode\n resizerSize: number\n snapThreshold?: number\n renderResizer?: (props: ResizerRenderProps) => React.ReactNode\n}\n\nconst PaneSplit: React.FC<PaneSplitProps> = ({\n currentNode,\n resizerSize,\n snapThreshold,\n renderResizer: propRenderResizer,\n}) => {\n const { layout, onLayoutChange, classNames, renderResizer: contextRenderResizer } = useDashboard()\n const [isResizing, setIsResizing] = useState(false)\n\n const renderResizer = propRenderResizer || contextRenderResizer\n\n const containerRef = useRef<HTMLDivElement>(null)\n const { direction, first, second, splitPercentage } = currentNode\n const isRow = direction === 'row'\n\n const handlePointerDown = useResizer({\n containerRef,\n isRow,\n direction,\n splitPercentage,\n resizerSize,\n snapThreshold: snapThreshold ?? 8,\n layout,\n currentNode,\n onLayoutChange,\n onResizeStart: () => setIsResizing(true),\n onResizeEnd: () => setIsResizing(false),\n })\n\n return (\n <div\n ref={containerRef}\n style={{\n display: 'flex',\n flexDirection: isRow ? 'row' : 'column',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <div style={{ flex: `${splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={first}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n {renderResizer ? (\n renderResizer({\n direction,\n splitPercentage,\n resizerSize,\n isResizing,\n onPointerDown: handlePointerDown,\n })\n ) : (\n <div\n className={classNames.resizer}\n data-direction={direction}\n style={{\n width: isRow ? `${resizerSize}px` : '100%',\n height: isRow ? '100%' : `${resizerSize}px`,\n cursor: isRow ? 'col-resize' : 'row-resize',\n position: 'relative',\n zIndex: 10,\n userSelect: 'none',\n boxSizing: 'border-box',\n flexShrink: 0,\n }}\n onPointerDown={handlePointerDown}\n role=\"separator\"\n aria-valuenow={splitPercentage}\n aria-valuemin={5}\n aria-valuemax={95}\n />\n )}\n <div style={{ flex: `${100 - splitPercentage} 1 0%`, overflow: 'hidden' }}>\n <PaneTree\n tree={second}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={propRenderResizer}\n />\n </div>\n </div>\n )\n}\n\nexport const PaneTree: React.FC<PaneTreeProps> = ({\n tree,\n resizerSize = 4,\n snapThreshold: propSnapThreshold,\n renderResizer,\n}) => {\n const {\n layout,\n renderPane,\n fullscreenPaneId,\n snapThreshold: contextSnapThreshold,\n } = useDashboard()\n\n const snapThreshold = propSnapThreshold !== undefined ? propSnapThreshold : contextSnapThreshold\n\n // Fullscreen bypass\n if (fullscreenPaneId && !tree) {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(fullscreenPaneId)}\n </div>\n )\n }\n\n const currentNode = tree !== undefined ? tree : layout\n\n if (!currentNode) return null\n\n if (currentNode.type === 'pane') {\n return (\n <div style={{ width: '100%', height: '100%', position: 'relative' }}>\n {renderPane(currentNode.paneId)}\n </div>\n )\n }\n\n return (\n <PaneSplit\n currentNode={currentNode}\n resizerSize={resizerSize}\n snapThreshold={snapThreshold}\n renderResizer={renderResizer}\n />\n )\n}\n","import { createContext } from 'react'\n\nexport const DragListenersCtx = createContext<Record<string, unknown> | null>(null)\n","import React, { useMemo } from 'react'\nimport { useDraggable, useDroppable } from '@dnd-kit/core'\nimport { useDashboard } from '../../dashboard'\nimport { DragListenersCtx } from '../model/context'\nimport { PaneRenderProps } from '../model/types'\n\ninterface DropZoneProps {\n id: string\n position: 'top' | 'bottom' | 'left' | 'right' | 'center'\n activeClassName?: string\n}\n\nconst activationPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: '25%',\n width: '50%',\n height: '25%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '25%',\n height: '100%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n center: {\n position: 'absolute',\n top: '25%',\n left: '25%',\n width: '50%',\n height: '50%',\n zIndex: 20,\n pointerEvents: 'auto',\n },\n}\n\nconst previewPositions: Record<string, React.CSSProperties> = {\n top: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n bottom: {\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n height: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n left: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n right: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n right: 0,\n width: '50%',\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n center: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 21,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n}\n\nconst DropZone: React.FC<DropZoneProps> = ({ id, position, activeClassName }) => {\n const { setNodeRef, isOver } = useDroppable({ id })\n return (\n <>\n <div ref={setNodeRef} style={activationPositions[position]} />\n {isOver && <div className={activeClassName} style={previewPositions[position]} />}\n </>\n )\n}\n\ninterface PaneProps {\n id: string\n children: (props: PaneRenderProps) => React.ReactNode\n style?: React.CSSProperties\n}\n\nexport const Pane: React.FC<PaneProps> = ({ id, children, style }) => {\n const { activeId, classNames, fullscreenPaneId, onRemove, onFullscreenChange, removePane } =\n useDashboard()\n const showDropZones = activeId !== null && activeId !== id\n\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id })\n const dragging = activeId === id || isDragging\n const isFullscreen = fullscreenPaneId === id\n\n const renderProps: PaneRenderProps = {\n isDragging: dragging,\n isFullscreen,\n toggleFullscreen: () => onFullscreenChange?.(isFullscreen ? null : id),\n remove: () => {\n if (isFullscreen) {\n onFullscreenChange?.(null)\n }\n if (onRemove) {\n onRemove(id)\n } else {\n removePane(id)\n }\n },\n }\n\n // Best practice: Memoize drag context value to prevent unnecessary re-renders of the drag handle.\n const contextValue = useMemo(\n () => ({\n ...listeners,\n ...attributes,\n }),\n [listeners, attributes],\n )\n\n return (\n <DragListenersCtx.Provider value={contextValue}>\n <div\n ref={setNodeRef}\n className={classNames.pane}\n style={{ position: 'relative', width: '100%', height: '100%', ...style }}\n >\n {children(renderProps)}\n\n {showDropZones && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 15,\n pointerEvents: 'none',\n }}\n >\n {(['top', 'bottom', 'left', 'right'] as const).map((pos) => (\n <DropZone\n key={pos}\n id={`drop-${pos}-${id}`}\n position={pos}\n activeClassName={classNames.dropPreview}\n />\n ))}\n <DropZone\n id={`drop-center-${id}`}\n position=\"center\"\n activeClassName={classNames.swapPreview}\n />\n </div>\n )}\n </div>\n </DragListenersCtx.Provider>\n )\n}\n","import React, { useContext } from 'react'\nimport { DragListenersCtx } from '../model/context'\n\ninterface DragHandleProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\nexport const DragHandle: React.FC<DragHandleProps> = ({ children, className, style }) => {\n const dragProps = useContext(DragListenersCtx)\n if (!dragProps) {\n throw new Error('<DragHandle> must be used inside a <Pane>')\n }\n return (\n <div\n className={className}\n style={{ cursor: 'grab', userSelect: 'none', ...style }}\n {...dragProps}\n >\n {children}\n </div>\n )\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-zeugma",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Recursive drag-and-drop dashboard layout engine for React — combining the tree-based splitting of react-mosaic with the declarative API of react-grid-layout.",
5
5
  "type": "module",
6
6
  "sideEffects": false,