@helixui/library 3.3.0 → 3.3.1-next.117

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 (129) hide show
  1. package/custom-elements.json +182 -13
  2. package/dist/components/hx-accordion/hx-accordion-item.d.ts +35 -0
  3. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  4. package/dist/components/hx-checkbox/hx-checkbox.d.ts +153 -1
  5. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  6. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  7. package/dist/components/hx-checkbox/index.js +1 -1
  8. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +151 -2
  9. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
  10. package/dist/components/hx-checkbox-group/index.js +1 -1
  11. package/dist/components/hx-color-picker/hx-color-picker.d.ts +163 -1
  12. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  13. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  14. package/dist/components/hx-color-picker/index.js +1 -1
  15. package/dist/components/hx-combobox/hx-combobox.d.ts +311 -2
  16. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  17. package/dist/components/hx-combobox/index.js +1 -1
  18. package/dist/components/hx-date-picker/hx-date-picker.d.ts +182 -56
  19. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  20. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  21. package/dist/components/hx-date-picker/index.js +1 -1
  22. package/dist/components/hx-dialog/hx-dialog.d.ts +240 -0
  23. package/dist/components/hx-dialog/hx-dialog.d.ts.map +1 -1
  24. package/dist/components/hx-dialog/index.js +1 -1
  25. package/dist/components/hx-dropdown/hx-dropdown.d.ts +80 -0
  26. package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
  27. package/dist/components/hx-dropdown/index.js +1 -1
  28. package/dist/components/hx-field/hx-field.d.ts +109 -0
  29. package/dist/components/hx-field/hx-field.d.ts.map +1 -1
  30. package/dist/components/hx-field/index.js +1 -1
  31. package/dist/components/hx-popover/hx-popover.d.ts +91 -0
  32. package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
  33. package/dist/components/hx-popover/index.js +1 -1
  34. package/dist/components/hx-radio-group/hx-radio-group.d.ts +152 -1
  35. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  36. package/dist/components/hx-radio-group/hx-radio.d.ts +14 -0
  37. package/dist/components/hx-radio-group/hx-radio.d.ts.map +1 -1
  38. package/dist/components/hx-radio-group/index.js +1 -1
  39. package/dist/components/hx-select/hx-select.d.ts +303 -2
  40. package/dist/components/hx-select/hx-select.d.ts.map +1 -1
  41. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  42. package/dist/components/hx-select/index.js +1 -1
  43. package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
  44. package/dist/components/hx-side-nav/index.js +1 -1
  45. package/dist/components/hx-switch/hx-switch.d.ts +78 -1
  46. package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
  47. package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
  48. package/dist/components/hx-switch/index.js +1 -1
  49. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +110 -0
  50. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
  51. package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
  52. package/dist/components/hx-toggle-button/index.js +1 -1
  53. package/dist/components/hx-tooltip/hx-tooltip.d.ts +52 -0
  54. package/dist/components/hx-tooltip/hx-tooltip.d.ts.map +1 -1
  55. package/dist/components/hx-tooltip/index.js +1 -1
  56. package/dist/css/helix-all.css +98 -1
  57. package/dist/css/helix-forms.css +98 -1
  58. package/dist/css/hx-checkbox.css +18 -0
  59. package/dist/css/hx-color-picker.css +25 -0
  60. package/dist/css/hx-date-picker.css +2 -1
  61. package/dist/css/hx-select.css +19 -0
  62. package/dist/css/hx-switch.css +17 -0
  63. package/dist/css/hx-toggle-button.css +17 -0
  64. package/dist/css/index.css +1 -1
  65. package/dist/css/manifest.json +2 -1
  66. package/dist/index.js +15 -15
  67. package/dist/shared/aria-flatten-DY6v2vah.js +22 -0
  68. package/dist/shared/aria-flatten-DY6v2vah.js.map +1 -0
  69. package/dist/shared/aria-idref-Q0yiSR3p.js +104 -0
  70. package/dist/shared/aria-idref-Q0yiSR3p.js.map +1 -0
  71. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -1
  72. package/dist/shared/hx-checkbox-BdgoUeWi.js +696 -0
  73. package/dist/shared/hx-checkbox-BdgoUeWi.js.map +1 -0
  74. package/dist/shared/hx-checkbox-group-LWezHrvS.js +496 -0
  75. package/dist/shared/hx-checkbox-group-LWezHrvS.js.map +1 -0
  76. package/dist/shared/hx-color-picker-DVhZl88b.js +1221 -0
  77. package/dist/shared/hx-color-picker-DVhZl88b.js.map +1 -0
  78. package/dist/shared/hx-combobox-DvlezcDV.js +1359 -0
  79. package/dist/shared/hx-combobox-DvlezcDV.js.map +1 -0
  80. package/dist/shared/{hx-date-picker-2iRG1p74.js → hx-date-picker-N-0aG5XL.js} +542 -206
  81. package/dist/shared/hx-date-picker-N-0aG5XL.js.map +1 -0
  82. package/dist/shared/hx-dialog-DzB7VytW.js +717 -0
  83. package/dist/shared/hx-dialog-DzB7VytW.js.map +1 -0
  84. package/dist/shared/{hx-dropdown-LyaRc8Rf.js → hx-dropdown-DJWlF94E.js} +130 -77
  85. package/dist/shared/hx-dropdown-DJWlF94E.js.map +1 -0
  86. package/dist/shared/{hx-field-B3Qo8OLS.js → hx-field-zw0U1KVi.js} +99 -38
  87. package/dist/shared/hx-field-zw0U1KVi.js.map +1 -0
  88. package/dist/shared/{hx-nav-item-xqRPOCWX.js → hx-nav-item-CODtUlew.js} +13 -9
  89. package/dist/shared/{hx-nav-item-xqRPOCWX.js.map → hx-nav-item-CODtUlew.js.map} +1 -1
  90. package/dist/shared/{hx-popover-B-FP3-wW.js → hx-popover-CHxWY_cd.js} +123 -66
  91. package/dist/shared/hx-popover-CHxWY_cd.js.map +1 -0
  92. package/dist/shared/hx-radio-CeGzARNk.js +822 -0
  93. package/dist/shared/hx-radio-CeGzARNk.js.map +1 -0
  94. package/dist/shared/hx-select-DrcS-YRJ.js +1089 -0
  95. package/dist/shared/hx-select-DrcS-YRJ.js.map +1 -0
  96. package/dist/shared/hx-switch-BX_8uNUs.js +540 -0
  97. package/dist/shared/hx-switch-BX_8uNUs.js.map +1 -0
  98. package/dist/shared/{hx-toggle-button-iLiYrMbD.js → hx-toggle-button-Dcz9IlUm.js} +226 -65
  99. package/dist/shared/hx-toggle-button-Dcz9IlUm.js.map +1 -0
  100. package/dist/shared/{hx-tooltip-nYOv9OLu.js → hx-tooltip-DVqtKPCD.js} +68 -46
  101. package/dist/shared/hx-tooltip-DVqtKPCD.js.map +1 -0
  102. package/dist/utils/aria-flatten.d.ts +56 -0
  103. package/dist/utils/aria-flatten.d.ts.map +1 -0
  104. package/dist/utils/aria-idref.d.ts +127 -0
  105. package/dist/utils/aria-idref.d.ts.map +1 -0
  106. package/figma-inventory.json +66 -3
  107. package/package.json +2 -2
  108. package/dist/shared/hx-checkbox-D7xma9YH.js +0 -524
  109. package/dist/shared/hx-checkbox-D7xma9YH.js.map +0 -1
  110. package/dist/shared/hx-checkbox-group-C9n315Ju.js +0 -323
  111. package/dist/shared/hx-checkbox-group-C9n315Ju.js.map +0 -1
  112. package/dist/shared/hx-color-picker-uRc865FJ.js +0 -882
  113. package/dist/shared/hx-color-picker-uRc865FJ.js.map +0 -1
  114. package/dist/shared/hx-combobox-DDzqNKEW.js +0 -924
  115. package/dist/shared/hx-combobox-DDzqNKEW.js.map +0 -1
  116. package/dist/shared/hx-date-picker-2iRG1p74.js.map +0 -1
  117. package/dist/shared/hx-dialog-DRN_1-Y-.js +0 -514
  118. package/dist/shared/hx-dialog-DRN_1-Y-.js.map +0 -1
  119. package/dist/shared/hx-dropdown-LyaRc8Rf.js.map +0 -1
  120. package/dist/shared/hx-field-B3Qo8OLS.js.map +0 -1
  121. package/dist/shared/hx-popover-B-FP3-wW.js.map +0 -1
  122. package/dist/shared/hx-radio-CJvNU2yP.js +0 -621
  123. package/dist/shared/hx-radio-CJvNU2yP.js.map +0 -1
  124. package/dist/shared/hx-select-C8fEHQhC.js +0 -807
  125. package/dist/shared/hx-select-C8fEHQhC.js.map +0 -1
  126. package/dist/shared/hx-switch-BrZFaRue.js +0 -420
  127. package/dist/shared/hx-switch-BrZFaRue.js.map +0 -1
  128. package/dist/shared/hx-toggle-button-iLiYrMbD.js.map +0 -1
  129. package/dist/shared/hx-tooltip-nYOv9OLu.js.map +0 -1
