@reliability-design/web 1.0.6 → 1.1.1
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/components/rel-accordion/rel-accordion.ts +4 -0
- package/dist/components/rel-alert/rel-alert.ts +83 -13
- package/dist/components/rel-avatar/rel-avatar.ts +3 -2
- package/dist/components/rel-badge/rel-badge.ts +6 -2
- package/dist/components/rel-button/rel-button.ts +64 -8
- package/dist/components/rel-calendar/rel-calendar.ts +3 -3
- package/dist/components/rel-carousel/rel-carousel.ts +10 -11
- package/dist/components/rel-checkbox/rel-checkbox.ts +33 -2
- package/dist/components/rel-chip/rel-chip.ts +63 -5
- package/dist/components/rel-divider/rel-divider.ts +9 -0
- package/dist/components/rel-drawer/rel-drawer-footer.ts +29 -0
- package/dist/components/rel-drawer/rel-drawer.ts +17 -26
- package/dist/components/rel-menu/rel-menu.ts +53 -21
- package/dist/components/rel-menubar/rel-menubar.ts +52 -23
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +240 -143
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +227 -331
- package/dist/components/rel-navbar/rel-navbar.ts +13 -0
- package/dist/components/rel-pagination/rel-pagination.ts +11 -6
- package/dist/components/rel-popover/rel-popover.ts +16 -13
- package/dist/components/rel-radio/rel-radio.ts +18 -1
- package/dist/components/rel-resizable/rel-resizable-handle.ts +4 -8
- package/dist/components/rel-select/rel-select.ts +14 -0
- package/dist/components/rel-sheet/rel-sheet.ts +7 -6
- package/dist/components/rel-sidebar/rel-sidebar.ts +13 -5
- package/dist/components/rel-slider/rel-slider.ts +25 -2
- package/dist/components/rel-snackbar/rel-snackbar.ts +46 -16
- package/dist/components/rel-stepper/rel-stepper.ts +32 -21
- package/dist/components/rel-switch/rel-switch.ts +19 -6
- package/dist/components/rel-tab/rel-tab.ts +49 -15
- package/dist/components/rel-table/rel-table-body.ts +5 -0
- package/dist/components/rel-table/rel-table-caption.ts +6 -1
- package/dist/components/rel-table/rel-table-cell.ts +42 -49
- package/dist/components/rel-table/rel-table-footer.ts +5 -0
- package/dist/components/rel-table/rel-table-head.ts +13 -1
- package/dist/components/rel-table/rel-table-header.ts +5 -0
- package/dist/components/rel-table/rel-table-row.ts +7 -3
- package/dist/components/rel-table/rel-table.ts +8 -2
- package/dist/components/rel-textfield/rel-textfield.ts +20 -20
- package/dist/components/rel-toast/rel-toast.ts +31 -10
- package/dist/components/rel-tooltip/rel-tooltip.ts +123 -80
- package/dist/components/rel-topbar/rel-topbar-actions.ts +23 -0
- package/dist/components/rel-topbar/rel-topbar-brand.ts +46 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +33 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +28 -0
- package/dist/components/rel-topbar/rel-topbar-item.ts +315 -0
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +23 -0
- package/dist/components/rel-topbar/rel-topbar-profile.ts +248 -0
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +23 -0
- package/dist/components/rel-topbar/rel-topbar.ts +329 -0
- package/dist/index.d.mts +278 -289
- package/dist/index.d.ts +278 -289
- package/dist/index.js +4498 -5727
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4535 -5756
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +346 -294
- package/dist/{vars-ITL2K3KO.css → vars-TBB4BMSD.css} +346 -294
- package/package.json +2 -1
- package/dist/components/rel-quote-page/README.md +0 -166
- package/dist/components/rel-quote-page/rel-quote-page.ts +0 -816
|
@@ -35,6 +35,7 @@ export class RelPopover extends LitElement {
|
|
|
35
35
|
|
|
36
36
|
private triggerEl: HTMLElement | null = null;
|
|
37
37
|
private returnFocusEl: HTMLElement | null = null;
|
|
38
|
+
private uniqueId = `popover-${Math.random().toString(36).slice(2)}`;
|
|
38
39
|
|
|
39
40
|
/* =======================
|
|
40
41
|
* STYLES
|
|
@@ -81,10 +82,8 @@ export class RelPopover extends LitElement {
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
firstUpdated() {
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
'[slot="trigger"]',
|
|
87
|
-
) as HTMLElement | null;
|
|
85
|
+
// triggerEl is resolved via onTriggerSlotChange; call aria in case slot
|
|
86
|
+
// content was already assigned before firstUpdated
|
|
88
87
|
this.applyTriggerAria();
|
|
89
88
|
}
|
|
90
89
|
|
|
@@ -134,18 +133,13 @@ export class RelPopover extends LitElement {
|
|
|
134
133
|
|
|
135
134
|
const path = e.composedPath();
|
|
136
135
|
|
|
137
|
-
// Toggle ONLY if pointerdown originated from trigger
|
|
138
|
-
|
|
139
|
-
(n) => n instanceof HTMLElement && n.getAttribute?.("slot") === "trigger",
|
|
140
|
-
) as HTMLElement | undefined;
|
|
141
|
-
|
|
142
|
-
if (!triggerNode) return;
|
|
136
|
+
// Toggle ONLY if pointerdown originated from the trigger element
|
|
137
|
+
if (!this.triggerEl || !path.includes(this.triggerEl)) return;
|
|
143
138
|
|
|
144
139
|
// Prevent this interaction from becoming an "outside click"
|
|
145
140
|
e.preventDefault();
|
|
146
141
|
e.stopPropagation();
|
|
147
142
|
|
|
148
|
-
this.triggerEl = triggerNode;
|
|
149
143
|
this.setOpen(!this.activeOpen);
|
|
150
144
|
};
|
|
151
145
|
|
|
@@ -295,10 +289,18 @@ export class RelPopover extends LitElement {
|
|
|
295
289
|
* ARIA
|
|
296
290
|
* ======================= */
|
|
297
291
|
|
|
292
|
+
private onTriggerSlotChange(e: Event) {
|
|
293
|
+
const slot = e.target as HTMLSlotElement;
|
|
294
|
+
const first = slot.assignedElements({ flatten: true })[0] as HTMLElement | undefined;
|
|
295
|
+
this.triggerEl = first ?? null;
|
|
296
|
+
this.applyTriggerAria();
|
|
297
|
+
}
|
|
298
|
+
|
|
298
299
|
private applyTriggerAria() {
|
|
299
300
|
if (!this.triggerEl) return;
|
|
300
301
|
this.triggerEl.setAttribute("aria-haspopup", "dialog");
|
|
301
302
|
this.triggerEl.setAttribute("aria-expanded", String(this.activeOpen));
|
|
303
|
+
this.triggerEl.setAttribute("aria-controls", this.uniqueId);
|
|
302
304
|
}
|
|
303
305
|
|
|
304
306
|
/* =======================
|
|
@@ -307,14 +309,15 @@ export class RelPopover extends LitElement {
|
|
|
307
309
|
|
|
308
310
|
render() {
|
|
309
311
|
return html`
|
|
310
|
-
<slot
|
|
312
|
+
<slot @slotchange=${this.onTriggerSlotChange}></slot>
|
|
311
313
|
|
|
312
314
|
<div
|
|
315
|
+
id="${this.uniqueId}"
|
|
313
316
|
class="content-wrapper"
|
|
314
317
|
style="${this.contentStyle}"
|
|
315
318
|
?open="${this.activeOpen}"
|
|
316
319
|
>
|
|
317
|
-
<slot></slot>
|
|
320
|
+
<slot name="content"></slot>
|
|
318
321
|
</div>
|
|
319
322
|
`;
|
|
320
323
|
}
|
|
@@ -21,6 +21,13 @@ export class RelRadio extends LitElement {
|
|
|
21
21
|
@property({ type: Boolean })
|
|
22
22
|
disabled = false;
|
|
23
23
|
|
|
24
|
+
@property({ type: String }) value = "";
|
|
25
|
+
|
|
26
|
+
checked = false;
|
|
27
|
+
|
|
28
|
+
private _onChange: (value: string) => void = () => {};
|
|
29
|
+
private _onTouched: () => void = () => {};
|
|
30
|
+
|
|
24
31
|
static styles = css`
|
|
25
32
|
:host {
|
|
26
33
|
display: block;
|
|
@@ -105,13 +112,22 @@ export class RelRadio extends LitElement {
|
|
|
105
112
|
|
|
106
113
|
this.selectedValue = value;
|
|
107
114
|
this.dispatchEvent(
|
|
108
|
-
new CustomEvent("
|
|
115
|
+
new CustomEvent("rel-change", {
|
|
116
|
+
detail: {
|
|
117
|
+
checked: this.selectedValue === value,
|
|
118
|
+
value,
|
|
119
|
+
},
|
|
109
120
|
bubbles: true,
|
|
110
121
|
composed: true,
|
|
111
122
|
})
|
|
112
123
|
);
|
|
124
|
+
this._onChange(this.value);
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
registerOnChange(fn: (value: string) => void): void { this._onChange = fn; }
|
|
128
|
+
registerOnTouched(fn: () => void): void { this._onTouched = fn; }
|
|
129
|
+
writeValue(value: string): void { this.checked = value === this.value; }
|
|
130
|
+
|
|
115
131
|
private renderOption(option: RadioOption) {
|
|
116
132
|
const isChecked = this.selectedValue === option.value;
|
|
117
133
|
const isDisabled = this.disabled || option.disabled;
|
|
@@ -133,6 +149,7 @@ export class RelRadio extends LitElement {
|
|
|
133
149
|
.checked="${isChecked}"
|
|
134
150
|
?disabled="${isDisabled}"
|
|
135
151
|
@change="${() => this.onChange(option.value)}"
|
|
152
|
+
@blur="${() => this._onTouched()}"
|
|
136
153
|
/>
|
|
137
154
|
<span class="radio-custom"></span>
|
|
138
155
|
<span class="radio-label">${option.label}</span>
|
|
@@ -36,19 +36,15 @@ export class RelResizableHandle extends LitElement {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
:host([orientation="horizontal"]) {
|
|
39
|
-
width:
|
|
40
|
-
min-width:
|
|
39
|
+
width: 8px;
|
|
40
|
+
min-width: 8px;
|
|
41
41
|
cursor: col-resize;
|
|
42
|
-
padding: 0 var(--rel-spacing-space-xs);
|
|
43
|
-
margin: 0 calc(var(--rel-spacing-space-xs) * -1);
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
:host([orientation="vertical"]) {
|
|
47
|
-
height:
|
|
48
|
-
min-height:
|
|
45
|
+
height: 8px;
|
|
46
|
+
min-height: 8px;
|
|
49
47
|
cursor: row-resize;
|
|
50
|
-
padding: var(--rel-spacing-space-xs) 0;
|
|
51
|
-
margin: calc(var(--rel-spacing-space-xs) * -1) 0;
|
|
52
48
|
}
|
|
53
49
|
|
|
54
50
|
:host(:hover),
|
|
@@ -176,6 +176,20 @@ export class RelSelect extends LitElement {
|
|
|
176
176
|
.error-text {
|
|
177
177
|
color: var(--rel-colors-red-secondary);
|
|
178
178
|
}
|
|
179
|
+
|
|
180
|
+
/* Dark mode — flip select background, text, border, and chevron icon to white */
|
|
181
|
+
:host-context([data-theme="dark"]) select,
|
|
182
|
+
:host-context(.dark) select {
|
|
183
|
+
background-color: var(--rel-color-bg-secondary);
|
|
184
|
+
color: #ffffff;
|
|
185
|
+
border-color: var(--rel-color-border-default);
|
|
186
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
:host-context([data-theme="dark"]) .select-label,
|
|
190
|
+
:host-context(.dark) .select-label {
|
|
191
|
+
color: var(--rel-color-text-primary);
|
|
192
|
+
}
|
|
179
193
|
`;
|
|
180
194
|
|
|
181
195
|
private onChange(event: Event) {
|
|
@@ -166,7 +166,7 @@ export class RelSheetContent extends LitElement {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
.sheet-container.open .overlay {
|
|
169
|
-
opacity: 1;
|
|
169
|
+
opacity: var(--rel-sheet-scrim-opacity, 1);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
.overlay.hidden {
|
|
@@ -354,9 +354,10 @@ export class RelSheetContent extends LitElement {
|
|
|
354
354
|
this.lockScroll();
|
|
355
355
|
|
|
356
356
|
if (this.sheet?.modal) {
|
|
357
|
-
|
|
358
|
-
this.
|
|
359
|
-
|
|
357
|
+
this.updateComplete.then(() => {
|
|
358
|
+
const focusTarget = this.shadowRoot?.querySelector<HTMLElement>("[autofocus], .close-button, .panel");
|
|
359
|
+
focusTarget?.focus();
|
|
360
|
+
});
|
|
360
361
|
}
|
|
361
362
|
|
|
362
363
|
document.addEventListener("keydown", this.handleKeydown);
|
|
@@ -367,10 +368,10 @@ export class RelSheetContent extends LitElement {
|
|
|
367
368
|
document.removeEventListener("keydown", this.handleKeydown);
|
|
368
369
|
|
|
369
370
|
if (this.previousFocus && this.previousFocus.focus) {
|
|
370
|
-
|
|
371
|
+
this.updateComplete.then(() => {
|
|
371
372
|
this.previousFocus?.focus();
|
|
372
373
|
this.previousFocus = null;
|
|
373
|
-
}
|
|
374
|
+
});
|
|
374
375
|
}
|
|
375
376
|
}
|
|
376
377
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { LitElement, html, css } from "lit";
|
|
1
|
+
import { LitElement, html, css, nothing } from "lit";
|
|
2
2
|
import { customElement, property, state, query } from "lit/decorators.js";
|
|
3
|
+
import "@reliability-design/icons/rel-icon";
|
|
3
4
|
|
|
4
5
|
export type SidebarVariant = "sidebar" | "floating" | "inset";
|
|
5
6
|
export type SidebarSide = "left" | "right";
|
|
@@ -31,6 +32,11 @@ export class RelSidebarProvider extends LitElement {
|
|
|
31
32
|
|
|
32
33
|
private mediaQuery: MediaQueryList | null = null;
|
|
33
34
|
private isInitialized = false;
|
|
35
|
+
private _uid = Math.random().toString(36).slice(2);
|
|
36
|
+
|
|
37
|
+
private get _storageKey(): string {
|
|
38
|
+
return `rel-sidebar:${this.id || this._uid}`;
|
|
39
|
+
}
|
|
34
40
|
|
|
35
41
|
static styles = css`
|
|
36
42
|
:host {
|
|
@@ -154,7 +160,7 @@ export class RelSidebarProvider extends LitElement {
|
|
|
154
160
|
|
|
155
161
|
private getPersistedState(): { open?: boolean; collapsed?: boolean } | null {
|
|
156
162
|
try {
|
|
157
|
-
const stored = localStorage.getItem(this.
|
|
163
|
+
const stored = localStorage.getItem(this._storageKey);
|
|
158
164
|
if (stored) {
|
|
159
165
|
return JSON.parse(stored);
|
|
160
166
|
}
|
|
@@ -184,7 +190,7 @@ export class RelSidebarProvider extends LitElement {
|
|
|
184
190
|
: { open: this.activeOpen, collapsed: this.activeCollapsed };
|
|
185
191
|
|
|
186
192
|
try {
|
|
187
|
-
localStorage.setItem(this.
|
|
193
|
+
localStorage.setItem(this._storageKey, JSON.stringify(stateToPersist));
|
|
188
194
|
} catch (e) {
|
|
189
195
|
// Silently fail if localStorage is unavailable
|
|
190
196
|
}
|
|
@@ -309,7 +315,8 @@ export class RelSidebar extends LitElement {
|
|
|
309
315
|
left: 0;
|
|
310
316
|
right: 0;
|
|
311
317
|
bottom: 0;
|
|
312
|
-
|
|
318
|
+
/* TODO: replace scrim fallback with a proper dark-aware token in vars.css */
|
|
319
|
+
background: var(--rel-overlay-scrim, rgba(0, 0, 0, 0.6));
|
|
313
320
|
z-index: 999;
|
|
314
321
|
opacity: 0;
|
|
315
322
|
pointer-events: none;
|
|
@@ -982,6 +989,7 @@ export class RelSidebarMenuButton extends LitElement {
|
|
|
982
989
|
@property({ type: Boolean }) active = false;
|
|
983
990
|
@property({ type: Boolean }) disabled = false;
|
|
984
991
|
@property({ type: String }) tooltip = "";
|
|
992
|
+
@property({ type: String }) icon: string = "";
|
|
985
993
|
|
|
986
994
|
@state() private isCollapsed = false;
|
|
987
995
|
|
|
@@ -1147,7 +1155,7 @@ export class RelSidebarMenuButton extends LitElement {
|
|
|
1147
1155
|
part="button"
|
|
1148
1156
|
>
|
|
1149
1157
|
<span class="icon" part="icon">
|
|
1150
|
-
|
|
1158
|
+
${this.icon ? html`<rel-icon name="${this.icon}"></rel-icon>` : nothing}
|
|
1151
1159
|
</span>
|
|
1152
1160
|
<span class="label" part="label">
|
|
1153
1161
|
<slot></slot>
|
|
@@ -26,6 +26,9 @@ export class RelSlider extends LitElement {
|
|
|
26
26
|
|
|
27
27
|
@state() private ticks: number[] = [];
|
|
28
28
|
|
|
29
|
+
private _onChange: (value: number) => void = () => {};
|
|
30
|
+
private _onTouched: () => void = () => {};
|
|
31
|
+
|
|
29
32
|
static styles = css`
|
|
30
33
|
:host {
|
|
31
34
|
--track-height: 5px;
|
|
@@ -112,6 +115,12 @@ export class RelSlider extends LitElement {
|
|
|
112
115
|
border: none;
|
|
113
116
|
}
|
|
114
117
|
|
|
118
|
+
.slider-input::slider-track {
|
|
119
|
+
background: transparent;
|
|
120
|
+
height: 100%;
|
|
121
|
+
border: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
115
124
|
/* Hide native thumb */
|
|
116
125
|
.slider-input::-webkit-slider-thumb {
|
|
117
126
|
-webkit-appearance: none;
|
|
@@ -131,6 +140,14 @@ export class RelSlider extends LitElement {
|
|
|
131
140
|
cursor: pointer;
|
|
132
141
|
}
|
|
133
142
|
|
|
143
|
+
.slider-input::slider-thumb {
|
|
144
|
+
width: 1px;
|
|
145
|
+
height: 1px;
|
|
146
|
+
background: transparent;
|
|
147
|
+
border: none;
|
|
148
|
+
cursor: pointer;
|
|
149
|
+
}
|
|
150
|
+
|
|
134
151
|
.slider-input:focus-visible ~ .thumb-container .custom-thumb {
|
|
135
152
|
box-shadow: 0 0 0 var(--thumb-stroke) var(--thumb-halo-color),
|
|
136
153
|
var(--shadow), var(--halo);
|
|
@@ -330,14 +347,19 @@ export class RelSlider extends LitElement {
|
|
|
330
347
|
this.value = next;
|
|
331
348
|
this.updateActiveWidth();
|
|
332
349
|
this.dispatchEvent(
|
|
333
|
-
new CustomEvent("
|
|
350
|
+
new CustomEvent("rel-change", {
|
|
334
351
|
detail: { value: this.value },
|
|
335
352
|
bubbles: true,
|
|
336
353
|
composed: true,
|
|
337
354
|
})
|
|
338
355
|
);
|
|
356
|
+
this._onChange(this.value);
|
|
339
357
|
}
|
|
340
358
|
|
|
359
|
+
registerOnChange(fn: (value: number) => void): void { this._onChange = fn; }
|
|
360
|
+
registerOnTouched(fn: () => void): void { this._onTouched = fn; }
|
|
361
|
+
writeValue(value: number): void { this.value = value; }
|
|
362
|
+
|
|
341
363
|
private updateActiveWidth() {
|
|
342
364
|
const activeEl = this.shadowRoot?.querySelector(".track-active") as HTMLDivElement;
|
|
343
365
|
if (activeEl) {
|
|
@@ -441,7 +463,8 @@ export class RelSlider extends LitElement {
|
|
|
441
463
|
.step="${this.type === 'discrete' ? String(this.step) : '1'}"
|
|
442
464
|
.value="${String(this.value)}"
|
|
443
465
|
?disabled="${this.disabled}"
|
|
444
|
-
@input="${this.onInput}"
|
|
466
|
+
@input="${this.onInput}"
|
|
467
|
+
@blur="${() => this._onTouched()}" />
|
|
445
468
|
|
|
446
469
|
${this.renderThumbContainer()}
|
|
447
470
|
${this.renderTicks()}
|
|
@@ -19,10 +19,11 @@ export class RelSnackbar extends LitElement {
|
|
|
19
19
|
@property({ type: Number }) duration: number = 4000;
|
|
20
20
|
|
|
21
21
|
@property({ type: String }) type: SnackbarType = "default";
|
|
22
|
+
@property({ type: Boolean, reflect: true }) show = false;
|
|
22
23
|
|
|
23
|
-
@state() private visible: boolean =
|
|
24
|
+
@state() private visible: boolean = false;
|
|
24
25
|
|
|
25
|
-
private
|
|
26
|
+
private _dismissTimer: ReturnType<typeof setTimeout> | null = null;
|
|
26
27
|
|
|
27
28
|
static styles = css`
|
|
28
29
|
:host {
|
|
@@ -56,17 +57,30 @@ export class RelSnackbar extends LitElement {
|
|
|
56
57
|
display: none;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
/* Type variants */
|
|
60
|
+
/* Type variants — border accent using semantic DS tokens */
|
|
60
61
|
.snackbar.type-success {
|
|
61
|
-
border-left-color: var(--rel-colors-green-
|
|
62
|
+
border-left-color: var(--rel-colors-green-600, #16a34a);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
.snackbar.type-error {
|
|
65
|
-
border-left-color: var(--rel-colors-red-
|
|
66
|
+
border-left-color: var(--rel-colors-red-600, #dc2626);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
.snackbar.type-warning {
|
|
69
|
-
border-left-color: var(--rel-colors-amber-
|
|
70
|
+
border-left-color: var(--rel-colors-amber-600, #d97706);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Icon color matches type accent */
|
|
74
|
+
.snackbar.type-success .snackbar-icon {
|
|
75
|
+
color: var(--rel-colors-green-400, #4ade80);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.snackbar.type-error .snackbar-icon {
|
|
79
|
+
color: var(--rel-colors-red-400, #f87171);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.snackbar.type-warning .snackbar-icon {
|
|
83
|
+
color: var(--rel-colors-amber-400, #fbbf24);
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
.snackbar-icon {
|
|
@@ -112,7 +126,7 @@ export class RelSnackbar extends LitElement {
|
|
|
112
126
|
.snackbar-action {
|
|
113
127
|
background: none;
|
|
114
128
|
border: none;
|
|
115
|
-
color: var(--rel-colors-green-
|
|
129
|
+
color: var(--rel-colors-green-400, #4ade80);
|
|
116
130
|
font-weight: var(--rel-fontWeights-semibold);
|
|
117
131
|
font-size: var(--rel-fontSizes-sm);
|
|
118
132
|
font-family: var(--rel-fontFamilies-primary);
|
|
@@ -164,6 +178,11 @@ export class RelSnackbar extends LitElement {
|
|
|
164
178
|
border-radius: 2px;
|
|
165
179
|
}
|
|
166
180
|
|
|
181
|
+
/* Prevent any inherited transform from firing on button click */
|
|
182
|
+
.snackbar button:active {
|
|
183
|
+
transform: none;
|
|
184
|
+
}
|
|
185
|
+
|
|
167
186
|
@media (prefers-reduced-motion: reduce) {
|
|
168
187
|
.snackbar {
|
|
169
188
|
animation: none;
|
|
@@ -184,32 +203,42 @@ export class RelSnackbar extends LitElement {
|
|
|
184
203
|
|
|
185
204
|
connectedCallback() {
|
|
186
205
|
super.connectedCallback();
|
|
187
|
-
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
willUpdate(changed: Map<string, unknown>) {
|
|
209
|
+
if (!changed.has('show')) return;
|
|
210
|
+
if (this.show) {
|
|
211
|
+
this.visible = true;
|
|
212
|
+
this.setAutoDismiss();
|
|
213
|
+
} else {
|
|
214
|
+
this.visible = false;
|
|
215
|
+
this.clearDismissTimer();
|
|
216
|
+
}
|
|
188
217
|
}
|
|
189
218
|
|
|
190
219
|
updated(changed: Map<string, unknown>) {
|
|
191
|
-
if (changed.has("duration") || changed.has("longerAction")) {
|
|
220
|
+
if ((changed.has("duration") || changed.has("longerAction")) && this.show) {
|
|
192
221
|
this.setAutoDismiss();
|
|
193
222
|
}
|
|
194
223
|
}
|
|
195
224
|
|
|
196
225
|
disconnectedCallback() {
|
|
197
226
|
super.disconnectedCallback();
|
|
198
|
-
this.
|
|
227
|
+
this.clearDismissTimer();
|
|
199
228
|
}
|
|
200
229
|
|
|
201
230
|
private setAutoDismiss() {
|
|
202
231
|
if (this.duration > 0) {
|
|
203
|
-
this.
|
|
232
|
+
this.clearDismissTimer();
|
|
204
233
|
const delay = this.longerAction ? this.duration * 2 : this.duration;
|
|
205
|
-
this.
|
|
234
|
+
this._dismissTimer = setTimeout(() => this.dismiss(), delay);
|
|
206
235
|
}
|
|
207
236
|
}
|
|
208
237
|
|
|
209
|
-
private
|
|
210
|
-
if (this.
|
|
211
|
-
|
|
212
|
-
this.
|
|
238
|
+
private clearDismissTimer() {
|
|
239
|
+
if (this._dismissTimer !== null) {
|
|
240
|
+
clearTimeout(this._dismissTimer);
|
|
241
|
+
this._dismissTimer = null;
|
|
213
242
|
}
|
|
214
243
|
}
|
|
215
244
|
|
|
@@ -224,6 +253,7 @@ export class RelSnackbar extends LitElement {
|
|
|
224
253
|
}
|
|
225
254
|
|
|
226
255
|
private dismiss() {
|
|
256
|
+
this.show = false;
|
|
227
257
|
this.visible = false;
|
|
228
258
|
this.dispatchEvent(
|
|
229
259
|
new CustomEvent("close", {
|
|
@@ -126,8 +126,8 @@ export class RelStepper extends LitElement {
|
|
|
126
126
|
display: flex;
|
|
127
127
|
align-items: center;
|
|
128
128
|
justify-content: center;
|
|
129
|
-
width: 22px;
|
|
130
|
-
height: 22px;
|
|
129
|
+
width: var(--rel-stepper-indicator-size, 22px);
|
|
130
|
+
height: var(--rel-stepper-indicator-size, 22px);
|
|
131
131
|
border: 2px solid var(--rel-colors-gray-border);
|
|
132
132
|
background: var(--rel-colors-white);
|
|
133
133
|
border-radius: 50%;
|
|
@@ -237,15 +237,15 @@ export class RelStepper extends LitElement {
|
|
|
237
237
|
* Step States
|
|
238
238
|
********************************************/
|
|
239
239
|
.rel-step.done .indicator {
|
|
240
|
-
background: var(--rel-
|
|
241
|
-
border-color: var(--rel-
|
|
242
|
-
color: var(--rel-
|
|
240
|
+
background: var(--rel-color-text-heading);
|
|
241
|
+
border-color: var(--rel-color-text-heading);
|
|
242
|
+
color: var(--rel-color-text-inverse);
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
.rel-step.progress .indicator {
|
|
246
|
-
border-color: var(--rel-
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
border-color: var(--rel-color-text-heading);
|
|
247
|
+
background: var(--rel-color-bg-primary);
|
|
248
|
+
color: var(--rel-color-text-heading);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
.rel-step.disabled .indicator {
|
|
@@ -255,20 +255,20 @@ export class RelStepper extends LitElement {
|
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
.rel-step.done .connector {
|
|
258
|
-
background: var(--rel-
|
|
258
|
+
background: var(--rel-color-text-heading);
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
.rel-step.progress .connector {
|
|
262
|
-
background: var(--rel-
|
|
262
|
+
background: var(--rel-color-text-heading);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
.rel-step.done .step-label {
|
|
266
|
-
color: var(--rel-
|
|
266
|
+
color: var(--rel-color-text-heading);
|
|
267
267
|
font-weight: var(--rel-fontWeights-semibold);
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
.rel-step.progress .step-label {
|
|
271
|
-
color: var(--rel-
|
|
271
|
+
color: var(--rel-color-text-heading);
|
|
272
272
|
font-weight: var(--rel-fontWeights-semibold);
|
|
273
273
|
}
|
|
274
274
|
|
|
@@ -276,41 +276,52 @@ export class RelStepper extends LitElement {
|
|
|
276
276
|
color: var(--rel-text-disabled, #9e9e9e);
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
/* Dark mode: ensure progress/done indicator and labels stay readable */
|
|
280
|
+
:host-context(:root[data-theme="dark"]) .rel-step.progress .step-label,
|
|
281
|
+
:host-context(.dark) .rel-step.progress .step-label {
|
|
282
|
+
color: var(--rel-color-text-primary);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
:host-context(:root[data-theme="dark"]) .rel-step.progress .indicator,
|
|
286
|
+
:host-context(.dark) .rel-step.progress .indicator {
|
|
287
|
+
color: #ffffff;
|
|
288
|
+
}
|
|
289
|
+
|
|
279
290
|
/********************************************
|
|
280
291
|
* Size Property — controls connector length
|
|
281
292
|
********************************************/
|
|
282
293
|
/* Horizontal */
|
|
283
294
|
.rel-stepper.large.horizontal {
|
|
284
|
-
gap: 86px;
|
|
295
|
+
gap: var(--rel-stepper-connector-length-lg, 86px);
|
|
285
296
|
}
|
|
286
297
|
|
|
287
298
|
.rel-stepper.small.horizontal {
|
|
288
|
-
gap: 60px;
|
|
299
|
+
gap: var(--rel-stepper-connector-length-md, 60px);
|
|
289
300
|
}
|
|
290
301
|
|
|
291
302
|
.rel-stepper.large.horizontal .connector {
|
|
292
|
-
width: 86px;
|
|
303
|
+
width: var(--rel-stepper-connector-length-lg, 86px);
|
|
293
304
|
}
|
|
294
305
|
|
|
295
306
|
.rel-stepper.small.horizontal .connector {
|
|
296
|
-
width: 60px;
|
|
307
|
+
width: var(--rel-stepper-connector-length-md, 60px);
|
|
297
308
|
}
|
|
298
309
|
|
|
299
310
|
/* Vertical */
|
|
300
311
|
.rel-stepper.large.vertical .connector {
|
|
301
|
-
height: 86px;
|
|
312
|
+
height: var(--rel-stepper-connector-length-lg, 86px);
|
|
302
313
|
}
|
|
303
314
|
|
|
304
315
|
.rel-stepper.large.vertical {
|
|
305
|
-
gap: 86px;
|
|
316
|
+
gap: var(--rel-stepper-connector-length-lg, 86px);
|
|
306
317
|
}
|
|
307
318
|
|
|
308
319
|
.rel-stepper.small.vertical .connector {
|
|
309
|
-
height: 42px;
|
|
320
|
+
height: var(--rel-stepper-connector-length-sm, 42px);
|
|
310
321
|
}
|
|
311
322
|
|
|
312
323
|
.rel-stepper.small.vertical {
|
|
313
|
-
gap: 42px;
|
|
324
|
+
gap: var(--rel-stepper-connector-length-sm, 42px);
|
|
314
325
|
}
|
|
315
326
|
`;
|
|
316
327
|
|
|
@@ -338,7 +349,7 @@ export class RelStepper extends LitElement {
|
|
|
338
349
|
if (step.status === "disabled") return;
|
|
339
350
|
|
|
340
351
|
this.dispatchEvent(
|
|
341
|
-
new CustomEvent("step-change", {
|
|
352
|
+
new CustomEvent("rel-step-change", {
|
|
342
353
|
detail: {
|
|
343
354
|
index,
|
|
344
355
|
step,
|
|
@@ -5,6 +5,10 @@ import { customElement, property, state } from "lit/decorators.js";
|
|
|
5
5
|
export class RelSwitch extends LitElement {
|
|
6
6
|
@property({ type: Boolean }) checked = false;
|
|
7
7
|
@property({ type: Boolean }) disabled = false;
|
|
8
|
+
@property({ type: String }) value = "";
|
|
9
|
+
|
|
10
|
+
private _onChange: (value: boolean) => void = () => {};
|
|
11
|
+
private _onTouched: () => void = () => {};
|
|
8
12
|
|
|
9
13
|
@state() private isFocused = false;
|
|
10
14
|
@state() private isPressed = false;
|
|
@@ -23,8 +27,8 @@ export class RelSwitch extends LitElement {
|
|
|
23
27
|
.switch-wrapper {
|
|
24
28
|
position: relative;
|
|
25
29
|
display: inline-block;
|
|
26
|
-
width: 42px;
|
|
27
|
-
height: 22px;
|
|
30
|
+
width: var(--rel-switch-track-width, 42px);
|
|
31
|
+
height: var(--rel-switch-track-height, 22px);
|
|
28
32
|
cursor: pointer;
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -60,8 +64,8 @@ export class RelSwitch extends LitElement {
|
|
|
60
64
|
top: 50%;
|
|
61
65
|
left: -2px;
|
|
62
66
|
transform: translateY(-50%);
|
|
63
|
-
height: 18px;
|
|
64
|
-
width: 18px;
|
|
67
|
+
height: var(--rel-switch-thumb-size, 18px);
|
|
68
|
+
width: var(--rel-switch-thumb-size, 18px);
|
|
65
69
|
background-color: var(--switch-knob-off);
|
|
66
70
|
border-radius: 50%;
|
|
67
71
|
transition: transform 0.25s ease, background-color 0.25s ease,
|
|
@@ -116,14 +120,22 @@ export class RelSwitch extends LitElement {
|
|
|
116
120
|
this.checked = input.checked;
|
|
117
121
|
|
|
118
122
|
this.dispatchEvent(
|
|
119
|
-
new CustomEvent
|
|
120
|
-
detail:
|
|
123
|
+
new CustomEvent("rel-change", {
|
|
124
|
+
detail: {
|
|
125
|
+
checked: this.checked,
|
|
126
|
+
value: this.value,
|
|
127
|
+
},
|
|
121
128
|
bubbles: true,
|
|
122
129
|
composed: true,
|
|
123
130
|
})
|
|
124
131
|
);
|
|
132
|
+
this._onChange(this.checked);
|
|
125
133
|
}
|
|
126
134
|
|
|
135
|
+
registerOnChange(fn: (value: boolean) => void): void { this._onChange = fn; }
|
|
136
|
+
registerOnTouched(fn: () => void): void { this._onTouched = fn; }
|
|
137
|
+
writeValue(checked: boolean): void { this.checked = checked; }
|
|
138
|
+
|
|
127
139
|
private handleFocus() {
|
|
128
140
|
this.isFocused = true;
|
|
129
141
|
}
|
|
@@ -131,6 +143,7 @@ export class RelSwitch extends LitElement {
|
|
|
131
143
|
private handleBlur() {
|
|
132
144
|
this.isFocused = false;
|
|
133
145
|
this.isPressed = false;
|
|
146
|
+
this._onTouched();
|
|
134
147
|
}
|
|
135
148
|
|
|
136
149
|
private handleMouseDown() {
|