@latty-ds/web 0.7.0 → 0.8.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.
Files changed (48) hide show
  1. package/custom-elements.json +272 -41
  2. package/dist/components/accordion/index.js +4 -4
  3. package/dist/components/alert/index.js +39 -5
  4. package/dist/components/avatar/index.js +1 -1
  5. package/dist/components/badge/index.js +6 -2
  6. package/dist/components/breadcrumb/index.js +1 -1
  7. package/dist/components/button/button.d.ts +7 -2
  8. package/dist/components/button/button.types.d.ts +3 -2
  9. package/dist/components/button/index.js +83 -4
  10. package/dist/components/calendar/index.js +3 -3
  11. package/dist/components/checkbox/index.js +2 -1
  12. package/dist/components/chip/index.js +6 -2
  13. package/dist/components/color-input/index.js +6 -3
  14. package/dist/components/combobox/index.js +4 -4
  15. package/dist/components/date-input/index.js +6 -6
  16. package/dist/components/datepicker/index.js +3 -3
  17. package/dist/components/dialog/index.js +40 -6
  18. package/dist/components/divider/index.js +1 -1
  19. package/dist/components/dropdown/index.js +5 -5
  20. package/dist/components/icon-button/icon-button.d.ts +4 -0
  21. package/dist/components/icon-button/index.js +35 -1
  22. package/dist/components/image/image.d.ts +32 -1
  23. package/dist/components/image/image.types.d.ts +7 -0
  24. package/dist/components/image/index.js +41 -2
  25. package/dist/components/list/index.js +86 -7
  26. package/dist/components/list/list-item.d.ts +35 -0
  27. package/dist/components/nav/index.js +19 -5
  28. package/dist/components/nav/nav-item.d.ts +7 -1
  29. package/dist/components/pagination/index.js +1 -1
  30. package/dist/components/radio/index.js +2 -1
  31. package/dist/components/radio-group/index.js +2 -2
  32. package/dist/components/select/index.js +6 -6
  33. package/dist/components/shared/aria-forwarding.d.ts +43 -0
  34. package/dist/components/sidepanel/index.js +36 -2
  35. package/dist/components/slider/index.js +2 -2
  36. package/dist/components/snackbar/index.js +4 -4
  37. package/dist/components/surface/index.js +3 -3
  38. package/dist/components/switch/index.js +2 -1
  39. package/dist/components/tab/index.js +1 -1
  40. package/dist/components/tab-group/index.js +2 -2
  41. package/dist/components/table/index.js +3 -3
  42. package/dist/components/text/index.js +1 -1
  43. package/dist/components/textfield/index.js +7 -3
  44. package/dist/components/tooltip/index.js +1 -1
  45. package/dist/index.cjs +294 -67
  46. package/dist/index.js +336 -106
  47. package/dist/manifest.json +45 -3
  48. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -1331,7 +1331,7 @@ __decorateClass([
1331
1331
  var accordionStyles = i`
1332
1332
  :host {
1333
1333
  display: block;
1334
- font-family: 'Hanken Grotesk', sans-serif;
1334
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
1335
1335
  width: 100%;
1336
1336
  }
1337
1337
 
@@ -1416,7 +1416,7 @@ var accordionStyles = i`
1416
1416
  /* Variant: default */
1417
1417
  :host([appearance='default']) details {
1418
1418
  background: var(--lt-bg-subtle);
1419
- border: 1px solid var(--lt-border-default);
1419
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
1420
1420
  }
1421
1421
 
1422
1422
  :host([appearance='default']) details:hover {
@@ -1436,7 +1436,7 @@ var accordionStyles = i`
1436
1436
  /* Variant: outlined */
1437
1437
  :host([appearance='outlined']) details {
1438
1438
  background: transparent;
1439
- border: 1px solid var(--lt-border-default);
1439
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
1440
1440
  }
1441
1441
 
1442
1442
  :host([appearance='outlined']) details:hover {
@@ -1508,7 +1508,7 @@ var textStyles = i`
1508
1508
  [part='base'] {
1509
1509
  margin: 0;
1510
1510
  color: inherit;
1511
- font-family: var(--lt-typography-fontfamily);
1511
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
1512
1512
  }
1513
1513
 
1514
1514
  /* ── Display ─────────────────────────────────────────────────────────── */
@@ -1781,7 +1781,7 @@ var o8 = (o10) => o10 ?? A;
1781
1781
  var buttonStyles = i`
1782
1782
  :host {
1783
1783
  display: inline-block;
1784
- font-family: 'Hanken Grotesk', sans-serif;
1784
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
1785
1785
 
1786
1786
  /* Internal state props — set per variant/appearance below */
1787
1787
  --_color: var(--lt-text-on-primary);
@@ -1804,7 +1804,7 @@ var buttonStyles = i`
1804
1804
  align-items: center;
1805
1805
  background: var(--lt-button-bg, var(--_bg));
1806
1806
  border-radius: var(--lt-border-radius);
1807
- border: 1px solid var(--lt-button-border-color, var(--_border-color));
1807
+ border: var(--lt-border-width, 1px) solid var(--lt-button-border-color, var(--_border-color));
1808
1808
  box-sizing: border-box;
1809
1809
  color: var(--lt-button-color, var(--_color));
1810
1810
  cursor: pointer;
@@ -1814,7 +1814,7 @@ var buttonStyles = i`
1814
1814
  gap: var(--lt-spacing-2);
1815
1815
  justify-content: center;
1816
1816
  line-height: 1;
1817
- min-width: 88px;
1817
+ min-width: var(--lt-button-min-width, 88px);
1818
1818
  user-select: none;
1819
1819
  transition:
1820
1820
  background-color 120ms ease,
@@ -1966,7 +1966,52 @@ var buttonStyles = i`
1966
1966
  --_active-bg: var(--lt-bg-info-subtle);
1967
1967
  }
1968
1968
 
1969
- :host([appearance='outlined']) [part='base']:active:not([disabled]):not([aria-disabled='true']) {
1969
+ /* ghost appearance — transparent background, no border, low-emphasis text button */
1970
+ :host([appearance='ghost'][variant='primary']) {
1971
+ --_bg: transparent;
1972
+ --_color: var(--lt-text-primary);
1973
+ --_hover-bg: var(--lt-bg-primary-subtle);
1974
+ --_active-bg: var(--lt-bg-primary-subtle);
1975
+ }
1976
+ :host([appearance='ghost'][variant='secondary']) {
1977
+ --_bg: transparent;
1978
+ --_color: var(--lt-text-secondary);
1979
+ --_hover-bg: var(--lt-bg-secondary-subtle);
1980
+ --_active-bg: var(--lt-bg-secondary-subtle);
1981
+ }
1982
+ :host([appearance='ghost'][variant='neutral']) {
1983
+ --_bg: transparent;
1984
+ --_color: var(--lt-text-neutral);
1985
+ --_hover-bg: var(--lt-bg-subtle);
1986
+ --_active-bg: var(--lt-bg-surface);
1987
+ }
1988
+ :host([appearance='ghost'][variant='success']) {
1989
+ --_bg: transparent;
1990
+ --_color: var(--lt-text-success);
1991
+ --_hover-bg: var(--lt-bg-success-subtle);
1992
+ --_active-bg: var(--lt-bg-success-subtle);
1993
+ }
1994
+ :host([appearance='ghost'][variant='warning']) {
1995
+ --_bg: transparent;
1996
+ --_color: var(--lt-text-warning);
1997
+ --_hover-bg: var(--lt-bg-warning-subtle);
1998
+ --_active-bg: var(--lt-bg-warning-subtle);
1999
+ }
2000
+ :host([appearance='ghost'][variant='error']) {
2001
+ --_bg: transparent;
2002
+ --_color: var(--lt-text-error);
2003
+ --_hover-bg: var(--lt-bg-error-subtle);
2004
+ --_active-bg: var(--lt-bg-error-subtle);
2005
+ }
2006
+ :host([appearance='ghost'][variant='info']) {
2007
+ --_bg: transparent;
2008
+ --_color: var(--lt-text-info);
2009
+ --_hover-bg: var(--lt-bg-info-subtle);
2010
+ --_active-bg: var(--lt-bg-info-subtle);
2011
+ }
2012
+
2013
+ :host([appearance='outlined']) [part='base']:active:not([disabled]):not([aria-disabled='true']),
2014
+ :host([appearance='ghost']) [part='base']:active:not([disabled]):not([aria-disabled='true']) {
1970
2015
  opacity: 0.8;
1971
2016
  }
1972
2017
 
@@ -2000,6 +2045,39 @@ var buttonStyles = i`
2000
2045
  }
2001
2046
  `;
2002
2047
 
2048
+ // src/components/shared/aria-forwarding.ts
2049
+ var FORWARDED_ARIA_ATTRIBUTES = [
2050
+ "aria-pressed",
2051
+ "aria-expanded",
2052
+ "aria-haspopup",
2053
+ "aria-controls",
2054
+ "aria-current"
2055
+ ];
2056
+ var AriaForwardingController = class {
2057
+ constructor(host, getTarget) {
2058
+ this._host = host;
2059
+ this._getTarget = getTarget;
2060
+ this._observer = new MutationObserver(() => this._host.requestUpdate());
2061
+ host.addController(this);
2062
+ }
2063
+ hostConnected() {
2064
+ this._observer.observe(this._host, { attributes: true, attributeFilter: [...FORWARDED_ARIA_ATTRIBUTES] });
2065
+ this._host.requestUpdate();
2066
+ }
2067
+ hostDisconnected() {
2068
+ this._observer.disconnect();
2069
+ }
2070
+ hostUpdated() {
2071
+ const target = this._getTarget();
2072
+ if (!target) return;
2073
+ for (const attr of FORWARDED_ARIA_ATTRIBUTES) {
2074
+ const value = this._host.getAttribute(attr);
2075
+ if (value === null) target.removeAttribute(attr);
2076
+ else if (target.getAttribute(attr) !== value) target.setAttribute(attr, value);
2077
+ }
2078
+ }
2079
+ };
2080
+
2003
2081
  // src/components/spinner/spinner.styles.ts
2004
2082
  var spinnerStyles = i`
2005
2083
  :host {
@@ -2094,6 +2172,7 @@ var import_icons2 = require("@latty-ds/icons");
2094
2172
  var Button = class extends ThemeableElement {
2095
2173
  constructor() {
2096
2174
  super();
2175
+ this._ariaForwarding = new AriaForwardingController(this, () => this.shadowRoot?.querySelector('[part="base"]'));
2097
2176
  this.variant = "primary";
2098
2177
  this.appearance = "filled";
2099
2178
  this.size = "md";
@@ -2248,7 +2327,7 @@ var o9 = e5(class extends i4 {
2248
2327
  var chipStyles = i`
2249
2328
  :host {
2250
2329
  display: inline-flex;
2251
- font-family: 'Hanken Grotesk', sans-serif;
2330
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
2252
2331
  vertical-align: middle;
2253
2332
  }
2254
2333
 
@@ -2256,7 +2335,11 @@ var chipStyles = i`
2256
2335
  align-items: center;
2257
2336
  background: var(--lt-chip-bg);
2258
2337
  border-radius: 999px;
2259
- border: 1px solid var(--lt-chip-border-color, transparent);
2338
+ /* Chips are small pills (as short as 20px tall at size="sm") — a "thick"
2339
+ (4px) themed border eats too much of that height and reads as
2340
+ compressed/squished, so cap what the chip actually renders at "medium"
2341
+ (2px) regardless of the theme's configured border width. */
2342
+ border: min(var(--lt-border-width, 1px), 2px) solid var(--lt-chip-border-color, transparent);
2260
2343
  color: var(--lt-chip-color);
2261
2344
  box-sizing: border-box;
2262
2345
  display: inline-flex;
@@ -2498,7 +2581,7 @@ Chip = __decorateClass([
2498
2581
  var checkboxStyles = i`
2499
2582
  :host {
2500
2583
  display: inline-block;
2501
- font-family: 'Hanken Grotesk', sans-serif;
2584
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
2502
2585
  }
2503
2586
 
2504
2587
  .checkbox-wrapper {
@@ -2698,6 +2781,7 @@ var Checkbox = class extends ThemeableElement {
2698
2781
  * @private
2699
2782
  */
2700
2783
  handleChange(e7) {
2784
+ e7.stopPropagation();
2701
2785
  const target = e7.target;
2702
2786
  this.checked = target.checked;
2703
2787
  this.indeterminate = false;
@@ -2788,7 +2872,7 @@ Checkbox = __decorateClass([
2788
2872
  // src/components/dialog/dialog.styles.ts
2789
2873
  var dialogStyles = i`
2790
2874
  :host {
2791
- font-family: 'Hanken Grotesk', sans-serif;
2875
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
2792
2876
  }
2793
2877
 
2794
2878
  /* Backdrop */
@@ -2940,7 +3024,7 @@ var iconButtonStyles = i`
2940
3024
  align-items: center;
2941
3025
  background: var(--lt-icon-button-bg, var(--_bg));
2942
3026
  border-radius: var(--lt-border-radius);
2943
- border: 1px solid var(--lt-icon-button-border-color, var(--_border-color));
3027
+ border: var(--lt-border-width, 1px) solid var(--lt-icon-button-border-color, var(--_border-color));
2944
3028
  box-sizing: border-box;
2945
3029
  color: var(--lt-icon-button-color, var(--_color));
2946
3030
  cursor: pointer;
@@ -3151,6 +3235,7 @@ var import_icons5 = require("@latty-ds/icons");
3151
3235
  var IconButton = class extends ThemeableElement {
3152
3236
  constructor() {
3153
3237
  super(...arguments);
3238
+ this._ariaForwarding = new AriaForwardingController(this, () => this.shadowRoot?.querySelector('[part="base"]'));
3154
3239
  this.icon = "";
3155
3240
  this.label = "";
3156
3241
  this.variant = "neutral";
@@ -3227,7 +3312,7 @@ IconButton = __decorateClass([
3227
3312
  var surfaceStyles = i`
3228
3313
  :host {
3229
3314
  display: block;
3230
- font-family: 'Hanken Grotesk', sans-serif;
3315
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
3231
3316
  }
3232
3317
 
3233
3318
  .surface {
@@ -3266,7 +3351,7 @@ var surfaceStyles = i`
3266
3351
 
3267
3352
  :host([appearance='outlined']) .surface {
3268
3353
  background: var(--lt-surface-bg, transparent);
3269
- border: 1px solid var(--lt-border-default);
3354
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
3270
3355
  }
3271
3356
 
3272
3357
  :host([appearance='outlined']:hover) .surface {
@@ -3283,7 +3368,7 @@ var Surface = class extends ThemeableElement {
3283
3368
  this.background = "";
3284
3369
  }
3285
3370
  render() {
3286
- const style = this.background ? { "--_surface-bg": resolveColorValue(this.background) } : {};
3371
+ const style = this.background ? { "--lt-surface-bg": resolveColorValue(this.background) } : {};
3287
3372
  return T`
3288
3373
  <div class="surface" part="surface" style=${o9(style)}>
3289
3374
  <slot></slot>
@@ -3472,7 +3557,7 @@ Dialog = __decorateClass([
3472
3557
  var listStyles = i`
3473
3558
  :host {
3474
3559
  display: block;
3475
- font-family: 'Hanken Grotesk', sans-serif;
3560
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
3476
3561
  --list-marker-color: var(--lt-color-neutral-500);
3477
3562
  }
3478
3563
 
@@ -3606,6 +3691,47 @@ var listItemStyles = i`
3606
3691
  color: var(--lt-color-neutral-500);
3607
3692
  font-size: inherit;
3608
3693
  }
3694
+
3695
+ /* interactive rows — native button/anchor reset + states */
3696
+ a.inner,
3697
+ button.inner {
3698
+ background: transparent;
3699
+ border: none;
3700
+ border-radius: var(--lt-border-radius);
3701
+ box-sizing: border-box;
3702
+ color: inherit;
3703
+ cursor: pointer;
3704
+ font: inherit;
3705
+ margin: 0;
3706
+ padding: var(--lt-spacing-2);
3707
+ text-align: start;
3708
+ text-decoration: none;
3709
+ transition: background-color 120ms ease;
3710
+ width: 100%;
3711
+ }
3712
+
3713
+ a.inner:hover:not([aria-disabled='true']),
3714
+ button.inner:hover:not([disabled]) {
3715
+ background: var(--lt-list-item-hover-bg, var(--lt-bg-subtle));
3716
+ }
3717
+
3718
+ a.inner:active:not([aria-disabled='true']),
3719
+ button.inner:active:not([disabled]) {
3720
+ background: var(--lt-list-item-active-bg, var(--lt-bg-surface));
3721
+ }
3722
+
3723
+ a.inner:focus-visible,
3724
+ button.inner:focus-visible {
3725
+ outline: 3px solid var(--lt-border-focus);
3726
+ outline-offset: -3px;
3727
+ }
3728
+
3729
+ button.inner[disabled],
3730
+ a.inner[aria-disabled='true'] {
3731
+ cursor: not-allowed;
3732
+ opacity: 0.6;
3733
+ pointer-events: none;
3734
+ }
3609
3735
  `;
3610
3736
 
3611
3737
  // src/components/list/list-item.ts
@@ -3615,19 +3741,41 @@ var ListItem = class extends ThemeableElement {
3615
3741
  super(...arguments);
3616
3742
  this.iconStart = "";
3617
3743
  this.iconEnd = "";
3744
+ this.clickable = false;
3745
+ this.href = "";
3746
+ this.target = "";
3747
+ this.rel = "";
3748
+ this.disabled = false;
3618
3749
  }
3619
3750
  connectedCallback() {
3620
3751
  super.connectedCallback();
3621
3752
  if (!this.hasAttribute("role")) this.setAttribute("role", "listitem");
3622
3753
  }
3623
3754
  render() {
3624
- return T`
3625
- <div class="inner">
3626
- ${this.iconStart ? T`<lt-icon class="icon-start" name=${this.iconStart}></lt-icon>` : A}
3627
- <span class="content"><slot></slot></span>
3628
- ${this.iconEnd ? T`<lt-icon class="icon-end" name=${this.iconEnd}></lt-icon>` : A}
3629
- </div>
3755
+ const inner = T`
3756
+ ${this.iconStart ? T`<lt-icon class="icon-start" name=${this.iconStart}></lt-icon>` : A}
3757
+ <span class="content"><slot></slot></span>
3758
+ ${this.iconEnd ? T`<lt-icon class="icon-end" name=${this.iconEnd}></lt-icon>` : A}
3630
3759
  `;
3760
+ if (this.href) {
3761
+ const rel = this.rel || (this.target === "_blank" ? "noopener noreferrer" : void 0);
3762
+ return T`
3763
+ <a
3764
+ class="inner"
3765
+ part="base"
3766
+ href=${this.href}
3767
+ target=${o8(this.target || void 0)}
3768
+ rel=${o8(rel)}
3769
+ aria-disabled=${this.disabled ? "true" : A}
3770
+ tabindex=${this.disabled ? "-1" : A}
3771
+ >${inner}</a
3772
+ >
3773
+ `;
3774
+ }
3775
+ if (this.clickable) {
3776
+ return T`<button class="inner" part="base" type="button" ?disabled=${this.disabled}>${inner}</button>`;
3777
+ }
3778
+ return T`<div class="inner" part="base">${inner}</div>`;
3631
3779
  }
3632
3780
  };
3633
3781
  ListItem.styles = listItemStyles;
@@ -3637,6 +3785,21 @@ __decorateClass([
3637
3785
  __decorateClass([
3638
3786
  n4({ attribute: "icon-end" })
3639
3787
  ], ListItem.prototype, "iconEnd", 2);
3788
+ __decorateClass([
3789
+ n4({ type: Boolean, reflect: true })
3790
+ ], ListItem.prototype, "clickable", 2);
3791
+ __decorateClass([
3792
+ n4()
3793
+ ], ListItem.prototype, "href", 2);
3794
+ __decorateClass([
3795
+ n4()
3796
+ ], ListItem.prototype, "target", 2);
3797
+ __decorateClass([
3798
+ n4()
3799
+ ], ListItem.prototype, "rel", 2);
3800
+ __decorateClass([
3801
+ n4({ type: Boolean, reflect: true })
3802
+ ], ListItem.prototype, "disabled", 2);
3640
3803
  ListItem = __decorateClass([
3641
3804
  t3("lt-list-item")
3642
3805
  ], ListItem);
@@ -3685,7 +3848,7 @@ List = __decorateClass([
3685
3848
  var radioStyles = i`
3686
3849
  :host {
3687
3850
  display: inline-block;
3688
- font-family: 'Hanken Grotesk', sans-serif;
3851
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
3689
3852
  }
3690
3853
 
3691
3854
  .radio-wrapper {
@@ -3889,6 +4052,7 @@ var Radio = class extends ThemeableElement {
3889
4052
  * @private
3890
4053
  */
3891
4054
  handleChange(e7) {
4055
+ e7.stopPropagation();
3892
4056
  const target = e7.target;
3893
4057
  this.checked = target.checked;
3894
4058
  this.dispatchEvent(
@@ -3957,7 +4121,7 @@ Radio = __decorateClass([
3957
4121
  var radioGroupStyles = i`
3958
4122
  :host {
3959
4123
  display: block;
3960
- font-family: 'Hanken Grotesk', sans-serif;
4124
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
3961
4125
  }
3962
4126
 
3963
4127
  .radio-group {
@@ -5514,7 +5678,7 @@ var selectStyles = [
5514
5678
  i`
5515
5679
  :host {
5516
5680
  display: inline-block;
5517
- font-family: 'Hanken Grotesk', sans-serif;
5681
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
5518
5682
  position: relative;
5519
5683
  width: 100%;
5520
5684
  }
@@ -5543,7 +5707,7 @@ var selectStyles = [
5543
5707
  align-items: center;
5544
5708
  background: var(--lt-bg-subtle);
5545
5709
  border-radius: var(--lt-border-radius);
5546
- border: 1px solid var(--lt-border-default);
5710
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
5547
5711
  box-sizing: border-box;
5548
5712
  cursor: pointer;
5549
5713
  display: flex;
@@ -5946,7 +6110,7 @@ Select = __decorateClass([
5946
6110
  var switchStyles = i`
5947
6111
  :host {
5948
6112
  display: inline-block;
5949
- font-family: 'Hanken Grotesk', sans-serif;
6113
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
5950
6114
  }
5951
6115
 
5952
6116
  .switch-wrapper {
@@ -6147,6 +6311,7 @@ var Switch = class extends ThemeableElement {
6147
6311
  return this._internals.reportValidity();
6148
6312
  }
6149
6313
  handleChange(e7) {
6314
+ e7.stopPropagation();
6150
6315
  const target = e7.target;
6151
6316
  this.checked = target.checked;
6152
6317
  this.dispatchEvent(
@@ -6217,7 +6382,7 @@ Switch = __decorateClass([
6217
6382
  var tabStyles = i`
6218
6383
  :host {
6219
6384
  display: inline-block;
6220
- font-family: 'Hanken Grotesk', sans-serif;
6385
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
6221
6386
  }
6222
6387
 
6223
6388
  .tab {
@@ -6421,7 +6586,7 @@ TabPanel = __decorateClass([
6421
6586
  var tabGroupStyles = i`
6422
6587
  :host {
6423
6588
  display: block;
6424
- font-family: 'Hanken Grotesk', sans-serif;
6589
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
6425
6590
  }
6426
6591
 
6427
6592
  .tab-group {
@@ -6716,7 +6881,7 @@ var c5 = e5(class extends i4 {
6716
6881
  var tableStyles = i`
6717
6882
  :host {
6718
6883
  display: block;
6719
- font-family: 'Hanken Grotesk', sans-serif;
6884
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
6720
6885
  overflow: hidden;
6721
6886
  width: 100%;
6722
6887
  }
@@ -6877,7 +7042,7 @@ var tableStyles = i`
6877
7042
 
6878
7043
  /* Border styling */
6879
7044
  :host([bordered]) table {
6880
- border: 1px solid var(--lt-border-default);
7045
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
6881
7046
  }
6882
7047
 
6883
7048
  :host([bordered]) th,
@@ -6933,7 +7098,7 @@ var tableStyles = i`
6933
7098
  :host([responsive-mode='stack']) tr {
6934
7099
  background: var(--lt-bg-subtle);
6935
7100
  border-radius: var(--lt-border-radius);
6936
- border: 1px solid var(--lt-border-default);
7101
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
6937
7102
  margin-bottom: var(--lt-spacing-3);
6938
7103
  padding: var(--lt-spacing-4);
6939
7104
  }
@@ -7253,7 +7418,7 @@ Table = __decorateClass([
7253
7418
  var textfieldStyles = i`
7254
7419
  :host {
7255
7420
  display: inline-block;
7256
- font-family: 'Hanken Grotesk', sans-serif;
7421
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
7257
7422
  width: 100%;
7258
7423
  }
7259
7424
 
@@ -7323,7 +7488,7 @@ var textfieldStyles = i`
7323
7488
  textarea {
7324
7489
  background: var(--lt-bg-subtle);
7325
7490
  border-radius: var(--lt-border-radius);
7326
- border: 1px solid var(--lt-border-default);
7491
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
7327
7492
  box-sizing: border-box;
7328
7493
  color: var(--lt-text-default);
7329
7494
  font-family: inherit;
@@ -7555,6 +7720,7 @@ var Textfield = class extends ThemeableElement {
7555
7720
  return true;
7556
7721
  }
7557
7722
  handleInput(e7) {
7723
+ e7.stopPropagation();
7558
7724
  const input = e7.target;
7559
7725
  this.value = input.value;
7560
7726
  if (this._touched) this._autoError = !this._validate();
@@ -7574,6 +7740,7 @@ var Textfield = class extends ThemeableElement {
7574
7740
  * @private
7575
7741
  */
7576
7742
  handleChange(e7) {
7743
+ e7.stopPropagation();
7577
7744
  const input = e7.target;
7578
7745
  this.value = input.value;
7579
7746
  this.dispatchEvent(
@@ -7660,6 +7827,7 @@ var Textfield = class extends ThemeableElement {
7660
7827
  ${isMultiline ? T`
7661
7828
  <textarea
7662
7829
  .value=${this.value}
7830
+ name=${o8(this.name || void 0)}
7663
7831
  placeholder=${this.placeholder}
7664
7832
  rows=${this.rows}
7665
7833
  minlength=${o8(this.min !== null ? this.min : void 0)}
@@ -7679,6 +7847,7 @@ var Textfield = class extends ThemeableElement {
7679
7847
  <input
7680
7848
  type=${actualInputType}
7681
7849
  .value=${this.value}
7850
+ name=${o8(this.name || void 0)}
7682
7851
  placeholder=${this.placeholder}
7683
7852
  min=${o8(isNumber && this.min !== null ? this.min : void 0)}
7684
7853
  max=${o8(isNumber && this.max !== null ? this.max : void 0)}
@@ -7798,7 +7967,7 @@ var avatarStyles = i`
7798
7967
  }
7799
7968
 
7800
7969
  .initials {
7801
- font-family: 'Hanken Grotesk', sans-serif;
7970
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
7802
7971
  font-weight: 600;
7803
7972
  letter-spacing: 0.02em;
7804
7973
  line-height: 1;
@@ -7956,7 +8125,7 @@ Avatar = __decorateClass([
7956
8125
  var badgeStyles = i`
7957
8126
  :host {
7958
8127
  display: inline-flex;
7959
- font-family: 'Hanken Grotesk', sans-serif;
8128
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
7960
8129
  vertical-align: middle;
7961
8130
  }
7962
8131
 
@@ -7964,7 +8133,11 @@ var badgeStyles = i`
7964
8133
  align-items: center;
7965
8134
  background: var(--lt-badge-bg);
7966
8135
  border-radius: 999px;
7967
- border: 1px solid var(--lt-badge-border-color, transparent);
8136
+ /* Badges are even smaller than chips (as short as 18px at size="sm") — a
8137
+ "thick" (4px) themed border reads as compressed, so cap what the badge
8138
+ actually renders at "medium" (2px) regardless of the theme's configured
8139
+ border width. */
8140
+ border: min(var(--lt-border-width, 1px), 2px) solid var(--lt-badge-border-color, transparent);
7968
8141
  color: var(--lt-badge-color);
7969
8142
  box-sizing: border-box;
7970
8143
  display: inline-flex;
@@ -8379,7 +8552,7 @@ var snackbarStyles = i`
8379
8552
  align-items: center;
8380
8553
  color: var(--lt-text-inverse);
8381
8554
  display: flex;
8382
- font-family: 'Hanken Grotesk', sans-serif;
8555
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
8383
8556
  font-size: 0.875rem;
8384
8557
  gap: var(--lt-spacing-2);
8385
8558
  line-height: 1.4;
@@ -8572,7 +8745,7 @@ Snackbar = __decorateClass([
8572
8745
  var alertStyles = i`
8573
8746
  :host {
8574
8747
  display: block;
8575
- font-family: 'Hanken Grotesk', sans-serif;
8748
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
8576
8749
  opacity: 1;
8577
8750
  transform: translateY(0);
8578
8751
  transition:
@@ -8642,14 +8815,14 @@ var alertStyles = i`
8642
8815
  :host([appearance='filled']) .inner,
8643
8816
  :host(:not([appearance])) .inner {
8644
8817
  background: var(--_bg-subtle);
8645
- border: 1px solid var(--_border);
8818
+ border: var(--lt-border-width, 1px) solid var(--_border);
8646
8819
  color: var(--_color);
8647
8820
  }
8648
8821
 
8649
8822
  /* outlined — white bg + colored border */
8650
8823
  :host([appearance='outlined']) .inner {
8651
8824
  background: var(--lt-bg-default);
8652
- border: 1px solid var(--_border);
8825
+ border: var(--lt-border-width, 1px) solid var(--_border);
8653
8826
  color: var(--_color);
8654
8827
  }
8655
8828
 
@@ -8790,7 +8963,7 @@ Alert = __decorateClass([
8790
8963
  var sliderStyles = i`
8791
8964
  :host {
8792
8965
  display: block;
8793
- font-family: 'Hanken Grotesk', sans-serif;
8966
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
8794
8967
  width: 100%;
8795
8968
  }
8796
8969
 
@@ -9056,7 +9229,7 @@ var dropdownStyles = [
9056
9229
  i`
9057
9230
  :host {
9058
9231
  display: inline-block;
9059
- font-family: 'Hanken Grotesk', sans-serif;
9232
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
9060
9233
  }
9061
9234
 
9062
9235
  .trigger-wrap {
@@ -9089,7 +9262,7 @@ var dropdownItemStyles = i`
9089
9262
  color: var(--lt-text-default);
9090
9263
  cursor: pointer;
9091
9264
  display: flex;
9092
- font-family: 'Hanken Grotesk', sans-serif;
9265
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
9093
9266
  font-size: 0.875rem;
9094
9267
  gap: var(--lt-spacing-2);
9095
9268
  padding: var(--lt-spacing-2) var(--lt-spacing-4);
@@ -9484,7 +9657,7 @@ var navItemStyles = i`
9484
9657
  min-width: 160px;
9485
9658
  background: var(--lt-bg-default);
9486
9659
  color: var(--lt-color-neutral-700);
9487
- border: 1px solid var(--lt-color-neutral-200);
9660
+ border: var(--lt-border-width, 1px) solid var(--lt-color-neutral-200);
9488
9661
  border-radius: 8px;
9489
9662
  box-shadow:
9490
9663
  0 4px 6px -1px rgb(0 0 0 / 0.08),
@@ -9549,13 +9722,15 @@ var NavItem = class extends ThemeableElement {
9549
9722
  }
9550
9723
  _handleTriggerClick(e7) {
9551
9724
  if (this.disabled) return;
9552
- this.dispatchEvent(
9725
+ const proceed = this.dispatchEvent(
9553
9726
  new CustomEvent("nav-item-click", {
9554
9727
  detail: { href: this.href, label: this.label },
9555
9728
  bubbles: true,
9556
- composed: true
9729
+ composed: true,
9730
+ cancelable: true
9557
9731
  })
9558
9732
  );
9733
+ if (!proceed) e7.preventDefault();
9559
9734
  if (this._hasChildren) {
9560
9735
  e7.preventDefault();
9561
9736
  this.open = !this.open;
@@ -9575,10 +9750,22 @@ var NavItem = class extends ThemeableElement {
9575
9750
  <span class="label">${this.label}</span>
9576
9751
  ${showChevron ? T`<lt-icon class="chevron" name="caret-down" size="sm"></lt-icon>` : A}
9577
9752
  `;
9753
+ const ariaCurrent = this.active ? "page" : A;
9578
9754
  if (this.href && !this._hasChildren) {
9579
- return T`<a class="item-trigger" href=${this.href} @click=${this._handleTriggerClick}>${inner}</a>`;
9580
- }
9581
- return T`<button class="item-trigger" @click=${this._handleTriggerClick} ?disabled=${this.disabled}>
9755
+ return T`<a
9756
+ class="item-trigger"
9757
+ href=${this.href}
9758
+ aria-current=${ariaCurrent}
9759
+ @click=${this._handleTriggerClick}
9760
+ >${inner}</a
9761
+ >`;
9762
+ }
9763
+ return T`<button
9764
+ class="item-trigger"
9765
+ aria-current=${ariaCurrent}
9766
+ @click=${this._handleTriggerClick}
9767
+ ?disabled=${this.disabled}
9768
+ >
9582
9769
  ${inner}
9583
9770
  </button>`;
9584
9771
  }
@@ -9751,7 +9938,7 @@ var breadcrumbItemStyles = i`
9751
9938
  :host {
9752
9939
  align-items: center;
9753
9940
  display: inline-flex;
9754
- font-family: var(--lt-typography-fontfamily);
9941
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
9755
9942
  font-size: 0.875rem;
9756
9943
  }
9757
9944
 
@@ -9906,7 +10093,7 @@ var dividerStyles = i`
9906
10093
 
9907
10094
  [part='label'] {
9908
10095
  color: var(--lt-text-subtle);
9909
- font-family: var(--lt-typography-fontfamily);
10096
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
9910
10097
  font-size: 0.75rem;
9911
10098
  font-weight: 600;
9912
10099
  padding-inline: var(--lt-spacing-3);
@@ -10440,15 +10627,47 @@ var Image = class extends ThemeableElement {
10440
10627
  this.alt = "";
10441
10628
  this.rounded = null;
10442
10629
  this.responsive = false;
10630
+ this.loading = "";
10631
+ this._errored = false;
10443
10632
  }
10444
10633
  get _borderRadius() {
10445
10634
  if (this.rounded === null) return void 0;
10446
10635
  return this.rounded || "var(--lt-border-radius)";
10447
10636
  }
10637
+ willUpdate(changed) {
10638
+ if (changed.has("src")) this._errored = false;
10639
+ }
10640
+ _dispatch(name) {
10641
+ this.dispatchEvent(
10642
+ new CustomEvent(name, {
10643
+ detail: { src: this.src },
10644
+ bubbles: true,
10645
+ composed: true
10646
+ })
10647
+ );
10648
+ }
10649
+ _handleLoad() {
10650
+ this._dispatch("lt-load");
10651
+ }
10652
+ _handleError() {
10653
+ this._errored = true;
10654
+ this._dispatch("lt-error");
10655
+ }
10448
10656
  render() {
10657
+ if (this._errored) {
10658
+ return T`<slot name="fallback"></slot>`;
10659
+ }
10449
10660
  const radius = this._borderRadius;
10450
10661
  return T`
10451
- <img part="image" src=${this.src} alt=${this.alt} style=${radius ? `border-radius: ${radius}` : ""} />
10662
+ <img
10663
+ part="image"
10664
+ src=${this.src}
10665
+ alt=${this.alt}
10666
+ loading=${o8(this.loading || void 0)}
10667
+ style=${radius ? `border-radius: ${radius}` : ""}
10668
+ @load=${this._handleLoad}
10669
+ @error=${this._handleError}
10670
+ />
10452
10671
  `;
10453
10672
  }
10454
10673
  };
@@ -10465,6 +10684,12 @@ __decorateClass([
10465
10684
  __decorateClass([
10466
10685
  n4({ type: Boolean, reflect: true })
10467
10686
  ], Image.prototype, "responsive", 2);
10687
+ __decorateClass([
10688
+ n4({ reflect: true })
10689
+ ], Image.prototype, "loading", 2);
10690
+ __decorateClass([
10691
+ r5()
10692
+ ], Image.prototype, "_errored", 2);
10468
10693
  Image = __decorateClass([
10469
10694
  t3("lt-image")
10470
10695
  ], Image);
@@ -10473,7 +10698,7 @@ Image = __decorateClass([
10473
10698
  var paginationStyles = i`
10474
10699
  :host {
10475
10700
  display: inline-flex;
10476
- font-family: 'Hanken Grotesk', sans-serif;
10701
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
10477
10702
  }
10478
10703
 
10479
10704
  nav {
@@ -10638,7 +10863,7 @@ Pagination = __decorateClass([
10638
10863
  var datepickerStyles = i`
10639
10864
  :host {
10640
10865
  display: block;
10641
- font-family: 'Hanken Grotesk', sans-serif;
10866
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
10642
10867
  }
10643
10868
 
10644
10869
  .wrapper {
@@ -10661,7 +10886,7 @@ var datepickerStyles = i`
10661
10886
  input {
10662
10887
  background: var(--lt-bg-surface);
10663
10888
  border-radius: var(--lt-border-radius);
10664
- border: 1px solid var(--lt-border-default);
10889
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
10665
10890
  color: var(--lt-text-default);
10666
10891
  font-family: inherit;
10667
10892
  font-size: 0.9375rem;
@@ -10863,13 +11088,13 @@ var import_icons16 = require("@latty-ds/icons");
10863
11088
  var calendarStyles = i`
10864
11089
  :host {
10865
11090
  display: inline-block;
10866
- font-family: 'Hanken Grotesk', sans-serif;
11091
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
10867
11092
  }
10868
11093
 
10869
11094
  .calendar {
10870
11095
  background: var(--lt-bg-default);
10871
11096
  border-radius: var(--lt-border-radius);
10872
- border: 1px solid var(--lt-border-default);
11097
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
10873
11098
  display: flex;
10874
11099
  flex-direction: column;
10875
11100
  gap: var(--lt-spacing-2);
@@ -11212,7 +11437,7 @@ var calendarStyles = i`
11212
11437
  .today-btn {
11213
11438
  background: transparent;
11214
11439
  border-radius: var(--lt-border-radius);
11215
- border: 1px solid var(--lt-border-default);
11440
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
11216
11441
  color: var(--lt-text-subtle);
11217
11442
  cursor: pointer;
11218
11443
  font-family: inherit;
@@ -11777,7 +12002,7 @@ var dateInputStyles = [
11777
12002
  i`
11778
12003
  :host {
11779
12004
  display: block;
11780
- font-family: 'Hanken Grotesk', sans-serif;
12005
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
11781
12006
  }
11782
12007
 
11783
12008
  .wrapper {
@@ -11806,7 +12031,7 @@ var dateInputStyles = [
11806
12031
  align-items: center;
11807
12032
  background: var(--lt-bg-surface);
11808
12033
  border-radius: var(--lt-border-radius);
11809
- border: 1px solid var(--lt-border-default);
12034
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
11810
12035
  color: var(--lt-text-default);
11811
12036
  cursor: pointer;
11812
12037
  display: flex;
@@ -12127,7 +12352,7 @@ var comboboxStyles = [
12127
12352
  i`
12128
12353
  :host {
12129
12354
  display: block;
12130
- font-family: 'Hanken Grotesk', sans-serif;
12355
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
12131
12356
  position: relative;
12132
12357
  }
12133
12358
 
@@ -12150,7 +12375,7 @@ var comboboxStyles = [
12150
12375
  align-items: center;
12151
12376
  background: var(--lt-bg-surface);
12152
12377
  border-radius: var(--lt-border-radius);
12153
- border: 1px solid var(--lt-border-default);
12378
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
12154
12379
  cursor: text;
12155
12380
  display: flex;
12156
12381
  gap: var(--lt-spacing-2);
@@ -12245,7 +12470,7 @@ var comboboxStyles = [
12245
12470
  .dropdown {
12246
12471
  background: var(--lt-bg-surface);
12247
12472
  border-radius: var(--lt-border-radius);
12248
- border: 1px solid var(--lt-border-default);
12473
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
12249
12474
  box-shadow: var(--lt-shadow-md);
12250
12475
  max-height: 240px;
12251
12476
  overflow-y: auto;
@@ -12516,7 +12741,7 @@ Combobox = __decorateClass([
12516
12741
  var colorInputStyles = i`
12517
12742
  :host {
12518
12743
  display: inline-block;
12519
- font-family: 'Hanken Grotesk', sans-serif;
12744
+ font-family: var(--lt-typography-fontFamily, 'Hanken Grotesk', sans-serif);
12520
12745
  width: 100%;
12521
12746
  }
12522
12747
 
@@ -12541,7 +12766,7 @@ var colorInputStyles = i`
12541
12766
  display: flex;
12542
12767
  align-items: center;
12543
12768
  background: var(--lt-bg-subtle);
12544
- border: 1px solid var(--lt-border-default);
12769
+ border: var(--lt-border-width, 1px) solid var(--lt-border-default);
12545
12770
  border-radius: var(--lt-border-radius);
12546
12771
  box-sizing: border-box;
12547
12772
  transition:
@@ -12753,6 +12978,7 @@ var ColorInput = class extends ThemeableElement {
12753
12978
  return this._internals.reportValidity();
12754
12979
  }
12755
12980
  _handleChange(e7) {
12981
+ e7.stopPropagation();
12756
12982
  const pickerHex = e7.target.value;
12757
12983
  this.value = formatColor(pickerHex, this.format);
12758
12984
  this.dispatchEvent(
@@ -12776,6 +13002,7 @@ var ColorInput = class extends ThemeableElement {
12776
13002
  type="color"
12777
13003
  class="native-picker"
12778
13004
  .value=${hex || "#000000"}
13005
+ name=${o8(this.name || void 0)}
12779
13006
  ?disabled=${this.disabled}
12780
13007
  aria-label=${this.label || this.placeholder}
12781
13008
  @change=${this._handleChange}