@@ -1,9 +1,11 @@
1
- import { css as d, html as u, nothing as b } from "lit";
2
- import { query as g, property as a, customElement as p } from "lit/decorators.js";
3
- import { classMap as c } from "lit/directives/class-map.js";
4
- import { f as x } from "./forced-colors-CTEDFRGa.js";
5
- import { H as f } from "./helix-element-BNEYeiys.js";
6
- const v = d`
1
+ import { css as x, html as p, nothing as v } from "lit";
2
+ import { query as m, property as n, state as u, customElement as y } from "lit/decorators.js";
3
+ import { classMap as _ } from "lit/directives/class-map.js";
4
+ import { ifDefined as b } from "lit/directives/if-defined.js";
5
+ import { f as k } from "./forced-colors-CTEDFRGa.js";
6
+ import { s as A, i as T, r as g } from "./aria-idref-Q0yiSR3p.js";
7
+ import { H as S } from "./helix-element-BNEYeiys.js";
8
+ const L = x`
7
9
  :host {
8
10
  display: inline-block;
9
11
  }
@@ -39,6 +41,22 @@ const v = d`
39
41
  -webkit-user-select: none;
40
42
  }
41
43
 
44
+ /*
45
+ * Host-focus path: on the modern (IDL element-references) render branch the
46
+ * host is the tabbable surface (tabindex=0) and the inner <button> is
47
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
48
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
49
+ */
50
+ :host(:focus-visible) .button {
51
+ outline: var(--hx-focus-ring-width, 2px) solid
52
+ var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
53
+ outline-offset: var(--hx-focus-ring-offset, 2px);
54
+ }
55
+
56
+ /*
57
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
58
+ * <button> is the tab target. Native :focus-visible drives the ring.
59
+ */
42
60
  .button:focus-visible {
43
61
  outline: var(--hx-focus-ring-width, 2px) solid
44
62
  var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -237,6 +255,7 @@ const v = d`
237
255
  border: 2px solid ButtonText;
238
256
  }
239
257
 
