luxen-ui 0.18.2 → 0.19.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.
Files changed (77) hide show
  1. package/README.md +1 -0
  2. package/cdn/color-scheme.d.ts +76 -0
  3. package/cdn/color-scheme.d.ts.map +1 -0
  4. package/cdn/color-scheme.js +2 -0
  5. package/cdn/color-scheme.js.map +1 -0
  6. package/cdn/config.d.ts +23 -0
  7. package/cdn/config.d.ts.map +1 -1
  8. package/cdn/custom-elements.json +142 -2
  9. package/cdn/elements/color-scheme-icon/color-scheme-icon.d.ts +55 -0
  10. package/cdn/elements/color-scheme-icon/color-scheme-icon.d.ts.map +1 -0
  11. package/cdn/elements/color-scheme-icon/color-scheme-icon.js +44 -0
  12. package/cdn/elements/color-scheme-icon/color-scheme-icon.js.map +1 -0
  13. package/cdn/elements/color-scheme-icon/index.d.ts +2 -0
  14. package/cdn/elements/color-scheme-icon/index.d.ts.map +1 -0
  15. package/cdn/elements/color-scheme-icon/index.js +2 -0
  16. package/cdn/elements/color-scheme-icon/index.js.map +1 -0
  17. package/cdn/elements/dropdown-item/dropdown-item.d.ts +9 -1
  18. package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
  19. package/cdn/elements/dropdown-item/dropdown-item.js +32 -23
  20. package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
  21. package/cdn/elements/segmented-control/segmented-control.d.ts +2 -0
  22. package/cdn/elements/segmented-control/segmented-control.d.ts.map +1 -1
  23. package/cdn/elements/segmented-control/segmented-control.js +1 -1
  24. package/cdn/elements/segmented-control/segmented-control.js.map +1 -1
  25. package/cdn/elements/tabs/tabs.d.ts +28 -1
  26. package/cdn/elements/tabs/tabs.d.ts.map +1 -1
  27. package/cdn/elements/tabs/tabs.js +1 -1
  28. package/cdn/elements/tabs/tabs.js.map +1 -1
  29. package/cdn/index.d.ts +2 -0
  30. package/cdn/index.d.ts.map +1 -1
  31. package/cdn/index.js +1 -1
  32. package/cdn/registry.d.ts +1 -1
  33. package/cdn/registry.d.ts.map +1 -1
  34. package/cdn/registry.js.map +1 -1
  35. package/cdn/standalone.css +23 -4
  36. package/cdn/standalone.js.map +1 -1
  37. package/cdn/styles/elements/tabs/enclosed.css +9 -1
  38. package/cdn/styles/elements/tabs/line.css +14 -3
  39. package/dist/color-scheme.d.ts +76 -0
  40. package/dist/color-scheme.d.ts.map +1 -0
  41. package/dist/color-scheme.js +203 -0
  42. package/dist/config.d.ts +23 -0
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/css/elements/tabs/enclosed.css +9 -1
  45. package/dist/css/elements/tabs/line.css +14 -3
  46. package/dist/custom-elements.json +142 -2
  47. package/dist/elements/color-scheme-icon/color-scheme-icon.css +98 -0
  48. package/dist/elements/color-scheme-icon/color-scheme-icon.d.ts +55 -0
  49. package/dist/elements/color-scheme-icon/color-scheme-icon.d.ts.map +1 -0
  50. package/dist/elements/color-scheme-icon/color-scheme-icon.js +138 -0
  51. package/dist/elements/color-scheme-icon/index.d.ts +2 -0
  52. package/dist/elements/color-scheme-icon/index.d.ts.map +1 -0
  53. package/dist/elements/color-scheme-icon/index.js +4 -0
  54. package/dist/elements/dropdown-item/dropdown-item.d.ts +9 -1
  55. package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
  56. package/dist/elements/dropdown-item/dropdown-item.js +49 -26
  57. package/dist/elements/segmented-control/segmented-control.d.ts +2 -0
  58. package/dist/elements/segmented-control/segmented-control.d.ts.map +1 -1
  59. package/dist/elements/segmented-control/segmented-control.js +11 -1
  60. package/dist/elements/tabs/tabs.d.ts +28 -1
  61. package/dist/elements/tabs/tabs.d.ts.map +1 -1
  62. package/dist/elements/tabs/tabs.js +121 -26
  63. package/dist/index.d.ts +2 -0
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +1 -0
  66. package/dist/metadata/color-scheme-icon.json +66 -0
  67. package/dist/metadata/dropdown-item.json +9 -1
  68. package/dist/metadata/index.json +82 -3
  69. package/dist/metadata/tabs.json +6 -1
  70. package/dist/registry.d.ts +1 -1
  71. package/dist/registry.d.ts.map +1 -1
  72. package/dist/templates/elements/color-scheme-icon.md +279 -0
  73. package/dist/templates/elements/dropdown.md +54 -1
  74. package/dist/templates/elements/tabs.md +40 -7
  75. package/elements.json +8 -0
  76. package/package.json +5 -1
  77. package/vite-plugin.ts +71 -8
