regular-layout 0.2.0 → 0.2.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/dist/index.js +6 -6
- package/dist/index.js.map +3 -3
- package/dist/layout/calculate_edge.d.ts +2 -1
- package/dist/layout/calculate_intersect.d.ts +8 -2
- package/dist/layout/constants.d.ts +76 -38
- package/dist/layout/generate_grid.d.ts +4 -3
- package/dist/layout/generate_overlay.d.ts +1 -1
- package/dist/layout/redistribute_panel_sizes.d.ts +1 -1
- package/dist/layout/types.d.ts +3 -7
- package/dist/regular-layout-frame.d.ts +10 -3
- package/dist/regular-layout.d.ts +63 -12
- package/package.json +4 -2
- package/src/layout/calculate_edge.ts +26 -16
- package/src/layout/calculate_intersect.ts +11 -9
- package/src/layout/constants.ts +94 -38
- package/src/layout/generate_grid.ts +71 -27
- package/src/layout/generate_overlay.ts +5 -3
- package/src/layout/insert_child.ts +5 -5
- package/src/layout/redistribute_panel_sizes.ts +20 -9
- package/src/layout/remove_child.ts +7 -7
- package/src/layout/types.ts +3 -7
- package/src/regular-layout-frame.ts +53 -65
- package/src/regular-layout-tab.ts +5 -5
- package/src/regular-layout.ts +206 -114
- package/themes/lorax.css +2 -1
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
|
|
10
10
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
import type { Layout, LayoutPath } from "./layout/types.ts";
|
|
12
|
+
import type { LayoutPath } from "./layout/types.ts";
|
|
14
13
|
import type { RegularLayoutEvent } from "./extensions.ts";
|
|
15
14
|
import type { RegularLayout } from "./regular-layout.ts";
|
|
16
15
|
import type { RegularLayoutTab } from "./regular-layout-tab.ts";
|
|
@@ -30,6 +29,8 @@ const HTML_TEMPLATE = `
|
|
|
30
29
|
<slot part="container"></slot>
|
|
31
30
|
`;
|
|
32
31
|
|
|
32
|
+
type DragState = { moved?: boolean; path: LayoutPath };
|
|
33
|
+
|
|
33
34
|
/**
|
|
34
35
|
* A custom element that represents a draggable panel within a
|
|
35
36
|
* `<regular-layout>`.
|
|
@@ -56,29 +57,31 @@ const HTML_TEMPLATE = `
|
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
58
59
|
export class RegularLayoutFrame extends HTMLElement {
|
|
59
|
-
private _shadowRoot
|
|
60
|
-
private _container_sheet
|
|
60
|
+
private _shadowRoot!: ShadowRoot;
|
|
61
|
+
private _container_sheet!: CSSStyleSheet;
|
|
61
62
|
private _layout!: RegularLayout;
|
|
62
63
|
private _header!: HTMLElement;
|
|
63
|
-
private
|
|
64
|
-
private _drag_moved: boolean = false;
|
|
64
|
+
private _drag: DragState | null = null;
|
|
65
65
|
private _tab_to_index_map: WeakMap<RegularLayoutTab, number> = new WeakMap();
|
|
66
|
-
constructor() {
|
|
67
|
-
super();
|
|
68
|
-
this._container_sheet = new CSSStyleSheet();
|
|
69
|
-
this._container_sheet.replaceSync(CSS);
|
|
70
|
-
this._shadowRoot = this.attachShadow({ mode: "open" });
|
|
71
|
-
this._shadowRoot.adoptedStyleSheets = [this._container_sheet];
|
|
72
|
-
}
|
|
73
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Initializes this elements. Override this method and
|
|
69
|
+
* `disconnectedCallback` to modify how this subclass renders the Shadow
|
|
70
|
+
* DOM and registers events.
|
|
71
|
+
*/
|
|
74
72
|
connectedCallback() {
|
|
73
|
+
this._container_sheet ??= new CSSStyleSheet();
|
|
74
|
+
this._container_sheet.replaceSync(CSS);
|
|
75
|
+
this._shadowRoot ??= this.attachShadow({ mode: "open" });
|
|
76
|
+
this._shadowRoot.adoptedStyleSheets = [this._container_sheet];
|
|
75
77
|
this._shadowRoot.innerHTML = HTML_TEMPLATE;
|
|
76
78
|
this._layout = this.parentElement as RegularLayout;
|
|
77
79
|
this._header = this._shadowRoot.children[0] as HTMLElement;
|
|
78
80
|
this._header.addEventListener("pointerdown", this.onPointerDown);
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
81
|
+
this.addEventListener("pointermove", this.onPointerMove);
|
|
82
|
+
this.addEventListener("pointerup", this.onPointerUp);
|
|
83
|
+
this.addEventListener("pointercancel", this.onPointerCancel);
|
|
84
|
+
this.addEventListener("lostpointercapture", this.onPointerLost);
|
|
82
85
|
this._layout.addEventListener("regular-layout-update", this.drawTabs);
|
|
83
86
|
this._layout.addEventListener(
|
|
84
87
|
"regular-layout-before-update",
|
|
@@ -86,11 +89,15 @@ export class RegularLayoutFrame extends HTMLElement {
|
|
|
86
89
|
);
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Destroys this element.
|
|
94
|
+
*/
|
|
89
95
|
disconnectedCallback() {
|
|
90
96
|
this._header.removeEventListener("pointerdown", this.onPointerDown);
|
|
91
|
-
this.
|
|
92
|
-
this.
|
|
93
|
-
this.
|
|
97
|
+
this.removeEventListener("pointermove", this.onPointerMove);
|
|
98
|
+
this.removeEventListener("pointerup", this.onPointerUp);
|
|
99
|
+
this.removeEventListener("pointercancel", this.onPointerUp);
|
|
100
|
+
this.removeEventListener("lostpointercapture", this.onPointerLost);
|
|
94
101
|
this._layout.removeEventListener("regular-layout-update", this.drawTabs);
|
|
95
102
|
this._layout.removeEventListener(
|
|
96
103
|
"regular-layout-before-update",
|
|
@@ -101,71 +108,52 @@ export class RegularLayoutFrame extends HTMLElement {
|
|
|
101
108
|
private onPointerDown = (event: PointerEvent): void => {
|
|
102
109
|
const elem = event.target as RegularLayoutTab;
|
|
103
110
|
if (elem.part.contains("tab")) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (this._drag_state) {
|
|
110
|
-
this._header.setPointerCapture(event.pointerId);
|
|
111
|
+
const path = this._layout.calculateIntersect(event);
|
|
112
|
+
if (path) {
|
|
113
|
+
this._drag = { path };
|
|
114
|
+
this.setPointerCapture(event.pointerId);
|
|
111
115
|
event.preventDefault();
|
|
116
|
+
} else {
|
|
117
|
+
this._drag = null;
|
|
112
118
|
}
|
|
113
119
|
}
|
|
114
120
|
};
|
|
115
121
|
|
|
116
122
|
private onPointerMove = (event: PointerEvent): void => {
|
|
117
|
-
if (this.
|
|
118
|
-
|
|
119
|
-
if (!this.
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const dx = (current_col - this._drag_state.column) * box.width;
|
|
124
|
-
const dy = (current_row - this._drag_state.row) * box.height;
|
|
125
|
-
if (Math.sqrt(dx * dx + dy * dy) <= MIN_DRAG_DISTANCE) {
|
|
123
|
+
if (this._drag) {
|
|
124
|
+
const physics = this._layout.savePhysics();
|
|
125
|
+
if (!this._drag.moved) {
|
|
126
|
+
const diff = this._layout.diffCoordinates(event, this._drag.path);
|
|
127
|
+
if (diff <= physics.MIN_DRAG_DISTANCE) {
|
|
126
128
|
return;
|
|
127
129
|
}
|
|
128
130
|
}
|
|
129
131
|
|
|
130
|
-
this.
|
|
131
|
-
this._layout.setOverlayState(
|
|
132
|
-
event.clientX,
|
|
133
|
-
event.clientY,
|
|
134
|
-
this._drag_state,
|
|
135
|
-
OVERLAY_CLASSNAME,
|
|
136
|
-
);
|
|
132
|
+
this._drag.moved = true;
|
|
133
|
+
this._layout.setOverlayState(event, this._drag.path);
|
|
137
134
|
}
|
|
138
135
|
};
|
|
139
136
|
|
|
140
137
|
private onPointerUp = (event: PointerEvent): void => {
|
|
141
|
-
if (this.
|
|
142
|
-
this._layout.clearOverlayState(
|
|
143
|
-
event.clientX,
|
|
144
|
-
event.clientY,
|
|
145
|
-
this._drag_state,
|
|
146
|
-
OVERLAY_CLASSNAME,
|
|
147
|
-
);
|
|
138
|
+
if (this._drag?.moved) {
|
|
139
|
+
this._layout.clearOverlayState(event, this._drag.path);
|
|
148
140
|
}
|
|
149
|
-
|
|
150
|
-
// TODO This may be handled by `onPointerLost`, not sure if this is
|
|
151
|
-
// browser-specific behavior ...
|
|
152
|
-
this._header.releasePointerCapture(event.pointerId);
|
|
153
|
-
this._drag_state = null;
|
|
154
|
-
this._drag_moved = false;
|
|
155
141
|
};
|
|
156
142
|
|
|
157
|
-
private
|
|
158
|
-
if (this.
|
|
159
|
-
this._layout.clearOverlayState(
|
|
143
|
+
private onPointerCancel = (_: PointerEvent): void => {
|
|
144
|
+
if (this._drag?.moved) {
|
|
145
|
+
this._layout.clearOverlayState(null, this._drag.path);
|
|
160
146
|
}
|
|
147
|
+
};
|
|
161
148
|
|
|
162
|
-
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
149
|
+
private onPointerLost = (event: PointerEvent): void => {
|
|
150
|
+
this.releasePointerCapture(event.pointerId);
|
|
151
|
+
this._drag = null;
|
|
165
152
|
};
|
|
166
153
|
|
|
167
154
|
private drawTabs = (event: RegularLayoutEvent) => {
|
|
168
|
-
const
|
|
155
|
+
const attr = this._layout.savePhysics().CHILD_ATTRIBUTE_NAME;
|
|
156
|
+
const slot = this.getAttribute(attr);
|
|
169
157
|
if (!slot) {
|
|
170
158
|
return;
|
|
171
159
|
}
|
|
@@ -175,12 +163,12 @@ export class RegularLayoutFrame extends HTMLElement {
|
|
|
175
163
|
if (!new_tab_panel) {
|
|
176
164
|
new_tab_panel = {
|
|
177
165
|
type: "child-panel",
|
|
178
|
-
|
|
166
|
+
tabs: [slot],
|
|
179
167
|
selected: 0,
|
|
180
168
|
};
|
|
181
169
|
}
|
|
182
170
|
|
|
183
|
-
for (let i = 0; i < new_tab_panel.
|
|
171
|
+
for (let i = 0; i < new_tab_panel.tabs.length; i++) {
|
|
184
172
|
if (i >= this._header.children.length) {
|
|
185
173
|
const new_tab = document.createElement("regular-layout-tab");
|
|
186
174
|
new_tab.populate(this._layout, new_tab_panel, i);
|
|
@@ -192,7 +180,7 @@ export class RegularLayoutFrame extends HTMLElement {
|
|
|
192
180
|
}
|
|
193
181
|
}
|
|
194
182
|
|
|
195
|
-
const last_index = new_tab_panel.
|
|
183
|
+
const last_index = new_tab_panel.tabs.length;
|
|
196
184
|
for (let j = this._header.children.length - 1; j >= last_index; j--) {
|
|
197
185
|
this._header.removeChild(this._header.children[j]);
|
|
198
186
|
}
|
|
@@ -40,11 +40,11 @@ export class RegularLayoutTab extends HTMLElement {
|
|
|
40
40
|
(index === this._tab_panel?.selected);
|
|
41
41
|
|
|
42
42
|
const index_changed =
|
|
43
|
-
tab_changed || this._tab_panel?.
|
|
43
|
+
tab_changed || this._tab_panel?.tabs[index] !== tab_panel.tabs[index];
|
|
44
44
|
|
|
45
45
|
if (index_changed) {
|
|
46
46
|
const selected = tab_panel.selected === index;
|
|
47
|
-
const slot = tab_panel.
|
|
47
|
+
const slot = tab_panel.tabs[index];
|
|
48
48
|
this.children[0].textContent = slot;
|
|
49
49
|
|
|
50
50
|
if (selected) {
|
|
@@ -56,7 +56,7 @@ export class RegularLayoutTab extends HTMLElement {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
} else {
|
|
59
|
-
const slot = tab_panel.
|
|
59
|
+
const slot = tab_panel.tabs[index];
|
|
60
60
|
const selected = tab_panel.selected === index;
|
|
61
61
|
const parts = selected ? "active-close close" : "close";
|
|
62
62
|
this.innerHTML = `<div part="title"></div><button part="${parts}"></button>`;
|
|
@@ -78,7 +78,7 @@ export class RegularLayoutTab extends HTMLElement {
|
|
|
78
78
|
|
|
79
79
|
private onTabClose = (_: Event) => {
|
|
80
80
|
if (this._tab_panel !== undefined && this._index !== undefined) {
|
|
81
|
-
this._layout?.removePanel(this._tab_panel.
|
|
81
|
+
this._layout?.removePanel(this._tab_panel.tabs[this._index]);
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
|
|
@@ -90,7 +90,7 @@ export class RegularLayoutTab extends HTMLElement {
|
|
|
90
90
|
) {
|
|
91
91
|
const new_layout = this._layout?.save();
|
|
92
92
|
const new_tab_panel = this._layout?.getPanel(
|
|
93
|
-
this._tab_panel.
|
|
93
|
+
this._tab_panel.tabs[this._index],
|
|
94
94
|
new_layout,
|
|
95
95
|
);
|
|
96
96
|
|