258
+ :host(:focus-visible) .button,
240
259
  .button:focus-visible {
241
260
  outline: 3px solid Highlight;
242
261
  outline-offset: 2px;
@@ -261,14 +280,18 @@ const v = d`
261
280
  }
262
281
  }
263
282
  `;
264
- var m = Object.defineProperty, y = Object.getOwnPropertyDescriptor, o = (t, s, i, n) => {
265
- for (var r = n > 1 ? void 0 : n ? y(s, i) : s, l = t.length - 1, h; l >= 0; l--)
266
- (h = t[l]) && (r = (n ? h(s, i, r) : h(r)) || r);
267
- return n && r && m(s, i, r), r;
283
+ var w = Object.defineProperty, I = Object.getOwnPropertyDescriptor, a = (t, e, o, i) => {
284
+ for (var s = i > 1 ? void 0 : i ? I(e, o) : e, l = t.length - 1, h; l >= 0; l--)
285
+ (h = t[l]) && (s = (i ? h(e, o, s) : h(s)) || s);
286
+ return i && s && w(e, o, s), s;
268
287
  };
269
- let e = class extends f {
288
+ let r = class extends S {
270
289
  constructor() {
271
- super(...arguments), this.pressed = !1, this.variant = "secondary", this.size = "md", this.disabled = !1, this.name = void 0, this.value = void 0, this.label = void 0, this.required = !1;
290
+ super(...arguments), this.pressed = !1, this.variant = "secondary", this.size = "md", this.disabled = !1, this.name = void 0, this.value = void 0, this.label = void 0, this.required = !1, this._ariaMirror = null, this._slotLabelText = "", this._fallbackAriaLabelledBy = null, this._fallbackAriaDescribedBy = null, this._fallbackAriaLabel = null, this._supportsIdrefRefs = !0, this._internalTabindexManaged = !1, this._handleHostKeyDown = (t) => {
291
+ this.disabled || this._supportsIdrefRefs && t.target === this && (t.key === " " || t.key === "Enter") && (t.preventDefault(), this._invokeToggle());
292
+ }, this._handleHostClickRouted = (t) => {
293
+ this.disabled || !this._supportsIdrefRefs || t.composedPath()[0] !== this || this._invokeToggle();
294
+ }, this._slotTextObserver = null;
272
295
  }
273
296
  // ─── Form API ───
274
297
  /** Returns the ValidityState object. */
@@ -288,24 +311,138 @@ let e = class extends f {
288
311
  return this._internals.reportValidity();
289
312
  }
290
313
  // ─── Lifecycle ───
314
+ connectedCallback() {
315
+ if (super.connectedCallback(), this._supportsIdrefRefs = A(this._internals), this._syncHostAriaSemantics(), !this.hasAttribute("tabindex")) {
316
+ this._internalTabindexManaged = !0;
317
+ const t = this._supportsIdrefRefs ? "0" : "-1";
318
+ this.setAttribute("tabindex", this.disabled ? "-1" : t);
319
+ }
320
+ this.addEventListener("keydown", this._handleHostKeyDown), this.addEventListener("click", this._handleHostClickRouted), this._ariaMirror = T(this, () => {
321
+ this._syncHostAriaSemantics();
322
+ });
323
+ }
324
+ disconnectedCallback() {
325
+ var t, e;
326
+ super.disconnectedCallback(), this.removeEventListener("keydown", this._handleHostKeyDown), this.removeEventListener("click", this._handleHostClickRouted), (t = this._slotTextObserver) == null || t.disconnect(), this._slotTextObserver = null, (e = this._ariaMirror) == null || e.disconnect(), this._ariaMirror = null;
327
+ }
328
+ /** @internal */
329
+ _invokeToggle() {
330
+ this.pressed = !this.pressed, this._syncFormValue(), this.dispatchEvent(
331
+ new CustomEvent("hx-toggle", {
332
+ bubbles: !0,
333
+ composed: !0,
334
+ detail: { pressed: this.pressed }
335
+ })
336
+ );
337
+ }
338
+ /**
339
+ * Moves focus to the announced toggle-button surface. Codex round-1 finding
340
+ * `#1` made the host the canonical focus target on modern engines so AT
341
+ * announces a single widget. Round-7 finding `#9` extends that contract to
342
+ * the no-IDL-ref fallback: when the host is demoted (`tabindex=-1`,
343
+ * role/state cleared on `internals`) the inner `<button>` owns the announced
344
+ * semantics and tab order, so programmatic `focus()` must redirect there —
345
+ * otherwise scripted focus and error recovery land on the demoted host on
346
+ * unsupported engines.
347
+ */
348
+ focus(t) {
349
+ var e, o;
350
+ if (this._supportsIdrefRefs) {
351
+ super.focus(t);
352
+ return;
353
+ }
354
+ (o = (e = this.shadowRoot) == null ? void 0 : e.querySelector('[part="button"]')) == null || o.focus(t);
355
+ }
291
356
  firstUpdated(t) {
292
- if (super.firstUpdated(t), !this.label) {
293
- const s = this._defaultSlot;
294
- (s ? s.assignedNodes({ flatten: !0 }).some((n) => {
295
- var r;
296
- return (r = n.textContent) == null ? void 0 : r.trim();
357
+ if (super.firstUpdated(t), this._captureSlotLabelText(), this._installSlotTextObserver(), !this.label) {
358
+ const e = this._defaultSlot;
359
+ (e ? e.assignedNodes({ flatten: !0 }).some((i) => {
360
+ var s;
361
+ return (s = i.textContent) == null ? void 0 : s.trim();
297
362
  }) : !1) || console.warn(
298
363
  "[hx-toggle-button] No accessible label found. Set the `label` attribute or provide slot text content for WCAG 4.1.2 compliance."
299
364
  );
300
365
  }
301
366
  }
302
367
  updated(t) {
303
- super.updated(t), (t.has("pressed") || t.has("value") || t.has("required")) && this._syncFormValue();
368
+ if (super.updated(t), (t.has("pressed") || t.has("value") || t.has("required")) && this._syncFormValue(), (t.has("disabled") || t.has("_supportsIdrefRefs")) && this._internalTabindexManaged) {
369
+ const e = this._supportsIdrefRefs ? "0" : "-1";
370
+ this.setAttribute("tabindex", this.disabled ? "-1" : e);
371
+ }
372
+ this._syncHostAriaSemantics();
373
+ }
374
+ /**
375
+ * Reads the default slot's flattened text content into `_slotLabelText`.
376
+ * Called from `firstUpdated()` and `slotchange` so host-canonical semantics
377
+ * pick up slotted label text. Codex round-1 finding #9.
378
+ * @internal
379
+ */
380
+ _captureSlotLabelText() {
381
+ const t = this._defaultSlot;
382
+ if (!t) {
383
+ this._slotLabelText = "";
384
+ return;
385
+ }
386
+ const e = t.assignedNodes({ flatten: !0 }).map((o) => o.textContent ?? "").join(" ").trim();
387
+ this._slotLabelText = e;
388
+ }
389
+ /**
390
+ * (Re-)installs the mutation observer over the current set of assigned
391
+ * default-slot nodes. Disconnects any prior observer first so detached
392
+ * nodes stop firing into a torn-down host.
393
+ * @internal
394
+ */
395
+ _installSlotTextObserver() {
396
+ var o;
397
+ (o = this._slotTextObserver) == null || o.disconnect();
398
+ const t = this._defaultSlot;
399
+ if (!t) {
400
+ this._slotTextObserver = null;
401
+ return;
402
+ }
403
+ const e = new MutationObserver(() => {
404
+ this._captureSlotLabelText(), this._syncHostAriaSemantics();
405
+ });
406
+ t.assignedNodes({ flatten: !0 }).forEach((i) => {
407
+ e.observe(i, {
408
+ characterData: !0,
409
+ childList: !0,
410
+ subtree: !0
411
+ });
412
+ }), this._slotTextObserver = e;
413
+ }
414
+ /** @internal */
415
+ _handleDefaultSlotChange() {
416
+ this._captureSlotLabelText(), this._syncHostAriaSemantics(), this._installSlotTextObserver();
417
+ }
418
+ /**
419
+ * Mirrors toggle-button semantics onto the host via ElementInternals so that
420
+ * consumer-supplied `aria-label`, `aria-labelledby`, and `aria-describedby`
421
+ * on `<hx-toggle-button>` reach the announced control. The codex aria-group-2
422
+ * finding identified that the inner shadow `<button>` was the only carrier of
423
+ * the toggle role + pressed state, leaving host-level IDREF tokens stranded
424
+ * across the shadow boundary.
425
+ *
426
+ * The shadow `<button>` keeps `aria-pressed`/`aria-label` mirrored for
427
+ * backwards-compat with existing tests and for browsers without IDL element
428
+ * references; the host is the canonical announced surface.
429
+ * @internal
430
+ */
431
+ _syncHostAriaSemantics() {
432
+ var c;
433
+ const t = this._internals, e = ((c = this.getAttribute("aria-label")) == null ? void 0 : c.trim()) || "", o = this.getAttribute("aria-labelledby"), i = this.getAttribute("aria-describedby"), s = g(this, o), l = g(this, i), h = s.length > 0;
434
+ let d;
435
+ if (e ? d = e : h ? d = null : this.label ? d = this.label : d = this._slotLabelText || null, this._supportsIdrefRefs) {
436
+ t.role = "button", t.ariaPressed = this.pressed ? "true" : "false", t.ariaDisabled = this.disabled ? "true" : "false", t.ariaInvalid = t.validity.valid ? "false" : "true", t.ariaLabel = d;
437
+ const f = t;
438
+ f.ariaLabelledByElements = h ? s : null, f.ariaDescribedByElements = l.length > 0 ? l : null, this._fallbackAriaLabelledBy = null, this._fallbackAriaDescribedBy = null, this._fallbackAriaLabel = null;
439
+ } else
440
+ t.role = null, t.ariaPressed = null, t.ariaDisabled = null, t.ariaInvalid = null, t.ariaLabel = null, this._fallbackAriaLabelledBy = h ? o : null, this._fallbackAriaDescribedBy = i || null, this._fallbackAriaLabel = d;
304
441
  }
305
442
  _onFormReset() {
306
443
  this.pressed = !1;
307
444
  }
308
- _onFormStateRestore(t, s) {
445
+ _onFormStateRestore(t, e) {
309
446
  this.pressed = typeof t == "string" && t === "pressed";
310
447
  }
311
448
  _onFormDisabled(t) {
@@ -319,11 +456,16 @@ let e = class extends f {
319
456
  /** @internal */
320
457
  _updateValidity() {
321
458
  var t;
322
- this.required && !this.pressed ? this._internals.setValidity(
323
- { valueMissing: !0 },
324
- "Please activate this toggle button.",
325
- ((t = this.shadowRoot) == null ? void 0 : t.querySelector('[part="button"]')) ?? void 0
326
- ) : this._internals.setValidity({});
459
+ if (this.required && !this.pressed) {
460
+ const e = this._supportsIdrefRefs ? this : ((t = this.shadowRoot) == null ? void 0 : t.querySelector('[part="button"]')) ?? void 0;
461
+ this._internals.setValidity(
462
+ { valueMissing: !0 },
463
+ "Please activate this toggle button.",
464
+ e
465
+ );
466
+ } else
467
+ this._internals.setValidity({});
468
+ this._syncHostAriaSemantics();
327
469
  }
328
470
  // ─── Event Handling ───
329
471
  /** @internal */
@@ -338,17 +480,17 @@ let e = class extends f {
338
480
  composed: !0,
339
481
  detail: { pressed: this.pressed }
340
482
  })
341
- );
483
+ ), this._supportsIdrefRefs && this.focus();
342
484
  }
343
485
  // ─── Render Helpers ───
344
486
  /** @internal */
345
487
  _renderInner() {
346
- return u`
488
+ return p`
347
489
  <span part="prefix" class="button__prefix">
348
490
  <slot name="prefix"></slot>
349
491
  </span>
350
492
  <span part="label" class="button__label">
351
- <slot></slot>
493
+ <slot @slotchange=${this._handleDefaultSlotChange}></slot>
352
494
  </span>
353
495
  <span part="suffix" class="button__suffix">
354
496
  <slot name="suffix"></slot>
@@ -362,15 +504,19 @@ let e = class extends f {
362
504
  [`button--${this.variant}`]: !0,
363
505
  [`button--${this.size}`]: !0,
364
506
  "button--pressed": this.pressed
365
- };
366
- return u`
507
+ }, e = !this._supportsIdrefRefs, o = e && !this.disabled ? "0" : "-1", i = this._fallbackAriaLabel ?? this.label ?? void 0, s = this._fallbackAriaLabelledBy ?? void 0, l = this._fallbackAriaDescribedBy ?? void 0;
508
+ return p`
367
509
  <button
368
510
  part="button"
369
- class=${c(t)}
511
+ class=${_(t)}
370
512
  ?disabled=${this.disabled}
371
513
  type="button"
514
+ tabindex=${o}
372
515
  aria-pressed=${this.pressed ? "true" : "false"}
373
- aria-label=${this.label ?? b}
516
+ aria-label=${b(i)}
517
+ aria-labelledby=${b(s)}
518
+ aria-describedby=${b(l)}
519
+ aria-hidden=${e ? v : "true"}
374
520
  @click=${this._handleClick}
375
521
  >
376
522
  ${this._renderInner()}
@@ -378,39 +524,54 @@ let e = class extends f {
378
524
  `;
379
525
  }
380
526
  };
381
- e.styles = [v, x];
382
- e.formAssociated = !0;
383
- o([
384
- g("slot:not([name])")
385
- ], e.prototype, "_defaultSlot", 2);
386
- o([
387
- a({ type: Boolean, reflect: !0 })
388
- ], e.prototype, "pressed", 2);
389
- o([
390
- a({ type: String, reflect: !0 })
391
- ], e.prototype, "variant", 2);
392
- o([
393
- a({ type: String, reflect: !0, attribute: "hx-size" })
394
- ], e.prototype, "size", 2);
395
- o([
396
- a({ type: Boolean, reflect: !0 })
397
- ], e.prototype, "disabled", 2);
398
- o([
399
- a({ type: String })
400
- ], e.prototype, "name", 2);
401
- o([
402
- a({ type: String })
403
- ], e.prototype, "value", 2);
404
- o([
405
- a({ type: String })
406
- ], e.prototype, "label", 2);
407
- o([
408
- a({ type: Boolean, reflect: !0 })
409
- ], e.prototype, "required", 2);
410
- e = o([
411
- p("hx-toggle-button")
412
- ], e);
527
+ r.styles = [L, k];
528
+ r.formAssociated = !0;
529
+ a([
530
+ m("slot:not([name])")
531
+ ], r.prototype, "_defaultSlot", 2);
532
+ a([
533
+ n({ type: Boolean, reflect: !0 })
534
+ ], r.prototype, "pressed", 2);
535
+ a([
536
+ n({ type: String, reflect: !0 })
537
+ ], r.prototype, "variant", 2);
538
+ a([
539
+ n({ type: String, reflect: !0, attribute: "hx-size" })
540
+ ], r.prototype, "size", 2);
541
+ a([
542
+ n({ type: Boolean, reflect: !0 })
543
+ ], r.prototype, "disabled", 2);
544
+ a([
545
+ n({ type: String })
546
+ ], r.prototype, "name", 2);
547
+ a([
548
+ n({ type: String })
549
+ ], r.prototype, "value", 2);
550
+ a([
551
+ n({ type: String })
552
+ ], r.prototype, "label", 2);
553
+ a([
554
+ n({ type: Boolean, reflect: !0 })
555
+ ], r.prototype, "required", 2);
556
+ a([
557
+ u()
558
+ ], r.prototype, "_slotLabelText", 2);
559
+ a([
560
+ u()
561
+ ], r.prototype, "_fallbackAriaLabelledBy", 2);
562
+ a([
563
+ u()
564
+ ], r.prototype, "_fallbackAriaDescribedBy", 2);
565
+ a([
566
+ u()
567
+ ], r.prototype, "_fallbackAriaLabel", 2);
568
+ a([
569
+ u()
570
+ ], r.prototype, "_supportsIdrefRefs", 2);
571
+ r = a([
572
+ y("hx-toggle-button")
573
+ ], r);
413
574
  export {
414
- e as H
575
+ r as H
415
576
  };
416
- //# sourceMappingURL=hx-toggle-button-iLiYrMbD.js.map
577
+ //# sourceMappingURL=hx-toggle-button-Dcz9IlUm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-toggle-button-Dcz9IlUm.js","sources":["../../src/components/hx-toggle-button/hx-toggle-button.styles.ts","../../src/components/hx-toggle-button/hx-toggle-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixToggleButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Base Button ─── */\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-toggle-button-border-color, transparent);\n border-radius: var(--hx-toggle-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toggle-button-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-toggle-button-color, var(--hx-color-text-on-primary, #ffffff));\n font-family: var(--hx-toggle-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-toggle-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n }\n\n /*\n * Host-focus path: on the modern (IDL element-references) render branch the\n * host is the tabbable surface (tabindex=0) and the inner <button> is\n * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'\n * so keyboard users still see a visible affordance. Codex round-11 P1.\n */\n :host(:focus-visible) .button {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /*\n * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner\n * <button> is the tab target. Native :focus-visible drives the ring.\n */\n .button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .button:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .button:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n /* ─── Size Variants ─── */\n\n /* WCAG 2.5.5 (healthcare mandate): minimum 44px touch target for sm variant.\n min-height uses --hx-touch-target-min to guarantee the interactive area\n meets the threshold even though the visual size token is smaller. */\n .button--sm {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n .button--md {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .button--lg {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Style Variants ─── */\n\n .button--primary {\n --hx-toggle-button-bg: var(--hx-color-primary-500, #429797);\n --hx-toggle-button-color: var(--hx-color-text-on-primary, #ffffff);\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * secondary/ghost paint primary text on the surface (white). primary-500\n * (#429797) on white = 3.43:1 — fails AA at body sizes. shift to\n * primary-600 (#0F7078) = 6.06:1 — AA pass. border keeps primary-500\n * for the brand affordance (3:1 non-text contrast still met).\n */\n .button--secondary {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n }\n\n .button--secondary:hover {\n --hx-toggle-button-bg: var(--hx-color-primary-50, #ebf8f8);\n }\n\n .button--tertiary {\n --hx-toggle-button-bg: var(--hx-color-surface-sunken, #ebeee9);\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--tertiary:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--ghost {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--ghost:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--outline {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: var(--hx-color-border-strong, #66787b);\n }\n\n .button--outline:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n /* ─── Pressed State ─── */\n\n /*\n * Primary: already uses solid primary bg; pressed deepens to primary-700\n * to give clear visual feedback without introducing a new color.\n *\n * AA fix: text.on-primary (= neutral-900 #0D1825) on primary-700 (#0F6363)\n * = 2.54:1 — fails AA. Pin fg at neutral-0 for the darker pressed fill\n * (neutral-0 on primary-700 = 7.03:1, AAA pass). Mirrors hx-toast\n * precedent (commit 300e21ab0) and hx-button hover treatment.\n * Note: secondary.pressed below uses primary-500 and stays at 5.20:1 —\n * leave it alone.\n */\n .button--primary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-700, #0f6363));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-neutral-0, #ffffff)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * Secondary: unpressed is outlined/transparent; pressed fills with primary bg\n * so the state change is immediately legible.\n */\n .button--secondary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-500, #429797));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-on-primary, #ffffff)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-500, #429797);\n }\n\n /* Tertiary pressed: use primary-100 bg + primary-700 text + border for WCAG 3:1 non-text contrast. */\n .button--tertiary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n box-shadow: inset 0 0 0 1px var(--hx-color-primary-600, #0f7078);\n }\n\n /* Ghost pressed: subtle neutral fill, matching hover behavior as a baseline. */\n .button--ghost.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /* Outline pressed: fills with a neutral tint, darkens the border, and adds an inset shadow for WCAG 3:1 non-text contrast. */\n .button--outline.button--pressed {\n --hx-toggle-button-bg: var(\n --hx-toggle-button-pressed-bg,\n var(--hx-color-surface-sunken, #ebeee9)\n );\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-primary, #0d1825)\n );\n --hx-toggle-button-border-color: var(--hx-color-text-muted, #4a5362);\n box-shadow: inset 0 0 0 1px var(--hx-color-neutral-500, #66787b);\n }\n\n /* ─── Disabled ─── */\n\n .button[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Prefix / Suffix / Label ─── */\n\n .button__prefix,\n .button__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .button__label {\n flex: 1 1 auto;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .button {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .button {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n :host(:focus-visible) .button,\n .button:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .button--pressed {\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n box-shadow: none;\n }\n\n .button[disabled] {\n background-color: ButtonFace;\n color: GrayText;\n border-color: GrayText;\n opacity: 1;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToggleButtonStyles } from './hx-toggle-button.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\n/** Detail for the hx-toggle event dispatched by hx-toggle-button. */\nexport interface HxToggleDetail {\n pressed: boolean;\n}\n\n/**\n * A two-state toggle button that communicates a pressed/unpressed status to\n * assistive technology via `aria-pressed`. Supports multiple visual variants\n * and sizes, prefix/suffix slots, full ElementInternals form association, and\n * a distinct pressed visual state for every variant.\n *\n * @summary Two-state toggle button with pressed/unpressed ARIA semantics.\n *\n * @tag hx-toggle-button\n *\n * @slot - Default slot for the button label text or content.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Icon or content rendered after the label.\n *\n * @fires {CustomEvent<{pressed: boolean}>} hx-toggle - Dispatched when the\n * toggle state changes. Not dispatched when the button is disabled.\n *\n * @csspart button - The native `<button>` element.\n * @csspart label - The label text wrapper span.\n * @csspart prefix - The prefix slot container span.\n * @csspart suffix - The suffix slot container span.\n *\n * @cssprop [--hx-toggle-button-bg=var(--hx-color-primary-500)] - Button background color.\n * @cssprop [--hx-toggle-button-color=var(--hx-color-neutral-0)] - Button text color.\n * @cssprop [--hx-toggle-button-border-color=transparent] - Button border color.\n * @cssprop [--hx-toggle-button-border-radius=var(--hx-border-radius-md)] - Button border radius.\n * @cssprop [--hx-toggle-button-font-family=var(--hx-font-family-sans)] - Button font family.\n * @cssprop [--hx-toggle-button-font-weight=var(--hx-font-weight-semibold)] - Button font weight.\n * @cssprop [--hx-toggle-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-toggle-button-pressed-bg=var(--hx-color-primary-500)] - Background when pressed (variant-specific fallback applies).\n * @cssprop [--hx-toggle-button-pressed-color=var(--hx-color-neutral-0)] - Text color when pressed (variant-specific fallback applies).\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-filter-brightness-hover] - CSS filter.\n * @cssprop [--hx-filter-brightness-active] - CSS filter.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-color-primary-700] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-color-neutral-50] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n */\n@customElement('hx-toggle-button')\nexport class HelixToggleButton extends HelixElement {\n static override styles = [helixToggleButtonStyles, forcedColorsInteractive];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n /** @internal */\n @query('slot:not([name])') private _defaultSlot!: HTMLSlotElement | null;\n\n // ─── Public Properties ───\n\n /**\n * Whether the toggle button is in the pressed state.\n * Reflected as an attribute so CSS selectors like `:host([pressed])` work.\n * @attr pressed\n */\n @property({ type: Boolean, reflect: true })\n pressed = false;\n\n /**\n * Visual style variant of the button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline' = 'secondary';\n\n /**\n * Size of the button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the button is disabled. Prevents all interaction and form actions.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Form field name submitted via ElementInternals when the button is pressed.\n * @attr name\n */\n @property({ type: String })\n name: string | undefined = undefined;\n\n /**\n * Form field value submitted via ElementInternals when the button is pressed.\n * @attr value\n */\n @property({ type: String })\n value: string | undefined = undefined;\n\n /**\n * Accessible label forwarded to the inner `<button>` as `aria-label`.\n * Required for icon-only toggle buttons where no visible text is present.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * When true, the button must be in the pressed state for the form to be submitted.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n // ─── Form API ───\n\n /** Returns the ValidityState object. */\n override get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** Returns the current validation message. */\n override get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Checks whether the button satisfies its constraints. */\n checkValidity(): boolean {\n return this._internals.checkValidity();\n }\n\n /** Reports validity and shows the browser's constraint validation UI. */\n reportValidity(): boolean {\n return this._internals.reportValidity();\n }\n\n /**\n * Handle for the shared IDREF observer. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Default-slot text content captured for use as the host's accessible name\n * when no explicit `label`/`aria-label`/`aria-labelledby` is supplied.\n * Codex round-1 finding #9.\n * @internal\n */\n @state() private _slotLabelText: string = '';\n\n /** No-IDL-ref fallback tokens applied to the inner button. @internal */\n @state() private _fallbackAriaLabelledBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaDescribedBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaLabel: string | null = null;\n\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the render-time branch between the modern path (host is the\n * announced surface, inner button is `aria-hidden + tabindex=-1`) and the\n * fallback path (inner button is the announced surface, host is demoted).\n * Codex round-2 finding #2.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n\n /**\n * Tracks whether the host's `tabindex` is managed by the component itself\n * (vs. set explicitly by a consumer). Codex round-14 P2: a consumer-supplied\n * `tabindex` (e.g. roving-tabindex toolbar pattern with `tabindex=\"-1\"`)\n * must survive disabled flips and re-renders. Only re-assert tabindex in\n * `updated()` when the component originally claimed it.\n * @internal\n */\n private _internalTabindexManaged = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Detect platform support for IDL element references. Codex round-2\n // finding #2: drives the render-time branch between modern (host\n // announced) and fallback (inner button announced) paths.\n this._supportsIdrefRefs = supportsIdrefElementReferences(this._internals);\n // Seed root-independent semantics from the moment of connection so AT\n // sees the toggle role + pressed state before the first paint.\n this._syncHostAriaSemantics();\n // Codex round-1 finding #1: host is the canonical announced surface on\n // modern browsers, so the inner `<button>` is demoted via\n // `aria-hidden + tabindex=-1`.\n // Codex round-2 finding #2: on no-IDL-ref browsers the inner button is\n // the announced surface (it carries native button + aria-pressed), so\n // the host is demoted to `tabindex=-1` and lets the inner button own\n // tab order + activation.\n // Codex round-14 P2: only claim ownership of `tabindex` when no consumer\n // value is present. Consumers using roving-tabindex toolbar patterns\n // must be able to set `tabindex=\"-1\"` on the host without it being\n // clobbered on every disabled flip. Note we still claim ownership when\n // disabled — the initial value is `-1` to keep the host out of tab order\n // and `updated()` re-asserts the appropriate value when disabled flips.\n if (!this.hasAttribute('tabindex')) {\n this._internalTabindexManaged = true;\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('click', this._handleHostClickRouted);\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('click', this._handleHostClickRouted);\n // Codex round-13 P2: tear down the assigned-node text observer so a\n // detached host does not receive mutation callbacks from nodes that may\n // outlive it (e.g. lifted out of the slot but kept in the document).\n this._slotTextObserver?.disconnect();\n this._slotTextObserver = null;\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n /**\n * Host-level keydown handler. Active only on the modern path; on the\n * no-IDL-ref fallback the inner `<button>` owns native Space/Enter\n * activation. Codex round-2 finding #2.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n if (e.target !== this) return;\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n this._invokeToggle();\n }\n };\n\n /**\n * Host-level click router. The inner `<button>` is `aria-hidden + tabindex=-1`\n * on modern browsers but still receives clicks via mouse activation; toggling\n * is handled by the inner `_handleClick`. Host-level clicks (composed path\n * origin === host) only come from AT activation or programmatic triggers,\n * so we route those to the toggle pipeline.\n *\n * Codex round-2 finding #2: on no-IDL-ref browsers the inner button is the\n * announced surface so this host-level routing is a no-op — AT activation\n * lands on the inner button directly.\n * @internal\n */\n private _handleHostClickRouted = (e: MouseEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n // Only fire when the host itself originated the click — inner-button\n // clicks bubble through here too but are handled by `_handleClick`.\n const path = e.composedPath();\n if (path[0] !== this) return;\n this._invokeToggle();\n };\n\n /** @internal */\n private _invokeToggle(): void {\n this.pressed = !this.pressed;\n this._syncFormValue();\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n }\n\n /**\n * Moves focus to the announced toggle-button surface. Codex round-1 finding\n * `#1` made the host the canonical focus target on modern engines so AT\n * announces a single widget. Round-7 finding `#9` extends that contract to\n * the no-IDL-ref fallback: when the host is demoted (`tabindex=-1`,\n * role/state cleared on `internals`) the inner `<button>` owns the announced\n * semantics and tab order, so programmatic `focus()` must redirect there —\n * otherwise scripted focus and error recovery land on the demoted host on\n * unsupported engines.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n super.focus(options);\n return;\n }\n this.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"button\"]')?.focus(options);\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n\n // Track default-slot text content so it can serve as the accessible\n // name when no explicit label is set. Codex round-1 finding #9.\n this._captureSlotLabelText();\n // Codex round-13 P2: also observe in-place text mutations on assigned\n // nodes so framework-driven `Mute` → `Unmute` rewrites refresh the\n // cached label without requiring the consumer to swap the node.\n this._installSlotTextObserver();\n\n if (!this.label) {\n const slot = this._defaultSlot;\n const hasSlotText = slot\n ? slot.assignedNodes({ flatten: true }).some((n) => n.textContent?.trim())\n : false;\n if (!hasSlotText) {\n console.warn(\n '[hx-toggle-button] No accessible label found. Set the `label` attribute or provide slot text content for WCAG 4.1.2 compliance.',\n );\n }\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n if (\n changedProperties.has('pressed') ||\n changedProperties.has('value') ||\n changedProperties.has('required')\n ) {\n this._syncFormValue();\n }\n\n if (\n changedProperties.has('disabled') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_supportsIdrefRefs')\n ) {\n // Codex round-2 finding #2: align host tabindex with the chosen\n // announced surface. On no-IDL-ref browsers the inner button owns\n // tab order, so re-enabling the host should leave it `tabindex=-1`.\n // Codex round-14 P2: only re-assert when the component owns tabindex.\n // Consumer-managed values (e.g. roving-tabindex toolbar with `-1`) must\n // not be overwritten on disabled flips or supports-flag transitions.\n if (this._internalTabindexManaged) {\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n }\n\n // Host-elevated ARIA semantics — see _syncHostAriaSemantics.\n this._syncHostAriaSemantics();\n }\n\n /**\n * Reads the default slot's flattened text content into `_slotLabelText`.\n * Called from `firstUpdated()` and `slotchange` so host-canonical semantics\n * pick up slotted label text. Codex round-1 finding #9.\n * @internal\n */\n private _captureSlotLabelText(): void {\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotLabelText = '';\n return;\n }\n const text = slot\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent ?? '')\n .join(' ')\n .trim();\n this._slotLabelText = text;\n }\n\n /**\n * Watches assigned default-slot nodes for in-place text mutations so the\n * cached `_slotLabelText` (and thus `internals.ariaLabel`) stays in sync\n * when a framework rewrites textContent of an already-assigned node without\n * replacing it. `slotchange` does NOT fire for those mutations, so a\n * separate observer is required. Codex round-13 P2.\n * @internal\n */\n private _slotTextObserver: MutationObserver | null = null;\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * default-slot nodes. Disconnects any prior observer first so detached\n * nodes stop firing into a torn-down host.\n * @internal\n */\n private _installSlotTextObserver(): void {\n this._slotTextObserver?.disconnect();\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotTextObserver = null;\n return;\n }\n const observer = new MutationObserver(() => {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes({ flatten: true }).forEach((node) => {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n });\n this._slotTextObserver = observer;\n }\n\n /** @internal */\n private _handleDefaultSlotChange(): void {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n // Re-tune the in-place text observer over the new assigned-node set\n // (codex round-13 P2).\n this._installSlotTextObserver();\n }\n\n /**\n * Mirrors toggle-button semantics onto the host via ElementInternals so that\n * consumer-supplied `aria-label`, `aria-labelledby`, and `aria-describedby`\n * on `<hx-toggle-button>` reach the announced control. The codex aria-group-2\n * finding identified that the inner shadow `<button>` was the only carrier of\n * the toggle role + pressed state, leaving host-level IDREF tokens stranded\n * across the shadow boundary.\n *\n * The shadow `<button>` keeps `aria-pressed`/`aria-label` mirrored for\n * backwards-compat with existing tests and for browsers without IDL element\n * references; the host is the canonical announced surface.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const externalLabelTokens = this.getAttribute('aria-labelledby');\n const externalDescTokens = this.getAttribute('aria-describedby');\n const labelEls = resolveIdrefTokens(this, externalLabelTokens);\n const descEls = resolveIdrefTokens(this, externalDescTokens);\n // Codex round-35 finding (CR major): `aria-labelledby` is only \"effective\"\n // when at least one IDREF resolves. A typo or transiently-missing target\n // must NOT erase the visible label — fall back to label/slot text so a\n // visibly-labeled toggle never becomes unnamed.\n const hasEffectiveLabelledBy = labelEls.length > 0;\n let resolvedLabel: string | null;\n if (hostAriaLabel) {\n resolvedLabel = hostAriaLabel;\n } else if (hasEffectiveLabelledBy) {\n resolvedLabel = null;\n } else if (this.label) {\n resolvedLabel = this.label;\n } else {\n // Codex round-1 finding #9: default-slot text becomes the accessible\n // name when no explicit label is provided. Without this, slotted text\n // never reaches the host's announced surface.\n resolvedLabel = this._slotLabelText || null;\n }\n\n // Codex round-2 finding #2: branch on platform support. Modern path —\n // host carries `role=button` + aria-pressed via ElementInternals.\n // Fallback path — inner native `<button>` is the announced surface; clear\n // host role/state on internals so AT does not double-announce.\n if (this._supportsIdrefRefs) {\n // ─── Modern path ───\n internals.role = 'button';\n internals.ariaPressed = this.pressed ? 'true' : 'false';\n internals.ariaDisabled = this.disabled ? 'true' : 'false';\n // Codex round-1 finding #6: drive aria-invalid from the live ValidityState\n // so a required-but-unpressed toggle is announced as invalid even before\n // any visible affordance renders. `_updateValidity()` calls this method\n // synchronously after every `setValidity()`.\n internals.ariaInvalid = !internals.validity.valid ? 'true' : 'false';\n internals.ariaLabel = resolvedLabel;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n ariaDescribedByElements: Element[] | null;\n };\n const refsInternals = internals as InternalsWithRefs;\n\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n refsInternals.ariaDescribedByElements = descEls.length > 0 ? descEls : null;\n // Clear fallbacks when IDL refs are available.\n this._fallbackAriaLabelledBy = null;\n this._fallbackAriaDescribedBy = null;\n this._fallbackAriaLabel = null;\n } else {\n // ─── Fallback path: inner button is the announced surface ───\n // Round-2 finding #2: round-1 set host role/state via internals AND\n // mirrored aria-* onto the `aria-hidden` inner button — making the\n // mirrored attributes inert. The fix is to clear host role/state and\n // let the inner native `<button>` (rendered without aria-hidden, with\n // `tabindex=0`, with aria-pressed) carry semantics natively.\n internals.role = null;\n internals.ariaPressed = null;\n internals.ariaDisabled = null;\n internals.ariaInvalid = null;\n internals.ariaLabel = null;\n\n // Codex round-36 (medium): gate the fallback label tokens on the\n // *effective* labelledby contract. Mirroring broken consumer tokens to\n // the inner button on legacy engines erases the accessible name —\n // exactly the bug the modern path now defends against. When tokens\n // don't resolve, fall through to `_fallbackAriaLabel` (resolvedLabel)\n // so the slot/property still names the announced surface.\n this._fallbackAriaLabelledBy = hasEffectiveLabelledBy ? externalLabelTokens : null;\n this._fallbackAriaDescribedBy = externalDescTokens || null;\n this._fallbackAriaLabel = resolvedLabel;\n }\n }\n\n protected override _onFormReset(): void {\n this.pressed = false;\n }\n\n protected override _onFormStateRestore(\n state: string | File | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n this.pressed = typeof state === 'string' && state === 'pressed';\n }\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _syncFormValue(): void {\n if (this.pressed && this.value !== undefined) {\n // Pass explicit state 'pressed' so formStateRestoreCallback can reliably detect it.\n this._internals.setFormValue(this.value, 'pressed');\n } else {\n this._internals.setFormValue(null);\n }\n this._updateValidity();\n }\n\n /** @internal */\n private _updateValidity(): void {\n if (this.required && !this.pressed) {\n // Codex round-17 P2: anchor validity UI to the announced surface. On\n // the modern path the host is the canonical announced/focus surface\n // (the inner button is `aria-hidden + tabindex=-1`), so passing the\n // host avoids `reportValidity()` landing focus on a hidden node. On\n // the fallback path the inner button is the announced surface.\n const anchor: HTMLElement | undefined = this._supportsIdrefRefs\n ? this\n : (this.shadowRoot?.querySelector<HTMLElement>('[part=\"button\"]') ?? undefined);\n this._internals.setValidity(\n { valueMissing: true },\n 'Please activate this toggle button.',\n anchor,\n );\n } else {\n this._internals.setValidity({});\n }\n // Codex round-1 finding #6: keep `internals.ariaInvalid` aligned with the\n // current `ValidityState`.\n this._syncHostAriaSemantics();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.pressed = !this.pressed;\n this._syncFormValue();\n\n /**\n * Dispatched when the toggle state changes.\n * @event hx-toggle\n */\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n\n // Codex round-12 P2: on the modern path the host owns role=\"button\" and\n // tabindex=0; the inner <button tabindex=\"-1\"> is aria-hidden. Native\n // click activation on a `<button>` still focuses it, which would leave\n // `document.activeElement` and AT focus on a hidden node. Move focus to\n // the host so the announced surface is also the focus target.\n if (this._supportsIdrefRefs) {\n this.focus();\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderInner() {\n return html`\n <span part=\"prefix\" class=\"button__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"button__label\">\n <slot @slotchange=${this._handleDefaultSlotChange}></slot>\n </span>\n <span part=\"suffix\" class=\"button__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const classes = {\n button: true,\n [`button--${this.variant}`]: true,\n [`button--${this.size}`]: true,\n 'button--pressed': this.pressed,\n };\n\n // Codex round-2 finding #2: branch the inner button on platform support.\n // Modern path — host announced, inner button is `aria-hidden + tabindex=-1`.\n // Fallback path — inner native `<button>` is announced (NO aria-hidden,\n // tabindex=0) so consumer-mirrored aria-* attributes resolve through a\n // visible accessibility-tree node and AT can name + activate it natively.\n const innerIsAnnounced = !this._supportsIdrefRefs;\n const innerTabIndex = innerIsAnnounced && !this.disabled ? '0' : '-1';\n // Round-1 finding #8: on no-IDL-ref browsers mirror host aria tokens onto\n // the inner button so it carries an accessible name. On modern browsers\n // we still mirror `label` onto the inner button for non-AT consumers\n // (testing, devtools) — does not affect announced semantics.\n const innerAriaLabel = this._fallbackAriaLabel ?? this.label ?? undefined;\n const innerAriaLabelledBy = this._fallbackAriaLabelledBy ?? undefined;\n const innerAriaDescribedBy = this._fallbackAriaDescribedBy ?? undefined;\n\n return html`\n <button\n part=\"button\"\n class=${classMap(classes)}\n ?disabled=${this.disabled}\n type=\"button\"\n tabindex=${innerTabIndex}\n aria-pressed=${this.pressed ? 'true' : 'false'}\n aria-label=${ifDefined(innerAriaLabel)}\n aria-labelledby=${ifDefined(innerAriaLabelledBy)}\n aria-describedby=${ifDefined(innerAriaDescribedBy)}\n aria-hidden=${innerIsAnnounced ? nothing : 'true'}\n @click=${this._handleClick}\n >\n ${this._renderInner()}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toggle-button': HelixToggleButton;\n }\n}\n"],"names":["helixToggleButtonStyles","css","HelixToggleButton","HelixElement","e","supportsIdrefElementReferences","enabledTabIndex","installAriaIdrefMirror","_a","_b","options","changedProperties","slot","n","text","observer","node","internals","hostAriaLabel","externalLabelTokens","externalDescTokens","labelEls","resolveIdrefTokens","descEls","hasEffectiveLabelledBy","resolvedLabel","refsInternals","state","_mode","disabled","anchor","html","classes","innerIsAnnounced","innerTabIndex","innerAriaLabel","innerAriaLabelledBy","innerAriaDescribedBy","classMap","ifDefined","nothing","forcedColorsInteractive","__decorateClass","query","property","customElement"],"mappings":";;;;;;;AAEO,MAAMA,IAA0BC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACsFhC,IAAMC,IAAN,cAAgCC,EAAa;AAAA,EAA7C,cAAA;AAAA,UAAA,GAAA,SAAA,GAmBL,KAAA,UAAU,IAOV,KAAA,UAAsE,aAOtE,KAAA,OAA2B,MAO3B,KAAA,WAAW,IAOX,KAAA,OAA2B,QAO3B,KAAA,QAA4B,QAQ5B,KAAA,QAA4B,QAO5B,KAAA,WAAW,IA4BX,KAAQ,cAA4C,MAQ3C,KAAQ,iBAAyB,IAGjC,KAAQ,0BAAyC,MAEjD,KAAQ,2BAA0C,MAElD,KAAQ,qBAAoC,MAU5C,KAAQ,qBAAqB,IAUtC,KAAQ,2BAA2B,IAyDnC,KAAQ,qBAAqB,CAACC,MAA2B;AACvD,MAAI,KAAK,YACJ,KAAK,sBACNA,EAAE,WAAW,SACbA,EAAE,QAAQ,OAAOA,EAAE,QAAQ,aAC7BA,EAAE,eAAA,GACF,KAAK,cAAA;AAAA,IAET,GAcA,KAAQ,yBAAyB,CAACA,MAAwB;AAMxD,MALI,KAAK,YACL,CAAC,KAAK,sBAGGA,EAAE,aAAA,EACN,CAAC,MAAM,QAChB,KAAK,cAAA;AAAA,IACP,GAoHA,KAAQ,oBAA6C;AAAA,EAAA;AAAA;AAAA;AAAA,EArQrD,IAAa,WAA0B;AACrC,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA,EAGA,IAAa,oBAA4B;AACvC,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA,EAGA,gBAAyB;AACvB,WAAO,KAAK,WAAW,cAAA;AAAA,EACzB;AAAA;AAAA,EAGA,iBAA0B;AACxB,WAAO,KAAK,WAAW,eAAA;AAAA,EACzB;AAAA;AAAA,EA6CS,oBAA0B;AAsBjC,QArBA,MAAM,kBAAA,GAIN,KAAK,qBAAqBC,EAA+B,KAAK,UAAU,GAGxE,KAAK,uBAAA,GAcD,CAAC,KAAK,aAAa,UAAU,GAAG;AAClC,WAAK,2BAA2B;AAChC,YAAMC,IAAkB,KAAK,qBAAqB,MAAM;AACxD,WAAK,aAAa,YAAY,KAAK,WAAW,OAAOA,CAAe;AAAA,IACtE;AACA,SAAK,iBAAiB,WAAW,KAAK,kBAAkB,GACxD,KAAK,iBAAiB,SAAS,KAAK,sBAAsB,GAC1D,KAAK,cAAcC,EAAuB,MAAM,MAAM;AACpD,WAAK,uBAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAES,uBAA6B;;AACpC,UAAM,qBAAA,GACN,KAAK,oBAAoB,WAAW,KAAK,kBAAkB,GAC3D,KAAK,oBAAoB,SAAS,KAAK,sBAAsB,IAI7DC,IAAA,KAAK,sBAAL,QAAAA,EAAwB,cACxB,KAAK,oBAAoB,OACzBC,IAAA,KAAK,gBAAL,QAAAA,EAAkB,cAClB,KAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAyCQ,gBAAsB;AAC5B,SAAK,UAAU,CAAC,KAAK,SACrB,KAAK,eAAA,GACL,KAAK;AAAA,MACH,IAAI,YAAkC,aAAa;AAAA,QACjD,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,SAAS,KAAK,QAAA;AAAA,MAAQ,CACjC;AAAA,IAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYS,MAAMC,GAA8B;;AAC3C,QAAI,KAAK,oBAAoB;AAC3B,YAAM,MAAMA,CAAO;AACnB;AAAA,IACF;AACA,KAAAD,KAAAD,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAiC,uBAAlD,QAAAC,EAAsE,MAAMC;AAAA,EAC9E;AAAA,EAES,aAAaC,GAA+C;AAWnE,QAVA,MAAM,aAAaA,CAAiB,GAIpC,KAAK,sBAAA,GAIL,KAAK,yBAAA,GAED,CAAC,KAAK,OAAO;AACf,YAAMC,IAAO,KAAK;AAIlB,OAHoBA,IAChBA,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,KAAK,CAACC,MAAA;;AAAM,gBAAAL,IAAAK,EAAE,gBAAF,gBAAAL,EAAe;AAAA,OAAM,IACvE,OAEF,QAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAGN;AAAA,EACF;AAAA,EAES,QAAQG,GAA+C;AAW9D,QAVA,MAAM,QAAQA,CAAiB,IAG7BA,EAAkB,IAAI,SAAS,KAC/BA,EAAkB,IAAI,OAAO,KAC7BA,EAAkB,IAAI,UAAU,MAEhC,KAAK,eAAA,IAILA,EAAkB,IAAI,UAAU,KAC/BA,EAAgD,IAAI,oBAAoB,MAQrE,KAAK,0BAA0B;AACjC,YAAML,IAAkB,KAAK,qBAAqB,MAAM;AACxD,WAAK,aAAa,YAAY,KAAK,WAAW,OAAOA,CAAe;AAAA,IACtE;AAIF,SAAK,uBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,wBAA8B;AACpC,UAAMM,IAAO,KAAK;AAClB,QAAI,CAACA,GAAM;AACT,WAAK,iBAAiB;AACtB;AAAA,IACF;AACA,UAAME,IAAOF,EACV,cAAc,EAAE,SAAS,GAAA,CAAM,EAC/B,IAAI,CAACC,MAAMA,EAAE,eAAe,EAAE,EAC9B,KAAK,GAAG,EACR,KAAA;AACH,SAAK,iBAAiBC;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBQ,2BAAiC;;AACvC,KAAAN,IAAA,KAAK,sBAAL,QAAAA,EAAwB;AACxB,UAAMI,IAAO,KAAK;AAClB,QAAI,CAACA,GAAM;AACT,WAAK,oBAAoB;AACzB;AAAA,IACF;AACA,UAAMG,IAAW,IAAI,iBAAiB,MAAM;AAC1C,WAAK,sBAAA,GACL,KAAK,uBAAA;AAAA,IACP,CAAC;AACD,IAAAH,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,QAAQ,CAACI,MAAS;AACtD,MAAAD,EAAS,QAAQC,GAAM;AAAA,QACrB,eAAe;AAAA,QACf,WAAW;AAAA,QACX,SAAS;AAAA,MAAA,CACV;AAAA,IACH,CAAC,GACD,KAAK,oBAAoBD;AAAA,EAC3B;AAAA;AAAA,EAGQ,2BAAiC;AACvC,SAAK,sBAAA,GACL,KAAK,uBAAA,GAGL,KAAK,yBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,yBAA+B;;AACrC,UAAME,IAAY,KAAK,YAEjBC,MAAgBV,IAAA,KAAK,aAAa,YAAY,MAA9B,gBAAAA,EAAiC,WAAU,IAC3DW,IAAsB,KAAK,aAAa,iBAAiB,GACzDC,IAAqB,KAAK,aAAa,kBAAkB,GACzDC,IAAWC,EAAmB,MAAMH,CAAmB,GACvDI,IAAUD,EAAmB,MAAMF,CAAkB,GAKrDI,IAAyBH,EAAS,SAAS;AACjD,QAAII;AAkBJ,QAjBIP,IACFO,IAAgBP,IACPM,IACTC,IAAgB,OACP,KAAK,QACdA,IAAgB,KAAK,QAKrBA,IAAgB,KAAK,kBAAkB,MAOrC,KAAK,oBAAoB;AAE3B,MAAAR,EAAU,OAAO,UACjBA,EAAU,cAAc,KAAK,UAAU,SAAS,SAChDA,EAAU,eAAe,KAAK,WAAW,SAAS,SAKlDA,EAAU,cAAeA,EAAU,SAAS,QAAiB,UAAT,QACpDA,EAAU,YAAYQ;AAMtB,YAAMC,IAAgBT;AAEtB,MAAAS,EAAc,yBAAyBF,IAAyBH,IAAW,MAC3EK,EAAc,0BAA0BH,EAAQ,SAAS,IAAIA,IAAU,MAEvE,KAAK,0BAA0B,MAC/B,KAAK,2BAA2B,MAChC,KAAK,qBAAqB;AAAA,IAC5B;AAOE,MAAAN,EAAU,OAAO,MACjBA,EAAU,cAAc,MACxBA,EAAU,eAAe,MACzBA,EAAU,cAAc,MACxBA,EAAU,YAAY,MAQtB,KAAK,0BAA0BO,IAAyBL,IAAsB,MAC9E,KAAK,2BAA2BC,KAAsB,MACtD,KAAK,qBAAqBK;AAAA,EAE9B;AAAA,EAEmB,eAAqB;AACtC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEmB,oBACjBE,GACAC,GACM;AACN,SAAK,UAAU,OAAOD,KAAU,YAAYA,MAAU;AAAA,EACxD;AAAA,EAEmB,gBAAgBE,GAAyB;AAC1D,SAAK,WAAWA;AAAA,EAClB;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,IAAI,KAAK,WAAW,KAAK,UAAU,SAEjC,KAAK,WAAW,aAAa,KAAK,OAAO,SAAS,IAElD,KAAK,WAAW,aAAa,IAAI,GAEnC,KAAK,gBAAA;AAAA,EACP;AAAA;AAAA,EAGQ,kBAAwB;;AAC9B,QAAI,KAAK,YAAY,CAAC,KAAK,SAAS;AAMlC,YAAMC,IAAkC,KAAK,qBACzC,SACCtB,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAA2B,uBAAsB;AACvE,WAAK,WAAW;AAAA,QACd,EAAE,cAAc,GAAA;AAAA,QAChB;AAAA,QACAsB;AAAA,MAAA;AAAA,IAEJ;AACE,WAAK,WAAW,YAAY,EAAE;AAIhC,SAAK,uBAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKQ,aAAa1B,GAAqB;AACxC,QAAI,KAAK,UAAU;AACjB,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AACF;AAAA,IACF;AAEA,SAAK,UAAU,CAAC,KAAK,SACrB,KAAK,eAAA,GAML,KAAK;AAAA,MACH,IAAI,YAAkC,aAAa;AAAA,QACjD,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,SAAS,KAAK,QAAA;AAAA,MAAQ,CACjC;AAAA,IAAA,GAQC,KAAK,sBACP,KAAK,MAAA;AAAA,EAET;AAAA;AAAA;AAAA,EAKQ,eAAe;AACrB,WAAO2B;AAAA;AAAA;AAAA;AAAA;AAAA,4BAKiB,KAAK,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvD;AAAA;AAAA,EAIS,SAAS;AAChB,UAAMC,IAAU;AAAA,MACd,QAAQ;AAAA,MACR,CAAC,WAAW,KAAK,OAAO,EAAE,GAAG;AAAA,MAC7B,CAAC,WAAW,KAAK,IAAI,EAAE,GAAG;AAAA,MAC1B,mBAAmB,KAAK;AAAA,IAAA,GAQpBC,IAAmB,CAAC,KAAK,oBACzBC,IAAgBD,KAAoB,CAAC,KAAK,WAAW,MAAM,MAK3DE,IAAiB,KAAK,sBAAsB,KAAK,SAAS,QAC1DC,IAAsB,KAAK,2BAA2B,QACtDC,IAAuB,KAAK,4BAA4B;AAE9D,WAAON;AAAA;AAAA;AAAA,gBAGKO,EAASN,CAAO,CAAC;AAAA,oBACb,KAAK,QAAQ;AAAA;AAAA,mBAEdE,CAAa;AAAA,uBACT,KAAK,UAAU,SAAS,OAAO;AAAA,qBACjCK,EAAUJ,CAAc,CAAC;AAAA,0BACpBI,EAAUH,CAAmB,CAAC;AAAA,2BAC7BG,EAAUF,CAAoB,CAAC;AAAA,sBACpCJ,IAAmBO,IAAU,MAAM;AAAA,iBACxC,KAAK,YAAY;AAAA;AAAA,UAExB,KAAK,cAAc;AAAA;AAAA;AAAA,EAG3B;AACF;AArmBatC,EACK,SAAS,CAACF,GAAyByC,CAAuB;AAD/DvC,EAMK,iBAAiB;AAGEwC,EAAA;AAAA,EAAlCC,EAAM,kBAAkB;AAAA,GATdzC,EASwB,WAAA,gBAAA,CAAA;AAUnCwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAlB/B1C,EAmBX,WAAA,WAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAzB9B1C,EA0BX,WAAA,WAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM,WAAW,WAAW;AAAA,GAhCpD1C,EAiCX,WAAA,QAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAvC/B1C,EAwCX,WAAA,YAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA9Cf1C,EA+CX,WAAA,QAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GArDf1C,EAsDX,WAAA,SAAA,CAAA;AAQAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GA7Df1C,EA8DX,WAAA,SAAA,CAAA;AAOAwC,EAAA;AAAA,EADCE,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GApE/B1C,EAqEX,WAAA,YAAA,CAAA;AAoCiBwC,EAAA;AAAA,EAAhBf,EAAA;AAAM,GAzGIzB,EAyGM,WAAA,kBAAA,CAAA;AAGAwC,EAAA;AAAA,EAAhBf,EAAA;AAAM,GA5GIzB,EA4GM,WAAA,2BAAA,CAAA;AAEAwC,EAAA;AAAA,EAAhBf,EAAA;AAAM,GA9GIzB,EA8GM,WAAA,4BAAA,CAAA;AAEAwC,EAAA;AAAA,EAAhBf,EAAA;AAAM,GAhHIzB,EAgHM,WAAA,sBAAA,CAAA;AAUAwC,EAAA;AAAA,EAAhBf,EAAA;AAAM,GA1HIzB,EA0HM,WAAA,sBAAA,CAAA;AA1HNA,IAANwC,EAAA;AAAA,EADNG,EAAc,kBAAkB;AAAA,GACpB3C,CAAA;"}