@@ -15,7 +15,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
15
15
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
16
16
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
17
17
  };
18
- var _DropdownItem_value_accessor_storage, _DropdownItem_disabled_accessor_storage, _DropdownItem_type_accessor_storage, _DropdownItem_variant_accessor_storage, _DropdownItem_checked_accessor_storage, _DropdownItem_submenuOpen_accessor_storage, _DropdownItem__hasSubmenu_accessor_storage;
18
+ var _DropdownItem_value_accessor_storage, _DropdownItem_disabled_accessor_storage, _DropdownItem_type_accessor_storage, _DropdownItem_variant_accessor_storage, _DropdownItem_checked_accessor_storage, _DropdownItem_submenuOpen_accessor_storage, _DropdownItem_checkPlacement_accessor_storage, _DropdownItem__hasSubmenu_accessor_storage;
19
19
  import { html, nothing, unsafeCSS } from 'lit';
20
20
  import { LuxenElement } from '../../shared/luxen-element.js';
21
21
  import { property, state } from 'lit/decorators.js';
@@ -28,7 +28,7 @@ const styles = unsafeCSS(rawStyles);
28
28
  * A menu item for use inside `<l-dropdown>`.
29
29
  *
30
30
  * @slot - Label text.
31
- * @slot prefix - Leading content (e.g. icon).
31
+ * @slot prefix - Leading content (e.g. icon). A `type="checkbox"` item ignores it unless `check-placement="end"` frees the leading column.
32
32
  * @slot suffix - Trailing content.
33
33
  * @slot submenu - Nested `l-dropdown-item` elements rendered in a submenu panel anchored to this item. Drop an `<hr>` between them for a separator.
34
34
  *
