@latty-ds/web 0.10.4 → 1.0.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/custom-elements.json +1969 -228
- package/dist/components/accordion/index.js +36 -2
- package/dist/components/alert/alert.d.ts +29 -6
- package/dist/components/alert/alert.types.d.ts +5 -0
- package/dist/components/alert/index.js +124 -17
- package/dist/components/avatar/avatar.d.ts +2 -0
- package/dist/components/avatar/index.js +10 -3
- package/dist/components/breadcrumb/breadcrumb.d.ts +4 -0
- package/dist/components/breadcrumb/breadcrumb.types.d.ts +5 -0
- package/dist/components/breadcrumb/index.js +20 -3
- package/dist/components/button/button.d.ts +33 -0
- package/dist/components/button/index.js +135 -12
- package/dist/components/calendar/calendar.d.ts +15 -7
- package/dist/components/calendar/calendar.types.d.ts +17 -1
- package/dist/components/calendar/index.js +78 -25
- package/dist/components/checkbox/checkbox.d.ts +14 -2
- package/dist/components/checkbox/checkbox.types.d.ts +5 -0
- package/dist/components/checkbox/index.js +82 -5
- package/dist/components/chip/chip.d.ts +4 -1
- package/dist/components/chip/chip.types.d.ts +5 -0
- package/dist/components/chip/index.js +29 -1
- package/dist/components/color-input/color-input.d.ts +11 -2
- package/dist/components/color-input/color-input.types.d.ts +5 -0
- package/dist/components/color-input/index.js +92 -8
- package/dist/components/combobox/combobox.d.ts +18 -2
- package/dist/components/combobox/combobox.types.d.ts +7 -0
- package/dist/components/combobox/index.js +164 -23
- package/dist/components/date-input/date-input.d.ts +22 -7
- package/dist/components/date-input/date-input.types.d.ts +7 -0
- package/dist/components/date-input/index.js +216 -53
- package/dist/components/datepicker/datepicker.d.ts +9 -1
- package/dist/components/datepicker/index.js +108 -15
- package/dist/components/dialog/dialog.d.ts +39 -19
- package/dist/components/dialog/dialog.types.d.ts +5 -0
- package/dist/components/dialog/index.js +237 -90
- package/dist/components/divider/index.js +2 -2
- package/dist/components/dropdown/dropdown.d.ts +4 -0
- package/dist/components/dropdown/index.js +43 -3
- package/dist/components/icon-button/icon-button.d.ts +4 -0
- package/dist/components/icon-button/index.js +36 -1
- package/dist/components/image/image.d.ts +7 -7
- package/dist/components/image/index.js +6 -11
- package/dist/components/list/index.js +14 -4
- package/dist/components/nav/index.js +37 -17
- package/dist/components/nav/nav-item.d.ts +8 -8
- package/dist/components/pagination/index.js +57 -16
- package/dist/components/pagination/pagination.d.ts +8 -1
- package/dist/components/pagination/pagination.types.d.ts +15 -0
- package/dist/components/progress/index.js +44 -6
- package/dist/components/progress/progress.d.ts +12 -0
- package/dist/components/radio/index.js +148 -9
- package/dist/components/radio/radio.d.ts +34 -2
- package/dist/components/radio/radio.types.d.ts +5 -0
- package/dist/components/radio-group/index.js +120 -29
- package/dist/components/radio-group/radio-group.d.ts +27 -2
- package/dist/components/select/index.js +197 -44
- package/dist/components/select/select.d.ts +38 -4
- package/dist/components/select/select.types.d.ts +5 -0
- package/dist/components/shared/aria-forwarding.d.ts +1 -1
- package/dist/components/shared/form-default.d.ts +30 -0
- package/dist/components/shared/form-disabled.d.ts +40 -0
- package/dist/components/shared/form-field.d.ts +7 -0
- package/dist/components/shared/form-validity.d.ts +17 -0
- package/dist/components/shared/roving.d.ts +11 -0
- package/dist/components/shared/scroll-lock.d.ts +2 -0
- package/dist/components/sidepanel/index.js +275 -72
- package/dist/components/sidepanel/sidepanel.d.ts +32 -10
- package/dist/components/sidepanel/sidepanel.types.d.ts +10 -1
- package/dist/components/skeleton/index.js +3 -8
- package/dist/components/slider/index.js +307 -75
- package/dist/components/slider/slider.d.ts +16 -3
- package/dist/components/snackbar/index.js +82 -9
- package/dist/components/snackbar/snackbar.d.ts +17 -1
- package/dist/components/snackbar/snackbar.types.d.ts +5 -0
- package/dist/components/surface/index.js +8 -0
- package/dist/components/switch/index.js +101 -5
- package/dist/components/switch/switch.d.ts +13 -2
- package/dist/components/switch/switch.types.d.ts +5 -0
- package/dist/components/tab/index.js +15 -14
- package/dist/components/tab/tab.d.ts +0 -1
- package/dist/components/tab-group/index.js +102 -30
- package/dist/components/tab-group/tab-group.d.ts +17 -2
- package/dist/components/table/index.js +105 -61
- package/dist/components/table/table.d.ts +8 -2
- package/dist/components/table/table.types.d.ts +4 -3
- package/dist/components/text/index.js +16 -1
- package/dist/components/text/text.d.ts +1 -1
- package/dist/components/textfield/index.js +243 -35
- package/dist/components/textfield/textfield.d.ts +24 -2
- package/dist/components/textfield/textfield.types.d.ts +11 -0
- package/dist/components/tooltip/index.js +176 -49
- package/dist/components/tooltip/tooltip.d.ts +17 -0
- package/dist/components/tooltip/tooltip.types.d.ts +5 -1
- package/dist/index.cjs +2458 -683
- package/dist/index.js +2469 -690
- package/dist/manifest.json +202 -32
- package/dist/utils/dev-warn.d.ts +5 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +3 -7
|
@@ -171,6 +171,24 @@ var accordionStyles = css`
|
|
|
171
171
|
letter-spacing: 0.05rem;
|
|
172
172
|
text-transform: lowercase;
|
|
173
173
|
}
|
|
174
|
+
|
|
175
|
+
/* ── Reduced motion ─────────────────────────────────────────────────────── */
|
|
176
|
+
|
|
177
|
+
@media (prefers-reduced-motion: reduce) {
|
|
178
|
+
details,
|
|
179
|
+
.chevron {
|
|
180
|
+
transition: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* .content's height transition can't just be removed — accordion.ts's handleTransitionEnd() clears
|
|
184
|
+
_animating and finalizes styles only when the CSS transition actually completes; transition:none fires no
|
|
185
|
+
transitionend at all, leaving _animating stuck true after the very first toggle and silently breaking
|
|
186
|
+
every subsequent open/close. A 1ms duration is imperceptible (satisfies the reduced-motion intent) but
|
|
187
|
+
still fires the event the component's own state machine depends on. */
|
|
188
|
+
.content {
|
|
189
|
+
transition: height 1ms;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
174
192
|
`;
|
|
175
193
|
|
|
176
194
|
// src/components/accordion/accordion.ts
|
|
@@ -345,6 +363,20 @@ var textStyles = css2`
|
|
|
345
363
|
`;
|
|
346
364
|
|
|
347
365
|
// src/components/text/text.ts
|
|
366
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
367
|
+
"h1",
|
|
368
|
+
"h2",
|
|
369
|
+
"h3",
|
|
370
|
+
"h4",
|
|
371
|
+
"h5",
|
|
372
|
+
"h6",
|
|
373
|
+
"p",
|
|
374
|
+
"span",
|
|
375
|
+
"div",
|
|
376
|
+
"label",
|
|
377
|
+
"strong",
|
|
378
|
+
"em"
|
|
379
|
+
]);
|
|
348
380
|
var VARIANT_TAG = {
|
|
349
381
|
"display-2xl": "p",
|
|
350
382
|
"display-xl": "p",
|
|
@@ -369,7 +401,8 @@ var Text = class extends ThemeableElement {
|
|
|
369
401
|
this.as = "";
|
|
370
402
|
}
|
|
371
403
|
render() {
|
|
372
|
-
const
|
|
404
|
+
const requested = this.as && ALLOWED_TAGS.has(this.as) ? this.as : "";
|
|
405
|
+
const tag = unsafeStatic(requested || VARIANT_TAG[this.variant] || "p");
|
|
373
406
|
return html`<${tag} part="base"><slot></slot></${tag}>`;
|
|
374
407
|
}
|
|
375
408
|
};
|
|
@@ -439,7 +472,8 @@ var Accordion = class extends ThemeableElement {
|
|
|
439
472
|
* Handles the end of the transition to clear inline styles.
|
|
440
473
|
* @private
|
|
441
474
|
*/
|
|
442
|
-
handleTransitionEnd() {
|
|
475
|
+
handleTransitionEnd(e) {
|
|
476
|
+
if (e.target !== this._content || e.propertyName !== "height") return;
|
|
443
477
|
this._animating = false;
|
|
444
478
|
if (this.open) {
|
|
445
479
|
this._content.style.height = "auto";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type PropertyValues } from 'lit';
|
|
1
2
|
import { ThemeableElement } from '../../base';
|
|
2
|
-
import type { AlertVariant, AlertAppearance } from './alert.types';
|
|
3
|
+
import type { AlertVariant, AlertAppearance, AlertLabels } from './alert.types';
|
|
3
4
|
import '../icon-button/icon-button';
|
|
4
5
|
import '../text/text';
|
|
5
6
|
/**
|
|
@@ -9,11 +10,11 @@ import '../text/text';
|
|
|
9
10
|
*
|
|
10
11
|
* @slot - Alert body. Accepts any HTML — bold, links, lists, etc.
|
|
11
12
|
*
|
|
12
|
-
* @fires close - Fired when the dismiss button is clicked, just before the element is
|
|
13
|
+
* @fires close - Fired when the dismiss button is clicked, just before the element is hidden. Cancelable.
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* ```html
|
|
16
|
-
* <lt-alert variant="success"
|
|
17
|
+
* <lt-alert variant="success" heading="Upload complete">
|
|
17
18
|
* Your file has been processed and is ready to download.
|
|
18
19
|
* </lt-alert>
|
|
19
20
|
* ```
|
|
@@ -32,20 +33,42 @@ export declare class Alert extends ThemeableElement {
|
|
|
32
33
|
/** Visual treatment. `filled` uses a tinted background with border, `outlined` uses a white background with border, `solid` uses a solid color background with no border. */
|
|
33
34
|
appearance: AlertAppearance;
|
|
34
35
|
/** Optional bold heading above the body content. */
|
|
35
|
-
|
|
36
|
+
heading: string;
|
|
37
|
+
/**
|
|
38
|
+
* @deprecated Use `heading` instead. `title` collides with the browser's own native tooltip attribute — every
|
|
39
|
+
* HTML element has one regardless of custom-element status, so `<lt-alert title="…">` made hovering anywhere
|
|
40
|
+
* over the alert show a browser tooltip, and assistive tech could read it as a duplicate description (ALR-3).
|
|
41
|
+
* This alias keeps existing markup/JS working; the native `title` attribute is always stripped as soon as
|
|
42
|
+
* it's read, so the tooltip never appears.
|
|
43
|
+
*/
|
|
44
|
+
get title(): string;
|
|
45
|
+
set title(value: string);
|
|
36
46
|
/**
|
|
37
47
|
* Icon to show before the body. Leave empty for auto (shows variant icon for status variants),
|
|
38
48
|
* set to `"none"` to suppress, or pass any icon name to override.
|
|
39
49
|
*/
|
|
40
50
|
icon: string;
|
|
41
|
-
/** Show a dismiss button. Clicking it fires
|
|
51
|
+
/** Show a dismiss button. Clicking it fires `close` and hides the element (sets `open` to false). */
|
|
42
52
|
closable: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the alert is visible. Defaults to true, so existing markup with no attribute keeps showing.
|
|
55
|
+
* Dismissing (or setting this to false directly) hides the alert but does not remove it from the DOM —
|
|
56
|
+
* that choice is left to the consumer, since a framework that owns this node would otherwise fight the
|
|
57
|
+
* alert over removing it out from under its own reconciliation.
|
|
58
|
+
*/
|
|
59
|
+
open: boolean;
|
|
43
60
|
/** Background color override. Accepts a hex value (#1a1a2e) or a CSS token name (--lt-color-primary-600). */
|
|
44
61
|
background: string;
|
|
45
|
-
/** Renders the
|
|
62
|
+
/** Renders the heading in small caps with wider letter spacing. */
|
|
46
63
|
uppercase: boolean;
|
|
64
|
+
/** Overridable UI text (the dismiss button's accessible name), for i18n. English defaults — override only the keys you need. */
|
|
65
|
+
labels: Partial<AlertLabels>;
|
|
66
|
+
private get _labels();
|
|
67
|
+
connectedCallback(): void;
|
|
47
68
|
private static readonly _iconMap;
|
|
48
69
|
private _handleClose;
|
|
70
|
+
updated(changed: PropertyValues<this>): void;
|
|
71
|
+
private get _role();
|
|
49
72
|
private get _resolvedIcon();
|
|
50
73
|
render(): import("lit").TemplateResult<1>;
|
|
51
74
|
}
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export type AlertVariant = 'default' | 'success' | 'warning' | 'error' | 'info';
|
|
2
2
|
export type AlertAppearance = 'filled' | 'outlined' | 'solid';
|
|
3
|
+
/** Overridable UI text, for i18n — English defaults; override only the keys you need. */
|
|
4
|
+
export interface AlertLabels {
|
|
5
|
+
/** Accessible label for the dismiss button. */
|
|
6
|
+
dismiss: string;
|
|
7
|
+
}
|
|
@@ -63,11 +63,16 @@ var alertStyles = css`
|
|
|
63
63
|
transform: translateY(-4px);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/* Hidden once the fade above finishes. Not removed from the DOM — see the open property's doc comment. */
|
|
67
|
+
:host(:not([open])) {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
66
71
|
/* ── Per-variant tokens ──────────────────────────────────── */
|
|
67
72
|
|
|
68
73
|
:host([variant='success']) {
|
|
69
74
|
--_bg-subtle: var(--lt-alert-bg, var(--lt-bg-success-subtle));
|
|
70
|
-
--_bg-solid: var(--lt-alert-bg, var(--lt-
|
|
75
|
+
--_bg-solid: var(--lt-alert-bg, var(--lt-interactive-success-bg));
|
|
71
76
|
--_border: var(--lt-alert-border-color, var(--lt-border-success-strong));
|
|
72
77
|
--_color: var(--lt-alert-color, var(--lt-text-success));
|
|
73
78
|
--_color-solid: var(--lt-alert-color, var(--lt-text-on-success));
|
|
@@ -75,7 +80,7 @@ var alertStyles = css`
|
|
|
75
80
|
|
|
76
81
|
:host([variant='warning']) {
|
|
77
82
|
--_bg-subtle: var(--lt-alert-bg, var(--lt-bg-warning-subtle));
|
|
78
|
-
--_bg-solid: var(--lt-alert-bg, var(--lt-
|
|
83
|
+
--_bg-solid: var(--lt-alert-bg, var(--lt-interactive-warning-bg));
|
|
79
84
|
--_border: var(--lt-alert-border-color, var(--lt-border-warning-strong));
|
|
80
85
|
--_color: var(--lt-alert-color, var(--lt-text-warning));
|
|
81
86
|
--_color-solid: var(--lt-alert-color, var(--lt-text-on-warning));
|
|
@@ -83,7 +88,7 @@ var alertStyles = css`
|
|
|
83
88
|
|
|
84
89
|
:host([variant='error']) {
|
|
85
90
|
--_bg-subtle: var(--lt-alert-bg, var(--lt-bg-error-subtle));
|
|
86
|
-
--_bg-solid: var(--lt-alert-bg, var(--lt-
|
|
91
|
+
--_bg-solid: var(--lt-alert-bg, var(--lt-interactive-error-bg));
|
|
87
92
|
--_border: var(--lt-alert-border-color, var(--lt-border-error-strong));
|
|
88
93
|
--_color: var(--lt-alert-color, var(--lt-text-error));
|
|
89
94
|
--_color-solid: var(--lt-alert-color, var(--lt-text-on-error));
|
|
@@ -91,7 +96,7 @@ var alertStyles = css`
|
|
|
91
96
|
|
|
92
97
|
:host([variant='info']) {
|
|
93
98
|
--_bg-subtle: var(--lt-alert-bg, var(--lt-bg-info-subtle));
|
|
94
|
-
--_bg-solid: var(--lt-alert-bg, var(--lt-
|
|
99
|
+
--_bg-solid: var(--lt-alert-bg, var(--lt-interactive-info-bg));
|
|
95
100
|
--_border: var(--lt-alert-border-color, var(--lt-border-info-strong));
|
|
96
101
|
--_color: var(--lt-alert-color, var(--lt-text-info));
|
|
97
102
|
--_color-solid: var(--lt-alert-color, var(--lt-text-on-info));
|
|
@@ -124,7 +129,8 @@ var alertStyles = css`
|
|
|
124
129
|
color: var(--_color);
|
|
125
130
|
}
|
|
126
131
|
|
|
127
|
-
/* solid — solid color bg, no border
|
|
132
|
+
/* solid — solid color bg, no border. Fills come from the interactive tokens, the same ones the on-colour is
|
|
133
|
+
picked against, so the text holds AA; body text is never dimmed with opacity, which would only lower it. */
|
|
128
134
|
:host([appearance='solid']) .inner {
|
|
129
135
|
background: var(--_bg-solid);
|
|
130
136
|
border: none;
|
|
@@ -155,10 +161,6 @@ var alertStyles = css`
|
|
|
155
161
|
line-height: 1.5;
|
|
156
162
|
}
|
|
157
163
|
|
|
158
|
-
.title + .content {
|
|
159
|
-
opacity: 0.8;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
164
|
/* ── Close button ────────────────────────────────────────── */
|
|
163
165
|
|
|
164
166
|
.close {
|
|
@@ -176,6 +178,14 @@ var alertStyles = css`
|
|
|
176
178
|
letter-spacing: 0.05rem;
|
|
177
179
|
text-transform: lowercase;
|
|
178
180
|
}
|
|
181
|
+
|
|
182
|
+
/* ── Reduced motion ─────────────────────────────────────────────────────── */
|
|
183
|
+
|
|
184
|
+
@media (prefers-reduced-motion: reduce) {
|
|
185
|
+
:host {
|
|
186
|
+
transition: none;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
179
189
|
`;
|
|
180
190
|
|
|
181
191
|
// src/utils/dispatch.ts
|
|
@@ -184,6 +194,13 @@ var dispatch = (host, name, detail, init) => host.dispatchEvent(new CustomEvent(
|
|
|
184
194
|
// src/utils/color.ts
|
|
185
195
|
var resolveColorValue = (value) => value.startsWith("--") ? `var(${value})` : value;
|
|
186
196
|
|
|
197
|
+
// src/utils/dev-warn.ts
|
|
198
|
+
var devWarn = (tag, message) => {
|
|
199
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
200
|
+
console.warn(`[${tag}] ${message}`);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
187
204
|
// src/components/icon-button/icon-button.ts
|
|
188
205
|
import { html, nothing } from "lit";
|
|
189
206
|
import { customElement, property as property2 } from "lit/decorators.js";
|
|
@@ -435,6 +452,14 @@ var iconButtonStyles = css2`
|
|
|
435
452
|
:host([round]) [part='base'] {
|
|
436
453
|
border-radius: 50%;
|
|
437
454
|
}
|
|
455
|
+
|
|
456
|
+
/* ── Reduced motion ─────────────────────────────────────────────────────── */
|
|
457
|
+
|
|
458
|
+
@media (prefers-reduced-motion: reduce) {
|
|
459
|
+
[part='base'] {
|
|
460
|
+
transition: none;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
438
463
|
`;
|
|
439
464
|
|
|
440
465
|
// src/components/shared/aria-forwarding.ts
|
|
@@ -443,7 +468,8 @@ var FORWARDED_ARIA_ATTRIBUTES = [
|
|
|
443
468
|
"aria-expanded",
|
|
444
469
|
"aria-haspopup",
|
|
445
470
|
"aria-controls",
|
|
446
|
-
"aria-current"
|
|
471
|
+
"aria-current",
|
|
472
|
+
"aria-description"
|
|
447
473
|
];
|
|
448
474
|
var AriaForwardingController = class {
|
|
449
475
|
constructor(host, getTarget) {
|
|
@@ -483,11 +509,30 @@ var IconButton = class extends ThemeableElement {
|
|
|
483
509
|
this.bordered = false;
|
|
484
510
|
this.size = "md";
|
|
485
511
|
this.disabled = false;
|
|
512
|
+
this._blockClickWhileDisabled = (e) => {
|
|
513
|
+
if (this.disabled) {
|
|
514
|
+
e.preventDefault();
|
|
515
|
+
e.stopImmediatePropagation();
|
|
516
|
+
}
|
|
517
|
+
};
|
|
486
518
|
this.href = "";
|
|
487
519
|
this.target = "";
|
|
488
520
|
this.rel = "";
|
|
489
521
|
this.round = false;
|
|
490
522
|
}
|
|
523
|
+
firstUpdated() {
|
|
524
|
+
if (!this.label && !this.textContent?.trim()) {
|
|
525
|
+
devWarn("lt-icon-button", "no label or visible text \u2014 set `label` so screen readers can name the button");
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
connectedCallback() {
|
|
529
|
+
super.connectedCallback();
|
|
530
|
+
this.addEventListener("click", this._blockClickWhileDisabled, { capture: true });
|
|
531
|
+
}
|
|
532
|
+
disconnectedCallback() {
|
|
533
|
+
super.disconnectedCallback();
|
|
534
|
+
this.removeEventListener("click", this._blockClickWhileDisabled, { capture: true });
|
|
535
|
+
}
|
|
491
536
|
_inner() {
|
|
492
537
|
return this.icon ? html`<lt-icon name=${this.icon}></lt-icon>` : html`<slot></slot>`;
|
|
493
538
|
}
|
|
@@ -721,6 +766,20 @@ var textStyles = css3`
|
|
|
721
766
|
`;
|
|
722
767
|
|
|
723
768
|
// src/components/text/text.ts
|
|
769
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
770
|
+
"h1",
|
|
771
|
+
"h2",
|
|
772
|
+
"h3",
|
|
773
|
+
"h4",
|
|
774
|
+
"h5",
|
|
775
|
+
"h6",
|
|
776
|
+
"p",
|
|
777
|
+
"span",
|
|
778
|
+
"div",
|
|
779
|
+
"label",
|
|
780
|
+
"strong",
|
|
781
|
+
"em"
|
|
782
|
+
]);
|
|
724
783
|
var VARIANT_TAG = {
|
|
725
784
|
"display-2xl": "p",
|
|
726
785
|
"display-xl": "p",
|
|
@@ -745,7 +804,8 @@ var Text = class extends ThemeableElement {
|
|
|
745
804
|
this.as = "";
|
|
746
805
|
}
|
|
747
806
|
render() {
|
|
748
|
-
const
|
|
807
|
+
const requested = this.as && ALLOWED_TAGS.has(this.as) ? this.as : "";
|
|
808
|
+
const tag = unsafeStatic(requested || VARIANT_TAG[this.variant] || "p");
|
|
749
809
|
return html2`<${tag} part="base"><slot></slot></${tag}>`;
|
|
750
810
|
}
|
|
751
811
|
};
|
|
@@ -761,22 +821,63 @@ Text = __decorateClass([
|
|
|
761
821
|
], Text);
|
|
762
822
|
|
|
763
823
|
// src/components/alert/alert.ts
|
|
824
|
+
var DEFAULT_LABELS = {
|
|
825
|
+
dismiss: "Dismiss"
|
|
826
|
+
};
|
|
764
827
|
var Alert = class extends ThemeableElement {
|
|
765
828
|
constructor() {
|
|
766
829
|
super(...arguments);
|
|
767
830
|
this.variant = "default";
|
|
768
831
|
this.appearance = "filled";
|
|
769
|
-
this.
|
|
832
|
+
this.heading = "";
|
|
770
833
|
this.icon = "";
|
|
771
834
|
this.closable = false;
|
|
835
|
+
this.open = true;
|
|
772
836
|
this.background = "";
|
|
773
837
|
this.uppercase = false;
|
|
838
|
+
this.labels = {};
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* @deprecated Use `heading` instead. `title` collides with the browser's own native tooltip attribute — every
|
|
842
|
+
* HTML element has one regardless of custom-element status, so `<lt-alert title="…">` made hovering anywhere
|
|
843
|
+
* over the alert show a browser tooltip, and assistive tech could read it as a duplicate description (ALR-3).
|
|
844
|
+
* This alias keeps existing markup/JS working; the native `title` attribute is always stripped as soon as
|
|
845
|
+
* it's read, so the tooltip never appears.
|
|
846
|
+
*/
|
|
847
|
+
get title() {
|
|
848
|
+
return this.heading;
|
|
849
|
+
}
|
|
850
|
+
set title(value) {
|
|
851
|
+
this.heading = value;
|
|
852
|
+
}
|
|
853
|
+
get _labels() {
|
|
854
|
+
return { ...DEFAULT_LABELS, ...this.labels };
|
|
855
|
+
}
|
|
856
|
+
connectedCallback() {
|
|
857
|
+
super.connectedCallback();
|
|
858
|
+
if (this.hasAttribute("title")) {
|
|
859
|
+
if (!this.heading) this.heading = this.getAttribute("title");
|
|
860
|
+
this.removeAttribute("title");
|
|
861
|
+
}
|
|
774
862
|
}
|
|
775
863
|
_handleClose() {
|
|
776
864
|
const cancelled = !dispatch(this, "close", void 0, { cancelable: true });
|
|
777
865
|
if (cancelled) return;
|
|
866
|
+
this.tabIndex = -1;
|
|
867
|
+
this.focus();
|
|
778
868
|
this.setAttribute("dismissed", "");
|
|
779
|
-
setTimeout(() =>
|
|
869
|
+
setTimeout(() => {
|
|
870
|
+
this.open = false;
|
|
871
|
+
}, 200);
|
|
872
|
+
}
|
|
873
|
+
updated(changed) {
|
|
874
|
+
super.updated(changed);
|
|
875
|
+
if (changed.has("open") && this.open) this.removeAttribute("dismissed");
|
|
876
|
+
}
|
|
877
|
+
// Error/warning alerts are urgent enough to interrupt the screen reader (`alert`, assertive); the rest are
|
|
878
|
+
// informational and should announce without cutting off whatever the user was already hearing (`status`, polite).
|
|
879
|
+
get _role() {
|
|
880
|
+
return this.variant === "error" || this.variant === "warning" ? "alert" : "status";
|
|
780
881
|
}
|
|
781
882
|
get _resolvedIcon() {
|
|
782
883
|
if (this.icon === "none") return "";
|
|
@@ -788,17 +889,17 @@ var Alert = class extends ThemeableElement {
|
|
|
788
889
|
const iconName = this._resolvedIcon;
|
|
789
890
|
const bgStyle = styleMap(this.background ? { background: resolveColorValue(this.background) } : {});
|
|
790
891
|
return html3`
|
|
791
|
-
<div class="inner" part="base" role
|
|
892
|
+
<div class="inner" part="base" role=${this._role} style=${bgStyle}>
|
|
792
893
|
${iconName ? html3`<lt-icon class="icon" name=${iconName} part="icon"></lt-icon>` : ""}
|
|
793
894
|
<div class="body">
|
|
794
|
-
${this.
|
|
895
|
+
${this.heading ? html3`<lt-text variant="h6" as="p" class="title" part="title">${this.heading}</lt-text>` : ""}
|
|
795
896
|
<div class="content" part="content"><slot></slot></div>
|
|
796
897
|
</div>
|
|
797
898
|
${this.closable ? html3`<lt-icon-button
|
|
798
899
|
class="close"
|
|
799
900
|
part="close"
|
|
800
901
|
icon="xmark"
|
|
801
|
-
label
|
|
902
|
+
label=${this._labels.dismiss}
|
|
802
903
|
size="sm"
|
|
803
904
|
@click=${this._handleClose}
|
|
804
905
|
></lt-icon-button>` : ""}
|
|
@@ -822,19 +923,25 @@ __decorateClass([
|
|
|
822
923
|
], Alert.prototype, "appearance", 2);
|
|
823
924
|
__decorateClass([
|
|
824
925
|
property4({ reflect: true })
|
|
825
|
-
], Alert.prototype, "
|
|
926
|
+
], Alert.prototype, "heading", 2);
|
|
826
927
|
__decorateClass([
|
|
827
928
|
property4({ reflect: true })
|
|
828
929
|
], Alert.prototype, "icon", 2);
|
|
829
930
|
__decorateClass([
|
|
830
931
|
property4({ type: Boolean, reflect: true })
|
|
831
932
|
], Alert.prototype, "closable", 2);
|
|
933
|
+
__decorateClass([
|
|
934
|
+
property4({ type: Boolean, reflect: true })
|
|
935
|
+
], Alert.prototype, "open", 2);
|
|
832
936
|
__decorateClass([
|
|
833
937
|
property4({ reflect: true })
|
|
834
938
|
], Alert.prototype, "background", 2);
|
|
835
939
|
__decorateClass([
|
|
836
940
|
property4({ type: Boolean, reflect: true })
|
|
837
941
|
], Alert.prototype, "uppercase", 2);
|
|
942
|
+
__decorateClass([
|
|
943
|
+
property4({ type: Object })
|
|
944
|
+
], Alert.prototype, "labels", 2);
|
|
838
945
|
Alert = __decorateClass([
|
|
839
946
|
customElement3("lt-alert")
|
|
840
947
|
], Alert);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ThemeableElement } from '../../base';
|
|
2
|
+
import type { PropertyValues } from 'lit';
|
|
2
3
|
import type { AvatarSize, AvatarShape, AvatarColor } from './avatar.types';
|
|
3
4
|
import '@latty-ds/icons';
|
|
4
5
|
/**
|
|
@@ -22,6 +23,7 @@ export declare class Avatar extends ThemeableElement {
|
|
|
22
23
|
color: AvatarColor;
|
|
23
24
|
private _imgError;
|
|
24
25
|
private get _initials();
|
|
26
|
+
willUpdate(changed: PropertyValues<this>): void;
|
|
25
27
|
private _handleImgError;
|
|
26
28
|
render(): import("lit").TemplateResult<1>;
|
|
27
29
|
}
|
|
@@ -11,6 +11,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
11
11
|
|
|
12
12
|
// src/components/avatar/avatar.ts
|
|
13
13
|
import { html } from "lit";
|
|
14
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
14
15
|
|
|
15
16
|
// src/base/themeable-element.ts
|
|
16
17
|
import { LitElement } from "lit";
|
|
@@ -176,17 +177,23 @@ var Avatar = class extends ThemeableElement {
|
|
|
176
177
|
this.color = "neutral";
|
|
177
178
|
this._imgError = false;
|
|
178
179
|
}
|
|
180
|
+
// Array.from walks code points, so an emoji or other astral character isn't cut in half; empty words are dropped,
|
|
181
|
+
// so a whitespace-only name yields no initials instead of throwing.
|
|
179
182
|
get _initials() {
|
|
180
|
-
return this.name.
|
|
183
|
+
return this.name.split(/\s+/).filter(Boolean).slice(0, 2).map((word) => Array.from(word)[0].toUpperCase()).join("");
|
|
184
|
+
}
|
|
185
|
+
willUpdate(changed) {
|
|
186
|
+
if (changed.has("src")) this._imgError = false;
|
|
181
187
|
}
|
|
182
188
|
_handleImgError() {
|
|
183
189
|
this._imgError = true;
|
|
184
190
|
}
|
|
185
191
|
render() {
|
|
186
192
|
const showImage = this.src && !this._imgError;
|
|
187
|
-
const showInitials = !showImage && this.
|
|
193
|
+
const showInitials = !showImage && this._initials;
|
|
194
|
+
const label = this.alt || this.name.trim();
|
|
188
195
|
return html`
|
|
189
|
-
<span part="base" aria-label=${
|
|
196
|
+
<span part="base" role=${label ? "img" : "presentation"} aria-label=${ifDefined(label || void 0)}>
|
|
190
197
|
${showImage ? html`<img part="image" src=${this.src} alt=${this.alt || this.name} @error=${this._handleImgError} />` : showInitials ? html`<span part="initials" class="initials">${this._initials}</span>` : html`<lt-icon part="icon" name="user" size="sm"></lt-icon>`}
|
|
191
198
|
</span>
|
|
192
199
|
`;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type PropertyValues } from 'lit';
|
|
2
2
|
import { ThemeableElement } from '../../base';
|
|
3
|
+
import type { BreadcrumbLabels } from './breadcrumb.types';
|
|
3
4
|
/**
|
|
4
5
|
* Navigation breadcrumb trail container.
|
|
5
6
|
* Place `lt-breadcrumb-item` elements inside as direct children.
|
|
@@ -23,6 +24,9 @@ export declare class Breadcrumb extends ThemeableElement {
|
|
|
23
24
|
* @default '/'
|
|
24
25
|
*/
|
|
25
26
|
separator: string;
|
|
27
|
+
/** Overridable UI text (the breadcrumb nav's landmark label), for i18n. English defaults — override only the keys you need. */
|
|
28
|
+
labels: Partial<BreadcrumbLabels>;
|
|
29
|
+
private get _labels();
|
|
26
30
|
updated(changed: PropertyValues<this>): void;
|
|
27
31
|
render(): import("lit").TemplateResult<1>;
|
|
28
32
|
}
|
|
@@ -62,13 +62,12 @@ var breadcrumbItemStyles = css`
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
[part='link'] {
|
|
65
|
-
color: var(--lt-
|
|
65
|
+
color: var(--lt-text-primary);
|
|
66
66
|
text-decoration: none;
|
|
67
67
|
transition: color 120ms ease;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
[part='link']:hover {
|
|
71
|
-
color: var(--lt-interactive-primary-bg-hover);
|
|
72
71
|
text-decoration: underline;
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -90,13 +89,28 @@ var breadcrumbItemStyles = css`
|
|
|
90
89
|
:host(:last-child) [part='separator'] {
|
|
91
90
|
display: none;
|
|
92
91
|
}
|
|
92
|
+
|
|
93
|
+
/* ── Reduced motion ─────────────────────────────────────────────────────── */
|
|
94
|
+
|
|
95
|
+
@media (prefers-reduced-motion: reduce) {
|
|
96
|
+
[part='link'] {
|
|
97
|
+
transition: none;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
93
100
|
`;
|
|
94
101
|
|
|
95
102
|
// src/components/breadcrumb/breadcrumb.ts
|
|
103
|
+
var DEFAULT_LABELS = {
|
|
104
|
+
navigation: "breadcrumb"
|
|
105
|
+
};
|
|
96
106
|
var Breadcrumb = class extends ThemeableElement {
|
|
97
107
|
constructor() {
|
|
98
108
|
super(...arguments);
|
|
99
109
|
this.separator = "/";
|
|
110
|
+
this.labels = {};
|
|
111
|
+
}
|
|
112
|
+
get _labels() {
|
|
113
|
+
return { ...DEFAULT_LABELS, ...this.labels };
|
|
100
114
|
}
|
|
101
115
|
updated(changed) {
|
|
102
116
|
super.updated(changed);
|
|
@@ -110,7 +124,7 @@ var Breadcrumb = class extends ThemeableElement {
|
|
|
110
124
|
}
|
|
111
125
|
render() {
|
|
112
126
|
return html`
|
|
113
|
-
<nav aria-label
|
|
127
|
+
<nav aria-label=${this._labels.navigation}>
|
|
114
128
|
<div part="list" role="list">
|
|
115
129
|
<slot></slot>
|
|
116
130
|
</div>
|
|
@@ -122,6 +136,9 @@ Breadcrumb.styles = breadcrumbStyles;
|
|
|
122
136
|
__decorateClass([
|
|
123
137
|
property2()
|
|
124
138
|
], Breadcrumb.prototype, "separator", 2);
|
|
139
|
+
__decorateClass([
|
|
140
|
+
property2({ type: Object })
|
|
141
|
+
], Breadcrumb.prototype, "labels", 2);
|
|
125
142
|
Breadcrumb = __decorateClass([
|
|
126
143
|
customElement("lt-breadcrumb")
|
|
127
144
|
], Breadcrumb);
|
|
@@ -42,9 +42,22 @@ import '@latty-ds/icons';
|
|
|
42
42
|
export declare class Button extends ThemeableElement {
|
|
43
43
|
static styles: import("lit").CSSResult;
|
|
44
44
|
static formAssociated: boolean;
|
|
45
|
+
static shadowRootOptions: {
|
|
46
|
+
delegatesFocus: boolean;
|
|
47
|
+
clonable?: boolean;
|
|
48
|
+
customElementRegistry?: CustomElementRegistry | null;
|
|
49
|
+
mode: ShadowRootMode;
|
|
50
|
+
serializable?: boolean;
|
|
51
|
+
slotAssignment?: SlotAssignmentMode;
|
|
52
|
+
};
|
|
45
53
|
private _internals;
|
|
46
54
|
private _ariaForwarding;
|
|
55
|
+
private _fieldsetDisabled;
|
|
47
56
|
constructor();
|
|
57
|
+
connectedCallback(): void;
|
|
58
|
+
disconnectedCallback(): void;
|
|
59
|
+
private _blockClickWhileBusy;
|
|
60
|
+
formDisabledCallback(disabled: boolean): void;
|
|
48
61
|
/**
|
|
49
62
|
* Visual variant that determines the button's color scheme.
|
|
50
63
|
* @default 'primary'
|
|
@@ -117,6 +130,26 @@ export declare class Button extends ThemeableElement {
|
|
|
117
130
|
* @default 'button'
|
|
118
131
|
*/
|
|
119
132
|
type: ButtonType;
|
|
133
|
+
/**
|
|
134
|
+
* Name submitted alongside `value` when this button triggers a form submission (`type="submit"`), matching a
|
|
135
|
+
* native `<button name value>` — only included in the submitted data for the button that actually triggered
|
|
136
|
+
* the submission, not every submit button in the form.
|
|
137
|
+
* @default ''
|
|
138
|
+
*/
|
|
139
|
+
name: string;
|
|
140
|
+
/**
|
|
141
|
+
* Value submitted alongside `name`. See `name`.
|
|
142
|
+
* @default ''
|
|
143
|
+
*/
|
|
144
|
+
value: string;
|
|
145
|
+
/**
|
|
146
|
+
* Overrides the form's own `action` for a submission triggered by this button, matching a native
|
|
147
|
+
* `<button formaction>`. Only applies when `type="submit"`.
|
|
148
|
+
* @default ''
|
|
149
|
+
*/
|
|
150
|
+
formAction: string;
|
|
151
|
+
private _proxySubmitBtn;
|
|
152
|
+
private _getProxySubmitBtn;
|
|
120
153
|
private _handleClick;
|
|
121
154
|
render(): import("lit").TemplateResult<1>;
|
|
122
155
|
}
|