@helixui/library 3.3.1-next.115 → 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 +64 -1
  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
@@ -0,0 +1,717 @@
1
+ import { css as I, nothing as S, html as m } from "lit";
2
+ import { query as H, state as k, property as p, customElement as R } from "lit/decorators.js";
3
+ import { l as N, u as F } from "./body-scroll-lock-VBa5TFP-.js";
4
+ import { a as $ } from "./forced-colors-CTEDFRGa.js";
5
+ import { f as D } from "./aria-flatten-DY6v2vah.js";
6
+ import { s as M, i as z, r as L } from "./aria-idref-Q0yiSR3p.js";
7
+ import { H as j } from "./helix-element-BNEYeiys.js";
8
+ import { c as V } from "./id-counter-DuX8vsui.js";
9
+ const U = I`
10
+ :host {
11
+ display: contents;
12
+ }
13
+
14
+ /* ─── Native dialog reset ─── */
15
+
16
+ dialog {
17
+ padding: 0;
18
+ border: none;
19
+ background: transparent;
20
+ color: inherit;
21
+ max-width: 100%;
22
+ max-height: 100%;
23
+ overflow: visible;
24
+ /* D5 — ensure native dialog element renders above the non-modal backdrop sibling */
25
+ position: relative;
26
+ z-index: calc(var(--hx-z-index-modal, 1400) + 1);
27
+ }
28
+
29
+ /* ─── Dialog container ─── */
30
+
31
+ .dialog {
32
+ display: flex;
33
+ flex-direction: column;
34
+ position: relative;
35
+ background-color: var(--hx-dialog-bg, var(--hx-color-surface-default, #ffffff));
36
+ color: var(--hx-dialog-color, var(--hx-color-text-primary, #0d1825));
37
+ border-radius: var(--hx-dialog-border-radius, var(--hx-border-radius-lg, 0.5rem));
38
+ box-shadow: var(--hx-dialog-shadow, var(--hx-shadow-xl, 0 20px 25px -5px rgb(0 0 0 / 0.1)));
39
+ width: var(--hx-dialog-width, var(--hx-container-narrow, 32rem));
40
+ max-width: calc(100vw - var(--hx-space-8, 2rem));
41
+ max-height: calc(100vh - var(--hx-space-8, 2rem));
42
+ overflow: hidden;
43
+ outline: none;
44
+
45
+ /* Open/close animation */
46
+ opacity: 0;
47
+ transform: translateY(var(--hx-space-4, 1rem)) scale(0.97);
48
+ transition:
49
+ opacity var(--hx-duration-normal, 200ms) var(--hx-easing-out, ease-out),
50
+ transform var(--hx-duration-normal, 200ms) var(--hx-easing-out, ease-out);
51
+ }
52
+
53
+ dialog[open] .dialog {
54
+ opacity: 1;
55
+ transform: translateY(0) scale(1);
56
+ }
57
+
58
+ @media (prefers-reduced-motion: reduce) {
59
+ .dialog {
60
+ transition: none;
61
+ }
62
+
63
+ .dialog__close-btn {
64
+ transition: none;
65
+ }
66
+ }
67
+
68
+ /* ─── Native backdrop (modal mode) ─── */
69
+
70
+ dialog::backdrop {
71
+ background-color: var(
72
+ --hx-dialog-backdrop-color,
73
+ var(--hx-color-surface-overlay, rgba(0, 0, 0, 0.75))
74
+ );
75
+ opacity: 0;
76
+ transition: opacity var(--hx-duration-normal, 200ms) var(--hx-easing-out, ease-out);
77
+ }
78
+
79
+ dialog[open]::backdrop {
80
+ opacity: var(--hx-dialog-backdrop-opacity, 0.5);
81
+ }
82
+
83
+ @media (prefers-reduced-motion: reduce) {
84
+ dialog::backdrop {
85
+ transition: none;
86
+ }
87
+ }
88
+
89
+ /* ─── Non-modal backdrop overlay ─── */
90
+
91
+ .dialog-backdrop {
92
+ position: fixed;
93
+ inset: 0;
94
+ background-color: var(
95
+ --hx-dialog-backdrop-color,
96
+ var(--hx-color-surface-overlay, rgba(0, 0, 0, 0.75))
97
+ );
98
+ opacity: var(--hx-dialog-backdrop-opacity, 0.5);
99
+ /* D5 — backdrop z-index must be lower than the dialog element's z-index */
100
+ z-index: var(--hx-z-index-modal, 1400);
101
+ }
102
+
103
+ /* ─── Header ─── */
104
+
105
+ .dialog__header {
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: space-between;
109
+ padding: var(--hx-dialog-header-padding, var(--hx-space-5, 1.25rem) var(--hx-space-6, 1.5rem));
110
+ border-bottom: var(--hx-border-width-thin, 1px) solid
111
+ var(--hx-dialog-header-border-color, var(--hx-color-border-default, #d6dbd5));
112
+ gap: var(--hx-space-4, 1rem);
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ .dialog__heading {
117
+ margin: 0;
118
+ font-family: var(--hx-dialog-font-family, var(--hx-font-family-sans, sans-serif));
119
+ font-size: var(--hx-font-size-lg, 1.125rem);
120
+ font-weight: var(--hx-font-weight-semibold, 600);
121
+ line-height: var(--hx-line-height-tight, 1.25);
122
+ color: var(--hx-dialog-heading-color, var(--hx-color-text-primary, #0d1825));
123
+ flex: 1 1 auto;
124
+ }
125
+
126
+ /* ─── Built-in close button (D17) ─── */
127
+
128
+ .dialog__close-btn {
129
+ display: inline-flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ flex-shrink: 0;
133
+ /* WCAG 2.5.5 (healthcare mandate): minimum 44x44px touch target */
134
+ min-width: var(--hx-touch-target-min, 2.75rem);
135
+ min-height: var(--hx-touch-target-min, 2.75rem);
136
+ width: var(--hx-touch-target-min, 2.75rem);
137
+ height: var(--hx-touch-target-min, 2.75rem);
138
+ padding: 0;
139
+ margin-inline-start: auto;
140
+ background: transparent;
141
+ border: none;
142
+ border-radius: var(--hx-border-radius-sm, 0.25rem);
143
+ cursor: pointer;
144
+ color: var(--hx-dialog-close-btn-color, var(--hx-color-text-muted, #4a5362));
145
+ font-size: var(--hx-font-size-xl, 1.25rem);
146
+ line-height: 1; /* intentional literal: icon button needs line-height 1; no token maps to exactly 1 */
147
+ transition:
148
+ color var(--hx-duration-fast, 100ms) ease,
149
+ background-color var(--hx-duration-fast, 100ms) ease;
150
+ }
151
+
152
+ .dialog__close-btn::before {
153
+ content: '×';
154
+ }
155
+
156
+ .dialog__close-btn:hover {
157
+ color: var(--hx-dialog-close-btn-hover-color, var(--hx-color-text-primary, #0d1825));
158
+ background-color: var(--hx-dialog-close-btn-hover-bg, var(--hx-color-surface-sunken, #ebeee9));
159
+ }
160
+
161
+ .dialog__close-btn:focus-visible {
162
+ outline: var(--hx-focus-ring-width, 2px) solid
163
+ var(--hx-dialog-close-btn-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
164
+ outline-offset: var(--hx-focus-ring-offset, 2px);
165
+ }
166
+
167
+ /* ─── Body ─── */
168
+
169
+ .dialog__body {
170
+ flex: 1 1 auto;
171
+ padding: var(--hx-dialog-body-padding, var(--hx-space-6, 1.5rem));
172
+ overflow-y: auto;
173
+ overscroll-behavior: contain;
174
+ }
175
+
176
+ /* ─── Footer ─── */
177
+
178
+ .dialog__footer {
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: flex-end;
182
+ gap: var(--hx-space-3, 0.75rem);
183
+ padding: var(--hx-dialog-footer-padding, var(--hx-space-4, 1rem) var(--hx-space-6, 1.5rem));
184
+ border-top: var(--hx-border-width-thin, 1px) solid
185
+ var(--hx-dialog-footer-border-color, var(--hx-color-border-default, #d6dbd5));
186
+ flex-shrink: 0;
187
+ }
188
+
189
+ /* ─── Visually-hidden description (D8) ─── */
190
+
191
+ .dialog__description {
192
+ position: absolute;
193
+ width: 1px;
194
+ height: 1px;
195
+ padding: 0;
196
+ margin: -1px;
197
+ overflow: hidden;
198
+ clip: rect(0, 0, 0, 0);
199
+ white-space: nowrap;
200
+ border: 0;
201
+ }
202
+
203
+ /* ─── Forced Colors (Windows High Contrast) ─── */
204
+ /* Belt-and-suspenders: rich per-class HC overrides PLUS the forcedColorsSurface mixin. */
205
+
206
+ @media (forced-colors: active) {
207
+ .dialog {
208
+ border: 1px solid CanvasText;
209
+ }
210
+
211
+ .dialog__header {
212
+ border-bottom-color: CanvasText;
213
+ }
214
+
215
+ .dialog__footer {
216
+ border-top-color: CanvasText;
217
+ }
218
+
219
+ .dialog__close-btn {
220
+ color: ButtonText;
221
+ border: 1px solid ButtonText;
222
+ }
223
+ }
224
+ `;
225
+ var q = Object.defineProperty, G = Object.getOwnPropertyDescriptor, c = (e, t, i, r) => {
226
+ for (var a = r > 1 ? void 0 : r ? G(t, i) : t, s = e.length - 1, o; s >= 0; s--)
227
+ (o = e[s]) && (a = (r ? o(t, i, a) : o(a)) || a);
228
+ return r && a && q(t, i, a), a;
229
+ };
230
+ const P = V("hx-dialog"), B = [
231
+ "a[href]",
232
+ "area[href]",
233
+ "button:not([disabled])",
234
+ "input:not([disabled])",
235
+ "select:not([disabled])",
236
+ "textarea:not([disabled])",
237
+ '[tabindex]:not([tabindex="-1"])',
238
+ "details > summary"
239
+ ].join(",");
240
+ let l = class extends j {
241
+ constructor() {
242
+ super(...arguments), this._hasHeaderSlot = !1, this._hasFooterSlot = !1, this._cachedFocusableElements = [], this._isTransitioning = !1, this._transitionFallbackTimer = null, this._triggerElement = null, this._pendingReturnValue = void 0, this._dialogId = P(), this._headingId = `${this._dialogId}-heading`, this._descriptionId = `${this._dialogId}-description`, this._consumerDescId = `${this._dialogId}-consumer-desc`, this._consumerLabelId = `${this._dialogId}-consumer-label`, this._supportsIdrefRefs = !0, this._slottedHeaderEls = [], this._headerSlotText = "", this._consumerLabelledBy = null, this._consumerDescribedBy = null, this._ariaMirror = null, this._headerSlotTextObserver = null, this._externalRefsObserver = null, this._hostDescribedByObserver = null, this.open = !1, this.modal = !1, this.closeOnBackdrop = !0, this.heading = "", this.variant = "dialog", this.description = "", this.labelClose = "Close dialog", this._handleKeyDown = (e) => {
243
+ if (e.key === "Escape") {
244
+ e.preventDefault(), this._cancel();
245
+ return;
246
+ }
247
+ e.key === "Tab" && this.modal && this._trapFocus(e);
248
+ }, this._handleDialogClick = (e) => {
249
+ if (!this.closeOnBackdrop) return;
250
+ e.target === this._dialogEl && this._cancel();
251
+ }, this._handleBackdropClick = () => {
252
+ this.closeOnBackdrop && this._cancel();
253
+ }, this._handleNativeCancel = (e) => {
254
+ e.preventDefault();
255
+ };
256
+ }
257
+ // D10 — observe aria-label attribute without shadowing ARIAMixin.ariaLabel
258
+ static get observedAttributes() {
259
+ return [...super.observedAttributes, "aria-label"];
260
+ }
261
+ /**
262
+ * Returns the dialog's return value — the string passed to `close(returnValue)`.
263
+ * Mirrors `HTMLDialogElement.returnValue`.
264
+ */
265
+ get returnValue() {
266
+ var e;
267
+ return ((e = this._dialogEl) == null ? void 0 : e.returnValue) ?? "";
268
+ }
269
+ // ─── Lifecycle ───
270
+ // D10 — re-render when aria-label attribute changes (without declaring a shadowing property)
271
+ attributeChangedCallback(e, t, i) {
272
+ super.attributeChangedCallback(e, t, i), e === "aria-label" && t !== i && this.requestUpdate("aria-label", t);
273
+ }
274
+ connectedCallback() {
275
+ super.connectedCallback();
276
+ const e = this.constructor;
277
+ this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : M(this._internals), this._hostDescribedByObserver = new MutationObserver((t) => {
278
+ let i = !1;
279
+ for (const r of t) {
280
+ if (r.attributeName !== "aria-describedby") continue;
281
+ const a = r.oldValue, s = this.getAttribute("aria-describedby");
282
+ a !== null && s === null && (this._consumerDescribedBy = null, i = !0);
283
+ }
284
+ i && this._syncHostAriaSemantics();
285
+ }), this._hostDescribedByObserver.observe(this, {
286
+ attributes: !0,
287
+ attributeFilter: ["aria-describedby"],
288
+ attributeOldValue: !0
289
+ }), this._syncHostAriaSemantics(), this._ariaMirror = z(this, () => {
290
+ this._syncHostAriaSemantics();
291
+ });
292
+ }
293
+ firstUpdated() {
294
+ !this.heading.trim() && this._hasHeaderSlot;
295
+ }
296
+ disconnectedCallback() {
297
+ var e, t, i, r;
298
+ super.disconnectedCallback(), this._clearTransitionFallback(), this._isTransitioning = !1, this._removeGlobalListeners(), this.modal && this.open && F(), (e = this._ariaMirror) == null || e.disconnect(), this._ariaMirror = null, (t = this._headerSlotTextObserver) == null || t.disconnect(), this._headerSlotTextObserver = null, (i = this._externalRefsObserver) == null || i.disconnect(), this._externalRefsObserver = null, (r = this._hostDescribedByObserver) == null || r.disconnect(), this._hostDescribedByObserver = null;
299
+ }
300
+ updated(e) {
301
+ super.updated(e), e.has("open") && (this.open ? this._openDialog() : this._closeDialog()), this._syncHostAriaSemantics();
302
+ }
303
+ // ─── Public Methods ───
304
+ /** Opens the dialog in the mode determined by the `modal` property. */
305
+ show() {
306
+ this.open = !0;
307
+ }
308
+ /** Opens the dialog as a modal regardless of the `modal` property setting. */
309
+ showModal() {
310
+ this.modal = !0, this.open = !0;
311
+ }
312
+ /**
313
+ * Closes the dialog.
314
+ * @param returnValue - Optional return value string stored as `dialog.returnValue`.
315
+ */
316
+ close(e) {
317
+ e !== void 0 && (this._pendingReturnValue = e), this.open = !1;
318
+ }
319
+ // ─── Private: Open / Close ───
320
+ /** Clears the fallback timer that releases `_isTransitioning`. @internal */
321
+ _clearTransitionFallback() {
322
+ this._transitionFallbackTimer !== null && (clearTimeout(this._transitionFallbackTimer), this._transitionFallbackTimer = null);
323
+ }
324
+ /** @internal */
325
+ _openDialog() {
326
+ const e = this._dialogEl;
327
+ if (!e || e.open || this._isTransitioning) return;
328
+ this._isTransitioning = !0, this._clearTransitionFallback(), this._transitionFallbackTimer = setTimeout(() => {
329
+ this._transitionFallbackTimer = null, this._isTransitioning = !1;
330
+ }, 200);
331
+ const t = document.activeElement;
332
+ this._triggerElement = t instanceof HTMLElement ? t : null, this.modal ? (e.showModal(), N()) : e.show(), this._addGlobalListeners(), this.updateComplete.then(() => {
333
+ var i;
334
+ this._clearTransitionFallback(), this._isTransitioning = !1, this.open && (this._cachedFocusableElements = this._getFocusableElements(), (i = this._cachedFocusableElements[0]) == null || i.focus());
335
+ }), this.dispatchEvent(
336
+ new CustomEvent("hx-open", {
337
+ bubbles: !0,
338
+ composed: !0
339
+ })
340
+ );
341
+ }
342
+ /** @internal */
343
+ _closeDialog() {
344
+ var t;
345
+ const e = this._dialogEl;
346
+ if (e) {
347
+ if (!e.open) {
348
+ this._clearTransitionFallback(), this._isTransitioning = !1;
349
+ return;
350
+ }
351
+ this._clearTransitionFallback(), this._isTransitioning = !1, this._pendingReturnValue !== void 0 ? (e.close(this._pendingReturnValue), this._pendingReturnValue = void 0) : e.close(), this.modal && F(), this._removeGlobalListeners(), this._cachedFocusableElements = [], (t = this._triggerElement) == null || t.focus(), this._triggerElement = null, this.dispatchEvent(
352
+ new CustomEvent("hx-close", {
353
+ bubbles: !0,
354
+ composed: !0
355
+ })
356
+ );
357
+ }
358
+ }
359
+ // ─── Event Listeners ───
360
+ /** @internal */
361
+ _addGlobalListeners() {
362
+ var e, t, i;
363
+ (e = this._dialogEl) == null || e.addEventListener("keydown", this._handleKeyDown), (t = this._dialogEl) == null || t.addEventListener("click", this._handleDialogClick), (i = this._dialogEl) == null || i.addEventListener("cancel", this._handleNativeCancel);
364
+ }
365
+ /** @internal */
366
+ _removeGlobalListeners() {
367
+ var e, t, i;
368
+ (e = this._dialogEl) == null || e.removeEventListener("keydown", this._handleKeyDown), (t = this._dialogEl) == null || t.removeEventListener("click", this._handleDialogClick), (i = this._dialogEl) == null || i.removeEventListener("cancel", this._handleNativeCancel);
369
+ }
370
+ // ─── Focus Trap ───
371
+ /** @internal */
372
+ _getFocusableElements() {
373
+ var r, a;
374
+ const e = ((r = this.shadowRoot) == null ? void 0 : r.querySelectorAll("slot")) ?? [], t = [];
375
+ e.forEach((s) => {
376
+ s.assignedElements({ flatten: !0 }).forEach((o) => {
377
+ o instanceof HTMLElement && (o.matches(B) && t.push(o), o.querySelectorAll(B).forEach((h) => {
378
+ t.push(h);
379
+ }));
380
+ });
381
+ });
382
+ const i = t.filter(
383
+ (s) => !s.hasAttribute("disabled") && s.getAttribute("tabindex") !== "-1"
384
+ );
385
+ if (i.length === 0) {
386
+ const s = (a = this.shadowRoot) == null ? void 0 : a.querySelector(".dialog__close-btn");
387
+ s && i.push(s);
388
+ }
389
+ return i;
390
+ }
391
+ /** @internal */
392
+ _trapFocus(e) {
393
+ var _, v;
394
+ const t = this._cachedFocusableElements.length > 0 ? this._cachedFocusableElements : this._getFocusableElements();
395
+ if (t.length === 0) {
396
+ e.preventDefault();
397
+ return;
398
+ }
399
+ const [i, ...r] = t, a = r.length > 0 ? r[r.length - 1] : i;
400
+ if (!i || !a) return;
401
+ const s = document.activeElement, o = (_ = this.shadowRoot) == null ? void 0 : _.activeElement, h = o ?? s, u = h instanceof HTMLElement ? h : null, g = (v = this.shadowRoot) == null ? void 0 : v.querySelector(".dialog__close-btn");
402
+ e.shiftKey ? (u === i || g !== null && o === g && i === g) && (e.preventDefault(), a.focus()) : u === a && (e.preventDefault(), i.focus());
403
+ }
404
+ // ─── Cancel logic ───
405
+ /** @internal */
406
+ _cancel() {
407
+ this.dispatchEvent(
408
+ new CustomEvent("hx-cancel", {
409
+ bubbles: !0,
410
+ composed: !0
411
+ })
412
+ ), this.open = !1;
413
+ }
414
+ // ─── Slot change handlers ───
415
+ /** @internal */
416
+ _handleHeaderSlotChange(e) {
417
+ if (!(e.target instanceof HTMLSlotElement)) return;
418
+ const t = this._readHeaderSlotState(e.target);
419
+ this._hasHeaderSlot = t.hasUsefulName || t.hasAnyAssigned, this._slottedHeaderEls = t.elements, this._headerSlotText = t.text, this._installHeaderSlotTextObserver(t.elements), this._syncHostAriaSemantics();
420
+ }
421
+ /** @internal */
422
+ _handleFooterSlotChange(e) {
423
+ const t = e.target;
424
+ this._hasFooterSlot = t.assignedNodes({ flatten: !0 }).length > 0;
425
+ }
426
+ // ─── Host-canonical ARIA helpers ───
427
+ /**
428
+ * Reads the header slot's assigned nodes and computes the discriminated
429
+ * naming state. Aggregates ALL assigned elements (not just the first) so
430
+ * composed headers project the FULL visible label via
431
+ * `internals.ariaLabelledByElements`. Per AccName 1.2 §4.3.10,
432
+ * `aria-hidden="true"` / `[hidden]` elements contribute zero to the
433
+ * accessible name but stay in `elements` so AT walking IDL refs sees the
434
+ * full visible group. `hasUsefulName` is gated on the flattened text
435
+ * length: a slot containing only decorative wrappers does NOT name the
436
+ * dialog, and the host falls through to the next naming source.
437
+ *
438
+ * `hasAnyAssigned` is the legacy semantic kept for the existing dev-warning
439
+ * + `_renderHeader()` empty-slot flag (the heading / built-in close button
440
+ * area is rendered regardless of useful-name state when the consumer has
441
+ * projected SOMETHING into the header slot).
442
+ * @internal
443
+ */
444
+ _readHeaderSlotState(e) {
445
+ const t = e.assignedNodes({ flatten: !0 }), i = [], r = [];
446
+ let a = !1;
447
+ for (const o of t)
448
+ if (o.nodeType === Node.ELEMENT_NODE) {
449
+ a = !0;
450
+ const h = o;
451
+ if (i.push(h), h.getAttribute("aria-hidden") === "true") continue;
452
+ const u = D(h);
453
+ u && r.push(u);
454
+ } else if (o.nodeType === Node.TEXT_NODE) {
455
+ const h = (o.textContent ?? "").trim();
456
+ h && (r.push(h), a = !0);
457
+ }
458
+ const s = r.join(" ").replace(/\s+/g, " ").trim();
459
+ return {
460
+ hasUsefulName: s.length > 0,
461
+ hasAnyAssigned: a,
462
+ elements: i,
463
+ text: s
464
+ };
465
+ }
466
+ /**
467
+ * (Re-)installs the mutation observer over the current set of slotted header
468
+ * elements. On any descendant text/visibility mutation we re-flatten and
469
+ * re-sync so the host's accessible name tracks the visible header.
470
+ * @internal
471
+ */
472
+ _installHeaderSlotTextObserver(e) {
473
+ var i;
474
+ if ((i = this._headerSlotTextObserver) == null || i.disconnect(), e.length === 0) {
475
+ this._headerSlotTextObserver = null;
476
+ return;
477
+ }
478
+ const t = new MutationObserver(() => {
479
+ const r = [];
480
+ for (const s of e) {
481
+ if (s.getAttribute("aria-hidden") === "true") continue;
482
+ const o = D(s);
483
+ o && r.push(o);
484
+ }
485
+ const a = r.join(" ").replace(/\s+/g, " ").trim();
486
+ this._headerSlotText = a, this._syncHostAriaSemantics();
487
+ });
488
+ for (const r of e)
489
+ t.observe(r, {
490
+ characterData: !0,
491
+ childList: !0,
492
+ subtree: !0,
493
+ attributes: !0,
494
+ attributeFilter: ["aria-hidden", "hidden"]
495
+ });
496
+ this._headerSlotTextObserver = t;
497
+ }
498
+ /**
499
+ * (Re-)installs a `MutationObserver` against the deduped union of
500
+ * consumer-resolved label/description elements. Watches `characterData`,
501
+ * `childList`, `subtree`, and `aria-hidden` / `hidden` attributes so any
502
+ * in-place mutation on the referenced light-DOM nodes triggers a fresh
503
+ * sync — keeping the modern-path IDL refs and the fallback-path text
504
+ * flatten aligned with the live consumer text.
505
+ * @internal
506
+ */
507
+ _installExternalRefsObserver(e) {
508
+ if (this._externalRefsObserver && (this._externalRefsObserver.disconnect(), this._externalRefsObserver = null), e.length === 0) return;
509
+ const t = new Set(e), i = new MutationObserver(() => {
510
+ this._syncHostAriaSemantics();
511
+ });
512
+ for (const r of t)
513
+ i.observe(r, {
514
+ characterData: !0,
515
+ subtree: !0,
516
+ childList: !0,
517
+ attributes: !0,
518
+ attributeFilter: ["aria-hidden", "hidden"]
519
+ });
520
+ this._externalRefsObserver = i;
521
+ }
522
+ /**
523
+ * Resolves consumer-supplied label/description IDREFs on the host and
524
+ * projects the canonical dialog ARIA onto **both** surfaces:
525
+ *
526
+ * 1. The **host** via `ElementInternals` (modern path) — IDL element
527
+ * references that AT honouring the host-internals contract pick up
528
+ * across the shadow boundary.
529
+ * 2. The inner native `<dialog>` via attribute writes — hybrid fallback
530
+ * so AT that walks the native dialog first (and ignores host
531
+ * `internals.aria*Elements`) still finds an announceable name and
532
+ * description.
533
+ *
534
+ * Path A native-dialog adaptation: the host does NOT carry `internals.role`
535
+ * or `internals.ariaModal` — the native `<dialog>` already declares those at
536
+ * the platform level and rewriting them on the host would create
537
+ * nested-dialog announcements.
538
+ *
539
+ * The inner `<dialog>` keeps `role="alertdialog"` ONLY when `variant ===
540
+ * 'alertdialog'` (the platform allows overriding the implicit `dialog` role
541
+ * with the more specific `alertdialog`); otherwise the implicit `dialog`
542
+ * role wins.
543
+ *
544
+ * Naming precedence (W3C AccName 1.2 §4.3.1):
545
+ * 1. Consumer `aria-labelledby` (resolved IDREFs, text-flattened)
546
+ * 2. Consumer `aria-label`
547
+ * 3. Slotted `<slot name="header">` text
548
+ * 4. `heading` property
549
+ * 5. Hard-coded `"Dialog"`
550
+ * @internal
551
+ */
552
+ _syncHostAriaSemantics() {
553
+ var C, O;
554
+ const e = this._internals, t = this.getAttribute("aria-labelledby");
555
+ this._consumerLabelledBy = t;
556
+ const i = this.getAttribute("aria-describedby");
557
+ this._consumerDescribedBy = i;
558
+ const r = L(this, this._consumerLabelledBy), a = r.length > 0, s = L(this, this._consumerDescribedBy);
559
+ this._installExternalRefsObserver([...r, ...s]);
560
+ const o = (f) => f.getAttribute("aria-hidden") !== "true" && !f.hasAttribute("hidden"), h = this.getAttribute("aria-label"), u = h !== null ? h.trim() : "", g = [];
561
+ g.push(...r.filter(o)), !a && !u && this._slottedHeaderEls.length > 0 && g.push(...this._slottedHeaderEls.filter(o));
562
+ const _ = [...s.filter(o)], v = (f) => f.filter(o).map((b) => D(b)).filter((b) => b.length > 0).join(" ");
563
+ let d = "";
564
+ if (a && (d = v(r)), !d && u && (d = u), !d && this._headerSlotText && (d = this._headerSlotText), !d && this.heading.trim() && (d = this.heading.trim()), d || (d = "Dialog"), this._supportsIdrefRefs) {
565
+ const f = e;
566
+ f.ariaLabelledByElements = g.length > 0 ? g : null, f.ariaDescribedByElements = _.length > 0 ? _ : null, a ? e.ariaLabel = null : e.ariaLabel = d;
567
+ } else
568
+ e.ariaLabel = d;
569
+ const y = ((C = this.shadowRoot) == null ? void 0 : C.getElementById(this._consumerDescId)) ?? null, w = v(s);
570
+ y && y.textContent !== w && (y.textContent = w);
571
+ const T = ((O = this.shadowRoot) == null ? void 0 : O.getElementById(this._consumerLabelId)) ?? null;
572
+ T && T.textContent !== d && (T.textContent = d);
573
+ const n = this._dialogEl ?? null;
574
+ if (n) {
575
+ const f = this.heading.trim().length > 0;
576
+ let b = null, x = null;
577
+ a ? b = this._consumerLabelId : this._headerSlotText ? b = this._consumerLabelId : u ? x = u : f ? b = this._headingId : x = d, b ? n.getAttribute("aria-labelledby") !== b && n.setAttribute("aria-labelledby", b) : n.hasAttribute("aria-labelledby") && n.removeAttribute("aria-labelledby"), x ? n.getAttribute("aria-label") !== x && n.setAttribute("aria-label", x) : n.hasAttribute("aria-label") && n.removeAttribute("aria-label");
578
+ const E = [];
579
+ this.description && E.push(this._descriptionId), w && y && E.push(this._consumerDescId);
580
+ const A = E.length > 0 ? E.join(" ") : null;
581
+ A ? n.getAttribute("aria-describedby") !== A && n.setAttribute("aria-describedby", A) : n.hasAttribute("aria-describedby") && n.removeAttribute("aria-describedby"), this.modal ? n.getAttribute("aria-modal") !== "true" && n.setAttribute("aria-modal", "true") : n.hasAttribute("aria-modal") && n.removeAttribute("aria-modal"), n.hasAttribute("aria-description") && n.removeAttribute("aria-description");
582
+ }
583
+ }
584
+ // ─── Render Helpers ───
585
+ /** @internal */
586
+ _renderHeader() {
587
+ const e = this.heading.trim().length > 0;
588
+ return m`
589
+ <div part="header" class="dialog__header">
590
+ ${e ? m`<h2 id=${this._headingId} class="dialog__heading">${this.heading}</h2>` : S}
591
+ <slot name="header" @slotchange=${this._handleHeaderSlotChange}></slot>
592
+ <button
593
+ part="close-button"
594
+ class="dialog__close-btn"
595
+ type="button"
596
+ aria-label=${this.labelClose}
597
+ @click=${() => this.close()}
598
+ ></button>
599
+ </div>
600
+ `;
601
+ }
602
+ /** @internal */
603
+ _renderFooter() {
604
+ return m`
605
+ <div part="footer" class="dialog__footer" ?hidden=${!this._hasFooterSlot}>
606
+ <slot name="footer" @slotchange=${this._handleFooterSlotChange}></slot>
607
+ </div>
608
+ `;
609
+ }
610
+ /** @internal */
611
+ _renderNonModalBackdrop() {
612
+ return this.modal || !this.open ? S : m`
613
+ <div
614
+ part="backdrop"
615
+ class="dialog-backdrop"
616
+ @click=${this._handleBackdropClick}
617
+ aria-hidden="true"
618
+ ></div>
619
+ `;
620
+ }
621
+ // D8 — render visually-hidden description for aria-describedby
622
+ /** @internal */
623
+ _renderDescription() {
624
+ return this.description ? m`<span id=${this._descriptionId} class="dialog__description"
625
+ >${this.description}</span
626
+ >` : S;
627
+ }
628
+ // ─── Render ───
629
+ render() {
630
+ return m`
631
+ ${this._renderNonModalBackdrop()}
632
+ <dialog role=${this.variant !== "dialog" ? this.variant : S}>
633
+ <div part="dialog" class="dialog">
634
+ ${this._renderHeader()} ${this._renderDescription()}
635
+ <div part="body" class="dialog__body">
636
+ <slot></slot>
637
+ </div>
638
+ ${this._renderFooter()}
639
+ </div>
640
+ <!--
641
+ Synthesized in-shadow span carrying the resolved accessible NAME for
642
+ the hybrid inner-dialog fallback (consumer aria-labelledby IDREF
643
+ chain flattened, or consumer aria-label, or slotted header text).
644
+ The host's \`internals.ariaLabelledByElements\` carries the live IDL
645
+ refs on the modern path; this span is the same-shadow-root target
646
+ referenced by the inner native \`<dialog>\`'s \`aria-labelledby\`
647
+ when the name source lives outside the shadow root. Updated
648
+ imperatively in \`_syncHostAriaSemantics()\`.
649
+ -->
650
+ <span id=${this._consumerLabelId} class="dialog__description" aria-hidden="false"></span>
651
+ <!--
652
+ Synthesized in-shadow span carrying consumer-resolved description
653
+ text. Updated imperatively on every sync. The inner native
654
+ \`<dialog>\`'s \`aria-describedby\` references this span so
655
+ cross-shadow consumer descriptions resolve through the standard
656
+ described-by channel without writing light-DOM ids that cannot
657
+ resolve from inside a shadow root. \`aria-description\` is
658
+ intentionally NEVER written — AccName ignores it whenever
659
+ \`aria-describedby\` is present.
660
+ -->
661
+ <span id=${this._consumerDescId} class="dialog__description" aria-hidden="false"></span>
662
+ </dialog>
663
+ `;
664
+ }
665
+ };
666
+ l.styles = [U, $];
667
+ l.__testSupportsIdrefRefsOverride = null;
668
+ c([
669
+ H("dialog")
670
+ ], l.prototype, "_dialogEl", 2);
671
+ c([
672
+ k()
673
+ ], l.prototype, "_hasHeaderSlot", 2);
674
+ c([
675
+ k()
676
+ ], l.prototype, "_hasFooterSlot", 2);
677
+ c([
678
+ k()
679
+ ], l.prototype, "_supportsIdrefRefs", 2);
680
+ c([
681
+ k()
682
+ ], l.prototype, "_headerSlotText", 2);
683
+ c([
684
+ p({ type: Boolean, reflect: !0 })
685
+ ], l.prototype, "open", 2);
686
+ c([
687
+ p({ type: Boolean, reflect: !0 })
688
+ ], l.prototype, "modal", 2);
689
+ c([
690
+ p({
691
+ attribute: "close-on-backdrop",
692
+ reflect: !0,
693
+ converter: {
694
+ fromAttribute: (e) => e !== "false",
695
+ toAttribute: (e) => String(e)
696
+ }
697
+ })
698
+ ], l.prototype, "closeOnBackdrop", 2);
699
+ c([
700
+ p({ type: String, reflect: !0 })
701
+ ], l.prototype, "heading", 2);
702
+ c([
703
+ p({ type: String, reflect: !0 })
704
+ ], l.prototype, "variant", 2);
705
+ c([
706
+ p({ type: String })
707
+ ], l.prototype, "description", 2);
708
+ c([
709
+ p({ type: String, attribute: "label-close" })
710
+ ], l.prototype, "labelClose", 2);
711
+ l = c([
712
+ R("hx-dialog")
713
+ ], l);
714
+ export {
715
+ l as H
716
+ };
717
+ //# sourceMappingURL=hx-dialog-DzB7VytW.js.map