@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
|
@@ -9,8 +9,13 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
9
9
|
return result;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// src/components/shared/form-field.ts
|
|
13
|
+
var fieldCount = 0;
|
|
14
|
+
var createFieldIds = () => ({ helper: `lt-field-${fieldCount++}-helper` });
|
|
15
|
+
|
|
12
16
|
// src/components/date-input/date-input.ts
|
|
13
|
-
import { html as html3, nothing } from "lit";
|
|
17
|
+
import { html as html3, nothing as nothing2 } from "lit";
|
|
18
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
14
19
|
import { customElement as customElement3, property as property4, state as state2 } from "lit/decorators.js";
|
|
15
20
|
|
|
16
21
|
// src/base/themeable-element.ts
|
|
@@ -39,7 +44,7 @@ __decorateClass([
|
|
|
39
44
|
import "@latty-ds/icons";
|
|
40
45
|
|
|
41
46
|
// src/components/calendar/calendar.ts
|
|
42
|
-
import { html } from "lit";
|
|
47
|
+
import { html, nothing } from "lit";
|
|
43
48
|
import { customElement, property as property2, state } from "lit/decorators.js";
|
|
44
49
|
import "@latty-ds/icons";
|
|
45
50
|
|
|
@@ -189,7 +194,9 @@ var calendarStyles = css`
|
|
|
189
194
|
width: 100%;
|
|
190
195
|
}
|
|
191
196
|
|
|
192
|
-
|
|
197
|
+
/* aria-disabled, not the disabled attribute — a disabled day stays focusable, so keyboard users can arrow
|
|
198
|
+
through it instead of the roving tabindex skipping straight over it (it just can't be selected). */
|
|
199
|
+
.day[aria-disabled='true'] {
|
|
193
200
|
cursor: not-allowed;
|
|
194
201
|
}
|
|
195
202
|
|
|
@@ -212,7 +219,7 @@ var calendarStyles = css`
|
|
|
212
219
|
width: 2.25rem;
|
|
213
220
|
}
|
|
214
221
|
|
|
215
|
-
.day:hover:not(
|
|
222
|
+
.day:hover:not([aria-disabled='true']) .day__inner {
|
|
216
223
|
background: var(--lt-bg-neutral-subtle);
|
|
217
224
|
}
|
|
218
225
|
|
|
@@ -235,7 +242,7 @@ var calendarStyles = css`
|
|
|
235
242
|
font-weight: 600;
|
|
236
243
|
}
|
|
237
244
|
|
|
238
|
-
.day--selected:hover:not(
|
|
245
|
+
.day--selected:hover:not([aria-disabled='true']) .day__inner {
|
|
239
246
|
background: var(--lt-interactive-primary-bg-hover);
|
|
240
247
|
}
|
|
241
248
|
|
|
@@ -253,7 +260,7 @@ var calendarStyles = css`
|
|
|
253
260
|
pointer-events: none;
|
|
254
261
|
}
|
|
255
262
|
|
|
256
|
-
.day
|
|
263
|
+
.day[aria-disabled='true'] .day__inner {
|
|
257
264
|
color: var(--lt-text-disabled);
|
|
258
265
|
opacity: 0.4;
|
|
259
266
|
}
|
|
@@ -280,7 +287,7 @@ var calendarStyles = css`
|
|
|
280
287
|
background: var(--lt-bg-primary-subtle);
|
|
281
288
|
}
|
|
282
289
|
|
|
283
|
-
.day--in-range:hover:not(
|
|
290
|
+
.day--in-range:hover:not([aria-disabled='true']) .day__inner {
|
|
284
291
|
background: var(--lt-bg-neutral-subtle);
|
|
285
292
|
}
|
|
286
293
|
|
|
@@ -298,7 +305,7 @@ var calendarStyles = css`
|
|
|
298
305
|
font-weight: 600;
|
|
299
306
|
}
|
|
300
307
|
|
|
301
|
-
.day--range-confirmed:hover:not(
|
|
308
|
+
.day--range-confirmed:hover:not([aria-disabled='true']) .day__inner {
|
|
302
309
|
background: var(--lt-interactive-primary-bg-hover);
|
|
303
310
|
}
|
|
304
311
|
|
|
@@ -421,6 +428,20 @@ var calendarStyles = css`
|
|
|
421
428
|
cursor: not-allowed;
|
|
422
429
|
opacity: 0.5;
|
|
423
430
|
}
|
|
431
|
+
|
|
432
|
+
/* ── Reduced motion ─────────────────────────────────────────────────────── */
|
|
433
|
+
|
|
434
|
+
@media (prefers-reduced-motion: reduce) {
|
|
435
|
+
.month-label-btn,
|
|
436
|
+
.picker-chevron,
|
|
437
|
+
.nav-btn,
|
|
438
|
+
.day,
|
|
439
|
+
.day__inner,
|
|
440
|
+
.picker-month-btn,
|
|
441
|
+
.today-btn {
|
|
442
|
+
transition: none;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
424
445
|
`;
|
|
425
446
|
|
|
426
447
|
// src/utils/dispatch.ts
|
|
@@ -437,7 +458,30 @@ var createClickOutsideHandler = (host, onOutside, options) => {
|
|
|
437
458
|
return () => document.removeEventListener(eventName, handler, capture ? { capture: true } : void 0);
|
|
438
459
|
};
|
|
439
460
|
|
|
461
|
+
// src/utils/dev-warn.ts
|
|
462
|
+
var devWarn = (tag, message) => {
|
|
463
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
464
|
+
console.warn(`[${tag}] ${message}`);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
440
468
|
// src/components/calendar/calendar.ts
|
|
469
|
+
var DEFAULT_LABELS = {
|
|
470
|
+
today: "Today",
|
|
471
|
+
previousMonth: "Previous month",
|
|
472
|
+
nextMonth: "Next month",
|
|
473
|
+
previousYear: "Previous year",
|
|
474
|
+
nextYear: "Next year",
|
|
475
|
+
chooseMonthYear: (monthYear) => `${monthYear}, choose month and year`
|
|
476
|
+
};
|
|
477
|
+
function deriveWeekStart(locale) {
|
|
478
|
+
try {
|
|
479
|
+
const info = new Intl.Locale(locale).getWeekInfo?.();
|
|
480
|
+
if (info) return String(info.firstDay % 7);
|
|
481
|
+
} catch {
|
|
482
|
+
}
|
|
483
|
+
return "0";
|
|
484
|
+
}
|
|
441
485
|
var Calendar = class extends ThemeableElement {
|
|
442
486
|
constructor() {
|
|
443
487
|
super(...arguments);
|
|
@@ -448,12 +492,11 @@ var Calendar = class extends ThemeableElement {
|
|
|
448
492
|
this.min = "";
|
|
449
493
|
this.max = "";
|
|
450
494
|
this.locale = "en-US";
|
|
451
|
-
this.weekStart = "0";
|
|
452
495
|
this.showOutsideDays = true;
|
|
453
496
|
this.disabled = false;
|
|
454
497
|
this.months = 1;
|
|
455
|
-
/** Specific dates to disable, as an array of Date objects. Not reflected as an attribute. */
|
|
456
498
|
this.disabledDates = [];
|
|
499
|
+
this.labels = {};
|
|
457
500
|
this._viewYear = (/* @__PURE__ */ new Date()).getFullYear();
|
|
458
501
|
this._viewMonth = (/* @__PURE__ */ new Date()).getMonth();
|
|
459
502
|
this._focusedDate = null;
|
|
@@ -480,10 +523,10 @@ var Calendar = class extends ThemeableElement {
|
|
|
480
523
|
if (this.mode === "range") this._hoverDate = null;
|
|
481
524
|
};
|
|
482
525
|
this._handleKeyDown = (e) => {
|
|
483
|
-
const
|
|
484
|
-
const focusedDate = this.
|
|
526
|
+
const currentIso = e.currentTarget.dataset.date ?? "";
|
|
527
|
+
const focusedDate = this._parseDate(currentIso) ?? new Date(this._viewYear, this._viewMonth, 1);
|
|
485
528
|
const next = new Date(focusedDate);
|
|
486
|
-
const weekStart = Number(this.
|
|
529
|
+
const weekStart = Number(this._weekStart);
|
|
487
530
|
switch (e.key) {
|
|
488
531
|
case "ArrowRight":
|
|
489
532
|
next.setDate(next.getDate() + 1);
|
|
@@ -535,6 +578,13 @@ var Calendar = class extends ThemeableElement {
|
|
|
535
578
|
this._focusCell(this._toIso(next));
|
|
536
579
|
};
|
|
537
580
|
}
|
|
581
|
+
/** `weekStart` if explicitly set, otherwise derived from `locale`. Internal code should always read this, never `weekStart` directly. */
|
|
582
|
+
get _weekStart() {
|
|
583
|
+
return this.weekStart ?? deriveWeekStart(this.locale);
|
|
584
|
+
}
|
|
585
|
+
get _labels() {
|
|
586
|
+
return { ...DEFAULT_LABELS, ...this.labels };
|
|
587
|
+
}
|
|
538
588
|
willUpdate(changed) {
|
|
539
589
|
super.willUpdate(changed);
|
|
540
590
|
if (changed.has("value") && this.value) {
|
|
@@ -593,7 +643,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
593
643
|
_buildDays(year = this._viewYear, month = this._viewMonth) {
|
|
594
644
|
const today = /* @__PURE__ */ new Date();
|
|
595
645
|
const selected = this._parseDate(this.value);
|
|
596
|
-
const weekStart = Number(this.
|
|
646
|
+
const weekStart = Number(this._weekStart);
|
|
597
647
|
const rangeStart = this.mode === "range" ? this._parseDate(this.valueStart) : null;
|
|
598
648
|
const rangeEnd = this.mode === "range" ? this._parseDate(this.valueEnd) : null;
|
|
599
649
|
let visHoverStart = null;
|
|
@@ -646,7 +696,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
646
696
|
return days;
|
|
647
697
|
}
|
|
648
698
|
_getWeekdayLabels() {
|
|
649
|
-
const weekStart = Number(this.
|
|
699
|
+
const weekStart = Number(this._weekStart);
|
|
650
700
|
const fmt = new Intl.DateTimeFormat(this.locale, { weekday: "narrow" });
|
|
651
701
|
const refSunday = new Date(2026, 0, 4);
|
|
652
702
|
return Array.from({ length: 7 }, (_, i) => {
|
|
@@ -673,7 +723,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
673
723
|
this._viewMonth = month;
|
|
674
724
|
this._viewYear = year;
|
|
675
725
|
this._focusedDate = null;
|
|
676
|
-
dispatch(this, "
|
|
726
|
+
dispatch(this, "monthchange", { year: this._viewYear, month: this._viewMonth });
|
|
677
727
|
}
|
|
678
728
|
_openPicker() {
|
|
679
729
|
this._pickerYear = this._viewYear;
|
|
@@ -687,7 +737,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
687
737
|
this._viewMonth = month;
|
|
688
738
|
this._pickingMonthYear = false;
|
|
689
739
|
this._focusedDate = null;
|
|
690
|
-
dispatch(this, "
|
|
740
|
+
dispatch(this, "monthchange", { year: this._viewYear, month: this._viewMonth });
|
|
691
741
|
}
|
|
692
742
|
_selectDay(day) {
|
|
693
743
|
if (day.isDisabled || this.disabled) return;
|
|
@@ -773,7 +823,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
773
823
|
role="gridcell"
|
|
774
824
|
class=${classes}
|
|
775
825
|
data-date=${iso}
|
|
776
|
-
|
|
826
|
+
aria-disabled=${day.isDisabled ? "true" : nothing}
|
|
777
827
|
aria-selected=${isSelected ? "true" : "false"}
|
|
778
828
|
aria-label=${this._dayAriaLabel(day.date)}
|
|
779
829
|
tabindex=${this._isSameDay(day.date, rovingDate) ? 0 : -1}
|
|
@@ -807,11 +857,19 @@ var Calendar = class extends ThemeableElement {
|
|
|
807
857
|
render() {
|
|
808
858
|
const today = /* @__PURE__ */ new Date();
|
|
809
859
|
const isMulti = this.months > 1;
|
|
860
|
+
const isInView = (date) => {
|
|
861
|
+
if (!isMulti) return date.getFullYear() === this._viewYear && date.getMonth() === this._viewMonth;
|
|
862
|
+
for (let i = 0; i < this.months; i++) {
|
|
863
|
+
const { year, month } = this._monthAtOffset(i);
|
|
864
|
+
if (date.getFullYear() === year && date.getMonth() === month) return true;
|
|
865
|
+
}
|
|
866
|
+
return false;
|
|
867
|
+
};
|
|
810
868
|
const rovingAnchor = this._parseDate(this.mode === "range" ? this.valueStart : this.value);
|
|
811
|
-
const rovingDate = this._focusedDate ?? rovingAnchor ?? (today.getFullYear() === this._viewYear && today.getMonth() === this._viewMonth ? today : null) ?? new Date(this._viewYear, this._viewMonth, 1);
|
|
869
|
+
const rovingDate = (this._focusedDate && isInView(this._focusedDate) ? this._focusedDate : null) ?? (rovingAnchor && isInView(rovingAnchor) ? rovingAnchor : null) ?? (today.getFullYear() === this._viewYear && today.getMonth() === this._viewMonth ? today : null) ?? new Date(this._viewYear, this._viewMonth, 1);
|
|
812
870
|
const footer = html`
|
|
813
871
|
<div class="footer">
|
|
814
|
-
<button class="today-btn" ?disabled=${this.disabled} @click=${this._goToToday}
|
|
872
|
+
<button class="today-btn" ?disabled=${this.disabled} @click=${this._goToToday}>${this._labels.today}</button>
|
|
815
873
|
</div>
|
|
816
874
|
`;
|
|
817
875
|
if (isMulti) {
|
|
@@ -824,7 +882,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
824
882
|
<div class="header">
|
|
825
883
|
<button
|
|
826
884
|
class="nav-btn"
|
|
827
|
-
aria-label
|
|
885
|
+
aria-label=${this._labels.previousMonth}
|
|
828
886
|
?disabled=${this.disabled}
|
|
829
887
|
@click=${() => this._navigate(-1)}
|
|
830
888
|
>
|
|
@@ -839,7 +897,7 @@ var Calendar = class extends ThemeableElement {
|
|
|
839
897
|
</div>
|
|
840
898
|
<button
|
|
841
899
|
class="nav-btn"
|
|
842
|
-
aria-label
|
|
900
|
+
aria-label=${this._labels.nextMonth}
|
|
843
901
|
?disabled=${this.disabled}
|
|
844
902
|
@click=${() => this._navigate(1)}
|
|
845
903
|
>
|
|
@@ -868,8 +926,9 @@ var Calendar = class extends ThemeableElement {
|
|
|
868
926
|
const monthLabel = new Intl.DateTimeFormat(this.locale, { month: "long", year: "numeric" }).format(
|
|
869
927
|
new Date(this._viewYear, this._viewMonth)
|
|
870
928
|
);
|
|
871
|
-
const prevLabel = this._pickingMonthYear ?
|
|
872
|
-
const nextLabel = this._pickingMonthYear ?
|
|
929
|
+
const prevLabel = this._pickingMonthYear ? this._labels.previousYear : this._labels.previousMonth;
|
|
930
|
+
const nextLabel = this._pickingMonthYear ? this._labels.nextYear : this._labels.nextMonth;
|
|
931
|
+
const monthYearVisibleText = this._pickingMonthYear ? String(this._pickerYear) : monthLabel;
|
|
873
932
|
const header = html`
|
|
874
933
|
<div class="header">
|
|
875
934
|
<button class="nav-btn" aria-label=${prevLabel} ?disabled=${this.disabled} @click=${() => this._navigate(-1)}>
|
|
@@ -878,11 +937,11 @@ var Calendar = class extends ThemeableElement {
|
|
|
878
937
|
<button
|
|
879
938
|
class="month-label-btn ${this._pickingMonthYear ? "month-label-btn--open" : ""}"
|
|
880
939
|
aria-expanded=${this._pickingMonthYear ? "true" : "false"}
|
|
881
|
-
aria-label
|
|
940
|
+
aria-label=${this._labels.chooseMonthYear(monthYearVisibleText)}
|
|
882
941
|
?disabled=${this.disabled}
|
|
883
942
|
@click=${() => this._pickingMonthYear ? this._closePicker() : this._openPicker()}
|
|
884
943
|
>
|
|
885
|
-
<span aria-live="polite" aria-atomic="true">${
|
|
944
|
+
<span aria-live="polite" aria-atomic="true">${monthYearVisibleText}</span>
|
|
886
945
|
<lt-icon name="arrow-down" size="sm" class="picker-chevron"></lt-icon>
|
|
887
946
|
</button>
|
|
888
947
|
<button class="nav-btn" aria-label=${nextLabel} ?disabled=${this.disabled} @click=${() => this._navigate(1)}>
|
|
@@ -948,6 +1007,12 @@ __decorateClass([
|
|
|
948
1007
|
__decorateClass([
|
|
949
1008
|
property2({ type: Number, reflect: true })
|
|
950
1009
|
], Calendar.prototype, "months", 2);
|
|
1010
|
+
__decorateClass([
|
|
1011
|
+
property2({ attribute: false })
|
|
1012
|
+
], Calendar.prototype, "disabledDates", 2);
|
|
1013
|
+
__decorateClass([
|
|
1014
|
+
property2({ type: Object })
|
|
1015
|
+
], Calendar.prototype, "labels", 2);
|
|
951
1016
|
__decorateClass([
|
|
952
1017
|
state()
|
|
953
1018
|
], Calendar.prototype, "_viewYear", 2);
|
|
@@ -1139,6 +1204,20 @@ var textStyles = css2`
|
|
|
1139
1204
|
`;
|
|
1140
1205
|
|
|
1141
1206
|
// src/components/text/text.ts
|
|
1207
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
1208
|
+
"h1",
|
|
1209
|
+
"h2",
|
|
1210
|
+
"h3",
|
|
1211
|
+
"h4",
|
|
1212
|
+
"h5",
|
|
1213
|
+
"h6",
|
|
1214
|
+
"p",
|
|
1215
|
+
"span",
|
|
1216
|
+
"div",
|
|
1217
|
+
"label",
|
|
1218
|
+
"strong",
|
|
1219
|
+
"em"
|
|
1220
|
+
]);
|
|
1142
1221
|
var VARIANT_TAG = {
|
|
1143
1222
|
"display-2xl": "p",
|
|
1144
1223
|
"display-xl": "p",
|
|
@@ -1163,7 +1242,8 @@ var Text = class extends ThemeableElement {
|
|
|
1163
1242
|
this.as = "";
|
|
1164
1243
|
}
|
|
1165
1244
|
render() {
|
|
1166
|
-
const
|
|
1245
|
+
const requested = this.as && ALLOWED_TAGS.has(this.as) ? this.as : "";
|
|
1246
|
+
const tag = unsafeStatic(requested || VARIANT_TAG[this.variant] || "p");
|
|
1167
1247
|
return html2`<${tag} part="base"><slot></slot></${tag}>`;
|
|
1168
1248
|
}
|
|
1169
1249
|
};
|
|
@@ -2588,8 +2668,8 @@ var dateInputStyles = [
|
|
|
2588
2668
|
}
|
|
2589
2669
|
|
|
2590
2670
|
.required-indicator {
|
|
2591
|
-
color: var(--lt-
|
|
2592
|
-
margin-
|
|
2671
|
+
color: var(--lt-text-error);
|
|
2672
|
+
margin-inline-start: 2px;
|
|
2593
2673
|
}
|
|
2594
2674
|
|
|
2595
2675
|
/* ── Field ── */
|
|
@@ -2609,7 +2689,7 @@ var dateInputStyles = [
|
|
|
2609
2689
|
font-family: inherit;
|
|
2610
2690
|
justify-content: space-between;
|
|
2611
2691
|
outline: none;
|
|
2612
|
-
text-align:
|
|
2692
|
+
text-align: start;
|
|
2613
2693
|
transition:
|
|
2614
2694
|
border-color 150ms ease,
|
|
2615
2695
|
box-shadow 150ms ease;
|
|
@@ -2642,7 +2722,7 @@ var dateInputStyles = [
|
|
|
2642
2722
|
color: var(--lt-text-subtle);
|
|
2643
2723
|
flex-shrink: 0;
|
|
2644
2724
|
line-height: 0;
|
|
2645
|
-
margin-
|
|
2725
|
+
margin-inline-start: var(--lt-spacing-2);
|
|
2646
2726
|
}
|
|
2647
2727
|
|
|
2648
2728
|
/* ── Sizes ── */
|
|
@@ -2685,7 +2765,7 @@ var dateInputStyles = [
|
|
|
2685
2765
|
}
|
|
2686
2766
|
|
|
2687
2767
|
:host([variant='error']) .field-btn {
|
|
2688
|
-
border-color: var(--lt-
|
|
2768
|
+
border-color: var(--lt-text-error);
|
|
2689
2769
|
}
|
|
2690
2770
|
|
|
2691
2771
|
:host([variant='error']) .field-btn:focus-visible {
|
|
@@ -2708,29 +2788,87 @@ var dateInputStyles = [
|
|
|
2708
2788
|
}
|
|
2709
2789
|
|
|
2710
2790
|
:host([variant='error']) .helper-text {
|
|
2711
|
-
color: var(--lt-
|
|
2791
|
+
color: var(--lt-text-error);
|
|
2712
2792
|
}
|
|
2713
2793
|
|
|
2714
2794
|
:host([variant='success']) .helper-text {
|
|
2715
|
-
color: var(--lt-
|
|
2795
|
+
color: var(--lt-text-success);
|
|
2716
2796
|
}
|
|
2717
2797
|
|
|
2718
2798
|
:host([variant='warning']) .helper-text {
|
|
2719
|
-
color: var(--lt-
|
|
2799
|
+
color: var(--lt-text-warning);
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
/* ── Reduced motion ───────────────────────────────────────────────────── */
|
|
2803
|
+
|
|
2804
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2805
|
+
.field-btn {
|
|
2806
|
+
transition: none;
|
|
2807
|
+
}
|
|
2720
2808
|
}
|
|
2721
2809
|
`
|
|
2722
2810
|
];
|
|
2723
2811
|
|
|
2812
|
+
// src/components/shared/form-default.ts
|
|
2813
|
+
var FormDefaultController = class {
|
|
2814
|
+
constructor(host, get) {
|
|
2815
|
+
this._captured = false;
|
|
2816
|
+
this._get = get;
|
|
2817
|
+
host.addController(this);
|
|
2818
|
+
}
|
|
2819
|
+
hostConnected() {
|
|
2820
|
+
if (this._captured) return;
|
|
2821
|
+
this._captured = true;
|
|
2822
|
+
this.value = this._get();
|
|
2823
|
+
}
|
|
2824
|
+
};
|
|
2825
|
+
|
|
2826
|
+
// src/components/shared/form-disabled.ts
|
|
2827
|
+
var FormDisabledController = class {
|
|
2828
|
+
constructor(host) {
|
|
2829
|
+
this._fieldsetDisabled = false;
|
|
2830
|
+
this._host = host;
|
|
2831
|
+
host.addController(this);
|
|
2832
|
+
}
|
|
2833
|
+
// No-op — this controller has no connect-time work of its own (formDisabledCallback drives it instead), but
|
|
2834
|
+
// ReactiveController's members are all optional, and a class satisfying an all-optional interface with no
|
|
2835
|
+
// members in common is a TS error (TS2559); this gives it one.
|
|
2836
|
+
hostConnected() {
|
|
2837
|
+
}
|
|
2838
|
+
/** Whether an ancestor `<fieldset>` is currently disabled. */
|
|
2839
|
+
get fieldsetDisabled() {
|
|
2840
|
+
return this._fieldsetDisabled;
|
|
2841
|
+
}
|
|
2842
|
+
setFieldsetDisabled(disabled) {
|
|
2843
|
+
if (this._fieldsetDisabled === disabled) return;
|
|
2844
|
+
this._fieldsetDisabled = disabled;
|
|
2845
|
+
this._host.requestUpdate();
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2848
|
+
|
|
2724
2849
|
// src/components/date-input/date-input.ts
|
|
2850
|
+
var ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
2851
|
+
var DEFAULT_LABELS2 = {
|
|
2852
|
+
validationMessage: "Please select a date",
|
|
2853
|
+
datePicker: "Date picker"
|
|
2854
|
+
};
|
|
2855
|
+
var parseIsoDate = (value) => {
|
|
2856
|
+
const match = ISO_DATE.exec(value);
|
|
2857
|
+
if (!match) return null;
|
|
2858
|
+
const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
2859
|
+
const date = new Date(year, month - 1, day);
|
|
2860
|
+
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day ? date : null;
|
|
2861
|
+
};
|
|
2725
2862
|
var DateInput = class extends ThemeableElement {
|
|
2726
2863
|
constructor() {
|
|
2727
2864
|
super();
|
|
2865
|
+
this._default = new FormDefaultController(this, () => this.value);
|
|
2866
|
+
this._fieldsetDisabled = new FormDisabledController(this);
|
|
2728
2867
|
this.value = "";
|
|
2729
2868
|
this.min = "";
|
|
2730
2869
|
this.max = "";
|
|
2731
2870
|
this.locale = "en-US";
|
|
2732
2871
|
this.format = "medium";
|
|
2733
|
-
this.weekStart = "0";
|
|
2734
2872
|
this.label = "";
|
|
2735
2873
|
this.placeholder = "Select a date";
|
|
2736
2874
|
this.helperText = "";
|
|
@@ -2739,21 +2877,28 @@ var DateInput = class extends ThemeableElement {
|
|
|
2739
2877
|
this.disabled = false;
|
|
2740
2878
|
this.required = false;
|
|
2741
2879
|
this.name = "";
|
|
2742
|
-
/** Individual dates to disable in the calendar, as Date objects. */
|
|
2743
2880
|
this.disabledDates = [];
|
|
2881
|
+
this.labels = {};
|
|
2744
2882
|
this._open = false;
|
|
2745
2883
|
this._cleanupClickOutside = null;
|
|
2746
2884
|
this._floatingCleanup = null;
|
|
2885
|
+
this._fieldIds = createFieldIds();
|
|
2747
2886
|
this._internals = this.attachInternals();
|
|
2748
2887
|
}
|
|
2888
|
+
get _labels() {
|
|
2889
|
+
return { ...DEFAULT_LABELS2, ...this.labels };
|
|
2890
|
+
}
|
|
2749
2891
|
get _displayValue() {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2892
|
+
const date = parseIsoDate(this.value);
|
|
2893
|
+
if (!date) return "";
|
|
2894
|
+
try {
|
|
2895
|
+
return new Intl.DateTimeFormat(this.locale, { dateStyle: this.format }).format(date);
|
|
2896
|
+
} catch {
|
|
2897
|
+
return new Intl.DateTimeFormat(void 0, { dateStyle: this.format }).format(date);
|
|
2898
|
+
}
|
|
2754
2899
|
}
|
|
2755
2900
|
async _openDropdown() {
|
|
2756
|
-
if (this.
|
|
2901
|
+
if (this._isDisabled || this._open) return;
|
|
2757
2902
|
this._open = true;
|
|
2758
2903
|
await this.updateComplete;
|
|
2759
2904
|
const btn = this.shadowRoot?.querySelector("#field-btn");
|
|
@@ -2790,22 +2935,33 @@ var DateInput = class extends ThemeableElement {
|
|
|
2790
2935
|
}
|
|
2791
2936
|
_handleDropdownKeyDown(e) {
|
|
2792
2937
|
if (e.key === "Escape") {
|
|
2938
|
+
e.preventDefault();
|
|
2793
2939
|
e.stopPropagation();
|
|
2794
2940
|
this._closeDropdown();
|
|
2795
2941
|
this.shadowRoot?.querySelector(".field-btn")?.focus();
|
|
2796
2942
|
}
|
|
2797
2943
|
}
|
|
2798
|
-
updated() {
|
|
2944
|
+
updated(changed) {
|
|
2945
|
+
if (changed.has("value") && this.value && !parseIsoDate(this.value)) {
|
|
2946
|
+
devWarn("lt-date-input", `value "${this.value}" isn't a plain YYYY-MM-DD date \u2014 showing the placeholder instead`);
|
|
2947
|
+
}
|
|
2799
2948
|
this._internals.setFormValue(this.value || null);
|
|
2800
2949
|
const btn = this.shadowRoot?.querySelector("#field-btn");
|
|
2801
2950
|
if (this.required && !this.value && btn) {
|
|
2802
|
-
this._internals.setValidity({ valueMissing: true },
|
|
2951
|
+
this._internals.setValidity({ valueMissing: true }, this._labels.validationMessage, btn);
|
|
2803
2952
|
} else {
|
|
2804
2953
|
this._internals.setValidity({});
|
|
2805
2954
|
}
|
|
2806
2955
|
}
|
|
2807
2956
|
formResetCallback() {
|
|
2808
|
-
this.value =
|
|
2957
|
+
this.value = this._default.value;
|
|
2958
|
+
}
|
|
2959
|
+
formDisabledCallback(disabled) {
|
|
2960
|
+
this._fieldsetDisabled.setFieldsetDisabled(disabled);
|
|
2961
|
+
}
|
|
2962
|
+
/** `this.disabled` combined with an ancestor `<fieldset>`'s own disabled state (see `FormDisabledController`). */
|
|
2963
|
+
get _isDisabled() {
|
|
2964
|
+
return this.disabled || this._fieldsetDisabled.fieldsetDisabled;
|
|
2809
2965
|
}
|
|
2810
2966
|
checkValidity() {
|
|
2811
2967
|
return this._internals.checkValidity();
|
|
@@ -2820,8 +2976,8 @@ var DateInput = class extends ThemeableElement {
|
|
|
2820
2976
|
<div class="wrapper">
|
|
2821
2977
|
${this.label ? html3`<label for="field-btn">
|
|
2822
2978
|
<lt-text variant="label" as="span">${this.label}</lt-text>
|
|
2823
|
-
${this.required ? html3`<span class="required-indicator" aria-hidden="true">*</span>` :
|
|
2824
|
-
</label>` :
|
|
2979
|
+
${this.required ? html3`<span class="required-indicator" aria-hidden="true">*</span>` : nothing2}
|
|
2980
|
+
</label>` : nothing2}
|
|
2825
2981
|
|
|
2826
2982
|
<div class="field">
|
|
2827
2983
|
<button
|
|
@@ -2829,8 +2985,9 @@ var DateInput = class extends ThemeableElement {
|
|
|
2829
2985
|
type="button"
|
|
2830
2986
|
class="field-btn"
|
|
2831
2987
|
aria-haspopup="dialog"
|
|
2988
|
+
aria-describedby=${this.helperText ? this._fieldIds.helper : nothing2}
|
|
2832
2989
|
aria-expanded=${this._open ? "true" : "false"}
|
|
2833
|
-
?disabled=${this.
|
|
2990
|
+
?disabled=${this._isDisabled}
|
|
2834
2991
|
?required=${this.required}
|
|
2835
2992
|
@click=${this._openDropdown}
|
|
2836
2993
|
>
|
|
@@ -2846,7 +3003,7 @@ var DateInput = class extends ThemeableElement {
|
|
|
2846
3003
|
class="dropdown"
|
|
2847
3004
|
popover="manual"
|
|
2848
3005
|
role="dialog"
|
|
2849
|
-
aria-label
|
|
3006
|
+
aria-label=${this._labels.datePicker}
|
|
2850
3007
|
@keydown=${this._handleDropdownKeyDown}
|
|
2851
3008
|
>
|
|
2852
3009
|
${this._open ? html3`<lt-calendar
|
|
@@ -2854,14 +3011,14 @@ var DateInput = class extends ThemeableElement {
|
|
|
2854
3011
|
min=${this.min}
|
|
2855
3012
|
max=${this.max}
|
|
2856
3013
|
locale=${this.locale}
|
|
2857
|
-
week-start=${this.weekStart}
|
|
3014
|
+
week-start=${ifDefined(this.weekStart)}
|
|
2858
3015
|
.disabledDates=${this.disabledDates}
|
|
2859
3016
|
@change=${this._handleCalendarChange}
|
|
2860
|
-
></lt-calendar>` :
|
|
3017
|
+
></lt-calendar>` : nothing2}
|
|
2861
3018
|
</div>
|
|
2862
3019
|
</div>
|
|
2863
3020
|
|
|
2864
|
-
${this.helperText ? html3`<span class="helper-text">${this.helperText}</span>` :
|
|
3021
|
+
${this.helperText ? html3`<span id=${this._fieldIds.helper} class="helper-text">${this.helperText}</span>` : nothing2}
|
|
2865
3022
|
</div>
|
|
2866
3023
|
`;
|
|
2867
3024
|
}
|
|
@@ -2869,7 +3026,7 @@ var DateInput = class extends ThemeableElement {
|
|
|
2869
3026
|
DateInput.styles = dateInputStyles;
|
|
2870
3027
|
DateInput.formAssociated = true;
|
|
2871
3028
|
__decorateClass([
|
|
2872
|
-
property4(
|
|
3029
|
+
property4()
|
|
2873
3030
|
], DateInput.prototype, "value", 2);
|
|
2874
3031
|
__decorateClass([
|
|
2875
3032
|
property4({ reflect: true })
|
|
@@ -2910,6 +3067,12 @@ __decorateClass([
|
|
|
2910
3067
|
__decorateClass([
|
|
2911
3068
|
property4({ reflect: true })
|
|
2912
3069
|
], DateInput.prototype, "name", 2);
|
|
3070
|
+
__decorateClass([
|
|
3071
|
+
property4({ attribute: false })
|
|
3072
|
+
], DateInput.prototype, "disabledDates", 2);
|
|
3073
|
+
__decorateClass([
|
|
3074
|
+
property4({ type: Object })
|
|
3075
|
+
], DateInput.prototype, "labels", 2);
|
|
2913
3076
|
__decorateClass([
|
|
2914
3077
|
state2()
|
|
2915
3078
|
], DateInput.prototype, "_open", 2);
|
|
@@ -24,10 +24,14 @@ export declare class Datepicker extends ThemeableElement {
|
|
|
24
24
|
static styles: import("lit").CSSResult;
|
|
25
25
|
static formAssociated: boolean;
|
|
26
26
|
private _internals;
|
|
27
|
+
private _default;
|
|
28
|
+
private _fieldsetDisabled;
|
|
27
29
|
constructor();
|
|
28
30
|
/** Native input type. */
|
|
29
31
|
type: DatepickerType;
|
|
30
|
-
/** Current value in the format required by the native input (`YYYY-MM-DD`, `HH:MM`, or `YYYY-MM-DDTHH:MM`).
|
|
32
|
+
/** Current value in the format required by the native input (`YYYY-MM-DD`, `HH:MM`, or `YYYY-MM-DDTHH:MM`).
|
|
33
|
+
* Not reflected as an attribute — read the property, or the `change` event's `detail.value`, instead of
|
|
34
|
+
* `getAttribute('value')`/`[value]`. */
|
|
31
35
|
value: string;
|
|
32
36
|
/** Minimum allowed value. */
|
|
33
37
|
min: string;
|
|
@@ -37,6 +41,7 @@ export declare class Datepicker extends ThemeableElement {
|
|
|
37
41
|
label: string;
|
|
38
42
|
/** Helper or error text displayed below the input. */
|
|
39
43
|
helperText: string;
|
|
44
|
+
private readonly _fieldIds;
|
|
40
45
|
/** Visual state variant. */
|
|
41
46
|
variant: DatepickerVariant;
|
|
42
47
|
/** Visual size. */
|
|
@@ -52,6 +57,9 @@ export declare class Datepicker extends ThemeableElement {
|
|
|
52
57
|
private input;
|
|
53
58
|
protected updated(changed: PropertyValues): void;
|
|
54
59
|
formResetCallback(): void;
|
|
60
|
+
formDisabledCallback(disabled: boolean): void;
|
|
61
|
+
/** `this.disabled` combined with an ancestor `<fieldset>`'s own disabled state (see `FormDisabledController`). */
|
|
62
|
+
private get _isDisabled();
|
|
55
63
|
checkValidity(): boolean;
|
|
56
64
|
reportValidity(): boolean;
|
|
57
65
|
private handleChange;
|