regular-layout 0.3.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/README.md +110 -22
- package/dist/{layout → core}/types.d.ts +6 -0
- package/dist/extensions.d.ts +13 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +10 -7
- package/dist/index.js.map +4 -4
- package/dist/layout/calculate_edge.d.ts +2 -2
- package/dist/layout/calculate_intersect.d.ts +1 -1
- package/dist/layout/calculate_path.d.ts +1 -1
- package/dist/layout/calculate_presize_paths.d.ts +10 -0
- package/dist/layout/flatten.d.ts +1 -1
- package/dist/layout/generate_grid.d.ts +11 -2
- package/dist/layout/generate_overlay.d.ts +18 -2
- package/dist/layout/insert_child.d.ts +1 -1
- package/dist/layout/redistribute_panel_sizes.d.ts +2 -2
- package/dist/layout/remove_child.d.ts +1 -1
- package/dist/model/overlay_controller.d.ts +34 -0
- package/dist/model/presize_queue.d.ts +17 -0
- package/dist/regular-layout-frame.d.ts +21 -0
- package/dist/regular-layout-tab.d.ts +1 -1
- package/dist/regular-layout.d.ts +76 -9
- package/package.json +5 -4
- package/src/{layout → core}/constants.ts +2 -2
- package/src/{layout → core}/types.ts +7 -0
- package/src/extensions.ts +25 -1
- package/src/index.ts +3 -1
- package/src/layout/calculate_edge.ts +2 -2
- package/src/layout/calculate_intersect.ts +5 -2
- package/src/layout/calculate_path.ts +1 -1
- package/src/layout/calculate_presize_paths.ts +93 -0
- package/src/layout/flatten.ts +1 -1
- package/src/layout/generate_grid.ts +20 -2
- package/src/layout/generate_overlay.ts +48 -16
- package/src/layout/insert_child.ts +1 -1
- package/src/layout/redistribute_panel_sizes.ts +2 -2
- package/src/layout/remove_child.ts +2 -2
- package/src/model/overlay_controller.ts +161 -0
- package/src/model/presize_queue.ts +79 -0
- package/src/regular-layout-frame.ts +58 -3
- package/src/regular-layout-tab.ts +20 -22
- package/src/regular-layout.ts +252 -132
- package/themes/borland.css +103 -0
- package/themes/chicago.css +55 -49
- package/themes/fluxbox.css +64 -60
- package/themes/gibson.css +174 -164
- package/themes/hotdog.css +53 -47
- package/themes/lorax.css +82 -75
- /package/dist/{layout → core}/constants.d.ts +0 -0
package/README.md
CHANGED
|
@@ -17,58 +17,146 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
A library for resizable & repositionable panel layouts
|
|
21
|
-
[CSS `grid`](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout).
|
|
20
|
+
A library for resizable & repositionable panel layouts.
|
|
22
21
|
|
|
23
22
|
- Zero depedencies, pure TypeScript, tiny.
|
|
24
23
|
- Implemented as a [Web Component](https://developer.mozilla.org/en-US/docs/Web/API/Web_components),
|
|
25
|
-
interoperable with any framework
|
|
24
|
+
interoperable with any framework.
|
|
25
|
+
- Zero DOM mutation at runtime, implemented entirely by generating using
|
|
26
|
+
[CSS `grid`](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout) rules.
|
|
27
|
+
- Supports arbitrary theming via CSS [variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascading_variables/Using_custom_properties) and [`::part`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::part).
|
|
28
|
+
- Supports async-aware container rendering for smooth animations even when rendering ovvurs over an event loop boundary.
|
|
26
29
|
- Covered in bees.
|
|
27
30
|
|
|
31
|
+
## Demo
|
|
32
|
+
|
|
33
|
+
<a href="https://texodus.github.io/regular-layout/"><img src="./examples/PREVIEW.png" /></a>
|
|
34
|
+
|
|
28
35
|
## Installation
|
|
29
36
|
|
|
30
37
|
```bash
|
|
31
38
|
npm install regular-layout
|
|
32
39
|
```
|
|
33
40
|
|
|
34
|
-
##
|
|
41
|
+
## Quick Start
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
Import the library and add `<regular-layout>` to your HTML. Children are
|
|
44
|
+
matched to layout slots by their `name` attribute.
|
|
37
45
|
|
|
38
46
|
```html
|
|
47
|
+
<script type="module" src="regular-layout/dist/index.js"></script>
|
|
48
|
+
|
|
39
49
|
<regular-layout>
|
|
40
50
|
<div name="main">Main content</div>
|
|
41
51
|
<div name="sidebar">Sidebar content</div>
|
|
42
52
|
</regular-layout>
|
|
43
53
|
```
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
For draggable, tabbed panels, use `<regular-layout-frame>`:
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<regular-layout>
|
|
59
|
+
<regular-layout-frame name="main">
|
|
60
|
+
Main content
|
|
61
|
+
</regular-layout-frame>
|
|
62
|
+
<regular-layout-frame name="sidebar">
|
|
63
|
+
Sidebar content
|
|
64
|
+
</regular-layout-frame>
|
|
65
|
+
</regular-layout>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Panels must be added and remove programmatically (e.g they are not
|
|
69
|
+
auto-registered):
|
|
46
70
|
|
|
47
71
|
```javascript
|
|
48
|
-
|
|
72
|
+
const layout = document.querySelector("regular-layout");
|
|
49
73
|
|
|
50
|
-
|
|
74
|
+
// This adds the panel definition to the layout (and makes it visible via CSS),
|
|
75
|
+
// but does not mutat the DOM.
|
|
76
|
+
layout.insertPanel("main");
|
|
77
|
+
layout.insertPanel("sidebar");
|
|
51
78
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
layout.
|
|
79
|
+
// This removes the panel from the layout (and hides it via CSS) but does not
|
|
80
|
+
// mutate the DOM.
|
|
81
|
+
layout.removePanel("sidebar");
|
|
82
|
+
```
|
|
55
83
|
|
|
56
|
-
|
|
84
|
+
## Save/Restore
|
|
85
|
+
|
|
86
|
+
Layout state serializes to a JSON tree of splits and tabs, which can be
|
|
87
|
+
persisted and restored:
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
57
90
|
const state = layout.save();
|
|
91
|
+
localStorage.setItem("layout", JSON.stringify(state));
|
|
92
|
+
|
|
93
|
+
// Later...
|
|
94
|
+
layout.restore(JSON.parse(localStorage.getItem("layout")));
|
|
95
|
+
```
|
|
58
96
|
|
|
59
|
-
|
|
60
|
-
|
|
97
|
+
`restore()` dispatches a cancelable `regular-layout-before-resize` event before
|
|
98
|
+
applying the new state. Call `preventDefault()` to suspend the update, then
|
|
99
|
+
`layout.resumeResize()` when ready:
|
|
61
100
|
|
|
62
|
-
|
|
63
|
-
layout.
|
|
101
|
+
```javascript
|
|
102
|
+
layout.addEventListener("regular-layout-before-resize", (event) => {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
// ... prepare for resize ...
|
|
105
|
+
layout.resumeResize();
|
|
106
|
+
});
|
|
64
107
|
```
|
|
65
108
|
|
|
66
|
-
|
|
109
|
+
The `restore()` API can also be used as an alternative to
|
|
110
|
+
`insertPanel`/`removePanel` for initializing a `<regular-layout>`.
|
|
111
|
+
|
|
112
|
+
## Theming
|
|
113
|
+
|
|
114
|
+
Themes are plain CSS files that style the layout and its `::part()` selectors,
|
|
115
|
+
scoped by a class on `<regular-layout>`. Apply a theme by adding its stylesheet
|
|
116
|
+
and setting the class:
|
|
67
117
|
|
|
68
118
|
```html
|
|
69
|
-
<regular-layout>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
119
|
+
<link rel="stylesheet" href="regular-layout/themes/chicago.css">
|
|
120
|
+
|
|
121
|
+
<regular-layout class="chicago">
|
|
122
|
+
...
|
|
73
123
|
</regular-layout>
|
|
74
|
-
```
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`<regular-layout-frame>` exposes these CSS parts:
|
|
127
|
+
|
|
128
|
+
| Part | Description |
|
|
129
|
+
|------|-------------|
|
|
130
|
+
| `titlebar` | Tab bar container |
|
|
131
|
+
| `tab` | Individual tab |
|
|
132
|
+
| `active-tab` | Currently selected tab |
|
|
133
|
+
| `close` | Close button |
|
|
134
|
+
| `active-close` | Close button on the active tab |
|
|
135
|
+
| `container` | Content area |
|
|
136
|
+
|
|
137
|
+
```css
|
|
138
|
+
regular-layout.mytheme regular-layout-frame::part(titlebar) {
|
|
139
|
+
background: #333;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
regular-layout.mytheme regular-layout-frame::part(active-tab) {
|
|
143
|
+
background: #fff;
|
|
144
|
+
color: #000;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
See [the example `themes/`](./themes) directory for examples of how to write a
|
|
149
|
+
complete theme for `<regular-layout>` and `regular-layout-frame>`.
|
|
150
|
+
|
|
151
|
+
## Events
|
|
152
|
+
|
|
153
|
+
| Event | Detail | Cancelable | Description |
|
|
154
|
+
|-------|--------|------------|-------------|
|
|
155
|
+
| `regular-layout-before-resize` | `{ calculatePresizePaths() }` | Yes | Fired before any layout change. Cancel to suspend until `resumeResize()`. |
|
|
156
|
+
| `regular-layout-update` | `Layout` | No | Fired after layout state is updated. |
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
layout.addEventListener("regular-layout-update", (event) => {
|
|
160
|
+
console.log("New layout:", event.detail);
|
|
161
|
+
});
|
|
162
|
+
```
|
|
@@ -75,6 +75,12 @@ export interface LayoutPath {
|
|
|
75
75
|
is_edge: boolean;
|
|
76
76
|
layout: Layout;
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The detail payload of the `regular-layout-before-resize` event.
|
|
80
|
+
*/
|
|
81
|
+
export interface PresizeDetail {
|
|
82
|
+
calculatePresizePaths(): Record<string, LayoutPath>;
|
|
83
|
+
}
|
|
78
84
|
/**
|
|
79
85
|
* An empty `Layout` with no panels.
|
|
80
86
|
*/
|
package/dist/extensions.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RegularLayout } from "./regular-layout.ts";
|
|
2
2
|
import { RegularLayoutFrame } from "./regular-layout-frame.ts";
|
|
3
|
-
import type { Layout } from "./
|
|
3
|
+
import type { Layout, PresizeDetail } from "./core/types.ts";
|
|
4
4
|
import { RegularLayoutTab } from "./regular-layout-tab.ts";
|
|
5
5
|
declare global {
|
|
6
6
|
interface Document {
|
|
@@ -23,8 +23,20 @@ declare global {
|
|
|
23
23
|
addEventListener(name: "regular-layout-before-update", cb: (e: RegularLayoutEvent) => void, options?: {
|
|
24
24
|
signal: AbortSignal;
|
|
25
25
|
}): void;
|
|
26
|
+
addEventListener(name: "regular-layout-before-resize", cb: (e: RegularLayoutPresizeEvent) => void, options?: {
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
}): void;
|
|
29
|
+
addEventListener(name: "regular-layout-select", cb: (e: RegularLayoutSelectEvent) => void, options?: {
|
|
30
|
+
signal: AbortSignal;
|
|
31
|
+
}): void;
|
|
26
32
|
removeEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void): void;
|
|
27
33
|
removeEventListener(name: "regular-layout-before-update", cb: (e: RegularLayoutEvent) => void): void;
|
|
34
|
+
removeEventListener(name: "regular-layout-before-resize", cb: (e: RegularLayoutPresizeEvent) => void): void;
|
|
35
|
+
removeEventListener(name: "regular-layout-select", cb: (e: RegularLayoutSelectEvent) => void): void;
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
export type RegularLayoutEvent = CustomEvent<Layout>;
|
|
39
|
+
export type RegularLayoutPresizeEvent = CustomEvent<PresizeDetail>;
|
|
40
|
+
export type RegularLayoutSelectEvent = CustomEvent<{
|
|
41
|
+
name: string;
|
|
42
|
+
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
*
|
|
48
48
|
* @packageDocumentation
|
|
49
49
|
*/
|
|
50
|
-
export type * from "./
|
|
50
|
+
export type * from "./core/types.ts";
|
|
51
51
|
export { RegularLayout } from "./regular-layout.ts";
|
|
52
52
|
export { RegularLayoutFrame } from "./regular-layout-frame.ts";
|
|
53
|
+
export type * from "./extensions.ts";
|
|
53
54
|
import "./extensions.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}let o=
|
|
3
|
-
`)}
|
|
4
|
-
`)
|
|
1
|
+
var g={type:"split-layout",orientation:"horizontal",sizes:[],children:[]};var _=Object.freeze({CUSTOM_EVENT_NAME_PREFIX:"regular-layout",CHILD_ATTRIBUTE_NAME:"name",MIN_DRAG_DISTANCE:10,SHOULD_ROUND:!1,OVERLAY_CLASSNAME:"overlay",MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD:.15,SPLIT_EDGE_TOLERANCE:.33,SPLIT_ROOT_EDGE_TOLERANCE:.03,GRID_TRACK_COLLAPSE_TOLERANCE:.001,OVERLAY_DEFAULT:"absolute",GRID_DIVIDER_SIZE:6,GRID_DIVIDER_CHECK_TARGET:!0});function K(i,t,e){return(t.length===0||Math.abs(e-t[t.length-1])>i.GRID_TRACK_COLLAPSE_TOLERANCE)&&t.push(e),t}function j(i,t){return t.sort((o,r)=>o-r).reduce(K.bind(void 0,i),[])}function R(i,t,e,o,r){if(i.type==="tab-layout")return[e,o];let n=[e,o];if(i.orientation===t){let s=e,a=o-e;for(let l=0;l<i.children.length;l++){let y=i.sizes[l],h=s+y*a;n.push(...R(i.children[l],t,s,h,r)),s=h}}else for(let s of i.children)n.push(...R(s,t,e,o,r));return j(r,n)}function P(i,t,e){let o=t.findIndex(r=>Math.abs(r-e)<i.GRID_TRACK_COLLAPSE_TOLERANCE);return o===-1?0:o}function U(i,t,e,o,r,n,s,a){if(i.type==="tab-layout"){let f=i.selected??0;return[{child:i.tabs[f],colStart:P(a,t,o),colEnd:P(a,t,r),rowStart:P(a,e,n),rowEnd:P(a,e,s)}]}let{children:l,sizes:y,orientation:h}=i,c=h==="horizontal",u=c?o:n,d=c?r-o:s-n,p=[];for(let f=0;f<l.length;f++){let m=u+y[f]*d;c?p.push(...U(l[f],t,e,u,m,n,s,a)):p.push(...U(l[f],t,e,o,r,u,m,a)),u=m}return p}var H=(i,t)=>`:host ::slotted(*){display:none}:host{display:grid;grid-template-rows:${i};grid-template-columns:${t}}`,C=(i,t,e,o)=>`:host ::slotted([${i.CHILD_ATTRIBUTE_NAME}="${t}"]){display:flex;grid-column:${o};grid-row:${e}}`;function E(i,t,e=_){if(i.type==="tab-layout"){let c=i.selected??0;return[H("100%","100%"),C(e,i.tabs[c],"1","1")].join(`
|
|
2
|
+
`)}let o=c=>c.slice(0,-1).map((d,p)=>c[p+1]-d).map(d=>`${e.SHOULD_ROUND?Math.round(d*100):d*100}fr`).join(" "),r=R(i,"horizontal",0,1,e),n=o(r),s=R(i,"vertical",0,1,e),a=o(s),l=(c,u)=>u-c===1?`${c+1}`:`${c+1} / ${u+1}`,y=U(i,r,s,0,1,0,1,e),h=[H(a,n)];for(let c of y){let u=l(c.colStart,c.colEnd),d=l(c.rowStart,c.rowEnd);h.push(C(e,c.child,d,u)),c.child===t?.[1]&&(h.push(C(e,t[0],d,u)),h.push(`:host ::slotted([${e.CHILD_ATTRIBUTE_NAME}=${t[0]}]){z-index:1}`))}return h.join(`
|
|
3
|
+
`)}function $(i,t=_){return[H("100%","100%"),C(t,i,"1","1")].join(`
|
|
4
|
+
`)}var Z={row_start:0,row_end:1,col_start:0,col_end:1};function L(i,t,e,o=null){return F(i,t,e,o)}function F(i,t,e,o,r=null,n=structuredClone(Z),s=[]){if(i<0||t<0||i>1||t>1)return null;if(e.type==="tab-layout"){let p=e.selected??0,f=n.col_end-n.col_start,m=n.row_end-n.row_start;return{type:"layout-path",layout:e,slot:e.tabs[p],path:s,view_window:n,is_edge:!1,column:i,row:t,column_offset:(i-n.col_start)/f,row_offset:(t-n.row_start)/m,orientation:r||"horizontal"}}let a=e.orientation==="vertical",l=a?t:i,y=a?"row_start":"col_start",h=a?"row_end":"col_end",c=a?o?.rect?.height:o?.rect?.width,u=n[y],d=n[h]-n[y];for(let p=0;p<e.children.length;p++){let f=u+d*e.sizes[p];if(o&&c){let m=o.size/c;if(Math.abs(l-f)<m)return{path:[...s,p],type:e.orientation,view_window:{...n,[y]:u,[h]:f}}}if(l>=u&&(l<f||p===e.children.length-1))return F(i,t,e.children[p],o,e.orientation,{...n,[y]:u,[h]:f},[...s,p]);u=f}return null}function b(i,t){if(i.type==="tab-layout"){if(i.tabs.includes(t)){let s=i.tabs.filter(a=>a!==t);return s.length===0?structuredClone(g):{type:"tab-layout",tabs:s}}return structuredClone(i)}let e=structuredClone(i),o=e.children.findIndex(s=>s.type==="tab-layout"?s.tabs.includes(t):!1);if(o!==-1){let s=e.children[o];if(s.tabs.length===1){let a=e.children.filter((y,h)=>h!==o),l=Q(e.sizes,o);if(a.length===1)return a[0];e.children=a,e.sizes=l}else s.tabs.splice(s.tabs.indexOf(t),1),s.selected&&s.selected>=s.tabs.length&&s.selected--;return e}let r=!1,n=e.children.map(s=>{if(s.type==="split-layout"){let a=b(s,t);return a!==s&&(r=!0),a}return s});return r&&(e.children=n),e}function Q(i,t){let e=[],o=i[t],r=0;for(let n=0;n<i.length;n++)n!==t&&(r+=i[n]);for(let n=0;n<i.length;n++)if(n!==t){let s=i[n]/r;e.push(i[n]+o*s)}return e}function v(i,t,e,o){let r=c=>({type:"tab-layout",tabs:[c]});if(e.length===0){if(i.type==="tab-layout")return{type:"tab-layout",tabs:[t,...i.tabs]};if(o)return{type:"split-layout",orientation:o,children:[r(t),i],sizes:[.5,.5]};{let c=[...i.children,r(t)],u=[...i.sizes,1/(c.length-1)];return{...i,children:c,sizes:w(u)}}}let[n,...s]=e;if(o&&s.length===0){if(i.type==="split-layout"&&i.orientation===o){let u=[...i.children];u.splice(n,0,r(t));let d=[...i.sizes];return d.splice(n,0,1/(u.length-1)),{...i,children:u,sizes:w(d)}}let c=n===0?[r(t),i]:[i,r(t)];return{type:"split-layout",orientation:o,children:c,sizes:[.5,.5]}}if(i.type==="tab-layout"){if(s.length===0&&o===void 0&&n>=0&&n<=i.tabs.length){let u=[...i.tabs];return u.splice(n,0,t),{...i,tabs:u}}return v({type:"split-layout",orientation:o||"horizontal",children:[i],sizes:[1]},t,e,o)}if(s.length===0||n===i.children.length){if(o&&i.children[n]){let d={type:"split-layout",orientation:o,children:[r(t),i.children[n]],sizes:[.5,.5]},p=[...i.children];return p[n]=d,{...i,children:p,sizes:w(i.sizes)}}let c=[...i.children];c.splice(n,0,r(t));let u=[...i.sizes];return u.splice(n,0,1/(c.length-1)),{...i,children:c,sizes:w(u)}}let a=i.children[n],l=a.type==="tab-layout"&&s.length>0&&o!==void 0?i.orientation==="horizontal"?"vertical":"horizontal":o,y=v(a,t,s,l),h=[...i.children];return h[n]=y,{...i,children:h}}function w(i){let t=i.reduce((e,o)=>e+o,0);return i.map(e=>e/t)}function D(i,t,e,o=_){let r=structuredClone(i),n=r,s={horizontal:e||0,vertical:e||0};for(let a=0;a<t.length-1;a++)n.type==="split-layout"&&(s[n.orientation]/=n.sizes[t[a]],n=n.children[t[a]]);if(n.type==="split-layout")if(e===void 0)n.sizes=n.sizes.map(a=>1/n.sizes.length);else{let a=s[n.orientation],l=t[t.length-1];l<n.sizes.length-1&&(n.sizes=J(o,n.sizes,l,a))}return r}function J(i,t,e,o){let r=[...t],n=0;for(let a=0;a<=e;a++)n+=t[a];let s=0;for(let a=e+1;a<t.length;a++)s+=t[a];o=Math.sign(o)*Math.min(Math.abs(o),(1-i.MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD)*(o>0?n:s));for(let a=0;a<=e;a++){let l=t[a]/n;r[a]=t[a]-o*l}for(let a=e+1;a<t.length;a++){let l=t[a]/s;r[a]=t[a]+o*l}return r}function G(i,t,e,o){let r=parseFloat(e.paddingLeft),n=parseFloat(e.paddingTop),s=t.width-r-parseFloat(e.paddingRight),a=t.height-n-parseFloat(e.paddingBottom),l=r+i.col_start*s,y=n+i.row_start*a,h=(i.col_end-i.col_start)*s,c=(i.row_end-i.row_start)*a;if(o){let u=parseFloat(o.marginTop),d=parseFloat(o.marginRight),p=parseFloat(o.marginBottom),f=parseFloat(o.marginLeft);h-=f+d,c-=u+p}return{x:l,y,width:h,height:c}}function Y(i,t,e,o,r=_,n){if(!o)return`:host ::slotted([${r.CHILD_ATTRIBUTE_NAME}="${i}"]){display:none;}`;let s=G(o.view_window,t,e,n),a=`display:flex;position:absolute!important;z-index:1;top:${s.y}px;left:${s.x}px;height:${s.height}px;width:${s.width}px;`;return`::slotted([${r.CHILD_ATTRIBUTE_NAME}="${i}"]){${a}}`}function I(i){if(i.type==="tab-layout")return i.selected=i.selected||0,i;let t=[],e=[];for(let o=0;o<i.children.length;o++){let r=i.children[o],n=i.sizes[o],s=I(r);if(s.type==="split-layout"&&s.orientation===i.orientation)for(let a=0;a<s.children.length;a++)t.push(s.children[a]),e.push(s.sizes[a]*n);else t.push(s),e.push(n)}return t.length===1?t[0]:{type:"split-layout",orientation:i.orientation,children:t,sizes:e}}function B(i,t){return k(i,t,[])}function k(i,t,e){if(t.type==="tab-layout")return t.tabs.includes(i)?e:null;for(let o=0;o<t.children.length;o++){let r=k(i,t.children[o],[...e,o]);if(r)return r}return null}function W(i){let t={};return q(i,t,[],null,{row_start:0,row_end:1,col_start:0,col_end:1}),t}function q(i,t,e,o,r){if(i.type==="tab-layout"){let h=i.selected??0,c=i.tabs[h],u=(r.col_start+r.col_end)/2,d=(r.row_start+r.row_end)/2;t[c]={type:"layout-path",layout:i,slot:c,path:e,view_window:r,is_edge:!1,column:u,row:d,column_offset:.5,row_offset:.5,orientation:o||"horizontal"};return}let n=i.orientation==="vertical",s=n?"row_start":"col_start",a=n?"row_end":"col_end",l=r[s],y=r[a]-r[s];for(let h=0;h<i.children.length;h++){let c=l+y*i.sizes[h],u={...r,[s]:l,[a]:c};q(i.children[h],t,[...e,h],i.orientation,u),l=c}}var O=class{constructor(t,e){this.b=t;this.v=e}#o=!1;#t=null;#e=null;async run(t,e){if(this.#o){this.#t={layout:t,fn:e};return}this.#o=!0;try{for(await this.#n(t,e);this.#t;){let{layout:o,fn:r}=this.#t;this.#t=null,await this.#n(o,r)}}finally{this.#o=!1}}resume(){if(this.#e){let t=this.#e;this.#e=null,t()}}async#n(t,e){let o={calculatePresizePaths:()=>W(t)},r=new CustomEvent(this.v,{cancelable:!0,detail:o});this.b.dispatchEvent(r)||await new Promise(s=>{this.#e=s}),e()}};function V(i,t,e,o,r,n,s=_){if(i<s.SPLIT_ROOT_EDGE_TOLERANCE)return A(e,o,r,[0],!0,"horizontal");if(i>1-s.SPLIT_ROOT_EDGE_TOLERANCE)return A(e,o,r,r.path.length>0?r.path:[1],!1,"horizontal");if(t<s.SPLIT_ROOT_EDGE_TOLERANCE)return A(e,o,r,[0],!0,"vertical");if(t>1-s.SPLIT_ROOT_EDGE_TOLERANCE)return A(e,o,r,r.path.length>0?r.path:[1],!1,"vertical");let a=r.column_offset<s.SPLIT_EDGE_TOLERANCE||r.column_offset>1-s.SPLIT_EDGE_TOLERANCE,l=r.row_offset<s.SPLIT_EDGE_TOLERANCE||r.row_offset>1-s.SPLIT_EDGE_TOLERANCE;if(a&&l){let y=Math.abs(r.column_offset-.5),h=Math.abs(r.row_offset-.5),c=(n?.width||1)*(r.view_window.col_end-r.view_window.col_start),u=(n?.height||1)*(r.view_window.row_end-r.view_window.row_start),d=c/2-y*c<u/2-h*u;return z(e,o,r,d?r.column_offset<s.SPLIT_EDGE_TOLERANCE:r.row_offset<s.SPLIT_EDGE_TOLERANCE,d?"horizontal":"vertical")}return a?z(e,o,r,r.column_offset<s.SPLIT_EDGE_TOLERANCE,"horizontal"):l?z(e,o,r,r.row_offset<s.SPLIT_EDGE_TOLERANCE,"vertical"):{...r,path:[...r.path,0]}}function A(i,t,e,o,r,n){return z(i,t,{...e,path:o,orientation:n},r,n)}function z(i,t,e,o,r){let n;if(e.orientation===r)if(e.path.length===0)n=[o?0:1];else{let l=e.path[e.path.length-1];n=[...e.path.slice(0,-1),o?l:l+1]}else n=[...e.path,o?0:1];let s=v(i,t,n,r),a=tt(s,n);return{...e,path:n,slot:e.slot,is_edge:!0,orientation:r,view_window:a}}function tt(i,t){let e={row_start:0,row_end:1,col_start:0,col_end:1},o=i;for(let r of t){if(o.type==="tab-layout")break;let n=Math.min(r,o.children.length-1),s=o.orientation==="vertical",a=s?"row_start":"col_start",l=s?"row_end":"col_end",y=e[l]-e[a],h=o.sizes.slice(0,n).reduce((c,u)=>c+u*y,e[a]);e={...e,[a]:h,[l]:h+y*o.sizes[n]},o=o.children[n]}return e}var M=class{constructor(t){this.d=t}async set(t,{slot:e},o=this.d.physics.OVERLAY_CLASSNAME,r=this.d.physics.OVERLAY_DEFAULT){let n=this.d,s=b(n.panel,e),a=`:scope > [${n.physics.CHILD_ATTRIBUTE_NAME}="${e}"]`,l=n.querySelector(a);l&&l.classList.add(o);let[y,h,c,u]=n.relativeCoordinates(t,!0),d=L(y,h,s);d&&(d=V(y,h,s,e,d,c,n.physics)),await n.presizeQueue.run(s,()=>{if(r==="grid"&&d){let m=[e,d?.slot],N=E(s,m,n.physics);n.stylesheet.replaceSync(N)}else if(r==="absolute"){let m=E(s,void 0,n.physics);for(;l?.tagName==="SLOT"&&l;)l=l.assignedElements()[0];let N=l?getComputedStyle(l):void 0,X=Y(e,c,u,d,n.physics,N);n.stylesheet.replaceSync([m,X].join(`
|
|
5
|
+
`))}});let p=`${n.physics.CUSTOM_EVENT_NAME_PREFIX}-before-update`,f=new CustomEvent(p,{detail:s});n.dispatchEvent(f)}async clear(t,{slot:e,layout:o},r=this.d.physics.OVERLAY_CLASSNAME){let n=this.d,s=b(n.panel,e),a=`:scope > [${n.physics.CHILD_ATTRIBUTE_NAME}="${e}"]`,l=n.querySelector(a);if(t===null){await n.restore(o);return}let[y,h,c]=n.relativeCoordinates(t,!1),u=L(y,h,s);if(u&&(u=V(y,h,s,e,u,c,n.physics)),u){let d=u?.is_edge?u.orientation:void 0,p=v(s,e,u.path,d);await n.restore(p)}else await n.restore(o);l&&l.classList.remove(r)}};var T=class extends HTMLElement{i;t;s;u;h;c;a;e;p;_;f;constructor(){super(),this.e=_,this.t=structuredClone(g),this.i=this.attachShadow({mode:"open"}),this.i.innerHTML="<slot></slot>",this.s=new CSSStyleSheet,this.u=new CSSStyleSheet,this.c=!1;let t=`${this.e.CUSTOM_EVENT_NAME_PREFIX}-before-resize`;this.p=new O(this,t),this._=new M(this.create_overlay_host()),this.i.adoptedStyleSheets=[this.s,this.u]}connectedCallback(){this.addEventListener("dblclick",this.onDblClick),this.addEventListener("pointerdown",this.onPointerDown),this.addEventListener("pointerup",this.onPointerUp),this.addEventListener("pointermove",this.onPointerMove)}disconnectedCallback(){this.removeEventListener("dblclick",this.onDblClick),this.removeEventListener("pointerdown",this.onPointerDown),this.removeEventListener("pointerup",this.onPointerUp),this.removeEventListener("pointermove",this.onPointerMove)}calculateIntersect=t=>{let[e,o,r]=this.relativeCoordinates(t,!1);return L(e,o,this.t)};calculatePath=t=>B(t,this.t);setOverlayState=async(t,e,o,r)=>{await this._.set(t,e,o,r)};clearOverlayState=async(t,e,o)=>{await this._.clear(t,e,o)};insertPanel=async(t,e=[],o)=>{let r;typeof o=="boolean"&&o?r="horizontal":typeof o=="string"&&(r=o),await this.restore(v(this.t,t,e,r))};removePanel=async t=>{await this.restore(b(this.t,t))};select=async t=>{let e=this.save(),o=this.getPanel(t,e);if(!o)return;let r=o.tabs.indexOf(t);r!==-1&&o.selected!==r&&(o.selected=r,await this.restore(e));let n=`${this.e.CUSTOM_EVENT_NAME_PREFIX}-select`;this.dispatchEvent(new CustomEvent(n,{detail:{name:t}}))};getPanel=(t,e=this.t)=>{if(e.type==="tab-layout")return e.tabs.includes(t)?e:null;for(let o of e.children){let r=this.getPanel(t,o);if(r)return r}return null};clear=async()=>{await this.restore(g)};maximize=t=>{this.getPanel(t)&&(this.f=t,this.s.replaceSync($(t,this.e)))};minimize=()=>{this.f!==void 0&&(this.f=void 0,this.s.replaceSync(E(this.t,void 0,this.e)))};restoreSync=(t,e=!1)=>{this.f=void 0,this.t=e?t:I(t);let o=E(this.t,void 0,this.e);this.s.replaceSync(o);let r=`${this.e.CUSTOM_EVENT_NAME_PREFIX}-update`,n=new CustomEvent(r,{detail:this.t});this.dispatchEvent(n)};restore=async(t,e=!1)=>{let o=e?t:I(t);await this.p.run(o,()=>{this.f=void 0,this.t=o;let r=E(this.t,void 0,this.e);this.s.replaceSync(r);let n=`${this.e.CUSTOM_EVENT_NAME_PREFIX}-update`,s=new CustomEvent(n,{detail:this.t});this.dispatchEvent(s)})};resumeResize=()=>{this.p.resume()};save=()=>structuredClone(this.t);restorePhysics(t){this.e=Object.freeze({...this.e,...t})}savePhysics(){return this.e}relativeCoordinates=(t,e=!0)=>{(e||!this.a)&&(this.a={box:this.getBoundingClientRect(),style:getComputedStyle(this)});let o=this.a.box,r=this.a.style,n=parseFloat(r.paddingLeft),s=parseFloat(r.paddingTop),a=o.width-n-parseFloat(r.paddingRight),l=o.height-s-parseFloat(r.paddingBottom),y=t.clientX-o.left-n,h=t.clientY-o.top-s,c=Math.max(0,Math.min(1,y/a)),u=Math.max(0,Math.min(1,h/l));return[c,u,o,r]};realCoordinates=(t,e)=>{this.a||(this.a={box:this.getBoundingClientRect(),style:getComputedStyle(this)});let o=this.a.box,r=this.a.style,n;e&&(n=getComputedStyle(e));let s=G(t,o,r,n);return new DOMRect(o.left+s.x,o.top+s.y,s.width,s.height)};diffCoordinates=(t,e)=>{let[o,r,n]=this.relativeCoordinates(t,!1),s=(o-e.column)*n.width,a=(r-e.row)*n.height;return Math.sqrt(s**2+a**2)};create_overlay_host(){let t=this;return{get panel(){return t.t},get physics(){return t.e},get stylesheet(){return t.s},get presizeQueue(){return t.p},relativeCoordinates:(e,o)=>t.relativeCoordinates(e,o),restore:(e,o)=>t.restore(e,o),querySelector:e=>t.querySelector(e),dispatchEvent:e=>t.dispatchEvent(e)}}onDblClick=async t=>{let[e,o,r]=this.relativeCoordinates(t,!1),n=L(e,o,this.t,{rect:r,size:this.e.GRID_DIVIDER_SIZE});if(n?.type==="horizontal"||n?.type==="vertical"){let s=D(this.t,n.path,void 0);await this.restore(s,!0)}};onPointerDown=t=>{if(t.button===0&&(!this.e.GRID_DIVIDER_CHECK_TARGET||t.target===this)){let[e,o,r]=this.relativeCoordinates(t),n=this.e.GRID_DIVIDER_SIZE,s=L(e,o,this.t,{rect:r,size:n});s&&s.type!=="layout-path"&&(this.h=[s,e,o],this.setPointerCapture(t.pointerId),t.preventDefault())}};onPointerMove=async t=>{if(this.h){let[s,a]=this.relativeCoordinates(t,!1),[{path:l,type:y},h,c]=this.h,u=y==="horizontal"?h-s:c-a,d=D(this.t,l,u);await this.p.run(d,()=>{this.s.replaceSync(E(d,void 0,this.e))})}if(this.e.GRID_DIVIDER_CHECK_TARGET&&t.target!==this){this.c&&(this.c=!1,this.u.replaceSync(""));return}let[e,o,r]=this.relativeCoordinates(t,!1),n=L(e,o,this.t,{rect:r,size:this.e.GRID_DIVIDER_SIZE});n?.type==="vertical"?(this.u.replaceSync(":host{cursor:row-resize"),this.c=!0):n?.type==="horizontal"?(this.u.replaceSync(":host{cursor:col-resize"),this.c=!0):this.c&&(this.c=!1,this.u.replaceSync(""))};onPointerUp=async t=>{if(this.h){this.releasePointerCapture(t.pointerId);let[e,o]=this.relativeCoordinates(t,!1),[{path:r,type:n},s,a]=this.h,l=n==="horizontal"?s-e:a-o,y=D(this.t,r,l);await this.restore(y,!0),this.h=void 0}}};var et=`
|
|
5
6
|
:host{box-sizing:border-box;flex-direction:column}
|
|
6
7
|
:host::part(titlebar){display:flex;height:24px;user-select:none;overflow:hidden}
|
|
7
8
|
:host::part(container){flex:1 1 auto}
|
|
@@ -9,8 +10,10 @@ var b={type:"split-layout",orientation:"horizontal",sizes:[],children:[]};var E=
|
|
|
9
10
|
:host::part(close){align-self:stretch}
|
|
10
11
|
:host::slotted{flex:1 1 auto;}
|
|
11
12
|
:host regular-layout-tab{width:0px;}
|
|
12
|
-
`,
|
|
13
|
+
`,ot=`
|
|
13
14
|
<div part="titlebar"></div>
|
|
14
|
-
<
|
|
15
|
-
`,
|
|
15
|
+
<div part="container"><slot></slot></div>
|
|
16
|
+
`,nt=i=>`"${i.replace(/[\\"\n]/g,t=>t===`
|
|
17
|
+
`?"\\A ":`\\${t}`)}"`,rt=i=>`--regular-layout-${globalThis.CSS.escape(i)}--title`,S=class extends HTMLElement{i;E;L;o;r;n=null;g=new WeakMap;connectedCallback(){this.E??=new CSSStyleSheet,this.E.replaceSync(et),this.L??=new CSSStyleSheet,this.i??=this.attachShadow({mode:"open"}),this.i.adoptedStyleSheets=[this.E,this.L],this.i.innerHTML=ot,this.o=this.parentElement,this.r=this.i.children[0],this.r.addEventListener("pointerdown",this.onPointerDown),this.addEventListener("pointermove",this.onPointerMove),this.addEventListener("pointerup",this.onPointerUp),this.addEventListener("pointercancel",this.onPointerCancel),this.addEventListener("lostpointercapture",this.onPointerLost),this.o.addEventListener("regular-layout-update",this.drawTabs),this.o.addEventListener("regular-layout-before-update",this.drawTabs)}disconnectedCallback(){this.r.removeEventListener("pointerdown",this.onPointerDown),this.removeEventListener("pointermove",this.onPointerMove),this.removeEventListener("pointerup",this.onPointerUp),this.removeEventListener("pointercancel",this.onPointerUp),this.removeEventListener("lostpointercapture",this.onPointerLost),this.o.removeEventListener("regular-layout-update",this.drawTabs),this.o.removeEventListener("regular-layout-before-update",this.drawTabs)}onPointerDown=t=>{if(t.button!==0)return;if(t.target.part.contains("tab")){let o=this.o.calculateIntersect(t);o?(this.n={path:o},this.setPointerCapture(t.pointerId),t.preventDefault()):this.n=null}};onPointerMove=t=>{if(this.n){let e=this.o.savePhysics();if(!this.n.moved&&this.o.diffCoordinates(t,this.n.path)<=e.MIN_DRAG_DISTANCE)return;this.n.moved=!0,this.o.setOverlayState(t,this.n.path)}};onPointerUp=t=>{this.n?.moved&&this.o.clearOverlayState(t,this.n.path)};onPointerCancel=t=>{this.n?.moved&&this.o.clearOverlayState(null,this.n.path)};onPointerLost=t=>{this.releasePointerCapture(t.pointerId),this.n=null};drawTabs=t=>{let e=this.o.savePhysics().CHILD_ATTRIBUTE_NAME,o=this.getAttribute(e);if(!o)return;let r=t.detail,n=this.o.getPanel(o,r);n||(n={type:"tab-layout",tabs:[o],selected:0});for(let a=0;a<n.tabs.length;a++)if(a>=this.r.children.length){let l=document.createElement("regular-layout-tab");l.populate(this.o,n,a),this.r.appendChild(l),this.g.set(l,a)}else this.r.children[a].populate(this.o,n,a);let s=n.tabs.length;for(let a=this.r.children.length-1;a>=s;a--)this.r.removeChild(this.r.children[a]);this.drawTitles(e,n.tabs)};drawTitles=(t,e)=>{let o=e.map(r=>`regular-layout-tab[${t}="${r}"] [part~="title"]::before{content:var(${rt(r)}, ${nt(r)})}`).join(`
|
|
18
|
+
`);this.L.replaceSync(o)}};var x=class extends HTMLElement{o;l;m;populate=(t,e,o)=>{if(this.setAttribute(t.savePhysics().CHILD_ATTRIBUTE_NAME,e.tabs[o]),this.l)(o===e.selected!=(o===this.l?.selected)||this.l?.tabs[o]!==e.tabs[o])&&(e.selected===o?(this.children[1].part.add("active-close"),this.part.add("active-tab")):(this.children[1].part.remove("active-close"),this.part.remove("active-tab")));else{let r=e.selected===o,n=r?"active-close close":"close";this.innerHTML=`<div part="title"></div><button part="${n}"></button>`,r?this.part.add("tab","active-tab"):this.part.add("tab"),this.addEventListener("pointerdown",this.onTabClick),this.children[1].addEventListener("pointerdown",this.onTabClose)}this.l=e,this.o=t,this.m=o};onTabClose=t=>{t instanceof PointerEvent&&t?.button!==0||this.l!==void 0&&this.m!==void 0&&this.o?.removePanel(this.l.tabs[this.m])};onTabClick=t=>{t.button===0&&this.l!==void 0&&this.m!==void 0&&this.o?.select(this.l.tabs[this.m])}};customElements.define("regular-layout",T);customElements.define("regular-layout-frame",S);customElements.define("regular-layout-tab",x);export{T as RegularLayout,S as RegularLayoutFrame};
|
|
16
19
|
//# sourceMappingURL=index.js.map
|