@@ -54,6 +54,7 @@ export class DropdownItem extends LuxenElement {
54
54
  _DropdownItem_variant_accessor_storage.set(this, undefined);
55
55
  _DropdownItem_checked_accessor_storage.set(this, false);
56
56
  _DropdownItem_submenuOpen_accessor_storage.set(this, false);
57
+ _DropdownItem_checkPlacement_accessor_storage.set(this, 'start');
57
58
  _DropdownItem__hasSubmenu_accessor_storage.set(this, false);
58
59
  this._onSubmenuSlotChange = (e) => {
59
60
  const slot = e.target;
@@ -80,6 +81,14 @@ export class DropdownItem extends LuxenElement {
80
81
  /** Whether this item's submenu is open. Managed by the parent `l-dropdown`. */
81
82
  get submenuOpen() { return __classPrivateFieldGet(this, _DropdownItem_submenuOpen_accessor_storage, "f"); }
82
83
  set submenuOpen(value) { __classPrivateFieldSet(this, _DropdownItem_submenuOpen_accessor_storage, value, "f"); }
84
+ /**
85
+ * Which side of a `type="checkbox"` item carries the check mark. `start` (the
86
+ * default) puts it in the leading column, where it takes the place of any
87
+ * `prefix`. `end` moves it to the trailing edge, freeing that column so the
88
+ * item can show its own icon alongside the state.
89
+ */
90
+ get checkPlacement() { return __classPrivateFieldGet(this, _DropdownItem_checkPlacement_accessor_storage, "f"); }
91
+ set checkPlacement(value) { __classPrivateFieldSet(this, _DropdownItem_checkPlacement_accessor_storage, value, "f"); }
83
92
  get _hasSubmenu() { return __classPrivateFieldGet(this, _DropdownItem__hasSubmenu_accessor_storage, "f"); }
84
93
  set _hasSubmenu(value) { __classPrivateFieldSet(this, _DropdownItem__hasSubmenu_accessor_storage, value, "f"); }
85
94
  /** Whether this item has nested `slot="submenu"` items. */
@@ -169,8 +178,32 @@ export class DropdownItem extends LuxenElement {
169
178
  panel.hidePopover();
170
179
  }
171
180
  }
181
+ _renderCheck() {
182
+ return html `
183
+ <span
184
+ class="check"
185
+ aria-hidden="true"
186
+ >
187
+ <svg
188
+ width="16"
189
+ height="16"
190
+ viewBox="0 0 16 16"
191
+ fill="none"
192
+ >
193
+ <path
194
+ d="M3.5 8.5L6.5 11.5L12.5 4.5"
195
+ stroke="currentColor"
196
+ stroke-width="1.5"
197
+ stroke-linecap="round"
198
+ stroke-linejoin="round"
199
+ />
200
+ </svg>
201
+ </span>
202
+ `;
203
+ }
172
204
  render() {
173
205
  const isCheckbox = this.type === 'checkbox';
206
+ const leadingCheck = isCheckbox && this.checkPlacement === 'start';
174
207
  return html `
175
208
  <div
176
209
  class="item"
@@ -182,35 +215,22 @@ export class DropdownItem extends LuxenElement {
182
215
  aria-controls=${this._hasSubmenu ? 'submenu' : nothing}
183
216
  tabindex="-1"
184
217
  >
185
- ${isCheckbox
186
- ? html `
187
- <span
188
- class="check"
189
- aria-hidden="true"
190
- >
191
- <svg
192
- width="16"
193
- height="16"
194
- viewBox="0 0 16 16"
195
- fill="none"
196
- >
197
- <path
198
- d="M3.5 8.5L6.5 11.5L12.5 4.5"
199
- stroke="currentColor"
200
- stroke-width="1.5"
201
- stroke-linecap="round"
202
- stroke-linejoin="round"
203
- />
204
- </svg>
205
- </span>
206
- `
207
- : html ` <slot name="prefix"></slot> `}
218
+ <!-- The check owns the leading column by default, which is why a
219
+ checkbox item has no room for a prefix there. Moving it to the
220
+ trailing edge frees that column, so an item can carry its own icon
221
+ and still show whether it is on — a theme row with a sun/moon, a
222
+ Show-grid row with a grid glyph. The aria-checked above is what
223
+ assistive tech reads, and it is unaffected by where the mark sits.
224
+ (No backticks in this comment: it lives inside a template literal.) -->
225
+ ${leadingCheck ? this._renderCheck() : nothing}
226
+ ${leadingCheck ? nothing : html `<slot name="prefix"></slot>`}
208
227
  <span
209
228
  class="label"
210
229
  id="label"
211
230
  ><slot></slot
212
231
  ></span>
213
232
  <slot name="suffix"></slot>
233
+ ${isCheckbox && this.checkPlacement === 'end' ? this._renderCheck() : nothing}
214
234
  ${this._hasSubmenu
215
235
  ? html `<span
216
236
  class="submenu-indicator"
@@ -234,7 +254,7 @@ export class DropdownItem extends LuxenElement {
234
254
  `;
235
255
  }
236
256
  }
237
- _DropdownItem_value_accessor_storage = new WeakMap(), _DropdownItem_disabled_accessor_storage = new WeakMap(), _DropdownItem_type_accessor_storage = new WeakMap(), _DropdownItem_variant_accessor_storage = new WeakMap(), _DropdownItem_checked_accessor_storage = new WeakMap(), _DropdownItem_submenuOpen_accessor_storage = new WeakMap(), _DropdownItem__hasSubmenu_accessor_storage = new WeakMap();
257
+ _DropdownItem_value_accessor_storage = new WeakMap(), _DropdownItem_disabled_accessor_storage = new WeakMap(), _DropdownItem_type_accessor_storage = new WeakMap(), _DropdownItem_variant_accessor_storage = new WeakMap(), _DropdownItem_checked_accessor_storage = new WeakMap(), _DropdownItem_submenuOpen_accessor_storage = new WeakMap(), _DropdownItem_checkPlacement_accessor_storage = new WeakMap(), _DropdownItem__hasSubmenu_accessor_storage = new WeakMap();
238
258
  DropdownItem.styles = [hostStyles, styles];
239
259
  __decorate([
240
260
  property()
@@ -254,6 +274,9 @@ __decorate([
254
274
  __decorate([
255
275
  property({ type: Boolean, reflect: true, attribute: 'submenu-open' })
256
276
  ], DropdownItem.prototype, "submenuOpen", null);
277
+ __decorate([
278
+ property({ reflect: true, attribute: 'check-placement' })
279
+ ], DropdownItem.prototype, "checkPlacement", null);
257
280
  __decorate([
258
281
  state()
259
282
  ], DropdownItem.prototype, "_hasSubmenu", null);
@@ -40,6 +40,8 @@ export declare class SegmentedControl extends LuxenFormAssociatedElement {
40
40
  private _setupTimer;
41
41
  private _buttons;
42
42
  private _resizeObserver;
43
+ /** Segments the consumer authored `aria-disabled` on — never ours to clear. */
44
+ private _authoredDisabled;
43
45
  /** Value of the selected segment (its `value` attribute, else its index). */
44
46
  value: string;
45
47
  /** Control height, aligned with buttons and form controls at the same size. */
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../../src/html/elements/segmented-control/segmented-control.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7D,sEAAsE;AACtE,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAKzC;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,qBAAa,gBAAiB,SAAQ,0BAA0B;IACrD,gBAAgB;IAIzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,eAAe,CAA+B;IAEtD,6EAA6E;IAE7E,KAAK,SAAM;IAEX,+EAA+E;IAE/E,IAAI,EAAE,oBAAoB,CAAQ;IAElC,yEAAyE;IAEzE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,oDAAoD;IAEpD,SAAS,UAAS;IAIT,iBAAiB;IAUjB,oBAAoB;IAM7B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAOR,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAsBrC,iBAAiB;IAMjB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,cAAc;IAOjF,OAAO,CAAC,MAAM;IAoDd,OAAO,CAAC,SAAS;IAUjB,wFAAwF;IACxF,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,OAAO;IAuBf,qFAAqF;IACrF,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;IAInB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,QAAQ,CAQd;IAKF,OAAO,CAAC,UAAU,CAkChB;CACH;AAQD,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EACvD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAC1D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
1
+ {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../../src/html/elements/segmented-control/segmented-control.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7D,sEAAsE;AACtE,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAKzC;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,qBAAa,gBAAiB,SAAQ,0BAA0B;IACrD,gBAAgB;IAIzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,eAAe,CAA+B;IACtD,+EAA+E;IAC/E,OAAO,CAAC,iBAAiB,CAAoC;IAE7D,6EAA6E;IAE7E,KAAK,SAAM;IAEX,+EAA+E;IAE/E,IAAI,EAAE,oBAAoB,CAAQ;IAElC,yEAAyE;IAEzE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,oDAAoD;IAEpD,SAAS,UAAS;IAIT,iBAAiB;IAUjB,oBAAoB;IAM7B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAOR,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAsBrC,iBAAiB;IAMjB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,cAAc;IAOjF,OAAO,CAAC,MAAM;IAyDd,OAAO,CAAC,SAAS;IAUjB,wFAAwF;IACxF,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,OAAO;IAuBf,qFAAqF;IACrF,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;IAInB,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,QAAQ,CAQd;IAKF,OAAO,CAAC,UAAU,CAkChB;CACH;AAQD,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EACvD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAC1D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3E,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
@@ -47,6 +47,8 @@ export class SegmentedControl extends LuxenFormAssociatedElement {
47
47
  this._setupTimer = 0;
48
48
  this._buttons = [];
49
49
  this._resizeObserver = null;
50
+ /** Segments the consumer authored `aria-disabled` on — never ours to clear. */
51
+ this._authoredDisabled = new WeakSet();
50
52
  /** Value of the selected segment (its `value` attribute, else its index). */
51
53
  this.value = '';
52
54
  /** Control height, aligned with buttons and form controls at the same size. */
@@ -181,6 +183,11 @@ export class SegmentedControl extends LuxenFormAssociatedElement {
181
183
  btn.setAttribute('role', 'radio');
182
184
  btn.setAttribute('aria-checked', String(i === activeIndex));
183
185
  btn.setAttribute('tabindex', i === activeIndex ? '0' : '-1');
186
+ // Record an authored `aria-disabled` before the host-level state is
187
+ // mirrored onto the segments: `_applyDisabledState()` clears that mirror
188
+ // whenever the control is enabled, and must not take this one with it.
189
+ if (btn.getAttribute('aria-disabled') === 'true')
190
+ this._authoredDisabled.add(btn);
184
191
  // A segment with no visible text is icon-only: square it and require an
185
192
  // accessible name (the icon itself is decorative to assistive tech).
186
193
  if ((btn.textContent ?? '').trim() === '') {
@@ -278,7 +285,10 @@ export class SegmentedControl extends LuxenFormAssociatedElement {
278
285
  btn.setAttribute('tabindex', '-1');
279
286
  }
280
287
  else {
281
- btn.removeAttribute('aria-disabled');
288
+ // Only clear the mirror this method set: a segment the consumer marked
289
+ // `aria-disabled` stays disabled when the control is re-enabled.
290
+ if (!this._authoredDisabled.has(btn))
291
+ btn.removeAttribute('aria-disabled');
282
292
  // Restore the roving tabindex (only the selected segment is tabbable).
283
293
  btn.setAttribute('tabindex', btn.getAttribute('aria-checked') === 'true' ? '0' : '-1');
284
294
  }
@@ -28,7 +28,15 @@ interface TabsEventMap {
28
28
  * </l-tabs>
29
29
  * ```
30
30
  *
31
- * @event change - Fired when the active tab changes. Bubbles. Properties: `index: number`, `name: string | null`.
31
+ * @example
32
+ * A tab button marked `disabled` (or `aria-disabled="true"`) is skipped by
33
+ * arrow keys, `Home` and `End`, and cannot be selected by a click or by
34
+ * `value` — it still owns its panel, so the tab/panel order is unchanged.
35
+ * ```html
36
+ * <button disabled>Billing</button>
37
+ * ```
38
+ *
39
+ * @event change - Fired when the active tab changes. Bubbles. Not cancelable. Properties: `index: number`, `name: string | null`.
32
40
  *
33
41
  * @cssproperty [--indicator-color=var(--l-color-text-primary)] - `line` variant: color of the active underline that slides under the selected tab.
34
42
  * @cssproperty [--indicator-thickness=2px] - `line` variant: thickness of the active underline.
@@ -64,6 +72,25 @@ export declare class Tabs extends LuxenElement {
64
72
  private _setup;
65
73
  private _teardown;
66
74
  private _selectTab;
75
+ /**
76
+ * Both spellings count, and they behave identically here. `aria-disabled`
77
+ * leaves the button focusable in principle, but a roving tabindex hands
78
+ * `tabindex="0"` to the selected tab only — so a tab that can never be
79
+ * selected is never in the tab sequence either, and the arrow keys skip it
80
+ * like a native one. It is the escape hatch for consumers who cannot set the
81
+ * native attribute (a framework binding, a non-`button` element), not a
82
+ * "reachable but inert" variant.
83
+ */
84
+ private _isDisabled;
85
+ private _isSelectable;
86
+ /** Index of the currently selected tab, read back from the DOM. */
87
+ private _activeIndex;
88
+ /** Resolve the initial selection from `value`, falling back to the first enabled tab. */
89
+ private _resolveActiveIndex;
90
+ /** Index of the next enabled tab from `from`, moving by `dir`, wrapping. */
91
+ private _nextEnabled;
92
+ /** Index of the first (`dir` 1) or last (`dir` -1) enabled tab. */
93
+ private _edgeEnabled;
67
94
  private _updateIndicator;
68
95
  private _onClick;
69
96
  private _onKeyDown;
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBACjB,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAK/C;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,qBAAa,IAAK,SAAQ,YAAY;IAC3B,gBAAgB;IAIzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,eAAe,CAA+B;IAEtD,sBAAsB;IAEtB,OAAO,EAAE,WAAW,CAAU;IAE9B,yCAAyC;IAEzC,KAAK,SAAO;IAEZ,4CAA4C;IAE5C,SAAS,UAAS;IAElB,uBAAuB;IAEvB,WAAW,EAAE,eAAe,CAAgB;IAInC,iBAAiB;IAUjB,oBAAoB;IAM7B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAOR,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAW9C,OAAO,CAAC,MAAM;IA0Dd,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,UAAU;IA2BlB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,QAAQ,CAQd;IAEF,OAAO,CAAC,UAAU,CAkChB;CACH;AA8BD,MAAM,WAAW,IAAI;IACnB,gBAAgB,CAAC,CAAC,SAAS,MAAM,YAAY,EAC3C,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,YAAY,EAC9C,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tabs/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;AAExD,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBACjB,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAK/C;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,qBAAa,IAAK,SAAQ,YAAY;IAC3B,gBAAgB;IAIzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,eAAe,CAA+B;IAEtD,sBAAsB;IAEtB,OAAO,EAAE,WAAW,CAAU;IAE9B,yCAAyC;IAEzC,KAAK,SAAO;IAEZ,4CAA4C;IAE5C,SAAS,UAAS;IAElB,uBAAuB;IAEvB,WAAW,EAAE,eAAe,CAAgB;IAInC,iBAAiB;IAUjB,oBAAoB;IAM7B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAOR,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAuB9C,OAAO,CAAC,MAAM;IAgEd,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,UAAU;IAmClB;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;IASrB,mEAAmE;IACnE,OAAO,CAAC,YAAY;IAKpB,yFAAyF;IACzF,OAAO,CAAC,mBAAmB;IAS3B,4EAA4E;IAC5E,OAAO,CAAC,YAAY;IASpB,mEAAmE;IACnE,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,QAAQ,CAUd;IAEF,OAAO,CAAC,UAAU,CAqChB;CACH;AA8BD,MAAM,WAAW,IAAI;IACnB,gBAAgB,CAAC,CAAC,SAAS,MAAM,YAAY,EAC3C,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,YAAY,EAC9C,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
@@ -33,7 +33,15 @@ export class TabsChangeEvent extends Event {
33
33
  * </l-tabs>
34
34
  * ```
35
35
  *
36
- * @event change - Fired when the active tab changes. Bubbles. Properties: `index: number`, `name: string | null`.
36
+ * @example
37
+ * A tab button marked `disabled` (or `aria-disabled="true"`) is skipped by
38
+ * arrow keys, `Home` and `End`, and cannot be selected by a click or by
39
+ * `value` — it still owns its panel, so the tab/panel order is unchanged.
40
+ * ```html
41
+ * <button disabled>Billing</button>
42
+ * ```
43
+ *
44
+ * @event change - Fired when the active tab changes. Bubbles. Not cancelable. Properties: `index: number`, `name: string | null`.
37
45
  *
38
46
  * @cssproperty [--indicator-color=var(--l-color-text-primary)] - `line` variant: color of the active underline that slides under the selected tab.
39
47
  * @cssproperty [--indicator-thickness=2px] - `line` variant: thickness of the active underline.
@@ -69,10 +77,13 @@ export class Tabs extends LuxenElement {
69
77
  if (!tab)
70
78
  return;
71
79
  const index = this._tabs.indexOf(tab);
72
- if (index >= 0) {
73
- this._selectTab(index);
74
- tab.focus();
75
- }
80
+ // A native `disabled` button dispatches no click at all, but an
81
+ // `aria-disabled` one does — `_selectTab` refuses it, and focus must not
82
+ // follow either.
83
+ if (index < 0 || this._isDisabled(tab))
84
+ return;
85
+ this._selectTab(index);
86
+ tab.focus();
76
87
  };
77
88
  this._onKeyDown = (e) => {
78
89
  const target = e.target;
@@ -81,31 +92,35 @@ export class Tabs extends LuxenElement {
81
92
  const isHorizontal = this.orientation === 'horizontal';
82
93
  const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';
83
94
  const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';
84
- let index = this._tabs.indexOf(target);
95
+ const current = this._tabs.indexOf(target);
96
+ if (current < 0)
97
+ return;
98
+ // Every move lands on an enabled tab: selection follows focus here
99
+ // (automatic activation), so a disabled target would split the two apart.
100
+ let index;
85
101
  switch (e.key) {
86
102
  case nextKey:
87
- e.preventDefault();
88
- index = (index + 1) % this._tabs.length;
89
- this._selectTab(index);
90
- this._tabs[index].focus();
103
+ index = this._nextEnabled(current, 1);
91
104
  break;
92
105
  case prevKey:
93
- e.preventDefault();
94
- index = (index - 1 + this._tabs.length) % this._tabs.length;
95
- this._selectTab(index);
96
- this._tabs[index].focus();
106
+ index = this._nextEnabled(current, -1);
97
107
  break;
98
108
  case 'Home':
99
- e.preventDefault();
100
- this._selectTab(0);
101
- this._tabs[0].focus();
109
+ index = this._edgeEnabled(1);
102
110
  break;
103
111
  case 'End':
104
- e.preventDefault();
105
- this._selectTab(this._tabs.length - 1);
106
- this._tabs[this._tabs.length - 1].focus();
112
+ index = this._edgeEnabled(-1);
107
113
  break;
114
+ default:
115
+ return;
108
116
  }
117
+ e.preventDefault();
118
+ // Only reachable when every tab is disabled — then there is nowhere to go
119
+ // and focus must not be dragged onto a disabled tab.
120
+ if (!this._isSelectable(index))
121
+ return;
122
+ this._selectTab(index);
123
+ this._tabs[index].focus();
109
124
  };
110
125
  }
111
126
  createRenderRoot() {
@@ -137,7 +152,20 @@ export class Tabs extends LuxenElement {
137
152
  }
138
153
  updated(changed) {
139
154
  if (changed.has('value') && this._tabs.length) {
140
- this._selectTab(Number(this.value), false);
155
+ const requested = Number(this.value);
156
+ if (this._isSelectable(requested)) {
157
+ this._selectTab(requested, false);
158
+ }
159
+ else {
160
+ // The target is disabled or out of range, so the selection stays put —
161
+ // and `value` must not keep claiming a tab that was never selected.
162
+ // Reverting here would schedule an update from within an update, so
163
+ // defer it (same reason as a vetoed dialog `show`).
164
+ const current = this._activeIndex();
165
+ queueMicrotask(() => {
166
+ this.value = String(current);
167
+ });
168
+ }
141
169
  }
142
170
  if (changed.has('orientation') && this._tablistEl) {
143
171
  this._tablistEl.setAttribute('aria-orientation', this.orientation);
@@ -155,9 +183,11 @@ export class Tabs extends LuxenElement {
155
183
  this._tablistEl.setAttribute('aria-orientation', this.orientation);
156
184
  // Buttons inside tablist become tabs
157
185
  this._tabs = Array.from(this._tablistEl.querySelectorAll('button'));
158
- // Remaining children become panels
186
+ // Remaining children become panels. Disabled buttons stay in `_tabs` so the
187
+ // tab↔panel pairing keeps following DOM order — they are filtered out at
188
+ // navigation time, not here.
159
189
  this._panels = children.slice(1);
160
- const activeIndex = Number(this.value) || 0;
190
+ const activeIndex = this._resolveActiveIndex();
161
191
  // Enhance tabs
162
192
  for (let i = 0; i < this._tabs.length; i++) {
163
193
  const tab = this._tabs[i];
@@ -183,6 +213,10 @@ export class Tabs extends LuxenElement {
183
213
  }
184
214
  }
185
215
  }
216
+ // `value` may have pointed at a disabled tab: canonicalize it to the tab
217
+ // that is actually selected.
218
+ if (Number(this.value) !== activeIndex)
219
+ this.value = String(activeIndex);
186
220
  // Attach listeners
187
221
  this._tablistEl.addEventListener('click', this._onClick);
188
222
  this._tablistEl.addEventListener('keydown', this._onKeyDown);
@@ -203,8 +237,15 @@ export class Tabs extends LuxenElement {
203
237
  }
204
238
  // --- Tab selection ---
205
239
  _selectTab(index, emitEvent = true) {
206
- if (index < 0 || index >= this._tabs.length)
240
+ // A disabled tab is never selectable: it cannot take focus, so selecting it
241
+ // would move the roving tabindex entry point onto an unfocusable button and
242
+ // drop the whole tablist out of the tab sequence (WCAG 2.1.1).
243
+ if (!this._isSelectable(index))
207
244
  return;
245
+ // Whether this is an actual change — re-selecting the current tab must not
246
+ // re-fire `change` (the event is documented as firing when the active tab
247
+ // changes, and this matches native `change` on radios / `<select>`).
248
+ const changed = this._tabs[index].getAttribute('aria-selected') !== 'true';
208
249
  for (let i = 0; i < this._tabs.length; i++) {
209
250
  const tab = this._tabs[i];
210
251
  const panel = this._panels[i];
@@ -217,16 +258,70 @@ export class Tabs extends LuxenElement {
217
258
  }
218
259
  this.value = String(index);
219
260
  this._updateIndicator();
220
- if (emitEvent) {
261
+ if (emitEvent && changed) {
221
262
  const name = this._tabs[index]?.getAttribute('name') ?? null;
222
263
  this.dispatchEvent(new TabsChangeEvent(index, name));
223
264
  }
224
265
  }
266
+ // --- Disabled tabs ---
267
+ /**
268
+ * Both spellings count, and they behave identically here. `aria-disabled`
269
+ * leaves the button focusable in principle, but a roving tabindex hands
270
+ * `tabindex="0"` to the selected tab only — so a tab that can never be
271
+ * selected is never in the tab sequence either, and the arrow keys skip it
272
+ * like a native one. It is the escape hatch for consumers who cannot set the
273
+ * native attribute (a framework binding, a non-`button` element), not a
274
+ * "reachable but inert" variant.
275
+ */
276
+ _isDisabled(tab) {
277
+ return tab.disabled || tab.getAttribute('aria-disabled') === 'true';
278
+ }
279
+ _isSelectable(index) {
280
+ return (Number.isInteger(index) &&
281
+ index >= 0 &&
282
+ index < this._tabs.length &&
283
+ !this._isDisabled(this._tabs[index]));
284
+ }
285
+ /** Index of the currently selected tab, read back from the DOM. */
286
+ _activeIndex() {
287
+ const i = this._tabs.findIndex((t) => t.getAttribute('aria-selected') === 'true');
288
+ return i >= 0 ? i : 0;
289
+ }
290
+ /** Resolve the initial selection from `value`, falling back to the first enabled tab. */
291
+ _resolveActiveIndex() {
292
+ const requested = Number(this.value) || 0;
293
+ if (this._isSelectable(requested))
294
+ return requested;
295
+ const firstEnabled = this._tabs.findIndex((t) => !this._isDisabled(t));
296
+ // Every tab disabled: nothing is focusable anyway, so index 0 is as good as
297
+ // any and the tablist is simply unreachable — which is what was asked for.
298
+ return firstEnabled >= 0 ? firstEnabled : 0;
299
+ }
300
+ /** Index of the next enabled tab from `from`, moving by `dir`, wrapping. */
301
+ _nextEnabled(from, dir) {
302
+ const len = this._tabs.length;
303
+ for (let step = 1; step <= len; step++) {
304
+ const i = (from + dir * step + len * step) % len;
305
+ if (!this._isDisabled(this._tabs[i]))
306
+ return i;
307
+ }
308
+ return from;
309
+ }
310
+ /** Index of the first (`dir` 1) or last (`dir` -1) enabled tab. */
311
+ _edgeEnabled(dir) {
312
+ const len = this._tabs.length;
313
+ const start = dir === 1 ? 0 : len - 1;
314
+ for (let i = start; i >= 0 && i < len; i += dir) {
315
+ if (!this._isDisabled(this._tabs[i]))
316
+ return i;
317
+ }
318
+ return start;
319
+ }
225
320
  // --- Indicator ---
226
321
  _updateIndicator() {
227
322
  if (!this._tablistEl)
228
323
  return;
229
- const activeTab = this._tabs[Number(this.value)];
324
+ const activeTab = this._tabs[this._activeIndex()];
230
325
  if (!activeTab)
231
326
  return;
232
327
  const isVertical = this.orientation === 'vertical';
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export * from './events/index.js';
4
4
  export { define } from './define.js';
5
5
  export { setPrefix, getPrefix, tagName, cls } from './registry.js';
6
6
  export type { ElementBaseName } from './registry.js';
7
+ export { colorScheme } from './color-scheme.js';
8
+ export type { ColorScheme, ColorSchemeConfig, ColorSchemeListener } from './color-scheme.js';
7
9
  export { defineConfig } from './config.js';
8
10
  export type { LuxenConfig, LuxenEmitTypesConfig } from './config.js';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/html/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/html/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -3,4 +3,5 @@ export { LuxenFormAssociatedElement } from './shared/luxen-form-associated-eleme
3
3
  export * from './events/index.js';
4
4
  export { define } from './define.js';
5
5
  export { setPrefix, getPrefix, tagName, cls } from './registry.js';
6
+ export { colorScheme } from './color-scheme.js';
6
7
  export { defineConfig } from './config.js';
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "color-scheme-icon",
3
+ "displayName": "Color scheme icon",
4
+ "type": "shadow",
5
+ "isCustomElement": true,
6
+ "tag": "l-color-scheme-icon",
7
+ "nativeTag": null,
8
+ "selector": "l-color-scheme-icon",
9
+ "subItemOf": null,
10
+ "summary": "A sun that morphs into a moon. Purely presentational: it shows a\ncolor scheme, it does not choose or store one.\n\nThe two glyphs are a single shape — the disc grows, a mask slides in to carve\nthe crescent, and the rays retract in a ripple — so the change reads as one\nobject turning rather than two icons swapping. That is why this is authored\nSVG rather than an `<l-icon>`: an Iconify icon is opaque, and you cannot grow\none into another or animate a mask inside it.\n\nUse it wherever a scheme needs a glyph and the surrounding element is already\nthe control — a `menuitemcheckbox` row, a button, a legend. With no `scheme`\nit follows the page's scheme from `luxen-ui/color-scheme`, so it needs no\nwiring; set `scheme` to pin it.",
11
+ "status": "stable",
12
+ "appearances": [],
13
+ "import": {
14
+ "css": null,
15
+ "js": "luxen-ui/color-scheme-icon"
16
+ },
17
+ "properties": [
18
+ {
19
+ "name": "scheme",
20
+ "attribute": "scheme",
21
+ "type": "ColorScheme | undefined",
22
+ "default": null,
23
+ "reflects": true,
24
+ "description": "Which glyph to show. Leave it unset and the icon follows the page's scheme\n(`colorScheme.current` — a stored override, else the OS preference), so it\nstays in step with every other control without wiring. Set it to pin the\nglyph, for a legend or a preview that must not move."
25
+ },
26
+ {
27
+ "name": "label",
28
+ "attribute": "label",
29
+ "type": "string | undefined",
30
+ "default": null,
31
+ "reflects": false,
32
+ "description": "Accessible label. When set, the glyph becomes meaningful (`role=\"img\"`);\nwhen absent it is decorative and hidden from assistive tech — the right\ndefault inside a row or button that already carries the name."
33
+ }
34
+ ],
35
+ "attributes": [],
36
+ "events": [],
37
+ "methods": [],
38
+ "slots": [],
39
+ "cssClasses": [],
40
+ "cssParts": [
41
+ {
42
+ "name": "base",
43
+ "description": "The root `<svg>`, for overriding the morph's timing or tilt."
44
+ }
45
+ ],
46
+ "cssProperties": [
47
+ {
48
+ "name": "--size",
49
+ "default": "1em",
50
+ "description": "Width and height of the glyph."
51
+ },
52
+ {
53
+ "name": "--color",
54
+ "default": "currentColor",
55
+ "description": "Glyph color."
56
+ }
57
+ ],
58
+ "commands": [],
59
+ "examples": [
60
+ {
61
+ "title": "In a menu row, where the row is the control",
62
+ "language": "html",
63
+ "code": "```html\n<l-dropdown-item type=\"checkbox\" checked>\n<l-color-scheme-icon slot=\"prefix\" scheme=\"dark\"></l-color-scheme-icon>\nDark theme\n</l-dropdown-item>\n```"
64
+ }
65
+ ]
66
+ }
@@ -63,6 +63,14 @@
63
63
  "reflects": true,
64
64
  "description": "Whether this item's submenu is open. Managed by the parent `l-dropdown`."
65
65
  },
66
+ {
67
+ "name": "checkPlacement",
68
+ "attribute": "check-placement",
69
+ "type": "'start' | 'end'",
70
+ "default": "'start'",
71
+ "reflects": true,
72
+ "description": "Which side of a `type=\"checkbox\"` item carries the check mark. `start` (the\ndefault) puts it in the leading column, where it takes the place of any\n`prefix`. `end` moves it to the trailing edge, freeing that column so the\nitem can show its own icon alongside the state."
73
+ },
66
74
  {
67
75
  "name": "hasSubmenu",
68
76
  "attribute": null,
@@ -114,7 +122,7 @@
114
122
  },
115
123
  {
116
124
  "name": "prefix",
117
- "description": "Leading content (e.g. icon)."
125
+ "description": "Leading content (e.g. icon). A `type=\"checkbox\"` item ignores it unless `check-placement=\"end\"` frees the leading column."
118
126
  },
119
127
  {
120
128
  "name": "suffix",