regular-layout 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # `<regular-layout>`
2
2
 
3
- A library for resizable panel layouts using CSS `grid`.
3
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/texodus/regular-layout/build.yaml?event=push&style=for-the-badge)](https://github.com/texodus/regular-layout/actions/workflows/build.yaml)
4
+ [![npm](https://img.shields.io/npm/v/regular-layout.svg?style=for-the-badge)](https://www.npmjs.com/package/regular-layout)
4
5
 
5
- - 7kb, zero dependencies
6
- - Web Component
7
- -
6
+ A library for resizable & repositionable panel layouts, using
7
+ [CSS `grid`](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout).
8
+
9
+ - Zero depedencies, pure TypeScript, tiny.
10
+ - Implemented as a [Web Component](https://developer.mozilla.org/en-US/docs/Web/API/Web_components),
11
+ interoperable with any framework and fully customizable.
12
+ - Covered in bees.
8
13
 
9
14
  ## Installation
10
15
 
@@ -1,2 +1,15 @@
1
1
  import { type Layout, type LayoutPath } from "./layout_config";
2
- export declare function calculate_split(col: number, row: number, panel: Layout, slot: string, config: LayoutPath): LayoutPath;
2
+ /**
3
+ * Calculates an insertion point (which may involve splitting a single
4
+ * `"child-panel"` into a new `"split-panel"`), based on the cursor position.
5
+ * *
6
+ * @param col - The cursor column.
7
+ * @param row - The cursor row.
8
+ * @param panel - The `Layout` to insert into.
9
+ * @param slot - The slot identifier where the insert should occur
10
+ * @param drop_target - The `LayoutPath` (from `calculateIntersect`) of the
11
+ * panel to either insert next to, or split by.
12
+ * @returns A new `LayoutPath` reflecting the updated (maybe) `"split-panel"`,
13
+ * which is enough to draw the overlay.
14
+ */
15
+ export declare function calculate_split(col: number, row: number, panel: Layout, slot: string, drop_target: LayoutPath): LayoutPath;
@@ -12,4 +12,4 @@ import type { Layout } from "./layout_config.ts";
12
12
  * "horizontal".
13
13
  * @returns A new layout tree with the child inserted (original is not mutated).
14
14
  */
15
- export declare function insert_child(panel: Layout, child: string, path: number[], orientation?: "horizontal" | "vertical"): Layout;
15
+ export declare function insert_child(panel: Layout, child: string, path: number[], orientation?: "horizontal" | "vertical", is_edge?: boolean): Layout;
@@ -6,14 +6,22 @@ export declare const MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD = 0.15;
6
6
  /**
7
7
  * Threshold from panel edge that is considered a split vs drop action.
8
8
  */
9
- export declare const SPLIT_EDGE_TOLERANCE = 0.15;
9
+ export declare const SPLIT_EDGE_TOLERANCE = 0.25;
10
10
  /**
11
11
  * Tolerance threshold for considering two grid track positions as identical.
12
12
  *
13
13
  * When collecting and deduplicating track positions, any positions closer than
14
14
  * this value are treated as the same position to avoid redundant grid tracks.
15
15
  */
16
- export declare const GRID_TRACK_COLLAPSE_TOLERANCE = 0.0001;
16
+ export declare const GRID_TRACK_COLLAPSE_TOLERANCE = 0.001;
17
+ /**
18
+ * The overlay default behavior.
19
+ */
20
+ export declare const OVERLAY_DEFAULT: OverlayMode;
21
+ /**
22
+ * The overlay behavior type.
23
+ */
24
+ export type OverlayMode = "grid" | "absolute" | "interactive";
17
25
  /**
18
26
  * The representation of a CSS grid, in JSON form.
19
27
  */
@@ -49,7 +57,8 @@ export interface SplitLayout {
49
57
  */
50
58
  export interface TabLayout {
51
59
  type: "child-panel";
52
- child: string;
60
+ child: string[];
61
+ selected?: number;
53
62
  }
54
63
  /**
55
64
  * Represents a draggable divider between two panels in the layout.
@@ -71,11 +80,13 @@ export interface LayoutDivider {
71
80
  export interface LayoutPath<T = undefined> {
72
81
  type: "layout-path";
73
82
  slot: string;
83
+ panel: TabLayout;
74
84
  path: number[];
75
85
  view_window: ViewWindow;
76
86
  column_offset: number;
77
87
  row_offset: number;
78
88
  orientation: Orientation;
89
+ is_edge: boolean;
79
90
  box: T;
80
91
  }
81
92
  /**
@@ -1,5 +1,6 @@
1
1
  import { RegularLayout } from "./regular-layout.ts";
2
2
  import { RegularLayoutFrame } from "./regular-layout-frame.ts";
3
+ import { Layout } from "./common/layout_config.ts";
3
4
  declare global {
4
5
  interface Document {
5
6
  createElement(tagName: "regular-layout", options?: ElementCreationOptions): RegularLayout;
@@ -12,4 +13,19 @@ declare global {
12
13
  get(tagName: "regular-layout"): typeof RegularLayout;
13
14
  get(tagName: "regular-layout-frame"): typeof RegularLayoutFrame;
14
15
  }
16
+ interface HTMLElement {
17
+ addEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void, options?: {
18
+ signal: AbortSignal;
19
+ }): void;
20
+ removeEventListener(name: "regular-layout-update", cb: any): void;
21
+ }
22
+ }
23
+ export interface RegularLayoutEvent extends CustomEvent {
24
+ detail: Layout;
25
+ }
26
+ export interface PerspectiveViewerElementExt {
27
+ addEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void, options?: {
28
+ signal: AbortSignal;
29
+ }): void;
30
+ removeEventListener(name: "regular-layout-update", cb: any): void;
15
31
  }
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- function*C(o){if(o.type==="split-panel")for(let t of o.children)yield*C(t);else yield o.child}var P={type:"split-panel",orientation:"horizontal",sizes:[],children:[]};function f(o,t){if(o.type==="child-panel")return structuredClone(P);let e=structuredClone(o),s=e.children.findIndex(i=>i.type==="child-panel"?i.child===t:!1);if(s!==-1){let i=e.children.filter((h,u)=>u!==s),l=$(e.sizes,s);return i.length===1?i[0]:(e.children=i,e.sizes=l,e)}let r=!1,n=e.children.map(i=>{if(i.type==="split-panel"){let l=f(i,t);return l!==i&&(r=!0),l}return i});return r&&(e.children=n),e}function $(o,t){let e=[],s=o[t],r=0;for(let n=0;n<o.length;n++)n!==t&&(r+=o[n]);for(let n=0;n<o.length;n++)if(n!==t){let i=o[n]/r;e.push(o[n]+s*i)}return e}function T(o){if(o.length===0)return[];let t=o.sort((s,r)=>s-r),e=[t[0]];for(let s=1;s<t.length;s++)Math.abs(t[s]-e[e.length-1])>1e-4&&e.push(t[s]);return e}function E(o,t,e,s){if(o.type==="child-panel")return[e,s];if(o.orientation===t){let r=[e,s],n=e;for(let i=0;i<o.children.length;i++){let l=o.sizes[i],h=E(o.children[i],t,n,n+l*(s-e));r.push(...h),n=n+l*(s-e)}return T(r)}else{let r=[e,s];for(let n of o.children){let i=E(n,t,e,s);r.push(...i)}return T(r)}}function v(o,t){for(let e=0;e<o.length;e++)if(Math.abs(o[e]-t)<1e-4)return e;throw new Error(`Position ${t} not found in ${o}`)}function z(o,t,e,s,r,n,i){if(o.type==="child-panel")return[{child:o.child,colStart:v(t,s),colEnd:v(t,r),rowStart:v(e,n),rowEnd:v(e,i)}];let l=[],{children:h,sizes:u,orientation:c}=o;if(c==="horizontal"){let a=s;for(let p=0;p<h.length;p++){let _=a+u[p]*(r-s);l.push(...z(h[p],t,e,a,_,n,i)),a=_}}else{let a=n;for(let p=0;p<h.length;p++){let _=a+u[p]*(i-n);l.push(...z(h[p],t,e,s,r,a,_)),a=_}}return l}var D=(o,t)=>`:host { display: grid; gap: 0px; grid-template-rows: ${o}; grid-template-columns: ${t}; }`,x=(o,t,e)=>`:host ::slotted([slot=${o}]) { grid-column: ${e}; grid-row: ${t}; }`;function y(o,t=!1,e){if(e&&(o=f(o,e[0])),o.type==="child-panel")return`${D("100%","100%")}
2
- ${x(o.child,"1","1")}`;let s=E(o,"horizontal",0,1),r=[];for(let a=0;a<s.length-1;a++)r.push(s[a+1]-s[a]);let n=r.map(a=>`${t?Math.round(a*100):a*100}%`).join(" "),i=E(o,"vertical",0,1),l=[];for(let a=0;a<i.length-1;a++)l.push(i[a+1]-i[a]);let h=l.map(a=>`${t?Math.round(a*100):a*100}%`).join(" "),u=z(o,s,i,0,1,0,1),c=[D(h,n)];for(let a of u){let p=a.colEnd-a.colStart===1?`${a.colStart+1}`:`${a.colStart+1} / ${a.colEnd+1}`,_=a.rowEnd-a.rowStart===1?`${a.rowStart+1}`:`${a.rowStart+1} / ${a.rowEnd+1}`;c.push(`${x(a.child,_,p)}`),a.child===e?.[1]&&(c.push(`${x(e[0],_,p)}`),c.push(`:host ::slotted([slot=${e[0]}]) { z-index: 1; }`))}return c.join(`
3
- `)}function m(o,t,e,s=!0){return R(o,t,e,s)}var N={row_start:0,row_end:1,col_start:0,col_end:1};function R(o,t,e,s,r="horizontal",n=structuredClone(N),i=[]){if(e.type==="child-panel")return{type:"layout-path",box:void 0,slot:e.child,path:i,view_window:n,column_offset:(o-n.col_start)/(n.col_end-n.col_start),row_offset:(t-n.row_start)/(n.row_end-n.row_start),orientation:r};if(e.orientation==="vertical"){let l=n.row_start;for(let h=0;h<e.children.length;h++){let c=(n.row_end-n.row_start)*e.sizes[h]+l;if(s&&Math.abs(t-c)<.01)return{path:[...i,h],type:"vertical",view_window:{...n,row_start:l,row_end:c}};if(t>=l&&t<c)return R(o,t,e.children[h],s,"vertical",{...n,row_start:l,row_end:c},[...i,h]);l=c}}else{let l=n.col_start;for(let h=0;h<e.children.length;h++){let u=n.col_end-n.col_start,c=l+u*e.sizes[h];if(s&&Math.abs(o-c)<.01)return{path:[...i,h],type:"horizontal",view_window:{...n,col_start:l,col_end:c}};if(o>=l&&o<c)return R(o,t,e.children[h],s,"horizontal",{...n,col_start:l,col_end:c},[...i,h]);l=c}}return null}function d(o,t,e,s="horizontal"){if(e.length===0){if(o.type==="child-panel")return{type:"split-panel",orientation:s,children:[o,{type:"child-panel",child:t}],sizes:[.5,.5]};{let u=[...o.children,{type:"child-panel",child:t}],c=u.length,a=Array(c).fill(1/c);return{...o,children:u,sizes:a}}}let[r,...n]=e;if(o.type==="child-panel")return d({type:"split-panel",orientation:s,children:[o],sizes:[1]},t,e,s);if(n.length===0||r===o.children.length){let u=[...o.children];u.splice(r,0,{type:"child-panel",child:t});let c=u.length,a=Array(c).fill(1/c);return{...o,children:u,sizes:a}}let i=o.children[r];if(i.type==="child-panel"&&n.length>0){let u=o.orientation==="horizontal"?"vertical":"horizontal",c=d(i,t,n,u),a=[...o.children];return a[r]=c,{...o,children:a}}let l=d(i,t,n,s),h=[...o.children];return h[r]=l,{...o,children:h}}function S(o,t,e){let s=structuredClone(o),r=s,n={horizontal:e,vertical:e};for(let i=0;i<t.length-1;i++)r.type==="split-panel"&&(n[r.orientation]/=r.sizes[t[i]],r=r.children[t[i]]);if(r.type==="split-panel"){let i=n[r.orientation],l=t[t.length-1];r.sizes=H(r.sizes,l,i)}return s}function H(o,t,e){let s=[...o],r=0;for(let i=0;i<=t;i++)r+=o[i];let n=0;for(let i=t+1;i<o.length;i++)n+=o[i];e=Math.sign(e)*Math.min(Math.abs(e),(1-.15)*(e>0?r:n));for(let i=0;i<=t;i++){let l=o[i]/r;s[i]=o[i]-e*l}for(let i=t+1;i<o.length;i++){let l=o[i]/n;s[i]=o[i]+e*l}return s}function O({view_window:{row_start:o,row_end:t,col_start:e,col_end:s},box:r}){let i=o*r.height+0,l=e*r.width+0/2,h=(t-o)*r.height-0,u=(s-e)*r.width-0;return`::slotted(:not([slot])){${`position:absolute!important;z-index:1;top:${i}px;left:${l}px;height:${h}px;width:${u}px;`}}`}function M(o,t,e,s,r){if(r.column_offset<.15||r.column_offset>1-.15)if(r.orientation==="vertical"){let n=d(e,s,[...r.path,r.column_offset<.15?0:1]);r=m(o,t,n,!1)}else{let n=d(e,s,r.path);r=m(o,t,n,!1)}if(r.row_offset<.15&&r.row_offset<r.column_offset||r.row_offset>1-.15&&r.row_offset>r.column_offset)if(r.orientation==="horizontal"){let n=d(e,s,[...r.path,r.row_offset<.15?0:1]);r=m(o,t,n,!1)}else{let n=d(e,s,r.path);r=m(o,t,n,!1)}return r}function w(o){if(o.type==="child-panel")return o;let t=[],e=[];for(let s=0;s<o.children.length;s++){let r=o.children[s],n=o.sizes[s],i=w(r);if(i.type==="split-panel"&&i.orientation===o.orientation)for(let l=0;l<i.children.length;l++)t.push(i.children[l]),e.push(i.sizes[l]*n);else t.push(i),e.push(n)}return{type:"split-panel",orientation:o.orientation,children:t,sizes:e}}var I="absolute",L=class extends HTMLElement{_shadowRoot;_panel;_stylesheet;_dragPath;_slots;_unslotted_slot;constructor(){super(),this._panel=structuredClone(P),this._stylesheet=new CSSStyleSheet,this._unslotted_slot=document.createElement("slot"),this._shadowRoot=this.attachShadow({mode:"open"}),this._shadowRoot.adoptedStyleSheets=[this._stylesheet],this._shadowRoot.appendChild(this._unslotted_slot),this._slots=new Map,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this)}connectedCallback(){this.addEventListener("pointerdown",this.onPointerDown),this.addEventListener("pointerup",this.onPointerUp),this.addEventListener("pointermove",this.onPointerMove)}disconnectedCallback(){this.removeEventListener("pointerdown",this.onPointerDown),this.removeEventListener("pointerup",this.onPointerUp),this.removeEventListener("pointermove",this.onPointerMove)}setOverlayState(t,e,{slot:s},r=I){let n=this._panel;r==="absolute"&&(n=f(n,s),this._slots.get(s)?.assignedElements()[0]?.removeAttribute("slot"));let[i,l,h]=this.relativeCoordinates(t,e),u=m(i,l,n,!1);if(u&&(u=M(i,l,n,s,u)),u){if(r==="interactive"){let c=f(this._panel,s);c=w(d(c,s,u.path));let a=y(c);this._stylesheet.replaceSync(a)}else if(r==="grid"){let c=[s,u.slot],a=y(this._panel,!1,c);this._stylesheet.replaceSync(a)}else if(r==="absolute"){let c=`${y(n)}
4
- ${O({...u,box:h})}`;this._stylesheet.replaceSync(c)}}}clearOverlayState(t,e,s,r=I){let n=this._panel;r==="absolute"&&(n=f(n,s.slot),this._unslotted_slot.assignedElements()[0]?.setAttribute("slot",s.slot));let[i,l,h]=this.relativeCoordinates(t,e),u=m(i,l,n,!1);u&&(u=M(i,l,n,s.slot,u));let{path:c}=u||s;this.removePanel(s.slot),this.insertPanel(s.slot,c)}insertPanel(t,e=[]){this.restore(d(this._panel,t,e))}removePanel(t){this.restore(f(this._panel,t))}calculateIntersect(t,e,s=!1){let[r,n,i]=this.relativeCoordinates(t,e),l=m(r,n,this._panel,s);return l?.type==="layout-path"?{...l,box:i}:null}restore(t,e=!1){this._panel=e?t:w(t);let s=y(t);this._stylesheet.replaceSync(s);let r=new Set(this._slots.keys());for(let n of C(t))if(r.delete(n),!this._slots.has(n)){let i=document.createElement("slot");i.setAttribute("name",n),this._shadowRoot.appendChild(i),this._slots.set(n,i)}for(let n of r){let i=this._slots.get(n);i&&(this._shadowRoot.removeChild(i),this._slots.delete(n))}}save(){return structuredClone(this._panel)}relativeCoordinates(t,e){let s=this.getBoundingClientRect(),r=(t-s.left)/(s.right-s.left),n=(e-s.top)/(s.bottom-s.top);return[r,n,s]}onPointerDown(t){let[e,s]=this.relativeCoordinates(t.clientX,t.clientY),r=m(e,s,this._panel);r&&r.type!=="layout-path"&&(this._dragPath=[r,e,s],this.setPointerCapture(t.pointerId),t.preventDefault(),t.stopImmediatePropagation())}onPointerMove(t){if(this._dragPath){let[e,s]=this.relativeCoordinates(t.clientX,t.clientY),r=this._panel,[{path:n,type:i},l,h]=this._dragPath,u=i==="horizontal"?l-e:h-s,c=S(r,n,u);this._stylesheet.replaceSync(y(c))}}onPointerUp(t){if(this._dragPath){this.releasePointerCapture(t.pointerId);let[e,s]=this.relativeCoordinates(t.clientX,t.clientY),r=this._panel,[{path:n},i,l]=this._dragPath;if(this._dragPath[0].type==="horizontal"){let h=S(r,n,i-e);this.restore(h,!0)}else{let h=S(r,n,l-s);this.restore(h,!0)}this._dragPath=void 0}}};var Y=`
1
+ var S="absolute";function*C(i){if(i.type==="split-panel")for(let t of i.children)yield*C(t);else yield*i.child}var g={type:"split-panel",orientation:"horizontal",sizes:[],children:[]};function m(i,t){if(i.type==="child-panel"){if(i.child.includes(t)){let n=i.child.filter(l=>l!==t);return n.length===0?structuredClone(g):{type:"child-panel",child:n}}return structuredClone(i)}let o=structuredClone(i),r=o.children.findIndex(n=>n.type==="child-panel"?n.child.includes(t):!1);if(r!==-1){let n=o.children[r];if(n.child.length===1){let l=o.children.filter((u,h)=>h!==r),c=A(o.sizes,r);if(l.length===1)return l[0];o.children=l,o.sizes=c}else n.child.splice(n.child.indexOf(t),1),n.selected&&n.selected>=n.child.length&&n.selected--;return o}let e=!1,s=o.children.map(n=>{if(n.type==="split-panel"){let l=m(n,t);return l!==n&&(e=!0),l}return n});return e&&(o.children=s),o}function A(i,t){let o=[],r=i[t],e=0;for(let s=0;s<i.length;s++)s!==t&&(e+=i[s]);for(let s=0;s<i.length;s++)if(s!==t){let n=i[s]/e;o.push(i[s]+r*n)}return o}function D(i){if(i.length===0)return[];let t=i.sort((r,e)=>r-e),o=[t[0]];for(let r=1;r<t.length;r++)Math.abs(t[r]-o[o.length-1])>.001&&o.push(t[r]);return o}function P(i,t,o,r){if(i.type==="child-panel")return[o,r];if(i.orientation===t){let e=[o,r],s=o;for(let n=0;n<i.children.length;n++){let l=i.sizes[n],c=P(i.children[n],t,s,s+l*(r-o));e.push(...c),s=s+l*(r-o)}return D(e)}else{let e=[o,r];for(let s of i.children){let n=P(s,t,o,r);e.push(...n)}return D(e)}}function E(i,t){for(let o=0;o<i.length;o++)if(Math.abs(i[o]-t)<.001)return o;throw new Error(`Position ${t} not found in ${i}`)}function z(i,t,o,r,e,s,n){if(i.type==="child-panel"){let a=i.selected??0;return[{child:i.child[a],colStart:E(t,r),colEnd:E(t,e),rowStart:E(o,s),rowEnd:E(o,n)}]}let l=[],{children:c,sizes:u,orientation:h}=i;if(h==="horizontal"){let a=r;for(let d=0;d<c.length;d++){let _=a+u[d]*(e-r);l.push(...z(c[d],t,o,a,_,s,n)),a=_}}else{let a=s;for(let d=0;d<c.length;d++){let _=a+u[d]*(n-s);l.push(...z(c[d],t,o,r,e,a,_)),a=_}}return l}var O=(i,t)=>`:host { display: grid; gap: 0px; grid-template-rows: ${i}; grid-template-columns: ${t}; }`,T=(i,t,o)=>`:host ::slotted([slot=${i}]) { grid-column: ${o}; grid-row: ${t}; }`;function b(i,t=!1,o){if(o&&(i=m(i,o[0])),i.type==="child-panel"){let a=i.selected??0;return`${O("100%","100%")}
2
+ ${T(i.child[a],"1","1")}`}let r=P(i,"horizontal",0,1),e=[];for(let a=0;a<r.length-1;a++)e.push(r[a+1]-r[a]);let s=e.map(a=>`${t?Math.round(a*100):a*100}%`).join(" "),n=P(i,"vertical",0,1),l=[];for(let a=0;a<n.length-1;a++)l.push(n[a+1]-n[a]);let c=l.map(a=>`${t?Math.round(a*100):a*100}%`).join(" "),u=z(i,r,n,0,1,0,1),h=[O(c,s)];for(let a of u){let d=a.colEnd-a.colStart===1?`${a.colStart+1}`:`${a.colStart+1} / ${a.colEnd+1}`,_=a.rowEnd-a.rowStart===1?`${a.rowStart+1}`:`${a.rowStart+1} / ${a.rowEnd+1}`;h.push(`${T(a.child,_,d)}`),a.child===o?.[1]&&(h.push(`${T(o[0],_,d)}`),h.push(`:host ::slotted([slot=${o[0]}]) { z-index: 1; }`))}return h.join(`
3
+ `)}function p(i,t,o,r=!0){return R(i,t,o,r)}var N={row_start:0,row_end:1,col_start:0,col_end:1};function R(i,t,o,r,e=null,s=structuredClone(N),n=[]){if(i<0||t<0||i>1||t>1)return null;if(o.type==="child-panel"){let l=o.selected??0,c=(i-s.col_start)/(s.col_end-s.col_start),u=(t-s.row_start)/(s.row_end-s.row_start);return{type:"layout-path",box:void 0,slot:o.child[l],panel:structuredClone(o),path:n,view_window:s,is_edge:!1,column_offset:c,row_offset:u,orientation:e||"horizontal"}}if(o.orientation==="vertical"){let l=s.row_start;for(let c=0;c<o.children.length;c++){let h=(s.row_end-s.row_start)*o.sizes[c]+l;if(r&&Math.abs(t-h)<.01)return{path:[...n,c],type:"vertical",view_window:{...s,row_start:l,row_end:h}};if(t>=l&&t<h)return R(i,t,o.children[c],r,"vertical",{...s,row_start:l,row_end:h},[...n,c]);l=h}}else{let l=s.col_start;for(let c=0;c<o.children.length;c++){let u=s.col_end-s.col_start,h=l+u*o.sizes[c];if(r&&Math.abs(i-h)<.01)return{path:[...n,c],type:"horizontal",view_window:{...s,col_start:l,col_end:h}};if(i>=l&&i<h)return R(i,t,o.children[c],r,"horizontal",{...s,col_start:l,col_end:h},[...n,c]);l=h}}return null}function f(i,t,o,r="horizontal",e){if(o.length===0){if(i.type==="child-panel")return{type:"child-panel",child:[t,...i.child]};{let h=[...i.children,{type:"child-panel",child:[t]}],a=h.length,d=Array(a).fill(1/a);return{...i,children:h,sizes:d}}}let[s,...n]=o;if(i.type==="child-panel")return f({type:"split-panel",orientation:r,children:[i],sizes:[1]},t,o,r,e);if(n.length===0||s===i.children.length){if(e&&i.children[s]?.type==="child-panel")return i.children[s].child.unshift(t),i;let h=[...i.children];h.splice(s,0,{type:"child-panel",child:[t]});let a=h.length,d=Array(a).fill(1/a);return{...i,children:h,sizes:d}}let l=i.children[s];if(l.type==="child-panel"&&n.length>0){let h=i.orientation==="horizontal"?"vertical":"horizontal",a=f(l,t,n,h,e),d=[...i.children];return d[s]=a,{...i,children:d}}let c=f(l,t,n,r,e),u=[...i.children];return u[s]=c,{...i,children:u}}function w(i,t,o){let r=structuredClone(i),e=r,s={horizontal:o,vertical:o};for(let n=0;n<t.length-1;n++)e.type==="split-panel"&&(s[e.orientation]/=e.sizes[t[n]],e=e.children[t[n]]);if(e.type==="split-panel"){let n=s[e.orientation],l=t[t.length-1];l<e.sizes.length-1&&(e.sizes=H(e.sizes,l,n))}return r}function H(i,t,o){let r=[...i],e=0;for(let n=0;n<=t;n++)e+=i[n];let s=0;for(let n=t+1;n<i.length;n++)s+=i[n];o=Math.sign(o)*Math.min(Math.abs(o),(1-.15)*(o>0?e:s));for(let n=0;n<=t;n++){let l=i[n]/e;r[n]=i[n]-o*l}for(let n=t+1;n<i.length;n++){let l=i[n]/s;r[n]=i[n]+o*l}return r}function $({view_window:{row_start:i,row_end:t,col_start:o,col_end:r},box:e}){let n=i*e.height+0,l=o*e.width+0/2,c=(t-i)*e.height-0,u=(r-o)*e.width-0;return`::slotted(:not([slot])){${`position:absolute!important;z-index:1;top:${n}px;left:${l}px;height:${c}px;width:${u}px;`}}`}function M(i,t,o,r,e){if(e.column_offset<.25||e.column_offset>1-.25){if(e.orientation==="horizontal"){let s=e.column_offset<.25;if(e.path.length===0){let l=f(o,r,[s?0:1]);s?e=p(i,t,l,!1):e={...p(i,t,l,!1),path:[0]}}else{let n=e.path.slice(0,-1),l=e.path[e.path.length-1],c=s?l:l+1,u=f(o,r,[...n,c]);s?e=p(i,t,u,!1):e={...p(i,t,u,!1),path:[...n,l]}}}else{let s=e.column_offset<.25?0:1,n=e.path,l=f(o,r,[...n,s],"horizontal");e=p(i,t,l,!1),e={...e,slot:r,path:[...n,s]}}e&&(e.is_edge=!0)}else if(e.row_offset<.25||e.row_offset>1-.25){if(e.orientation==="vertical"){let s=e.row_offset<.25;if(e.path.length===0){let l=f(o,r,[s?0:1]);s?e=p(i,t,l,!1):e={...p(i,t,l,!1),path:[0]}}else{let n=e.path.slice(0,-1),l=e.path[e.path.length-1],c=s?l:l+1,u=f(o,r,[...n,c]);s?e=p(i,t,u,!1):e={...p(i,t,u,!1),path:[...n,l]}}}else{let s=e.row_offset<.25?0:1,n=e.path,l=f(o,r,[...n,s],"vertical");e=p(i,t,l,!1),e={...e,slot:r,path:[...n,s]}}e&&(e.is_edge=!0)}return e}function x(i){if(i.type==="child-panel")return i;let t=[],o=[];for(let r=0;r<i.children.length;r++){let e=i.children[r],s=i.sizes[r],n=x(e);if(n.type==="split-panel"&&n.orientation===i.orientation)for(let l=0;l<n.children.length;l++)t.push(n.children[l]),o.push(n.sizes[l]*s);else t.push(n),o.push(s)}return t.length===1?t[0]:{type:"split-panel",orientation:i.orientation,children:t,sizes:o}}var L=class extends HTMLElement{_shadowRoot;_panel;_stylesheet;_dragPath;_slots;_unslotted_slot;constructor(){super(),this._panel=structuredClone(g),this._stylesheet=new CSSStyleSheet,this._unslotted_slot=document.createElement("slot"),this._shadowRoot=this.attachShadow({mode:"open"}),this._shadowRoot.adoptedStyleSheets=[this._stylesheet],this._shadowRoot.appendChild(this._unslotted_slot),this._slots=new Map,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this)}connectedCallback(){this.addEventListener("pointerdown",this.onPointerDown),this.addEventListener("pointerup",this.onPointerUp),this.addEventListener("pointermove",this.onPointerMove)}disconnectedCallback(){this.removeEventListener("pointerdown",this.onPointerDown),this.removeEventListener("pointerup",this.onPointerUp),this.removeEventListener("pointermove",this.onPointerMove)}setOverlayState(t,o,{slot:r},e=S){let s=this._panel;e==="absolute"&&(s=m(s,r),this._slots.get(r)?.assignedElements()[0]?.removeAttribute("slot"));let[n,l,c]=this.relativeCoordinates(t,o),u=p(n,l,s,!1);if(u){if(u=M(n,l,s,r,u),e==="interactive"){let a=m(this._panel,r);a=x(f(a,r,u.path));let d=b(a);this._stylesheet.replaceSync(d)}else if(e==="grid"){let a=[r,u.slot],d=b(this._panel,!1,a);this._stylesheet.replaceSync(d)}else if(e==="absolute"){let a=`${b(s)}
4
+ ${$({...u,box:c})}`;this._stylesheet.replaceSync(a)}}else{let a=`${b(s)}}`;this._stylesheet.replaceSync(a)}let h=new CustomEvent("regular-layout-update",{detail:s});this.dispatchEvent(h)}clearOverlayState(t,o,r,e=S){let s=this._panel;e==="absolute"&&(s=m(s,r.slot),this._unslotted_slot.assignedElements()[0]?.setAttribute("slot",r.slot));let[n,l,c]=this.relativeCoordinates(t,o),u=p(n,l,s,!1);u&&(u=M(n,l,s,r.slot,u));let{path:h,orientation:a}=u||r;this.restore(f(s,r.slot,h,a,!u?.is_edge))}insertPanel(t,o=[]){this.restore(f(this._panel,t,o))}removePanel(t){this.restore(m(this._panel,t))}getPanel(t,o=this._panel){if(o.type==="child-panel")return o.child.includes(t)?o:null;for(let r of o.children){let e=this.getPanel(t,r);if(e)return e}return null}calculateIntersect(t,o,r=!1){let[e,s,n]=this.relativeCoordinates(t,o),l=p(e,s,this._panel,r);return l?.type==="layout-path"?{...l,box:n}:null}clear(){this.restore(g)}restore(t,o=!1){this._panel=o?t:x(t);let r=b(t);this._stylesheet.replaceSync(r);let e=new Set(this._slots.keys());for(let n of C(t))if(e.delete(n),!this._slots.has(n)){let l=document.createElement("slot");l.setAttribute("name",n),this._shadowRoot.appendChild(l),this._slots.set(n,l)}for(let n of e){let l=this._slots.get(n);l&&(this._shadowRoot.removeChild(l),this._slots.delete(n))}let s=new CustomEvent("regular-layout-update",{detail:t});this.dispatchEvent(s)}save(){return structuredClone(this._panel)}relativeCoordinates(t,o){let r=this.getBoundingClientRect(),e=(t-r.left)/(r.right-r.left),s=(o-r.top)/(r.bottom-r.top);return[e,s,r]}onPointerDown(t){if(t.target===this){let[o,r]=this.relativeCoordinates(t.clientX,t.clientY),e=p(o,r,this._panel);e&&e.type!=="layout-path"&&(this._dragPath=[e,o,r],this.setPointerCapture(t.pointerId))}}onPointerMove(t){if(this._dragPath){let[o,r]=this.relativeCoordinates(t.clientX,t.clientY),e=this._panel,[{path:s,type:n},l,c]=this._dragPath,u=n==="horizontal"?l-o:c-r,h=w(e,s,u);this._stylesheet.replaceSync(b(h))}}onPointerUp(t){if(this._dragPath){this.releasePointerCapture(t.pointerId);let[o,r]=this.relativeCoordinates(t.clientX,t.clientY),e=this._panel,[{path:s},n,l]=this._dragPath;if(this._dragPath[0].type==="horizontal"){let c=w(e,s,n-o);this.restore(c,!0)}else{let c=w(e,s,l-r);this.restore(c,!0)}this._dragPath=void 0}}};var k=`
5
5
  :host{--titlebar--height:24px;box-sizing:border-box}
6
6
  :host([slot]){margin-top:calc(var(--titlebar--height) + 3px)!important;}
7
7
  :host([slot])::part(container){position:absolute;top:0;left:0;right:0;bottom:0;display:flex;flex-direction:column;background-color:inherit;border-radius:inherit}
8
- :host([slot])::part(titlebar){height:var(--titlebar--height);margin-top:calc(-2px - var(--titlebar--height));user-select: none;}
8
+ :host([slot])::part(titlebar){height:var(--titlebar--height);margin-top:calc(0px - var(--titlebar--height));user-select: none;}
9
9
  :host([slot])::part(body){flex:1 1 auto;}
10
- `,g=class extends HTMLElement{_shadowRoot;_container_sheet;_layout;_header;_drag_state=null;constructor(){super(),this._container_sheet=new CSSStyleSheet,this._container_sheet.replaceSync(Y),this._shadowRoot=this.attachShadow({mode:"open"}),this._shadowRoot.adoptedStyleSheets=[this._container_sheet],this._shadowRoot.innerHTML='<slot part="container"><slot part="titlebar">header</slot><slot part="body"><slot></slot></slot></slot>',this._layout=this.parentElement,this._header=this._shadowRoot.children[0].children[0]}connectedCallback(){this._header.addEventListener("pointerdown",this.onPointerDown),this._header.addEventListener("pointermove",this.onPointerMove),this._header.addEventListener("pointerup",this.onPointerUp)}disconnectedCallback(){this._header.removeEventListener("pointerdown",this.onPointerDown),this._header.removeEventListener("pointermove",this.onPointerMove),this._header.removeEventListener("pointerup",this.onPointerUp)}onPointerDown=t=>{this._drag_state=this._layout.calculateIntersect(t.clientX,t.clientY),this._drag_state&&(this._header.setPointerCapture(t.pointerId),t.preventDefault(),t.stopImmediatePropagation())};onPointerMove=t=>{this._drag_state&&this._layout.setOverlayState(t.clientX,t.clientY,this._drag_state)};onPointerUp=t=>{this._drag_state&&(this._layout.clearOverlayState(t.clientX,t.clientY,this._drag_state),this._header.releasePointerCapture(t.pointerId),this._drag_state=null)}};customElements.define("regular-layout-frame",g);customElements.define("regular-layout",L);export{L as RegularLayout,g as RegularLayoutFrame};
10
+ `,Y='<slot part="container"><slot part="titlebar"></slot><slot part="body"><slot></slot></slot></slot>',v=class extends HTMLElement{_shadowRoot;_container_sheet;_layout;_header;_drag_state=null;_drag_moved=!1;_tab_to_index_map=new WeakMap;constructor(){super(),this._container_sheet=new CSSStyleSheet,this._container_sheet.replaceSync(k),this._shadowRoot=this.attachShadow({mode:"open"}),this._shadowRoot.adoptedStyleSheets=[this._container_sheet],this.drawTabs=this.drawTabs.bind(this),this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.onPointerLost=this.onPointerLost.bind(this)}connectedCallback(){this._shadowRoot.innerHTML=Y,this._layout=this.parentElement,this._header=this._shadowRoot.children[0].children[0],this._header.addEventListener("pointerdown",this.onPointerDown),this._header.addEventListener("pointermove",this.onPointerMove),this._header.addEventListener("pointerup",this.onPointerUp),this._header.addEventListener("lostpointercapture",this.onPointerLost),this._layout.addEventListener("regular-layout-update",this.drawTabs)}disconnectedCallback(){this._header.removeEventListener("pointerdown",this.onPointerDown),this._header.removeEventListener("pointermove",this.onPointerMove),this._header.removeEventListener("pointerup",this.onPointerUp),this._header.removeEventListener("lostpointercapture",this.onPointerLost),this._layout.removeEventListener("regular-layout-update",this.drawTabs)}drawTabs(t){let o=this.getAttribute("slot");if(o){let r=this._layout.getPanel(o,t.detail);if(this._header.textContent="",!r)return;for(let e=0;e<(r?.child?.length||0);e++){let s=r?.child[e],n=document.createElement("div");this._tab_to_index_map.set(n,e),n.textContent=s||"",n.setAttribute("part",e===(r?.selected||0)?"tab active-tab":"tab");let l=e;e!==(r?.selected||0)&&n.addEventListener("pointerdown",c=>{r.selected=l,this._layout.restore(t.detail),c.preventDefault(),c.stopImmediatePropagation(),c.stopPropagation()}),this._header.appendChild(n)}}}onPointerDown=t=>{if(this._drag_state=this._layout.calculateIntersect(t.clientX,t.clientY),this._drag_state){let o=t.target;if(o.part.contains("tab")){let r=this._drag_state.path.length-1,e=this._tab_to_index_map.get(o);e&&(this._drag_state.path[r]=e)}this._header.setPointerCapture(t.pointerId)}};onPointerMove=t=>{this._drag_state&&(this._drag_moved=!0,this._layout.setOverlayState(t.clientX,t.clientY,this._drag_state))};onPointerUp=t=>{this._drag_state&&this._drag_moved&&this._layout.clearOverlayState(t.clientX,t.clientY,this._drag_state),this._header.releasePointerCapture(t.pointerId),this._drag_state=null,this._drag_moved=!1};onPointerLost=t=>{this._drag_state&&this._layout.clearOverlayState(-1,-1,this._drag_state),this._header.releasePointerCapture(t.pointerId),this._drag_state=null,this._drag_moved=!1}};customElements.define("regular-layout",L);customElements.define("regular-layout-frame",v);export{L as RegularLayout,v as RegularLayoutFrame};
11
11
  //# sourceMappingURL=index.js.map