@reliability-design/web 1.4.6 → 1.4.8
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/CHANGELOG.md +246 -49
- package/dist/components/rel-accordion/README.md +133 -132
- package/dist/components/rel-alert/README.md +145 -141
- package/dist/components/rel-autocomplete/README.md +172 -61
- package/dist/components/rel-avatar/README.md +118 -130
- package/dist/components/rel-badge/README.md +97 -93
- package/dist/components/rel-breadcrumb/README.md +96 -102
- package/dist/components/rel-button/README.md +190 -130
- package/dist/components/rel-calendar/README.md +109 -109
- package/dist/components/rel-card/README.md +75 -94
- package/dist/components/rel-cardmedia/README.md +100 -127
- package/dist/components/rel-carousel/README.md +186 -166
- package/dist/components/rel-checkbox/README.md +96 -75
- package/dist/components/rel-chip/README.md +138 -121
- package/dist/components/rel-container/README.md +107 -99
- package/dist/components/rel-date-picker/README.md +200 -289
- package/dist/components/rel-divider/README.md +88 -100
- package/dist/components/rel-drawer/README.md +187 -200
- package/dist/components/rel-kbd/README.md +141 -151
- package/dist/components/rel-layout/README.md +34 -0
- package/dist/components/rel-menu/README.md +180 -151
- package/dist/components/rel-menubar/README.md +218 -329
- package/dist/components/rel-otp/README.md +171 -440
- package/dist/components/rel-pagination/README.md +100 -424
- package/dist/components/rel-popover/README.md +203 -568
- package/dist/components/rel-progress/README.md +88 -110
- package/dist/components/rel-radio/README.md +131 -138
- package/dist/components/rel-range-picker/README.md +165 -0
- package/dist/components/rel-resizable/README.md +199 -140
- package/dist/components/rel-segmented-button/README.md +156 -141
- package/dist/components/rel-select/README.md +156 -93
- package/dist/components/rel-sheet/README.md +168 -224
- package/dist/components/rel-skeleton/README.md +104 -0
- package/dist/components/rel-slider/README.md +131 -135
- package/dist/components/rel-snackbar/README.md +168 -134
- package/dist/components/rel-stepper/README.md +162 -160
- package/dist/components/rel-switch/README.md +117 -102
- package/dist/components/rel-tab/README.md +173 -163
- package/dist/components/rel-textfield/README.md +176 -69
- package/dist/components/rel-time-picker/README.md +122 -157
- package/dist/components/rel-toast/README.md +165 -148
- package/dist/components/rel-tooltip/README.md +119 -111
- package/dist/components/rel-upload/README.md +220 -0
- package/dist/index.d.mts +1726 -447
- package/dist/index.d.ts +1726 -447
- package/dist/index.js +13715 -10870
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14018 -11163
- package/dist/index.mjs.map +1 -1
- package/dist/styles/focus-ring.ts +84 -0
- package/dist/styles/vars.css +892 -866
- package/dist/{vars-XNMTSRVN.css → vars-DXX6QOAG.css} +892 -866
- package/package.json +3 -2
- package/dist/components/rel-accordion/rel-accordion.ts +0 -336
- package/dist/components/rel-alert/rel-alert.ts +0 -305
- package/dist/components/rel-autocomplete/rel-autocomplete.ts +0 -720
- package/dist/components/rel-avatar/rel-avatar.ts +0 -142
- package/dist/components/rel-badge/rel-badge.ts +0 -175
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +0 -106
- package/dist/components/rel-button/rel-button.ts +0 -560
- package/dist/components/rel-calendar/index.ts +0 -1
- package/dist/components/rel-calendar/rel-calendar.ts +0 -565
- package/dist/components/rel-card/rel-card.ts +0 -88
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +0 -88
- package/dist/components/rel-carousel/index.ts +0 -1
- package/dist/components/rel-carousel/rel-carousel.ts +0 -723
- package/dist/components/rel-chart/README.md +0 -286
- package/dist/components/rel-chart/index.ts +0 -1
- package/dist/components/rel-chart/rel-chart.ts +0 -754
- package/dist/components/rel-checkbox/rel-checkbox.ts +0 -382
- package/dist/components/rel-chip/rel-chip.ts +0 -483
- package/dist/components/rel-container/rel-container.ts +0 -95
- package/dist/components/rel-date-picker/date-format.test.ts +0 -43
- package/dist/components/rel-date-picker/date-format.ts +0 -47
- package/dist/components/rel-date-picker/date-parse.test.ts +0 -116
- package/dist/components/rel-date-picker/date-parse.ts +0 -178
- package/dist/components/rel-date-picker/index.ts +0 -1
- package/dist/components/rel-date-picker/rel-date-picker.ts +0 -1676
- package/dist/components/rel-divider/rel-divider.ts +0 -54
- package/dist/components/rel-drawer/index.ts +0 -1
- package/dist/components/rel-drawer/rel-drawer-footer.ts +0 -27
- package/dist/components/rel-drawer/rel-drawer.ts +0 -607
- package/dist/components/rel-kbd/rel-kbd.ts +0 -188
- package/dist/components/rel-layout/rel-layout.ts +0 -49
- package/dist/components/rel-menu/rel-menu.ts +0 -541
- package/dist/components/rel-menubar/index.ts +0 -2
- package/dist/components/rel-menubar/rel-menubar-menu.css +0 -3
- package/dist/components/rel-menubar/rel-menubar-menu.ts +0 -17
- package/dist/components/rel-menubar/rel-menubar.ts +0 -777
- package/dist/components/rel-nav-menu/README.md +0 -289
- package/dist/components/rel-nav-menu/index.ts +0 -3
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +0 -243
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +0 -72
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +0 -270
- package/dist/components/rel-navbar/README.md +0 -126
- package/dist/components/rel-navbar/rel-navbar.ts +0 -105
- package/dist/components/rel-otp/index.ts +0 -1
- package/dist/components/rel-otp/rel-otp.ts +0 -527
- package/dist/components/rel-pagination/index.ts +0 -1
- package/dist/components/rel-pagination/rel-pagination.ts +0 -522
- package/dist/components/rel-popover/index.ts +0 -2
- package/dist/components/rel-popover/rel-popover-content.ts +0 -81
- package/dist/components/rel-popover/rel-popover.ts +0 -475
- package/dist/components/rel-progress/rel-progress.ts +0 -234
- package/dist/components/rel-radio/rel-radio.ts +0 -481
- package/dist/components/rel-range-picker/rel-range-picker.ts +0 -1688
- package/dist/components/rel-resizable/index.ts +0 -3
- package/dist/components/rel-resizable/rel-resizable-group.ts +0 -405
- package/dist/components/rel-resizable/rel-resizable-handle.ts +0 -150
- package/dist/components/rel-resizable/rel-resizable-panel.ts +0 -58
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +0 -217
- package/dist/components/rel-select/rel-select.ts +0 -1416
- package/dist/components/rel-sheet/rel-sheet.ts +0 -610
- package/dist/components/rel-sidebar/README.md +0 -209
- package/dist/components/rel-sidebar/rel-sidebar.ts +0 -1191
- package/dist/components/rel-skeleton/rel-skeleton.ts +0 -143
- package/dist/components/rel-slider/rel-slider.ts +0 -673
- package/dist/components/rel-snackbar/rel-snackbar.ts +0 -329
- package/dist/components/rel-stepper/rel-stepper.ts +0 -567
- package/dist/components/rel-switch/rel-switch.ts +0 -199
- package/dist/components/rel-tab/rel-tab.ts +0 -264
- package/dist/components/rel-table/README.md +0 -178
- package/dist/components/rel-table/rel-table-body.ts +0 -22
- package/dist/components/rel-table/rel-table-caption.ts +0 -30
- package/dist/components/rel-table/rel-table-cell.ts +0 -43
- package/dist/components/rel-table/rel-table-footer.ts +0 -24
- package/dist/components/rel-table/rel-table-head.ts +0 -47
- package/dist/components/rel-table/rel-table-header.ts +0 -22
- package/dist/components/rel-table/rel-table-row.ts +0 -37
- package/dist/components/rel-table/rel-table.ts +0 -62
- package/dist/components/rel-textfield/rel-textfield.ts +0 -1054
- package/dist/components/rel-time-picker/rel-time-picker.ts +0 -1482
- package/dist/components/rel-time-picker/time-parse.test.ts +0 -67
- package/dist/components/rel-time-picker/time-parse.ts +0 -85
- package/dist/components/rel-toast/rel-toast.ts +0 -206
- package/dist/components/rel-tooltip/rel-tooltip.ts +0 -193
- package/dist/components/rel-topbar/rel-topbar-actions.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-brand.ts +0 -54
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +0 -69
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +0 -31
- package/dist/components/rel-topbar/rel-topbar-item.ts +0 -324
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar-profile.ts +0 -243
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +0 -27
- package/dist/components/rel-topbar/rel-topbar.ts +0 -446
- package/dist/components/rel-upload/UPLOAD-DESIGN-CHANGES.md +0 -134
- package/dist/components/rel-upload/rel-upload-actions.ts +0 -163
- package/dist/components/rel-upload/rel-upload.ts +0 -968
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
import type { RelResizablePanel } from "./rel-resizable-panel";
|
|
4
|
-
import type { RelResizableHandle } from "./rel-resizable-handle";
|
|
5
|
-
|
|
6
|
-
@customElement("rel-resizable-group")
|
|
7
|
-
export class RelResizableGroup extends LitElement {
|
|
8
|
-
/* =======================
|
|
9
|
-
* PUBLIC API
|
|
10
|
-
* ======================= */
|
|
11
|
-
|
|
12
|
-
// reflect: CSS targets :host([direction="…"]) for flex-direction — without
|
|
13
|
-
// reflection, setting the property in JS leaves the layout unchanged.
|
|
14
|
-
@property({ type: String, reflect: true }) direction: "horizontal" | "vertical" = "horizontal";
|
|
15
|
-
|
|
16
|
-
/* =======================
|
|
17
|
-
* INTERNAL STATE
|
|
18
|
-
* ======================= */
|
|
19
|
-
|
|
20
|
-
private panels: RelResizablePanel[] = [];
|
|
21
|
-
private handles: RelResizableHandle[] = [];
|
|
22
|
-
private isDragging = false;
|
|
23
|
-
private activeHandleIndex = -1;
|
|
24
|
-
private startPointerPos = 0;
|
|
25
|
-
private startSizes: number[] = [];
|
|
26
|
-
|
|
27
|
-
/* =======================
|
|
28
|
-
* STYLES
|
|
29
|
-
* ======================= */
|
|
30
|
-
|
|
31
|
-
static styles = css`
|
|
32
|
-
:host {
|
|
33
|
-
color: var(--rel-text-default);
|
|
34
|
-
display: flex;
|
|
35
|
-
width: 100%;
|
|
36
|
-
height: 100%;
|
|
37
|
-
position: relative;
|
|
38
|
-
box-sizing: border-box;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
:host([direction="horizontal"]) {
|
|
42
|
-
flex-direction: row;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
:host([direction="vertical"]) {
|
|
46
|
-
flex-direction: column;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
::slotted(rel-resizable-panel) {
|
|
50
|
-
flex-shrink: 0;
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
/* =======================
|
|
55
|
-
* LIFECYCLE
|
|
56
|
-
* ======================= */
|
|
57
|
-
|
|
58
|
-
connectedCallback() {
|
|
59
|
-
super.connectedCallback();
|
|
60
|
-
this.addEventListener("pointerdown", this.onPointerDown);
|
|
61
|
-
this.addEventListener("keydown", this.onKeyDown);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
disconnectedCallback() {
|
|
65
|
-
super.disconnectedCallback();
|
|
66
|
-
this.removeEventListener("pointerdown", this.onPointerDown);
|
|
67
|
-
this.removeEventListener("keydown", this.onKeyDown);
|
|
68
|
-
this.removeGlobalListeners();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
firstUpdated() {
|
|
72
|
-
this.initializeLayout();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* =======================
|
|
76
|
-
* INITIALIZATION
|
|
77
|
-
* ======================= */
|
|
78
|
-
|
|
79
|
-
private initializeLayout() {
|
|
80
|
-
// Query light DOM for panels and handles
|
|
81
|
-
this.panels = Array.from(
|
|
82
|
-
this.querySelectorAll(":scope > rel-resizable-panel")
|
|
83
|
-
) as RelResizablePanel[];
|
|
84
|
-
this.handles = Array.from(
|
|
85
|
-
this.querySelectorAll(":scope > rel-resizable-handle")
|
|
86
|
-
) as RelResizableHandle[];
|
|
87
|
-
|
|
88
|
-
// Set handle indices and orientations
|
|
89
|
-
this.handles.forEach((handle, idx) => {
|
|
90
|
-
handle.handleIndex = idx;
|
|
91
|
-
handle.orientation = this.direction;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Calculate initial sizes
|
|
95
|
-
const sizes = this.calculateInitialSizes();
|
|
96
|
-
this.applySizes(sizes);
|
|
97
|
-
|
|
98
|
-
// Initialize each handle's aria-valuenow — before this, AT had no value
|
|
99
|
-
// to announce until the first drag/keypress.
|
|
100
|
-
this.handles.forEach((handle, idx) => {
|
|
101
|
-
const left = sizes[idx];
|
|
102
|
-
const right = sizes[idx + 1];
|
|
103
|
-
if (left !== undefined && right !== undefined && left + right > 0) {
|
|
104
|
-
handle.updateAriaValue((left / (left + right)) * 100);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private calculateInitialSizes(): number[] {
|
|
110
|
-
const sizes: number[] = [];
|
|
111
|
-
let specifiedTotal = 0;
|
|
112
|
-
let unspecifiedCount = 0;
|
|
113
|
-
|
|
114
|
-
// First pass: collect specified sizes
|
|
115
|
-
this.panels.forEach((panel) => {
|
|
116
|
-
if (panel.defaultSize !== undefined) {
|
|
117
|
-
sizes.push(panel.defaultSize);
|
|
118
|
-
specifiedTotal += panel.defaultSize;
|
|
119
|
-
} else {
|
|
120
|
-
sizes.push(0);
|
|
121
|
-
unspecifiedCount++;
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Second pass: distribute remaining space to unspecified panels
|
|
126
|
-
if (unspecifiedCount > 0) {
|
|
127
|
-
const remaining = Math.max(0, 100 - specifiedTotal);
|
|
128
|
-
const perPanel = remaining / unspecifiedCount;
|
|
129
|
-
sizes.forEach((size, idx) => {
|
|
130
|
-
if (size === 0) {
|
|
131
|
-
sizes[idx] = perPanel;
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Normalize to 100%
|
|
137
|
-
const total = sizes.reduce((sum, s) => sum + s, 0);
|
|
138
|
-
if (total > 0) {
|
|
139
|
-
return sizes.map((s) => (s / total) * 100);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Fallback: equal distribution
|
|
143
|
-
return this.panels.map(() => 100 / this.panels.length);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* =======================
|
|
147
|
-
* POINTER HANDLING
|
|
148
|
-
* ======================= */
|
|
149
|
-
|
|
150
|
-
private onPointerDown = (e: PointerEvent) => {
|
|
151
|
-
// Find the handle anywhere in the composed path — a pointerdown on the
|
|
152
|
-
// visible `.grabber` (which lives inside the handle's shadow DOM) makes
|
|
153
|
-
// composedPath()[0] a <div>, not the handle, so indexing [0] would abort
|
|
154
|
-
// the drag whenever the user grabs the obvious target.
|
|
155
|
-
const handle = e
|
|
156
|
-
.composedPath()
|
|
157
|
-
.find(
|
|
158
|
-
(el): el is RelResizableHandle =>
|
|
159
|
-
el instanceof HTMLElement && el.tagName === "REL-RESIZABLE-HANDLE"
|
|
160
|
-
);
|
|
161
|
-
if (!handle) return;
|
|
162
|
-
|
|
163
|
-
const handleIndex = this.handles.indexOf(handle);
|
|
164
|
-
if (handleIndex === -1) return;
|
|
165
|
-
|
|
166
|
-
e.preventDefault();
|
|
167
|
-
this.startDrag(handleIndex, e);
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
private startDrag(handleIndex: number, e: PointerEvent) {
|
|
171
|
-
this.isDragging = true;
|
|
172
|
-
this.activeHandleIndex = handleIndex;
|
|
173
|
-
this.startPointerPos = this.direction === "horizontal" ? e.clientX : e.clientY;
|
|
174
|
-
this.startSizes = this.panels.map((p) => p.currentSize);
|
|
175
|
-
|
|
176
|
-
const handle = this.handles[handleIndex];
|
|
177
|
-
handle.setAttribute("data-dragging", "");
|
|
178
|
-
|
|
179
|
-
this.addGlobalListeners();
|
|
180
|
-
|
|
181
|
-
// Capture pointer
|
|
182
|
-
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private onPointerMove = (e: PointerEvent) => {
|
|
186
|
-
if (!this.isDragging || this.activeHandleIndex === -1) return;
|
|
187
|
-
|
|
188
|
-
e.preventDefault();
|
|
189
|
-
|
|
190
|
-
const currentPos = this.direction === "horizontal" ? e.clientX : e.clientY;
|
|
191
|
-
const delta = currentPos - this.startPointerPos;
|
|
192
|
-
|
|
193
|
-
this.applyDragResize(delta);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
private onPointerUp = (e: PointerEvent) => {
|
|
197
|
-
if (!this.isDragging) return;
|
|
198
|
-
|
|
199
|
-
e.preventDefault();
|
|
200
|
-
|
|
201
|
-
const handle = this.handles[this.activeHandleIndex];
|
|
202
|
-
if (handle) {
|
|
203
|
-
handle.removeAttribute("data-dragging");
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
this.isDragging = false;
|
|
207
|
-
this.activeHandleIndex = -1;
|
|
208
|
-
|
|
209
|
-
this.removeGlobalListeners();
|
|
210
|
-
|
|
211
|
-
// Dispatch resize-end event
|
|
212
|
-
this.dispatchResizeEvent("rel-resize-end");
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
private applyDragResize(deltaPixels: number) {
|
|
216
|
-
const rect = this.getBoundingClientRect();
|
|
217
|
-
const totalSize = this.direction === "horizontal" ? rect.width : rect.height;
|
|
218
|
-
const deltaPercent = (deltaPixels / totalSize) * 100;
|
|
219
|
-
|
|
220
|
-
const leftIdx = this.activeHandleIndex;
|
|
221
|
-
const rightIdx = this.activeHandleIndex + 1;
|
|
222
|
-
|
|
223
|
-
if (leftIdx < 0 || rightIdx >= this.panels.length) return;
|
|
224
|
-
|
|
225
|
-
const leftPanel = this.panels[leftIdx];
|
|
226
|
-
const rightPanel = this.panels[rightIdx];
|
|
227
|
-
|
|
228
|
-
let newLeftSize = this.startSizes[leftIdx] + deltaPercent;
|
|
229
|
-
let newRightSize = this.startSizes[rightIdx] - deltaPercent;
|
|
230
|
-
|
|
231
|
-
// Clamp to min/max
|
|
232
|
-
newLeftSize = Math.max(leftPanel.minSize, Math.min(leftPanel.maxSize, newLeftSize));
|
|
233
|
-
newRightSize = Math.max(rightPanel.minSize, Math.min(rightPanel.maxSize, newRightSize));
|
|
234
|
-
|
|
235
|
-
// Ensure total is preserved
|
|
236
|
-
const pairTotal = this.startSizes[leftIdx] + this.startSizes[rightIdx];
|
|
237
|
-
const adjustedTotal = newLeftSize + newRightSize;
|
|
238
|
-
if (adjustedTotal !== pairTotal) {
|
|
239
|
-
const ratio = pairTotal / adjustedTotal;
|
|
240
|
-
newLeftSize *= ratio;
|
|
241
|
-
newRightSize *= ratio;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Update sizes
|
|
245
|
-
const newSizes = [...this.startSizes];
|
|
246
|
-
newSizes[leftIdx] = newLeftSize;
|
|
247
|
-
newSizes[rightIdx] = newRightSize;
|
|
248
|
-
|
|
249
|
-
this.applySizes(newSizes);
|
|
250
|
-
|
|
251
|
-
// Update handle aria value
|
|
252
|
-
const handle = this.handles[this.activeHandleIndex];
|
|
253
|
-
if (handle) {
|
|
254
|
-
const splitPercent = (newLeftSize / pairTotal) * 100;
|
|
255
|
-
handle.updateAriaValue(splitPercent);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Dispatch resize event
|
|
259
|
-
this.dispatchResizeEvent("rel-resize");
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/* =======================
|
|
263
|
-
* KEYBOARD HANDLING
|
|
264
|
-
* ======================= */
|
|
265
|
-
|
|
266
|
-
private onKeyDown = (e: KeyboardEvent) => {
|
|
267
|
-
const target = e.composedPath()[0] as HTMLElement;
|
|
268
|
-
if (target.tagName !== "REL-RESIZABLE-HANDLE") return;
|
|
269
|
-
|
|
270
|
-
const handle = target as RelResizableHandle;
|
|
271
|
-
const handleIndex = this.handles.indexOf(handle);
|
|
272
|
-
if (handleIndex === -1) return;
|
|
273
|
-
|
|
274
|
-
const isHorizontal = this.direction === "horizontal";
|
|
275
|
-
const step = e.shiftKey ? 5 : 2;
|
|
276
|
-
let applied = false;
|
|
277
|
-
|
|
278
|
-
if (isHorizontal && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
|
|
279
|
-
e.preventDefault();
|
|
280
|
-
const delta = e.key === "ArrowLeft" ? -step : step;
|
|
281
|
-
this.applyKeyboardResize(handleIndex, delta);
|
|
282
|
-
applied = true;
|
|
283
|
-
} else if (!isHorizontal && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
|
|
284
|
-
e.preventDefault();
|
|
285
|
-
const delta = e.key === "ArrowUp" ? -step : step;
|
|
286
|
-
this.applyKeyboardResize(handleIndex, delta);
|
|
287
|
-
applied = true;
|
|
288
|
-
} else if (e.key === "Home" || e.key === "End") {
|
|
289
|
-
// APG window-splitter: Home collapses the leading panel to its min,
|
|
290
|
-
// End grows it to its max (both still clamped by the neighbor).
|
|
291
|
-
const leftPanel = this.panels[handleIndex];
|
|
292
|
-
if (leftPanel && handleIndex + 1 < this.panels.length) {
|
|
293
|
-
e.preventDefault();
|
|
294
|
-
const target = e.key === "Home" ? leftPanel.minSize : leftPanel.maxSize;
|
|
295
|
-
this.applyKeyboardResize(handleIndex, target - leftPanel.currentSize);
|
|
296
|
-
applied = true;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (applied) {
|
|
301
|
-
this.dispatchResizeEvent("rel-resize-end");
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
private applyKeyboardResize(handleIndex: number, deltaPercent: number) {
|
|
306
|
-
const leftIdx = handleIndex;
|
|
307
|
-
const rightIdx = handleIndex + 1;
|
|
308
|
-
|
|
309
|
-
if (leftIdx < 0 || rightIdx >= this.panels.length) return;
|
|
310
|
-
|
|
311
|
-
const leftPanel = this.panels[leftIdx];
|
|
312
|
-
const rightPanel = this.panels[rightIdx];
|
|
313
|
-
const currentSizes = this.panels.map((p) => p.currentSize);
|
|
314
|
-
|
|
315
|
-
let newLeftSize = currentSizes[leftIdx] + deltaPercent;
|
|
316
|
-
let newRightSize = currentSizes[rightIdx] - deltaPercent;
|
|
317
|
-
|
|
318
|
-
// Clamp to min/max
|
|
319
|
-
newLeftSize = Math.max(leftPanel.minSize, Math.min(leftPanel.maxSize, newLeftSize));
|
|
320
|
-
newRightSize = Math.max(rightPanel.minSize, Math.min(rightPanel.maxSize, newRightSize));
|
|
321
|
-
|
|
322
|
-
// Ensure total is preserved
|
|
323
|
-
const pairTotal = currentSizes[leftIdx] + currentSizes[rightIdx];
|
|
324
|
-
const adjustedTotal = newLeftSize + newRightSize;
|
|
325
|
-
if (adjustedTotal !== pairTotal) {
|
|
326
|
-
const ratio = pairTotal / adjustedTotal;
|
|
327
|
-
newLeftSize *= ratio;
|
|
328
|
-
newRightSize *= ratio;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Update sizes
|
|
332
|
-
const newSizes = [...currentSizes];
|
|
333
|
-
newSizes[leftIdx] = newLeftSize;
|
|
334
|
-
newSizes[rightIdx] = newRightSize;
|
|
335
|
-
|
|
336
|
-
this.applySizes(newSizes);
|
|
337
|
-
|
|
338
|
-
// Update handle aria value
|
|
339
|
-
const handle = this.handles[handleIndex];
|
|
340
|
-
if (handle) {
|
|
341
|
-
const splitPercent = (newLeftSize / pairTotal) * 100;
|
|
342
|
-
handle.updateAriaValue(splitPercent);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/* =======================
|
|
347
|
-
* SIZE APPLICATION
|
|
348
|
-
* ======================= */
|
|
349
|
-
|
|
350
|
-
private applySizes(sizes: number[]) {
|
|
351
|
-
this.panels.forEach((panel, idx) => {
|
|
352
|
-
const size = sizes[idx] || 0;
|
|
353
|
-
panel.currentSize = size;
|
|
354
|
-
panel.style.flexBasis = `${size}%`;
|
|
355
|
-
panel.style.flexGrow = "0";
|
|
356
|
-
panel.style.flexShrink = "0";
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/* =======================
|
|
361
|
-
* EVENTS
|
|
362
|
-
* ======================= */
|
|
363
|
-
|
|
364
|
-
private dispatchResizeEvent(eventName: string) {
|
|
365
|
-
const sizes = this.panels.map((p) => p.currentSize);
|
|
366
|
-
this.dispatchEvent(
|
|
367
|
-
new CustomEvent(eventName, {
|
|
368
|
-
detail: {
|
|
369
|
-
direction: this.direction,
|
|
370
|
-
sizes,
|
|
371
|
-
},
|
|
372
|
-
bubbles: true,
|
|
373
|
-
composed: true,
|
|
374
|
-
})
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/* =======================
|
|
379
|
-
* GLOBAL LISTENERS
|
|
380
|
-
* ======================= */
|
|
381
|
-
|
|
382
|
-
private addGlobalListeners() {
|
|
383
|
-
document.addEventListener("pointermove", this.onPointerMove);
|
|
384
|
-
document.addEventListener("pointerup", this.onPointerUp);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
private removeGlobalListeners() {
|
|
388
|
-
document.removeEventListener("pointermove", this.onPointerMove);
|
|
389
|
-
document.removeEventListener("pointerup", this.onPointerUp);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/* =======================
|
|
393
|
-
* RENDER
|
|
394
|
-
* ======================= */
|
|
395
|
-
|
|
396
|
-
render() {
|
|
397
|
-
return html`<slot></slot>`;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
declare global {
|
|
402
|
-
interface HTMLElementTagNameMap {
|
|
403
|
-
"rel-resizable-group": RelResizableGroup;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
|
|
4
|
-
@customElement("rel-resizable-handle")
|
|
5
|
-
export class RelResizableHandle extends LitElement {
|
|
6
|
-
/* =======================
|
|
7
|
-
* PUBLIC API
|
|
8
|
-
* ======================= */
|
|
9
|
-
|
|
10
|
-
@property({ type: String, reflect: true }) orientation: "horizontal" | "vertical" = "horizontal";
|
|
11
|
-
|
|
12
|
-
/* =======================
|
|
13
|
-
* INTERNAL STATE
|
|
14
|
-
* ======================= */
|
|
15
|
-
|
|
16
|
-
/** Index of this handle in the parent group */
|
|
17
|
-
public handleIndex = -1;
|
|
18
|
-
|
|
19
|
-
/** Current split value (0-100) for aria-valuenow */
|
|
20
|
-
public splitValue = 50;
|
|
21
|
-
|
|
22
|
-
/* =======================
|
|
23
|
-
* STYLES
|
|
24
|
-
* ======================= */
|
|
25
|
-
|
|
26
|
-
static styles = css`
|
|
27
|
-
:host {
|
|
28
|
-
color: var(--rel-text-default);
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
justify-content: center;
|
|
32
|
-
flex-shrink: 0;
|
|
33
|
-
position: relative;
|
|
34
|
-
outline: none;
|
|
35
|
-
background: var(--rel-border-default);
|
|
36
|
-
transition: background 0.15s ease;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
:host([orientation="horizontal"]) {
|
|
40
|
-
width: 8px;
|
|
41
|
-
min-width: 8px;
|
|
42
|
-
cursor: col-resize;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
:host([orientation="vertical"]) {
|
|
46
|
-
height: 8px;
|
|
47
|
-
min-height: 8px;
|
|
48
|
-
cursor: row-resize;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
:host(:hover),
|
|
52
|
-
:host(:focus-visible) {
|
|
53
|
-
background: var(--rel-bg-neutral-elevated-1);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
:host([dragging]) {
|
|
57
|
-
background: var(--rel-bg-neutral-elevated-3);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
:host(:focus-visible) {
|
|
61
|
-
outline: 2px solid var(--rel-border-focus);
|
|
62
|
-
outline-offset: 2px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.grabber {
|
|
66
|
-
background: var(--rel-text-body);
|
|
67
|
-
border-radius: var(--rel-border-radius-full-rounded);
|
|
68
|
-
transition: background 0.15s ease;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
:host([orientation="horizontal"]) .grabber {
|
|
72
|
-
width: 4px;
|
|
73
|
-
height: 24px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
:host([orientation="vertical"]) .grabber {
|
|
77
|
-
width: 24px;
|
|
78
|
-
height: 4px;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
:host(:hover) .grabber,
|
|
82
|
-
:host(:focus-visible) .grabber {
|
|
83
|
-
background: var(--rel-bg-surface);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
:host([data-dragging]) {
|
|
87
|
-
background: var(--rel-bg-neutral-elevated-1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
:host([data-dragging]) .grabber {
|
|
91
|
-
background: var(--rel-text-default);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@media (prefers-reduced-motion: reduce) {
|
|
95
|
-
:host {
|
|
96
|
-
transition: none;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.grabber {
|
|
100
|
-
transition: none;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
`;
|
|
104
|
-
|
|
105
|
-
/* =======================
|
|
106
|
-
* LIFECYCLE
|
|
107
|
-
* ======================= */
|
|
108
|
-
|
|
109
|
-
connectedCallback() {
|
|
110
|
-
super.connectedCallback();
|
|
111
|
-
this.setAttribute("tabindex", "0");
|
|
112
|
-
this.setAttribute("role", "separator");
|
|
113
|
-
this.updateAriaOrientation();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
updated(changed: Map<string, unknown>) {
|
|
117
|
-
if (changed.has("orientation")) {
|
|
118
|
-
this.updateAriaOrientation();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/* =======================
|
|
123
|
-
* ARIA
|
|
124
|
-
* ======================= */
|
|
125
|
-
|
|
126
|
-
private updateAriaOrientation() {
|
|
127
|
-
this.setAttribute("aria-orientation", this.orientation);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public updateAriaValue(value: number) {
|
|
131
|
-
this.splitValue = value;
|
|
132
|
-
this.setAttribute("aria-valuenow", String(Math.round(value)));
|
|
133
|
-
this.setAttribute("aria-valuemin", "0");
|
|
134
|
-
this.setAttribute("aria-valuemax", "100");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/* =======================
|
|
138
|
-
* RENDER
|
|
139
|
-
* ======================= */
|
|
140
|
-
|
|
141
|
-
render() {
|
|
142
|
-
return html`<div class="grabber"></div>`;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
declare global {
|
|
147
|
-
interface HTMLElementTagNameMap {
|
|
148
|
-
"rel-resizable-handle": RelResizableHandle;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
2
|
-
import { customElement, property } from "lit/decorators.js";
|
|
3
|
-
|
|
4
|
-
@customElement("rel-resizable-panel")
|
|
5
|
-
export class RelResizablePanel extends LitElement {
|
|
6
|
-
/* =======================
|
|
7
|
-
* PUBLIC API
|
|
8
|
-
* ======================= */
|
|
9
|
-
|
|
10
|
-
@property({ type: Number, attribute: "defaultsize" }) defaultSize?: number;
|
|
11
|
-
@property({ type: Number, attribute: "minsize" }) minSize = 10;
|
|
12
|
-
@property({ type: Number, attribute: "maxsize" }) maxSize = 90;
|
|
13
|
-
|
|
14
|
-
/* =======================
|
|
15
|
-
* INTERNAL STATE
|
|
16
|
-
* ======================= */
|
|
17
|
-
|
|
18
|
-
/** Current computed size in percentage */
|
|
19
|
-
public currentSize = 0;
|
|
20
|
-
|
|
21
|
-
/* =======================
|
|
22
|
-
* STYLES
|
|
23
|
-
* ======================= */
|
|
24
|
-
|
|
25
|
-
static styles = css`
|
|
26
|
-
/* Default typography for slotted panel headings (Figma headings-md) */
|
|
27
|
-
::slotted(h1), ::slotted(h2), ::slotted(h3), ::slotted(h4) {
|
|
28
|
-
font-family: var(--rel-headings-md-font-family);
|
|
29
|
-
font-weight: var(--rel-headings-md-font-weight);
|
|
30
|
-
font-size: var(--rel-headings-md-font-size);
|
|
31
|
-
line-height: var(--rel-headings-md-line-height);
|
|
32
|
-
letter-spacing: var(--rel-headings-md-letter-spacing);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
:host {
|
|
36
|
-
padding: var(--rel-spacing-md);
|
|
37
|
-
color: var(--rel-text-default);
|
|
38
|
-
display: flex;
|
|
39
|
-
flex-direction: column;
|
|
40
|
-
overflow: auto;
|
|
41
|
-
box-sizing: border-box;
|
|
42
|
-
}
|
|
43
|
-
`;
|
|
44
|
-
|
|
45
|
-
/* =======================
|
|
46
|
-
* RENDER
|
|
47
|
-
* ======================= */
|
|
48
|
-
|
|
49
|
-
render() {
|
|
50
|
-
return html`<slot></slot>`;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
declare global {
|
|
55
|
-
interface HTMLElementTagNameMap {
|
|
56
|
-
"rel-resizable-panel": RelResizablePanel;
|
|
57
|
-
}
|
|
58
|
-
}
|