regular-layout 0.2.2 → 0.4.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 +14 -4
- package/dist/extensions.d.ts +6 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +4 -4
- package/dist/layout/calculate_edge.d.ts +4 -4
- package/dist/layout/calculate_intersect.d.ts +1 -1
- package/dist/layout/calculate_path.d.ts +12 -0
- 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 +5 -5
- package/dist/layout/generate_overlay.d.ts +18 -2
- package/dist/layout/insert_child.d.ts +2 -2
- 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-tab.d.ts +1 -1
- package/dist/regular-layout.d.ts +44 -9
- package/package.json +5 -4
- package/src/{layout → core}/constants.ts +2 -2
- package/src/{layout → core}/types.ts +17 -5
- package/src/extensions.ts +13 -1
- package/src/index.ts +3 -1
- package/src/layout/calculate_edge.ts +17 -8
- package/src/layout/calculate_intersect.ts +13 -4
- package/src/layout/calculate_path.ts +53 -0
- package/src/layout/calculate_presize_paths.ts +93 -0
- package/src/layout/flatten.ts +4 -4
- package/src/layout/generate_grid.ts +8 -8
- package/src/layout/generate_overlay.ts +48 -16
- package/src/layout/insert_child.ts +16 -16
- package/src/layout/redistribute_panel_sizes.ts +5 -5
- package/src/layout/remove_child.ts +6 -6
- package/src/model/overlay_controller.ts +162 -0
- package/src/model/presize_queue.ts +79 -0
- package/src/regular-layout-frame.ts +3 -3
- package/src/regular-layout-tab.ts +1 -1
- package/src/regular-layout.ts +180 -133
- 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
|
+
```
|
|
@@ -32,7 +32,7 @@ export interface ViewWindow {
|
|
|
32
32
|
* opposite `orientation` as its parent.
|
|
33
33
|
*/
|
|
34
34
|
export interface SplitLayout {
|
|
35
|
-
type: "split-
|
|
35
|
+
type: "split-layout";
|
|
36
36
|
children: Layout[];
|
|
37
37
|
sizes: number[];
|
|
38
38
|
orientation: Orientation;
|
|
@@ -41,17 +41,21 @@ export interface SplitLayout {
|
|
|
41
41
|
* A leaf panel node that contains a single named child element.
|
|
42
42
|
*/
|
|
43
43
|
export interface TabLayout {
|
|
44
|
-
type: "
|
|
44
|
+
type: "tab-layout";
|
|
45
45
|
tabs: string[];
|
|
46
46
|
selected?: number;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Represents a panel location relative to a `Layout` struct.
|
|
50
|
+
*/
|
|
51
|
+
export type LayoutPathTraversal = number[];
|
|
48
52
|
/**
|
|
49
53
|
* Represents a draggable divider between two panels in the layout.
|
|
50
54
|
*
|
|
51
55
|
* Used for hit detection.
|
|
52
56
|
*/
|
|
53
57
|
export interface LayoutDivider {
|
|
54
|
-
path:
|
|
58
|
+
path: LayoutPathTraversal;
|
|
55
59
|
view_window: ViewWindow;
|
|
56
60
|
type: Orientation;
|
|
57
61
|
}
|
|
@@ -61,7 +65,7 @@ export interface LayoutDivider {
|
|
|
61
65
|
export interface LayoutPath {
|
|
62
66
|
type: "layout-path";
|
|
63
67
|
slot: string;
|
|
64
|
-
path:
|
|
68
|
+
path: LayoutPathTraversal;
|
|
65
69
|
view_window: ViewWindow;
|
|
66
70
|
column: number;
|
|
67
71
|
row: number;
|
|
@@ -71,6 +75,12 @@ export interface LayoutPath {
|
|
|
71
75
|
is_edge: boolean;
|
|
72
76
|
layout: Layout;
|
|
73
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The detail payload of the `regular-layout-before-resize` event.
|
|
80
|
+
*/
|
|
81
|
+
export interface PresizeDetail {
|
|
82
|
+
calculatePresizePaths(): Record<string, LayoutPath>;
|
|
83
|
+
}
|
|
74
84
|
/**
|
|
75
85
|
* An empty `Layout` with no panels.
|
|
76
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,13 @@ 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;
|
|
26
29
|
removeEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void): void;
|
|
27
30
|
removeEventListener(name: "regular-layout-before-update", cb: (e: RegularLayoutEvent) => void): void;
|
|
31
|
+
removeEventListener(name: "regular-layout-before-resize", cb: (e: RegularLayoutPresizeEvent) => void): void;
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
34
|
export type RegularLayoutEvent = CustomEvent<Layout>;
|
|
35
|
+
export type RegularLayoutPresizeEvent = CustomEvent<PresizeDetail>;
|
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,7 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}let
|
|
3
|
-
`)}var
|
|
4
|
-
`))}let p=`${
|
|
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 X(r,t,e){return(t.length===0||Math.abs(e-t[t.length-1])>r.GRID_TRACK_COLLAPSE_TOLERANCE)&&t.push(e),t}function K(r,t){return t.sort((o,i)=>o-i).reduce(X.bind(void 0,r),[])}function C(r,t,e,o,i){if(r.type==="tab-layout")return[e,o];let n=[e,o];if(r.orientation===t){let s=e,a=o-e;for(let l=0;l<r.children.length;l++){let y=r.sizes[l],h=s+y*a;n.push(...C(r.children[l],t,s,h,i)),s=h}}else for(let s of r.children)n.push(...C(s,t,e,o,i));return K(i,n)}function S(r,t,e){let o=t.findIndex(i=>Math.abs(i-e)<r.GRID_TRACK_COLLAPSE_TOLERANCE);return o===-1?0:o}function U(r,t,e,o,i,n,s,a){if(r.type==="tab-layout"){let f=r.selected??0;return[{child:r.tabs[f],colStart:S(a,t,o),colEnd:S(a,t,i),rowStart:S(a,e,n),rowEnd:S(a,e,s)}]}let{children:l,sizes:y,orientation:h}=r,c=h==="horizontal",u=c?o:n,d=c?i-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,i,u,m,a)),u=m}return p}var V=(r,t)=>`:host ::slotted(*){display:none}:host{display:grid;grid-template-rows:${r};grid-template-columns:${t}}`,N=(r,t,e,o)=>`:host ::slotted([${r.CHILD_ATTRIBUTE_NAME}="${t}"]){display:flex;grid-column:${o};grid-row:${e}}`;function v(r,t,e=_){if(r.type==="tab-layout"){let c=r.selected??0;return[V("100%","100%"),N(e,r.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(" "),i=C(r,"horizontal",0,1,e),n=o(i),s=C(r,"vertical",0,1,e),a=o(s),l=(c,u)=>u-c===1?`${c+1}`:`${c+1} / ${u+1}`,y=U(r,i,s,0,1,0,1,e),h=[V(a,n)];for(let c of y){let u=l(c.colStart,c.colEnd),d=l(c.rowStart,c.rowEnd);h.push(N(e,c.child,d,u)),c.child===t?.[1]&&(h.push(N(e,t[0],d,u)),h.push(`:host ::slotted([${e.CHILD_ATTRIBUTE_NAME}=${t[0]}]){z-index:1}`))}return h.join(`
|
|
3
|
+
`)}var Z={row_start:0,row_end:1,col_start:0,col_end:1};function L(r,t,e,o=null){return F(r,t,e,o)}function F(r,t,e,o,i=null,n=structuredClone(Z),s=[]){if(r<0||t<0||r>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:r,row:t,column_offset:(r-n.col_start)/f,row_offset:(t-n.row_start)/m,orientation:i||"horizontal"}}let a=e.orientation==="vertical",l=a?t:r,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(r,t,e.children[p],o,e.orientation,{...n,[y]:u,[h]:f},[...s,p]);u=f}return null}function b(r,t){if(r.type==="tab-layout"){if(r.tabs.includes(t)){let s=r.tabs.filter(a=>a!==t);return s.length===0?structuredClone(g):{type:"tab-layout",tabs:s}}return structuredClone(r)}let e=structuredClone(r),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=j(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 i=!1,n=e.children.map(s=>{if(s.type==="split-layout"){let a=b(s,t);return a!==s&&(i=!0),a}return s});return i&&(e.children=n),e}function j(r,t){let e=[],o=r[t],i=0;for(let n=0;n<r.length;n++)n!==t&&(i+=r[n]);for(let n=0;n<r.length;n++)if(n!==t){let s=r[n]/i;e.push(r[n]+o*s)}return e}function E(r,t,e,o){let i=c=>({type:"tab-layout",tabs:[c]});if(e.length===0){if(r.type==="tab-layout")return{type:"tab-layout",tabs:[t,...r.tabs]};if(o)return{type:"split-layout",orientation:o,children:[i(t),r],sizes:[.5,.5]};{let c=[...r.children,i(t)],u=[...r.sizes,1/(c.length-1)];return{...r,children:c,sizes:R(u)}}}let[n,...s]=e;if(o&&s.length===0){if(r.type==="split-layout"&&r.orientation===o){let u=[...r.children];u.splice(n,0,i(t));let d=[...r.sizes];return d.splice(n,0,1/(u.length-1)),{...r,children:u,sizes:R(d)}}let c=n===0?[i(t),r]:[r,i(t)];return{type:"split-layout",orientation:o,children:c,sizes:[.5,.5]}}if(r.type==="tab-layout"){if(s.length===0&&o===void 0&&n>=0&&n<=r.tabs.length){let u=[...r.tabs];return u.splice(n,0,t),{...r,tabs:u}}return E({type:"split-layout",orientation:o||"horizontal",children:[r],sizes:[1]},t,e,o)}if(s.length===0||n===r.children.length){if(o&&r.children[n]){let d={type:"split-layout",orientation:o,children:[i(t),r.children[n]],sizes:[.5,.5]},p=[...r.children];return p[n]=d,{...r,children:p,sizes:R(r.sizes)}}let c=[...r.children];c.splice(n,0,i(t));let u=[...r.sizes];return u.splice(n,0,1/(c.length-1)),{...r,children:c,sizes:R(u)}}let a=r.children[n],l=a.type==="tab-layout"&&s.length>0&&o!==void 0?r.orientation==="horizontal"?"vertical":"horizontal":o,y=E(a,t,s,l),h=[...r.children];return h[n]=y,{...r,children:h}}function R(r){let t=r.reduce((e,o)=>e+o,0);return r.map(e=>e/t)}function w(r,t,e,o=_){let i=structuredClone(r),n=i,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=Q(o,n.sizes,l,a))}return i}function Q(r,t,e,o){let i=[...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-r.MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD)*(o>0?n:s));for(let a=0;a<=e;a++){let l=t[a]/n;i[a]=t[a]-o*l}for(let a=e+1;a<t.length;a++){let l=t[a]/s;i[a]=t[a]+o*l}return i}function H(r,t,e,o){let i=parseFloat(e.paddingLeft),n=parseFloat(e.paddingTop),s=t.width-i-parseFloat(e.paddingRight),a=t.height-n-parseFloat(e.paddingBottom),l=i+r.col_start*s,y=n+r.row_start*a,h=(r.col_end-r.col_start)*s,c=(r.row_end-r.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 $(r,t,e,o,i=_,n){if(!o)return`:host ::slotted([${i.CHILD_ATTRIBUTE_NAME}="${r}"]){display:none;}`;let s=H(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([${i.CHILD_ATTRIBUTE_NAME}="${r}"]){${a}}`}function D(r){if(r.type==="tab-layout")return r.selected=r.selected||0,r;let t=[],e=[];for(let o=0;o<r.children.length;o++){let i=r.children[o],n=r.sizes[o],s=D(i);if(s.type==="split-layout"&&s.orientation===r.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:r.orientation,children:t,sizes:e}}function Y(r,t){return k(r,t,[])}function k(r,t,e){if(t.type==="tab-layout")return t.tabs.includes(r)?e:null;for(let o=0;o<t.children.length;o++){let i=k(r,t.children[o],[...e,o]);if(i)return i}return null}function B(r){let t={};return W(r,t,[],null,{row_start:0,row_end:1,col_start:0,col_end:1}),t}function W(r,t,e,o,i){if(r.type==="tab-layout"){let h=r.selected??0,c=r.tabs[h],u=(i.col_start+i.col_end)/2,d=(i.row_start+i.row_end)/2;t[c]={type:"layout-path",layout:r,slot:c,path:e,view_window:i,is_edge:!1,column:u,row:d,column_offset:.5,row_offset:.5,orientation:o||"horizontal"};return}let n=r.orientation==="vertical",s=n?"row_start":"col_start",a=n?"row_end":"col_end",l=i[s],y=i[a]-i[s];for(let h=0;h<r.children.length;h++){let c=l+y*r.sizes[h],u={...i,[s]:l,[a]:c};W(r.children[h],t,[...e,h],r.orientation,u),l=c}}var I=class{constructor(t,e){this.E=t;this.L=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:i}=this.#t;this.#t=null,await this.#n(o,i)}}finally{this.#o=!1}}resume(){if(this.#e){let t=this.#e;this.#e=null,t()}}async#n(t,e){let o={calculatePresizePaths:()=>B(t)},i=new CustomEvent(this.L,{cancelable:!0,detail:o});this.E.dispatchEvent(i)||await new Promise(s=>{this.#e=s}),e()}};function G(r,t,e,o,i,n,s=_){if(r<s.SPLIT_ROOT_EDGE_TOLERANCE)return O(e,o,i,[0],!0,"horizontal");if(r>1-s.SPLIT_ROOT_EDGE_TOLERANCE)return O(e,o,i,i.path.length>0?i.path:[1],!1,"horizontal");if(t<s.SPLIT_ROOT_EDGE_TOLERANCE)return O(e,o,i,[0],!0,"vertical");if(t>1-s.SPLIT_ROOT_EDGE_TOLERANCE)return O(e,o,i,i.path.length>0?i.path:[1],!1,"vertical");let a=i.column_offset<s.SPLIT_EDGE_TOLERANCE||i.column_offset>1-s.SPLIT_EDGE_TOLERANCE,l=i.row_offset<s.SPLIT_EDGE_TOLERANCE||i.row_offset>1-s.SPLIT_EDGE_TOLERANCE;if(a&&l){let y=Math.abs(i.column_offset-.5),h=Math.abs(i.row_offset-.5),c=(n?.width||1)*(i.view_window.col_end-i.view_window.col_start),u=(n?.height||1)*(i.view_window.row_end-i.view_window.row_start),d=c/2-y*c<u/2-h*u;return A(e,o,i,d?i.column_offset<s.SPLIT_EDGE_TOLERANCE:i.row_offset<s.SPLIT_EDGE_TOLERANCE,d?"horizontal":"vertical")}return a?A(e,o,i,i.column_offset<s.SPLIT_EDGE_TOLERANCE,"horizontal"):l?A(e,o,i,i.row_offset<s.SPLIT_EDGE_TOLERANCE,"vertical"):{...i,path:[...i.path,0]}}function O(r,t,e,o,i,n){return A(r,t,{...e,path:o,orientation:n},i,n)}function A(r,t,e,o,i){let n;if(e.orientation===i)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=E(r,t,n,i),a=J(s,n);return{...e,path:n,slot:e.slot,is_edge:!0,orientation:i,view_window:a}}function J(r,t){let e={row_start:0,row_end:1,col_start:0,col_end:1},o=r;for(let i of t){if(o.type==="tab-layout")break;let n=Math.min(i,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 z=class{constructor(t){this.p=t}async set(t,{slot:e},o=this.p.physics.OVERLAY_CLASSNAME,i=this.p.physics.OVERLAY_DEFAULT){let n=this.p,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);console.log(h,y,d),d&&(d=G(y,h,s,e,d,c,n.physics)),await n.presizeQueue.run(s,()=>{if(i==="grid"&&d){let m=[e,d?.slot],x=v(s,m,n.physics);n.stylesheet.replaceSync(x)}else if(i==="absolute"){let m=v(s,void 0,n.physics);for(;l?.tagName==="SLOT"&&l;)l=l.assignedElements()[0];let x=l?getComputedStyle(l):void 0,q=$(e,c,u,d,n.physics,x);n.stylesheet.replaceSync([m,q].join(`
|
|
4
|
+
`))}});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},i=this.p.physics.OVERLAY_CLASSNAME){let n=this.p,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=G(y,h,s,e,u,c,n.physics)),u){let d=u?.is_edge?u.orientation:void 0,p=E(s,e,u.path,d);await n.restore(p)}else await n.restore(o);l&&l.classList.remove(i)}};var T=class extends HTMLElement{s;e;u;h;d;l;a;o;f;m;constructor(){super(),this.o=_,this.e=structuredClone(g),this.s=this.attachShadow({mode:"open"}),this.s.innerHTML="<slot></slot>",this.u=new CSSStyleSheet,this.h=new CSSStyleSheet,this.l=!1;let t=`${this.o.CUSTOM_EVENT_NAME_PREFIX}-before-resize`;this.f=new I(this,t),this.m=new z(this.create_overlay_host()),this.s.adoptedStyleSheets=[this.u,this.h]}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,i]=this.relativeCoordinates(t,!1);return L(e,o,this.e)};calculatePath=t=>Y(t,this.e);setOverlayState=async(t,e,o,i)=>{await this.m.set(t,e,o,i)};clearOverlayState=async(t,e,o)=>{await this.m.clear(t,e,o)};insertPanel=async(t,e=[],o)=>{let i;typeof o=="boolean"&&o?i="horizontal":typeof o=="string"&&(i=o),await this.restore(E(this.e,t,e,i))};removePanel=async t=>{await this.restore(b(this.e,t))};getPanel=(t,e=this.e)=>{if(e.type==="tab-layout")return e.tabs.includes(t)?e:null;for(let o of e.children){let i=this.getPanel(t,o);if(i)return i}return null};clear=async()=>{await this.restore(g)};restoreSync=(t,e=!1)=>{this.e=e?t:D(t);let o=v(this.e,void 0,this.o);this.u.replaceSync(o);let i=`${this.o.CUSTOM_EVENT_NAME_PREFIX}-update`,n=new CustomEvent(i,{detail:this.e});this.dispatchEvent(n)};restore=async(t,e=!1)=>{let o=e?t:D(t);await this.f.run(o,()=>{this.e=o;let i=v(this.e,void 0,this.o);this.u.replaceSync(i);let n=`${this.o.CUSTOM_EVENT_NAME_PREFIX}-update`,s=new CustomEvent(n,{detail:this.e});this.dispatchEvent(s)})};resumeResize=()=>{this.f.resume()};save=()=>structuredClone(this.e);restorePhysics(t){this.o=Object.freeze({...this.o,...t})}savePhysics(){return this.o}relativeCoordinates=(t,e=!0)=>{(e||!this.a)&&(this.a={box:this.getBoundingClientRect(),style:getComputedStyle(this)});let o=this.a.box,i=this.a.style,n=parseFloat(i.paddingLeft),s=parseFloat(i.paddingTop),a=o.width-n-parseFloat(i.paddingRight),l=o.height-s-parseFloat(i.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,i]};realCoordinates=(t,e)=>{this.a||(this.a={box:this.getBoundingClientRect(),style:getComputedStyle(this)});let o=this.a.box,i=this.a.style,n;e&&(n=getComputedStyle(e));let s=H(t,o,i,n);return new DOMRect(o.left+s.x,o.top+s.y,s.width,s.height)};diffCoordinates=(t,e)=>{let[o,i,n]=this.relativeCoordinates(t,!1),s=(o-e.column)*n.width,a=(i-e.row)*n.height;return Math.sqrt(s**2+a**2)};create_overlay_host(){let t=this;return{get panel(){return t.e},get physics(){return t.o},get stylesheet(){return t.u},get presizeQueue(){return t.f},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,i]=this.relativeCoordinates(t,!1),n=L(e,o,this.e,{rect:i,size:this.o.GRID_DIVIDER_SIZE});if(n?.type==="horizontal"||n?.type==="vertical"){let s=w(this.e,n.path,void 0);await this.restore(s,!0)}};onPointerDown=t=>{if(!this.o.GRID_DIVIDER_CHECK_TARGET||t.target===this){let[e,o,i]=this.relativeCoordinates(t),n=this.o.GRID_DIVIDER_SIZE,s=L(e,o,this.e,{rect:i,size:n});s&&s.type!=="layout-path"&&(this.d=[s,e,o],this.setPointerCapture(t.pointerId),t.preventDefault())}};onPointerMove=async t=>{if(this.d){let[s,a]=this.relativeCoordinates(t,!1),[{path:l,type:y},h,c]=this.d,u=y==="horizontal"?h-s:c-a,d=w(this.e,l,u);await this.f.run(d,()=>{this.u.replaceSync(v(d,void 0,this.o))})}if(this.o.GRID_DIVIDER_CHECK_TARGET&&t.target!==this){this.l&&(this.l=!1,this.h.replaceSync(""));return}let[e,o,i]=this.relativeCoordinates(t,!1),n=L(e,o,this.e,{rect:i,size:this.o.GRID_DIVIDER_SIZE});n?.type==="vertical"?(this.h.replaceSync(":host{cursor:row-resize"),this.l=!0):n?.type==="horizontal"?(this.h.replaceSync(":host{cursor:col-resize"),this.l=!0):this.l&&(this.l=!1,this.h.replaceSync(""))};onPointerUp=async t=>{if(this.d){this.releasePointerCapture(t.pointerId);let[e,o]=this.relativeCoordinates(t,!1),[{path:i,type:n},s,a]=this.d,l=n==="horizontal"?s-e:a-o,y=w(this.e,i,l);await this.restore(y,!0),this.d=void 0}}};var tt=`
|
|
5
5
|
:host{box-sizing:border-box;flex-direction:column}
|
|
6
6
|
:host::part(titlebar){display:flex;height:24px;user-select:none;overflow:hidden}
|
|
7
7
|
:host::part(container){flex:1 1 auto}
|
|
@@ -9,8 +9,8 @@ var b={type:"split-panel",orientation:"horizontal",sizes:[],children:[]};var _=O
|
|
|
9
9
|
:host::part(close){align-self:stretch}
|
|
10
10
|
:host::slotted{flex:1 1 auto;}
|
|
11
11
|
:host regular-layout-tab{width:0px;}
|
|
12
|
-
`,
|
|
12
|
+
`,et=`
|
|
13
13
|
<div part="titlebar"></div>
|
|
14
|
-
<
|
|
15
|
-
`,
|
|
14
|
+
<div part="container"><slot></slot></div>
|
|
15
|
+
`,P=class extends HTMLElement{s;_;t;r;n=null;v=new WeakMap;connectedCallback(){this._??=new CSSStyleSheet,this._.replaceSync(tt),this.s??=this.attachShadow({mode:"open"}),this.s.adoptedStyleSheets=[this._],this.s.innerHTML=et,this.t=this.parentElement,this.r=this.s.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.t.addEventListener("regular-layout-update",this.drawTabs),this.t.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.t.removeEventListener("regular-layout-update",this.drawTabs),this.t.removeEventListener("regular-layout-before-update",this.drawTabs)}onPointerDown=t=>{if(t.target.part.contains("tab")){let o=this.t.calculateIntersect(t);o?(this.n={path:o},this.setPointerCapture(t.pointerId),t.preventDefault()):this.n=null}};onPointerMove=t=>{if(this.n){let e=this.t.savePhysics();if(!this.n.moved&&this.t.diffCoordinates(t,this.n.path)<=e.MIN_DRAG_DISTANCE)return;this.n.moved=!0,this.t.setOverlayState(t,this.n.path)}};onPointerUp=t=>{this.n?.moved&&this.t.clearOverlayState(t,this.n.path)};onPointerCancel=t=>{this.n?.moved&&this.t.clearOverlayState(null,this.n.path)};onPointerLost=t=>{this.releasePointerCapture(t.pointerId),this.n=null};drawTabs=t=>{let e=this.t.savePhysics().CHILD_ATTRIBUTE_NAME,o=this.getAttribute(e);if(!o)return;let i=t.detail,n=this.t.getPanel(o,i);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.t,n,a),this.r.appendChild(l),this.v.set(l,a)}else this.r.children[a].populate(this.t,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])}};var M=class extends HTMLElement{t;i;c;populate=(t,e,o)=>{if(this.i){if(o===e.selected!=(o===this.i?.selected)||this.i?.tabs[o]!==e.tabs[o]){let s=e.selected===o,a=e.tabs[o];this.children[0].textContent=a,s?(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 i=e.tabs[o],n=e.selected===o,s=n?"active-close close":"close";this.innerHTML=`<div part="title"></div><button part="${s}"></button>`,n?this.part.add("tab","active-tab"):this.part.add("tab"),this.addEventListener("pointerdown",this.onTabClick),this.children[0].textContent=i,this.children[1].addEventListener("pointerdown",this.onTabClose)}this.i=e,this.t=t,this.c=o};onTabClose=t=>{this.i!==void 0&&this.c!==void 0&&this.t?.removePanel(this.i.tabs[this.c])};onTabClick=t=>{if(this.i!==void 0&&this.c!==void 0&&this.c!==this.i.selected){let e=this.t?.save(),o=this.t?.getPanel(this.i.tabs[this.c],e);o&&e&&(o.selected=this.c,this.t?.restore(e))}}};customElements.define("regular-layout",T);customElements.define("regular-layout-frame",P);customElements.define("regular-layout-tab",M);export{T as RegularLayout,P as RegularLayoutFrame};
|
|
16
16
|
//# sourceMappingURL=index.js.map
|