@helixui/library 3.2.0-next.81 → 3.2.0-next.83

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.
@@ -32075,12 +32075,12 @@
32075
32075
  {
32076
32076
  "description": "Toast background color.",
32077
32077
  "name": "--hx-toast-bg",
32078
- "default": "var(--hx-color-neutral-900)"
32078
+ "default": "var(--hx-color-surface-inverse)"
32079
32079
  },
32080
32080
  {
32081
32081
  "description": "Toast text color.",
32082
32082
  "name": "--hx-toast-color",
32083
- "default": "var(--hx-color-neutral-0)"
32083
+ "default": "var(--hx-color-text-inverse)"
32084
32084
  },
32085
32085
  {
32086
32086
  "description": "Toast border radius.",
@@ -24,8 +24,8 @@ export type ToastVariant = 'default' | 'success' | 'warning' | 'danger' | 'info'
24
24
  * @csspart close-button - The dismiss button (only when closable).
25
25
  * @csspart action - The action slot wrapper.
26
26
  *
27
- * @cssprop [--hx-toast-bg=var(--hx-color-neutral-900)] - Toast background color.
28
- * @cssprop [--hx-toast-color=var(--hx-color-neutral-0)] - Toast text color.
27
+ * @cssprop [--hx-toast-bg=var(--hx-color-surface-inverse)] - Toast background color.
28
+ * @cssprop [--hx-toast-color=var(--hx-color-text-inverse)] - Toast text color.
29
29
  * @cssprop [--hx-toast-border-radius=var(--hx-border-radius-md)] - Toast border radius.
30
30
  * @cssprop [--hx-toast-shadow] - Toast box shadow.
31
31
  * @cssprop [--hx-toast-width=20rem] - Toast width.
@@ -1,4 +1,4 @@
1
- import { H as s, a as o, t as e } from "../../shared/toast-factory-CIiZDZGZ.js";
1
+ import { H as s, a as o, t as e } from "../../shared/toast-factory-Mz1GaaFF.js";
2
2
  export {
3
3
  s as HelixToast,
4
4
  o as HelixToastStack,
@@ -12218,10 +12218,10 @@ export const helixTableSectionBaseStyles = css`
12218
12218
  * are tuned for the lighter -500 surfaces and would fail here (e.g.
12219
12219
  * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens
12220
12220
  * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.
12221
- * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.39:1
12221
+ * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1
12222
12222
  * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1
12223
- * (success-600 #0E8A4A on white = 4.41:1 — drifts under AA at 14px)
12224
- * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.92:1
12223
+ * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)
12224
+ * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1
12225
12225
  * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1
12226
12226
  * (warning stays on the lighter -500 surface so on-warning works)
12227
12227
  *
@@ -1235,10 +1235,10 @@
1235
1235
  * are tuned for the lighter -500 surfaces and would fail here (e.g.
1236
1236
  * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens
1237
1237
  * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.
1238
- * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.39:1
1238
+ * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1
1239
1239
  * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1
1240
- * (success-600 #0E8A4A on white = 4.41:1 — drifts under AA at 14px)
1241
- * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.92:1
1240
+ * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)
1241
+ * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1
1242
1242
  * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1
1243
1243
  * (warning stays on the lighter -500 surface so on-warning works)
1244
1244
  *
@@ -51,10 +51,10 @@
51
51
  * are tuned for the lighter -500 surfaces and would fail here (e.g.
52
52
  * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens
53
53
  * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.
54
- * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.39:1
54
+ * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1
55
55
  * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1
56
- * (success-600 #0E8A4A on white = 4.41:1 — drifts under AA at 14px)
57
- * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.92:1
56
+ * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)
57
+ * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1
58
58
  * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1
59
59
  * (warning stays on the lighter -500 surface so on-warning works)
60
60
  *
@@ -1,4 +1,4 @@
1
- /* index.css — generated 2026-04-25T20:44:53.981Z */
1
+ /* index.css — generated 2026-04-25T21:20:27.891Z */
2
2
  /* Imports all per-component CSS files for Drupal asset pipeline */
3
3
 
4
4
  @import './hx-accordion.css';
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-04-25T20:44:53.980Z",
2
+ "generated": "2026-04-25T21:20:27.890Z",
3
3
  "components": [
4
4
  {
5
5
  "name": "hx-accordion",
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ import { F as St, H as yt } from "./shared/hx-text-input-ClrrmoE1.js";
74
74
  import { H as bt } from "./shared/hx-textarea-D9O4U8cb.js";
75
75
  import { H as gt } from "./shared/hx-theme-BiyQ7UUK.js";
76
76
  import { H as vt } from "./shared/hx-time-picker-m0z4nFB-.js";
77
- import { H as Et, a as Dt, t as kt } from "./shared/toast-factory-CIiZDZGZ.js";
77
+ import { H as Et, a as Dt, t as kt } from "./shared/toast-factory-Mz1GaaFF.js";
78
78
  import { H as Bt } from "./shared/hx-toggle-button-Dd8clXB4.js";
79
79
  import { H as Ft } from "./shared/hx-tooltip-nYOv9OLu.js";
80
80
  import { H as Lt } from "./shared/hx-top-nav-CchPYaiV.js";
@@ -56,10 +56,10 @@ const w = m`
56
56
  * are tuned for the lighter -500 surfaces and would fail here (e.g.
57
57
  * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens
58
58
  * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.
59
- * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.39:1
59
+ * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1
60
60
  * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1
61
- * (success-600 #0E8A4A on white = 4.41:1 — drifts under AA at 14px)
62
- * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.92:1
61
+ * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)
62
+ * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1
63
63
  * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1
64
64
  * (warning stays on the lighter -500 surface so on-warning works)
65
65
  *
@@ -563,4 +563,4 @@ export {
563
563
  d as a,
564
564
  H as t
565
565
  };
566
- //# sourceMappingURL=toast-factory-CIiZDZGZ.js.map
566
+ //# sourceMappingURL=toast-factory-Mz1GaaFF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-factory-Mz1GaaFF.js","sources":["../../src/components/hx-toast/hx-toast.styles.ts","../../src/components/hx-toast/hx-toast.ts","../../src/components/hx-toast/hx-toast-stack.ts","../../src/components/hx-toast/toast-factory.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-toast styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-toast-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * neutral-0 = #FFFFFF, neutral-900 = #0D1825 (surface-inverse anchor),\n * primary-600 = #0F7078, success-600 = #0E8A4A, warning-500 = #C2711C,\n * error-600 = #C92A2A.\n */\nexport const helixToastStyles = css`\n /* ─── hx-toast host ─── */\n\n :host {\n display: block;\n pointer-events: none;\n }\n\n :host([open]) {\n pointer-events: auto;\n }\n\n /* ─── Toast base ─── */\n\n .toast {\n display: flex;\n align-items: flex-start;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n border-radius: var(--hx-toast-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toast-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-toast-color, var(--hx-color-text-inverse, #ffffff));\n font-family: var(--hx-toast-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n line-height: var(--hx-line-height-normal, 1.5);\n box-shadow: var(\n --hx-toast-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n opacity: 0;\n transform: translateY(var(--hx-toast-enter-translate, var(--hx-space-2, 0.5rem)));\n transition:\n opacity var(--hx-transition-normal, 250ms ease),\n transform var(--hx-transition-normal, 250ms ease);\n width: var(--hx-toast-width, 20rem);\n max-width: 100%;\n pointer-events: auto;\n }\n\n :host([open]) .toast {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ─── Variant overrides ─── */\n\n /*\n * Toast variants paint on darker brand fills (primary-600/success-700/\n * error-600) because the lighter -500 fills can't pass AA against white\n * text in the precision-cool palette. The neutral-900 on-{role} tokens\n * are tuned for the lighter -500 surfaces and would fail here (e.g.\n * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens\n * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.\n * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1\n * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1\n * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)\n * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1\n * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1\n * (warning stays on the lighter -500 surface so on-warning works)\n *\n * 3.2.1 token-cascade: bg variants now route through surface.{role}-strong\n * semantics; fg variants route through text.on-{role}-strong (or on-warning\n * for the warning variant). Component-tier tokens are NOT bypassed — the\n * --hx-toast-bg / --hx-toast-color slots remain the single override point.\n */\n .toast--success {\n --hx-toast-bg: var(--hx-color-surface-success-strong, #146831);\n --hx-toast-color: var(--hx-color-text-on-success-strong, #ffffff);\n }\n\n .toast--warning {\n --hx-toast-bg: var(--hx-color-surface-warning-strong, #c2711c);\n --hx-toast-color: var(--hx-color-text-on-warning, #0d1825);\n }\n\n .toast--danger {\n --hx-toast-bg: var(--hx-color-surface-danger-strong, #c92a2a);\n --hx-toast-color: var(--hx-color-text-on-error-strong, #ffffff);\n }\n\n .toast--info {\n --hx-toast-bg: var(--hx-color-surface-info-strong, #0f7078);\n --hx-toast-color: var(--hx-color-text-on-primary-strong, #ffffff);\n }\n\n /* ─── Severity Label (WCAG 1.4.1) ─── */\n /* Visually hidden — non-color cue for severity variants (success/warning/danger/info). */\n /* Ensures variant is not conveyed by color alone for color-blind users. */\n\n .toast__severity-label {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ─── Icon ─── */\n\n .toast__icon {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n }\n\n .toast__icon:empty {\n display: none;\n }\n\n /* ─── Message ─── */\n\n .toast__message {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n /* ─── Action slot ─── */\n\n .toast__action {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n .toast__action:empty {\n display: none;\n }\n\n /* ─── Close button ─── */\n\n .toast__close {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* WCAG 2.5.5: minimum 44×44px touch target */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n padding: var(--hx-space-1, 0.25rem);\n background: transparent;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n color: inherit;\n cursor: pointer;\n opacity: var(--hx-opacity-75, 0.75);\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .toast__close:hover {\n opacity: 1;\n }\n\n .toast__close:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid currentColor;\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Reduced motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .toast {\n transition: none;\n }\n\n .toast__close {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n /* Belt-and-suspenders: rich per-class HC overrides PLUS the forcedColorsSurface mixin. */\n\n @media (forced-colors: active) {\n .toast {\n border: 1px solid CanvasText;\n }\n\n .toast__close {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n }\n`;\n\nexport const helixToastStackStyles = css`\n :host {\n display: block;\n position: fixed;\n z-index: var(--hx-z-index-toast, 1700);\n pointer-events: none;\n }\n\n .toast-stack {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-4, 1rem);\n pointer-events: none;\n }\n\n /* ─── Placements ─── */\n\n :host([placement='top-start']) {\n top: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-center']) {\n top: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-end']) {\n top: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n bottom: auto;\n }\n\n :host([placement='bottom-start']) {\n bottom: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-center']) {\n bottom: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-end']) {\n bottom: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n top: auto;\n }\n\n /* ─── Bottom placements: reverse order so newest is on top ─── */\n\n :host([placement^='bottom']) .toast-stack {\n flex-direction: column-reverse;\n }\n\n /* ─── Slide direction by placement ─── */\n\n :host([placement^='top']) ::slotted(hx-toast) {\n --hx-toast-enter-translate: calc(var(--hx-space-2, 0.5rem) * -1);\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 { HelixElement } from '../../base/index.js';\nimport { helixToastStyles } from './hx-toast.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\n\nexport type ToastVariant = 'default' | 'success' | 'warning' | 'danger' | 'info';\n\n/**\n * A transient notification message that auto-dismisses after a configurable duration.\n * Supports multiple visual variants, a closable button, icon/action slots, and full\n * ARIA live region semantics for screen readers.\n *\n * @summary Transient notification toast component.\n *\n * @tag hx-toast\n *\n * @slot - Default slot for the notification message.\n * @slot icon - Optional icon rendered before the message.\n * @slot action - Optional action button rendered after the message.\n *\n * @fires {CustomEvent} hx-show - Dispatched when the toast becomes visible.\n * @fires {CustomEvent} hx-hide - Dispatched when the toast begins hiding.\n * @fires {CustomEvent} hx-after-hide - Dispatched after the hide animation completes.\n *\n * @csspart base - The inner toast container div.\n * @csspart icon - The icon slot wrapper.\n * @csspart message - The message slot wrapper.\n * @csspart close-button - The dismiss button (only when closable).\n * @csspart action - The action slot wrapper.\n *\n * @cssprop [--hx-toast-bg=var(--hx-color-surface-inverse)] - Toast background color.\n * @cssprop [--hx-toast-color=var(--hx-color-text-inverse)] - Toast text color.\n * @cssprop [--hx-toast-border-radius=var(--hx-border-radius-md)] - Toast border radius.\n * @cssprop [--hx-toast-shadow] - Toast box shadow.\n * @cssprop [--hx-toast-width=20rem] - Toast width.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-toast-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-toast-enter-translate=var(--hx-space-2)] - CSS custom property.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-transition-normal] - Transition timing.\n * @cssprop [--hx-color-success-600] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-error-600] - Color.\n * @cssprop [--hx-color-primary-600] - Color.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-opacity-75] - Opacity.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n */\n@customElement('hx-toast')\nexport class HelixToast extends HelixElement {\n static override styles = [helixToastStyles, forcedColorsSurface];\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'success' | 'warning' | 'danger' | 'info' = 'default';\n\n /**\n * Auto-dismiss duration in milliseconds. Set to 0 for persistent toasts.\n * @attr duration\n */\n @property({ type: Number })\n duration = 5000;\n\n /**\n * Whether to show a close button.\n * @attr closable\n */\n @property({ type: Boolean, reflect: true })\n closable = false;\n\n /**\n * Whether the toast is currently visible.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Accessible label for the close button. Override for localization.\n * @attr label-close\n */\n @property({ attribute: 'label-close' })\n labelClose = 'Dismiss notification';\n\n // ─── Private State ───\n\n /** @internal */\n @query('.toast') private _toastEl!: HTMLElement | null;\n\n /** @internal Tracks whether the action slot has slotted content. */\n @state() private _hasActionContent = false;\n\n /** @internal */\n private _timer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Reduced Motion ───\n\n /** @internal Returns true when the user has opted into reduced motion. */\n private get _reducedMotion(): boolean {\n // Guard for SSR — window.matchMedia is unavailable server-side\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /** @internal */\n private _timerStartedAt: number | null = null;\n\n /** @internal */\n private _timerRemaining: number | null = null;\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('open')) {\n if (this.open) {\n this.removeAttribute('aria-hidden');\n this._emitShow();\n if (this.duration > 0 && !this._reducedMotion && !this._hasActionContent) {\n this._startTimer();\n }\n } else {\n this.setAttribute('aria-hidden', 'true');\n this._clearTimer();\n this._emitHide();\n }\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._clearTimer();\n }\n\n // ─── Public API ───\n\n /** Show the toast. */\n show(): void {\n if (!this.open) {\n this.open = true;\n }\n }\n\n /** Hide the toast. */\n hide(): void {\n if (this.open) {\n this.open = false;\n }\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _startTimer(remaining?: number): void {\n this._clearTimerHandle();\n const delay = remaining ?? this.duration;\n this._timerStartedAt = Date.now();\n this._timerRemaining = delay;\n this._timer = setTimeout(() => {\n this.open = false;\n }, delay);\n }\n\n /** @internal */\n private _pauseTimer(): void {\n if (this._timer === null || this._timerStartedAt === null || this._timerRemaining === null) {\n return;\n }\n const elapsed = Date.now() - this._timerStartedAt;\n this._timerRemaining = Math.max(0, this._timerRemaining - elapsed);\n this._clearTimerHandle();\n }\n\n /** @internal */\n private _clearTimerHandle(): void {\n if (this._timer !== null) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n }\n\n /** @internal */\n private _clearTimer(): void {\n this._clearTimerHandle();\n this._timerStartedAt = null;\n this._timerRemaining = null;\n }\n\n /** @internal */\n private _emitShow(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _emitHide(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n\n let fired = false;\n const fireAfterHide = () => {\n if (fired) return;\n fired = true;\n this.dispatchEvent(new CustomEvent<void>('hx-after-hide', { bubbles: true, composed: true }));\n };\n\n // Fire on transitionend if available; fallback ensures it fires in test environments\n // and when transitions are disabled (prefers-reduced-motion, no CSS transitions).\n const base = this._toastEl;\n if (base) {\n base.addEventListener('transitionend', fireAfterHide, { once: true });\n }\n // Fallback fires after the CSS transition duration (250ms) plus a small buffer.\n setTimeout(fireAfterHide, 300);\n }\n\n // ─── Event Handlers ───\n\n /** @internal */\n private _handleMouseEnter(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleMouseLeave(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleFocusIn(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleFocusOut(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleClose(): void {\n this.hide();\n }\n\n /** @internal */\n private _handleActionSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasActionContent = slot.assignedNodes({ flatten: true }).length > 0;\n if (this._hasActionContent && this.open) {\n this._pauseTimer();\n }\n }\n\n // ─── ARIA Helpers ───\n\n /** @internal */\n private get _role(): 'alert' | 'status' {\n return this.variant === 'danger' ? 'alert' : 'status';\n }\n\n /** @internal */\n private get _ariaLive(): 'assertive' | 'polite' {\n return this.variant === 'danger' ? 'assertive' : 'polite';\n }\n\n // ─── WCAG 1.4.1: Default Icons ───\n // Each semantic variant renders a default icon when no icon is slotted,\n // ensuring the severity is not conveyed by color alone.\n\n /** @internal */\n private _renderSuccessIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm3.03 6.28a.75.75 0 00-1.06-1.06L9 10.19 7.78 8.97a.75.75 0 00-1.06 1.06l1.75 1.75a.75.75 0 001.06 0l3.5-3.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderWarningIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M8.49 2.92a1.75 1.75 0 013.02 0l6.25 10.83A1.75 1.75 0 0116.25 16H3.75a1.75 1.75 0 01-1.51-2.25L8.49 2.92zM10 7a.75.75 0 01.75.75v3a.75.75 0 01-1.5 0v-3A.75.75 0 0110 7zm0 7.5a.75.75 0 100-1.5.75.75 0 000 1.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderDangerIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm-1.72 5.22a.75.75 0 011.06 0L10 7.94l.66-.72a.75.75 0 111.06 1.06L11.06 9l.66.72a.75.75 0 11-1.06 1.06L10 10.06l-.66.72a.75.75 0 01-1.06-1.06L8.94 9l-.66-.72a.75.75 0 010-1.06z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderInfoIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm.75 4.75a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM9.25 9a.75.75 0 011.5 0v4a.75.75 0 01-1.5 0V9z\"\n />\n </svg>`;\n }\n\n /** @internal Returns the default icon for the current variant, or nothing for 'default'. */\n private get _defaultIcon() {\n switch (this.variant) {\n case 'success':\n return this._renderSuccessIcon();\n case 'warning':\n return this._renderWarningIcon();\n case 'danger':\n return this._renderDangerIcon();\n case 'info':\n return this._renderInfoIcon();\n default:\n return nothing;\n }\n }\n\n // ─── WCAG 1.4.1: Severity label map ───\n\n /** @internal */\n private static readonly _SEVERITY_LABELS: Partial<Record<ToastVariant, string>> = {\n success: 'Success',\n warning: 'Warning',\n danger: 'Error',\n info: 'Info',\n };\n\n /** @internal */\n private get _severityLabel(): string {\n return HelixToast._SEVERITY_LABELS[this.variant] ?? '';\n }\n\n // ─── Render ───\n\n override render() {\n const severityLabel = this._severityLabel;\n\n return html`\n <div\n part=\"base\"\n class=${classMap({\n toast: true,\n [`toast--${this.variant}`]: true,\n })}\n role=${this._role}\n aria-live=${this._ariaLive}\n aria-atomic=\"true\"\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n @focusin=${this._handleFocusIn}\n @focusout=${this._handleFocusOut}\n >\n ${this.open\n ? html`\n ${severityLabel\n ? html`<span class=\"toast__severity-label\">${severityLabel}: </span>`\n : nothing}\n <span part=\"icon\" class=\"toast__icon\">\n <slot name=\"icon\">${this._defaultIcon}</slot>\n </span>\n <span part=\"message\" class=\"toast__message\">\n <slot></slot>\n </span>\n <span part=\"action\" class=\"toast__action\">\n <slot name=\"action\" @slotchange=${this._handleActionSlotChange}></slot>\n </span>\n ${this.closable\n ? html`\n <button\n part=\"close-button\"\n class=\"toast__close\"\n aria-label=${this.labelClose}\n @click=${this._handleClose}\n >\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n `\n : nothing}\n `\n : nothing}\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast': HelixToast;\n }\n}\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToastStackStyles } from './hx-toast.styles.js';\n\nexport type ToastStackPlacement =\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end';\n\n/**\n * A fixed-position container that stacks `hx-toast` elements at the specified\n * corner of the viewport. Enforces a maximum visible toast count via `stack-limit`.\n *\n * @summary Toast stack container managing position and count limits.\n *\n * @tag hx-toast-stack\n *\n * @slot - Accepts `hx-toast` elements.\n *\n * @csspart base - The inner stack container div.\n *\n * @cssprop [--hx-z-index-toast=9000] - Z-index for the fixed stack.\n */\n@customElement('hx-toast-stack')\nexport class HelixToastStack extends HelixElement {\n static override styles = [helixToastStackStyles];\n\n /**\n * Corner of the viewport where toasts appear.\n * @attr placement\n */\n @property({ type: String, reflect: true })\n placement:\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end' = 'bottom-end';\n\n /**\n * Maximum number of simultaneously visible toasts. 0 = unlimited.\n * @attr stack-limit\n */\n @property({ type: Number, attribute: 'stack-limit' })\n stackLimit = 3;\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=${classMap({\n 'toast-stack': true,\n [`toast-stack--${this.placement}`]: true,\n })}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast-stack': HelixToastStack;\n }\n}\n","import { HelixToast } from './hx-toast.js';\nimport { HelixToastStack } from './hx-toast-stack.js';\nimport type { ToastVariant } from './hx-toast.js';\nimport type { ToastStackPlacement } from './hx-toast-stack.js';\n\nexport interface ToastOptions {\n /** The notification message text. */\n message: string;\n /** Visual variant. Defaults to 'default'. */\n variant?: ToastVariant;\n /** Auto-dismiss duration in ms. 0 = persistent. Defaults to 3000. */\n duration?: number;\n /** Placement of the shared stack. Defaults to 'bottom-end'. */\n placement?: ToastStackPlacement;\n}\n\n/**\n * Imperatively create and display a toast notification.\n *\n * Creates a shared `hx-toast-stack` on `document.body` if one does not exist,\n * then appends a new `hx-toast` with the given options. Respects the stack's\n * `stackLimit` by hiding the oldest visible toast when the limit is exceeded.\n *\n * @example\n * import { toast } from '@helixui/library/components/hx-toast/index.js';\n * toast({ message: 'Patient record saved.', variant: 'success' });\n */\nexport function toast(options: ToastOptions): HelixToast {\n if (typeof document === 'undefined') throw new Error('toast() requires a browser environment');\n const placement = options.placement ?? 'bottom-end';\n\n // Find or create a dedicated stack for this placement\n const stackSelector = `hx-toast-stack[placement=\"${placement}\"]`;\n let stack = document.querySelector<HelixToastStack>(stackSelector);\n if (!stack) {\n stack = document.createElement('hx-toast-stack');\n stack.placement = placement;\n // Intentional design decision: the toast stack is appended to document.body rather\n // than inserted near the caller. This is required so that the fixed-position overlay\n // is not clipped by an ancestor with `overflow: hidden`, `transform`, or `filter`\n // (all of which create a new stacking context and break fixed positioning).\n // Drupal compatibility note: Drupal's BigPipe / AJAX behaviors can re-attach the\n // document body without removing these stacks. The selector check above\n // (`document.querySelector`) ensures only one stack per placement is ever created,\n // preventing duplicates on re-attach cycles.\n document.body.appendChild(stack);\n }\n\n // Enforce stack limit: hide oldest open toast if at capacity\n if (stack.stackLimit > 0) {\n const openToasts = [...stack.querySelectorAll<HelixToast>('hx-toast')].filter((t) => t.open);\n if (openToasts.length >= stack.stackLimit) {\n openToasts[0]?.hide();\n }\n }\n\n // Create toast element\n const toastEl = document.createElement('hx-toast');\n toastEl.variant = options.variant ?? 'default';\n toastEl.duration = options.duration ?? 3000;\n toastEl.closable = true;\n toastEl.textContent = options.message;\n\n // Remove from DOM after hiding\n toastEl.addEventListener('hx-after-hide', () => {\n toastEl.remove();\n });\n\n stack.appendChild(toastEl);\n toastEl.show();\n\n return toastEl;\n}\n"],"names":["helixToastStyles","css","helixToastStackStyles","HelixToast","HelixElement","changedProperties","remaining","delay","elapsed","fired","fireAfterHide","base","e","slot","html","nothing","severityLabel","classMap","forcedColorsSurface","__decorateClass","property","query","state","customElement","HelixToastStack","toast","options","placement","stackSelector","stack","openToasts","t","_a","toastEl"],"mappings":";;;;;AAYO,MAAMA,IAAmBC;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,GA6LnBC,IAAwBD;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;AA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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-04-25T20:02:01.523Z",
3
+ "generatedAt": "2026-04-25T20:44:50.116Z",
4
4
  "sourceCem": "custom-elements.json",
5
5
  "helixVersion": "3.2.0",
6
6
  "tokensVersion": "3.2.0",
@@ -25019,24 +25019,24 @@
25019
25019
  {
25020
25020
  "description": "Toast background color.",
25021
25021
  "name": "--hx-toast-bg",
25022
- "default": "var(--hx-color-neutral-900)",
25022
+ "default": "var(--hx-color-surface-inverse)",
25023
25023
  "figmaBinding": {
25024
25024
  "target": "Fill",
25025
25025
  "layerSelector": "root",
25026
- "semanticToken": "color/neutral",
25027
- "fallbackPrimitive": "color/neutral/900",
25026
+ "semanticToken": "color/surface/inverse",
25027
+ "fallbackPrimitive": null,
25028
25028
  "literalFallback": null
25029
25029
  }
25030
25030
  },
25031
25031
  {
25032
25032
  "description": "Toast text color.",
25033
25033
  "name": "--hx-toast-color",
25034
- "default": "var(--hx-color-neutral-0)",
25034
+ "default": "var(--hx-color-text-inverse)",
25035
25035
  "figmaBinding": {
25036
25036
  "target": "Fill",
25037
25037
  "layerSelector": "root",
25038
- "semanticToken": "color/neutral",
25039
- "fallbackPrimitive": "color/neutral/0",
25038
+ "semanticToken": "color/text/inverse",
25039
+ "fallbackPrimitive": null,
25040
25040
  "literalFallback": null
25041
25041
  }
25042
25042
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helixui/library",
3
- "version": "3.2.0-next.81",
3
+ "version": "3.2.0-next.83",
4
4
  "description": "Enterprise Web Component Library built with Lit 3.x",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -59,7 +59,7 @@
59
59
  "customElements": "custom-elements.json",
60
60
  "dependencies": {
61
61
  "lit": "^3.3.2",
62
- "@helixui/tokens": "3.2.0-next.81"
62
+ "@helixui/tokens": "3.2.0-next.83"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "@floating-ui/dom": "^1.7.6"
@@ -1 +0,0 @@
1
- {"version":3,"file":"toast-factory-CIiZDZGZ.js","sources":["../../src/components/hx-toast/hx-toast.styles.ts","../../src/components/hx-toast/hx-toast.ts","../../src/components/hx-toast/hx-toast-stack.ts","../../src/components/hx-toast/toast-factory.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-toast styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-toast-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * neutral-0 = #FFFFFF, neutral-900 = #0D1825 (surface-inverse anchor),\n * primary-600 = #0F7078, success-600 = #0E8A4A, warning-500 = #C2711C,\n * error-600 = #C92A2A.\n */\nexport const helixToastStyles = css`\n /* ─── hx-toast host ─── */\n\n :host {\n display: block;\n pointer-events: none;\n }\n\n :host([open]) {\n pointer-events: auto;\n }\n\n /* ─── Toast base ─── */\n\n .toast {\n display: flex;\n align-items: flex-start;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n border-radius: var(--hx-toast-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toast-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-toast-color, var(--hx-color-text-inverse, #ffffff));\n font-family: var(--hx-toast-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n line-height: var(--hx-line-height-normal, 1.5);\n box-shadow: var(\n --hx-toast-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n opacity: 0;\n transform: translateY(var(--hx-toast-enter-translate, var(--hx-space-2, 0.5rem)));\n transition:\n opacity var(--hx-transition-normal, 250ms ease),\n transform var(--hx-transition-normal, 250ms ease);\n width: var(--hx-toast-width, 20rem);\n max-width: 100%;\n pointer-events: auto;\n }\n\n :host([open]) .toast {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ─── Variant overrides ─── */\n\n /*\n * Toast variants paint on darker brand fills (primary-600/success-700/\n * error-600) because the lighter -500 fills can't pass AA against white\n * text in the precision-cool palette. The neutral-900 on-{role} tokens\n * are tuned for the lighter -500 surfaces and would fail here (e.g.\n * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens\n * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.\n * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.39:1\n * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1\n * (success-600 #0E8A4A on white = 4.41:1 — drifts under AA at 14px)\n * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.92:1\n * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1\n * (warning stays on the lighter -500 surface so on-warning works)\n *\n * 3.2.1 token-cascade: bg variants now route through surface.{role}-strong\n * semantics; fg variants route through text.on-{role}-strong (or on-warning\n * for the warning variant). Component-tier tokens are NOT bypassed — the\n * --hx-toast-bg / --hx-toast-color slots remain the single override point.\n */\n .toast--success {\n --hx-toast-bg: var(--hx-color-surface-success-strong, #146831);\n --hx-toast-color: var(--hx-color-text-on-success-strong, #ffffff);\n }\n\n .toast--warning {\n --hx-toast-bg: var(--hx-color-surface-warning-strong, #c2711c);\n --hx-toast-color: var(--hx-color-text-on-warning, #0d1825);\n }\n\n .toast--danger {\n --hx-toast-bg: var(--hx-color-surface-danger-strong, #c92a2a);\n --hx-toast-color: var(--hx-color-text-on-error-strong, #ffffff);\n }\n\n .toast--info {\n --hx-toast-bg: var(--hx-color-surface-info-strong, #0f7078);\n --hx-toast-color: var(--hx-color-text-on-primary-strong, #ffffff);\n }\n\n /* ─── Severity Label (WCAG 1.4.1) ─── */\n /* Visually hidden — non-color cue for severity variants (success/warning/danger/info). */\n /* Ensures variant is not conveyed by color alone for color-blind users. */\n\n .toast__severity-label {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ─── Icon ─── */\n\n .toast__icon {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n }\n\n .toast__icon:empty {\n display: none;\n }\n\n /* ─── Message ─── */\n\n .toast__message {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n /* ─── Action slot ─── */\n\n .toast__action {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n .toast__action:empty {\n display: none;\n }\n\n /* ─── Close button ─── */\n\n .toast__close {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* WCAG 2.5.5: minimum 44×44px touch target */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n padding: var(--hx-space-1, 0.25rem);\n background: transparent;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n color: inherit;\n cursor: pointer;\n opacity: var(--hx-opacity-75, 0.75);\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .toast__close:hover {\n opacity: 1;\n }\n\n .toast__close:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid currentColor;\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Reduced motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .toast {\n transition: none;\n }\n\n .toast__close {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n /* Belt-and-suspenders: rich per-class HC overrides PLUS the forcedColorsSurface mixin. */\n\n @media (forced-colors: active) {\n .toast {\n border: 1px solid CanvasText;\n }\n\n .toast__close {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n }\n`;\n\nexport const helixToastStackStyles = css`\n :host {\n display: block;\n position: fixed;\n z-index: var(--hx-z-index-toast, 1700);\n pointer-events: none;\n }\n\n .toast-stack {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-4, 1rem);\n pointer-events: none;\n }\n\n /* ─── Placements ─── */\n\n :host([placement='top-start']) {\n top: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-center']) {\n top: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-end']) {\n top: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n bottom: auto;\n }\n\n :host([placement='bottom-start']) {\n bottom: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-center']) {\n bottom: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-end']) {\n bottom: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n top: auto;\n }\n\n /* ─── Bottom placements: reverse order so newest is on top ─── */\n\n :host([placement^='bottom']) .toast-stack {\n flex-direction: column-reverse;\n }\n\n /* ─── Slide direction by placement ─── */\n\n :host([placement^='top']) ::slotted(hx-toast) {\n --hx-toast-enter-translate: calc(var(--hx-space-2, 0.5rem) * -1);\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 { HelixElement } from '../../base/index.js';\nimport { helixToastStyles } from './hx-toast.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\n\nexport type ToastVariant = 'default' | 'success' | 'warning' | 'danger' | 'info';\n\n/**\n * A transient notification message that auto-dismisses after a configurable duration.\n * Supports multiple visual variants, a closable button, icon/action slots, and full\n * ARIA live region semantics for screen readers.\n *\n * @summary Transient notification toast component.\n *\n * @tag hx-toast\n *\n * @slot - Default slot for the notification message.\n * @slot icon - Optional icon rendered before the message.\n * @slot action - Optional action button rendered after the message.\n *\n * @fires {CustomEvent} hx-show - Dispatched when the toast becomes visible.\n * @fires {CustomEvent} hx-hide - Dispatched when the toast begins hiding.\n * @fires {CustomEvent} hx-after-hide - Dispatched after the hide animation completes.\n *\n * @csspart base - The inner toast container div.\n * @csspart icon - The icon slot wrapper.\n * @csspart message - The message slot wrapper.\n * @csspart close-button - The dismiss button (only when closable).\n * @csspart action - The action slot wrapper.\n *\n * @cssprop [--hx-toast-bg=var(--hx-color-neutral-900)] - Toast background color.\n * @cssprop [--hx-toast-color=var(--hx-color-neutral-0)] - Toast text color.\n * @cssprop [--hx-toast-border-radius=var(--hx-border-radius-md)] - Toast border radius.\n * @cssprop [--hx-toast-shadow] - Toast box shadow.\n * @cssprop [--hx-toast-width=20rem] - Toast width.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-toast-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-toast-enter-translate=var(--hx-space-2)] - CSS custom property.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-transition-normal] - Transition timing.\n * @cssprop [--hx-color-success-600] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-error-600] - Color.\n * @cssprop [--hx-color-primary-600] - Color.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-opacity-75] - Opacity.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n */\n@customElement('hx-toast')\nexport class HelixToast extends HelixElement {\n static override styles = [helixToastStyles, forcedColorsSurface];\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'success' | 'warning' | 'danger' | 'info' = 'default';\n\n /**\n * Auto-dismiss duration in milliseconds. Set to 0 for persistent toasts.\n * @attr duration\n */\n @property({ type: Number })\n duration = 5000;\n\n /**\n * Whether to show a close button.\n * @attr closable\n */\n @property({ type: Boolean, reflect: true })\n closable = false;\n\n /**\n * Whether the toast is currently visible.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Accessible label for the close button. Override for localization.\n * @attr label-close\n */\n @property({ attribute: 'label-close' })\n labelClose = 'Dismiss notification';\n\n // ─── Private State ───\n\n /** @internal */\n @query('.toast') private _toastEl!: HTMLElement | null;\n\n /** @internal Tracks whether the action slot has slotted content. */\n @state() private _hasActionContent = false;\n\n /** @internal */\n private _timer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Reduced Motion ───\n\n /** @internal Returns true when the user has opted into reduced motion. */\n private get _reducedMotion(): boolean {\n // Guard for SSR — window.matchMedia is unavailable server-side\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /** @internal */\n private _timerStartedAt: number | null = null;\n\n /** @internal */\n private _timerRemaining: number | null = null;\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('open')) {\n if (this.open) {\n this.removeAttribute('aria-hidden');\n this._emitShow();\n if (this.duration > 0 && !this._reducedMotion && !this._hasActionContent) {\n this._startTimer();\n }\n } else {\n this.setAttribute('aria-hidden', 'true');\n this._clearTimer();\n this._emitHide();\n }\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._clearTimer();\n }\n\n // ─── Public API ───\n\n /** Show the toast. */\n show(): void {\n if (!this.open) {\n this.open = true;\n }\n }\n\n /** Hide the toast. */\n hide(): void {\n if (this.open) {\n this.open = false;\n }\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _startTimer(remaining?: number): void {\n this._clearTimerHandle();\n const delay = remaining ?? this.duration;\n this._timerStartedAt = Date.now();\n this._timerRemaining = delay;\n this._timer = setTimeout(() => {\n this.open = false;\n }, delay);\n }\n\n /** @internal */\n private _pauseTimer(): void {\n if (this._timer === null || this._timerStartedAt === null || this._timerRemaining === null) {\n return;\n }\n const elapsed = Date.now() - this._timerStartedAt;\n this._timerRemaining = Math.max(0, this._timerRemaining - elapsed);\n this._clearTimerHandle();\n }\n\n /** @internal */\n private _clearTimerHandle(): void {\n if (this._timer !== null) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n }\n\n /** @internal */\n private _clearTimer(): void {\n this._clearTimerHandle();\n this._timerStartedAt = null;\n this._timerRemaining = null;\n }\n\n /** @internal */\n private _emitShow(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _emitHide(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n\n let fired = false;\n const fireAfterHide = () => {\n if (fired) return;\n fired = true;\n this.dispatchEvent(new CustomEvent<void>('hx-after-hide', { bubbles: true, composed: true }));\n };\n\n // Fire on transitionend if available; fallback ensures it fires in test environments\n // and when transitions are disabled (prefers-reduced-motion, no CSS transitions).\n const base = this._toastEl;\n if (base) {\n base.addEventListener('transitionend', fireAfterHide, { once: true });\n }\n // Fallback fires after the CSS transition duration (250ms) plus a small buffer.\n setTimeout(fireAfterHide, 300);\n }\n\n // ─── Event Handlers ───\n\n /** @internal */\n private _handleMouseEnter(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleMouseLeave(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleFocusIn(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleFocusOut(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleClose(): void {\n this.hide();\n }\n\n /** @internal */\n private _handleActionSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasActionContent = slot.assignedNodes({ flatten: true }).length > 0;\n if (this._hasActionContent && this.open) {\n this._pauseTimer();\n }\n }\n\n // ─── ARIA Helpers ───\n\n /** @internal */\n private get _role(): 'alert' | 'status' {\n return this.variant === 'danger' ? 'alert' : 'status';\n }\n\n /** @internal */\n private get _ariaLive(): 'assertive' | 'polite' {\n return this.variant === 'danger' ? 'assertive' : 'polite';\n }\n\n // ─── WCAG 1.4.1: Default Icons ───\n // Each semantic variant renders a default icon when no icon is slotted,\n // ensuring the severity is not conveyed by color alone.\n\n /** @internal */\n private _renderSuccessIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm3.03 6.28a.75.75 0 00-1.06-1.06L9 10.19 7.78 8.97a.75.75 0 00-1.06 1.06l1.75 1.75a.75.75 0 001.06 0l3.5-3.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderWarningIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M8.49 2.92a1.75 1.75 0 013.02 0l6.25 10.83A1.75 1.75 0 0116.25 16H3.75a1.75 1.75 0 01-1.51-2.25L8.49 2.92zM10 7a.75.75 0 01.75.75v3a.75.75 0 01-1.5 0v-3A.75.75 0 0110 7zm0 7.5a.75.75 0 100-1.5.75.75 0 000 1.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderDangerIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm-1.72 5.22a.75.75 0 011.06 0L10 7.94l.66-.72a.75.75 0 111.06 1.06L11.06 9l.66.72a.75.75 0 11-1.06 1.06L10 10.06l-.66.72a.75.75 0 01-1.06-1.06L8.94 9l-.66-.72a.75.75 0 010-1.06z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderInfoIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm.75 4.75a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM9.25 9a.75.75 0 011.5 0v4a.75.75 0 01-1.5 0V9z\"\n />\n </svg>`;\n }\n\n /** @internal Returns the default icon for the current variant, or nothing for 'default'. */\n private get _defaultIcon() {\n switch (this.variant) {\n case 'success':\n return this._renderSuccessIcon();\n case 'warning':\n return this._renderWarningIcon();\n case 'danger':\n return this._renderDangerIcon();\n case 'info':\n return this._renderInfoIcon();\n default:\n return nothing;\n }\n }\n\n // ─── WCAG 1.4.1: Severity label map ───\n\n /** @internal */\n private static readonly _SEVERITY_LABELS: Partial<Record<ToastVariant, string>> = {\n success: 'Success',\n warning: 'Warning',\n danger: 'Error',\n info: 'Info',\n };\n\n /** @internal */\n private get _severityLabel(): string {\n return HelixToast._SEVERITY_LABELS[this.variant] ?? '';\n }\n\n // ─── Render ───\n\n override render() {\n const severityLabel = this._severityLabel;\n\n return html`\n <div\n part=\"base\"\n class=${classMap({\n toast: true,\n [`toast--${this.variant}`]: true,\n })}\n role=${this._role}\n aria-live=${this._ariaLive}\n aria-atomic=\"true\"\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n @focusin=${this._handleFocusIn}\n @focusout=${this._handleFocusOut}\n >\n ${this.open\n ? html`\n ${severityLabel\n ? html`<span class=\"toast__severity-label\">${severityLabel}: </span>`\n : nothing}\n <span part=\"icon\" class=\"toast__icon\">\n <slot name=\"icon\">${this._defaultIcon}</slot>\n </span>\n <span part=\"message\" class=\"toast__message\">\n <slot></slot>\n </span>\n <span part=\"action\" class=\"toast__action\">\n <slot name=\"action\" @slotchange=${this._handleActionSlotChange}></slot>\n </span>\n ${this.closable\n ? html`\n <button\n part=\"close-button\"\n class=\"toast__close\"\n aria-label=${this.labelClose}\n @click=${this._handleClose}\n >\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n `\n : nothing}\n `\n : nothing}\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast': HelixToast;\n }\n}\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToastStackStyles } from './hx-toast.styles.js';\n\nexport type ToastStackPlacement =\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end';\n\n/**\n * A fixed-position container that stacks `hx-toast` elements at the specified\n * corner of the viewport. Enforces a maximum visible toast count via `stack-limit`.\n *\n * @summary Toast stack container managing position and count limits.\n *\n * @tag hx-toast-stack\n *\n * @slot - Accepts `hx-toast` elements.\n *\n * @csspart base - The inner stack container div.\n *\n * @cssprop [--hx-z-index-toast=9000] - Z-index for the fixed stack.\n */\n@customElement('hx-toast-stack')\nexport class HelixToastStack extends HelixElement {\n static override styles = [helixToastStackStyles];\n\n /**\n * Corner of the viewport where toasts appear.\n * @attr placement\n */\n @property({ type: String, reflect: true })\n placement:\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end' = 'bottom-end';\n\n /**\n * Maximum number of simultaneously visible toasts. 0 = unlimited.\n * @attr stack-limit\n */\n @property({ type: Number, attribute: 'stack-limit' })\n stackLimit = 3;\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=${classMap({\n 'toast-stack': true,\n [`toast-stack--${this.placement}`]: true,\n })}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast-stack': HelixToastStack;\n }\n}\n","import { HelixToast } from './hx-toast.js';\nimport { HelixToastStack } from './hx-toast-stack.js';\nimport type { ToastVariant } from './hx-toast.js';\nimport type { ToastStackPlacement } from './hx-toast-stack.js';\n\nexport interface ToastOptions {\n /** The notification message text. */\n message: string;\n /** Visual variant. Defaults to 'default'. */\n variant?: ToastVariant;\n /** Auto-dismiss duration in ms. 0 = persistent. Defaults to 3000. */\n duration?: number;\n /** Placement of the shared stack. Defaults to 'bottom-end'. */\n placement?: ToastStackPlacement;\n}\n\n/**\n * Imperatively create and display a toast notification.\n *\n * Creates a shared `hx-toast-stack` on `document.body` if one does not exist,\n * then appends a new `hx-toast` with the given options. Respects the stack's\n * `stackLimit` by hiding the oldest visible toast when the limit is exceeded.\n *\n * @example\n * import { toast } from '@helixui/library/components/hx-toast/index.js';\n * toast({ message: 'Patient record saved.', variant: 'success' });\n */\nexport function toast(options: ToastOptions): HelixToast {\n if (typeof document === 'undefined') throw new Error('toast() requires a browser environment');\n const placement = options.placement ?? 'bottom-end';\n\n // Find or create a dedicated stack for this placement\n const stackSelector = `hx-toast-stack[placement=\"${placement}\"]`;\n let stack = document.querySelector<HelixToastStack>(stackSelector);\n if (!stack) {\n stack = document.createElement('hx-toast-stack');\n stack.placement = placement;\n // Intentional design decision: the toast stack is appended to document.body rather\n // than inserted near the caller. This is required so that the fixed-position overlay\n // is not clipped by an ancestor with `overflow: hidden`, `transform`, or `filter`\n // (all of which create a new stacking context and break fixed positioning).\n // Drupal compatibility note: Drupal's BigPipe / AJAX behaviors can re-attach the\n // document body without removing these stacks. The selector check above\n // (`document.querySelector`) ensures only one stack per placement is ever created,\n // preventing duplicates on re-attach cycles.\n document.body.appendChild(stack);\n }\n\n // Enforce stack limit: hide oldest open toast if at capacity\n if (stack.stackLimit > 0) {\n const openToasts = [...stack.querySelectorAll<HelixToast>('hx-toast')].filter((t) => t.open);\n if (openToasts.length >= stack.stackLimit) {\n openToasts[0]?.hide();\n }\n }\n\n // Create toast element\n const toastEl = document.createElement('hx-toast');\n toastEl.variant = options.variant ?? 'default';\n toastEl.duration = options.duration ?? 3000;\n toastEl.closable = true;\n toastEl.textContent = options.message;\n\n // Remove from DOM after hiding\n toastEl.addEventListener('hx-after-hide', () => {\n toastEl.remove();\n });\n\n stack.appendChild(toastEl);\n toastEl.show();\n\n return toastEl;\n}\n"],"names":["helixToastStyles","css","helixToastStackStyles","HelixToast","HelixElement","changedProperties","remaining","delay","elapsed","fired","fireAfterHide","base","e","slot","html","nothing","severityLabel","classMap","forcedColorsSurface","__decorateClass","property","query","state","customElement","HelixToastStack","toast","options","placement","stackSelector","stack","openToasts","t","_a","toastEl"],"mappings":";;;;;AAYO,MAAMA,IAAmBC;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,GA6LnBC,IAAwBD;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;;;;;;ACzI9B,IAAME,IAAN,cAAyBC,EAAa;AAAA,EAAtC,cAAA;AAAA,UAAA,GAAA,SAAA,GAUL,KAAA,UAAiE,WAOjE,KAAA,WAAW,KAOX,KAAA,WAAW,IAOX,KAAA,OAAO,IAOP,KAAA,aAAa,wBAQJ,KAAQ,oBAAoB,IAGrC,KAAQ,SAA+C,MAYvD,KAAQ,kBAAiC,MAGzC,KAAQ,kBAAiC;AAAA,EAAA;AAAA;AAAA;AAAA,EAVzC,IAAY,iBAA0B;AAEpC,WAAI,OAAO,SAAW,MAAoB,KACnC,OAAO,WAAW,kCAAkC,EAAE;AAAA,EAC/D;AAAA;AAAA,EAUS,QAAQC,GAA+C;AAC9D,UAAM,QAAQA,CAAiB,GAC3BA,EAAkB,IAAI,MAAM,MAC1B,KAAK,QACP,KAAK,gBAAgB,aAAa,GAClC,KAAK,UAAA,GACD,KAAK,WAAW,KAAK,CAAC,KAAK,kBAAkB,CAAC,KAAK,qBACrD,KAAK,YAAA,MAGP,KAAK,aAAa,eAAe,MAAM,GACvC,KAAK,YAAA,GACL,KAAK,UAAA;AAAA,EAGX;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA,GACN,KAAK,YAAA;AAAA,EACP;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,IAAK,KAAK,SACR,KAAK,OAAO;AAAA,EAEhB;AAAA;AAAA,EAGA,OAAa;AACX,IAAI,KAAK,SACP,KAAK,OAAO;AAAA,EAEhB;AAAA;AAAA;AAAA,EAKQ,YAAYC,GAA0B;AAC5C,SAAK,kBAAA;AACL,UAAMC,IAAQD,KAAa,KAAK;AAChC,SAAK,kBAAkB,KAAK,IAAA,GAC5B,KAAK,kBAAkBC,GACvB,KAAK,SAAS,WAAW,MAAM;AAC7B,WAAK,OAAO;AAAA,IACd,GAAGA,CAAK;AAAA,EACV;AAAA;AAAA,EAGQ,cAAoB;AAC1B,QAAI,KAAK,WAAW,QAAQ,KAAK,oBAAoB,QAAQ,KAAK,oBAAoB;AACpF;AAEF,UAAMC,IAAU,KAAK,IAAA,IAAQ,KAAK;AAClC,SAAK,kBAAkB,KAAK,IAAI,GAAG,KAAK,kBAAkBA,CAAO,GACjE,KAAK,kBAAA;AAAA,EACP;AAAA;AAAA,EAGQ,oBAA0B;AAChC,IAAI,KAAK,WAAW,SAClB,aAAa,KAAK,MAAM,GACxB,KAAK,SAAS;AAAA,EAElB;AAAA;AAAA,EAGQ,cAAoB;AAC1B,SAAK,kBAAA,GACL,KAAK,kBAAkB,MACvB,KAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA,EAGQ,YAAkB;AACxB,SAAK,cAAc,IAAI,YAAkB,WAAW,EAAE,SAAS,IAAM,UAAU,GAAA,CAAM,CAAC;AAAA,EACxF;AAAA;AAAA,EAGQ,YAAkB;AACxB,SAAK,cAAc,IAAI,YAAkB,WAAW,EAAE,SAAS,IAAM,UAAU,GAAA,CAAM,CAAC;AAEtF,QAAIC,IAAQ;AACZ,UAAMC,IAAgB,MAAM;AAC1B,MAAID,MACJA,IAAQ,IACR,KAAK,cAAc,IAAI,YAAkB,iBAAiB,EAAE,SAAS,IAAM,UAAU,GAAA,CAAM,CAAC;AAAA,IAC9F,GAIME,IAAO,KAAK;AAClB,IAAIA,KACFA,EAAK,iBAAiB,iBAAiBD,GAAe,EAAE,MAAM,IAAM,GAGtE,WAAWA,GAAe,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AAChC,SAAK,YAAA;AAAA,EACP;AAAA;AAAA,EAGQ,oBAA0B;AAChC,IAAI,KAAK,QAAQ,KAAK,WAAW,KAC/B,KAAK,YAAY,KAAK,mBAAmB,MAAS;AAAA,EAEtD;AAAA;AAAA,EAGQ,iBAAuB;AAC7B,SAAK,YAAA;AAAA,EACP;AAAA;AAAA,EAGQ,kBAAwB;AAC9B,IAAI,KAAK,QAAQ,KAAK,WAAW,KAC/B,KAAK,YAAY,KAAK,mBAAmB,MAAS;AAAA,EAEtD;AAAA;AAAA,EAGQ,eAAqB;AAC3B,SAAK,KAAA;AAAA,EACP;AAAA;AAAA,EAGQ,wBAAwBE,GAAgB;AAC9C,UAAMC,IAAOD,EAAE;AACf,SAAK,oBAAoBC,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS,GACpE,KAAK,qBAAqB,KAAK,QACjC,KAAK,YAAA;AAAA,EAET;AAAA;AAAA;AAAA,EAKA,IAAY,QAA4B;AACtC,WAAO,KAAK,YAAY,WAAW,UAAU;AAAA,EAC/C;AAAA;AAAA,EAGA,IAAY,YAAoC;AAC9C,WAAO,KAAK,YAAY,WAAW,cAAc;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAqB;AAC3B,WAAOC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT;AAAA;AAAA,EAGQ,qBAAqB;AAC3B,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT;AAAA;AAAA,EAGQ,oBAAoB;AAC1B,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT;AAAA;AAAA,EAGQ,kBAAkB;AACxB,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT;AAAA;AAAA,EAGA,IAAY,eAAe;AACzB,YAAQ,KAAK,SAAA;AAAA,MACX,KAAK;AACH,eAAO,KAAK,mBAAA;AAAA,MACd,KAAK;AACH,eAAO,KAAK,mBAAA;AAAA,MACd,KAAK;AACH,eAAO,KAAK,kBAAA;AAAA,MACd,KAAK;AACH,eAAO,KAAK,gBAAA;AAAA,MACd;AACE,eAAOC;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA,EAaA,IAAY,iBAAyB;AACnC,WAAOZ,EAAW,iBAAiB,KAAK,OAAO,KAAK;AAAA,EACtD;AAAA;AAAA,EAIS,SAAS;AAChB,UAAMa,IAAgB,KAAK;AAE3B,WAAOF;AAAA;AAAA;AAAA,gBAGKG,EAAS;AAAA,MACf,OAAO;AAAA,MACP,CAAC,UAAU,KAAK,OAAO,EAAE,GAAG;AAAA,IAAA,CAC7B,CAAC;AAAA,eACK,KAAK,KAAK;AAAA,oBACL,KAAK,SAAS;AAAA;AAAA,sBAEZ,KAAK,iBAAiB;AAAA,sBACtB,KAAK,iBAAiB;AAAA,mBACzB,KAAK,cAAc;AAAA,oBAClB,KAAK,eAAe;AAAA;AAAA,UAE9B,KAAK,OACHH;AAAA,gBACIE,IACEF,wCAA2CE,CAAa,cACxDD,CAAO;AAAA;AAAA,oCAEW,KAAK,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kDAMH,KAAK,uBAAuB;AAAA;AAAA,gBAE9D,KAAK,WACHD;AAAA;AAAA;AAAA;AAAA,mCAIiB,KAAK,UAAU;AAAA,+BACnB,KAAK,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAiB9BC,CAAO;AAAA,gBAEbA,CAAO;AAAA;AAAA;AAAA,EAGjB;AACF;AAxWaZ,EACK,SAAS,CAACH,GAAkBkB,CAAmB;AADpDf,EA6Ra,mBAA0D;AAAA,EAChF,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAxRAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAT9BjB,EAUX,WAAA,WAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAhBfjB,EAiBX,WAAA,YAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAvB/BjB,EAwBX,WAAA,YAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA9B/BjB,EA+BX,WAAA,QAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,cAAA,CAAe;AAAA,GArC3BjB,EAsCX,WAAA,cAAA,CAAA;AAKyBgB,EAAA;AAAA,EAAxBE,EAAM,QAAQ;AAAA,GA3CJlB,EA2Cc,WAAA,YAAA,CAAA;AAGRgB,EAAA;AAAA,EAAhBG,EAAA;AAAM,GA9CInB,EA8CM,WAAA,qBAAA,CAAA;AA9CNA,IAANgB,EAAA;AAAA,EADNI,EAAc,UAAU;AAAA,GACZpB,CAAA;;;;;;AClCN,IAAMqB,IAAN,cAA8BpB,EAAa;AAAA,EAA3C,cAAA;AAAA,UAAA,GAAA,SAAA,GAQL,KAAA,YAMmB,cAOnB,KAAA,aAAa;AAAA,EAAA;AAAA,EAEJ,SAAS;AAChB,WAAOU;AAAA;AAAA;AAAA,gBAGKG,EAAS;AAAA,MACf,eAAe;AAAA,MACf,CAAC,gBAAgB,KAAK,SAAS,EAAE,GAAG;AAAA,IAAA,CACrC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKR;AACF;AApCaO,EACK,SAAS,CAACtB,CAAqB;AAO/CiB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAP9BI,EAQX,WAAA,aAAA,CAAA;AAaAL,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,eAAe;AAAA,GApBzCI,EAqBX,WAAA,cAAA,CAAA;AArBWA,IAANL,EAAA;AAAA,EADNI,EAAc,gBAAgB;AAAA,GAClBC,CAAA;ACHN,SAASC,EAAMC,GAAmC;;AACvD,MAAI,OAAO,WAAa,IAAa,OAAM,IAAI,MAAM,wCAAwC;AAC7F,QAAMC,IAAYD,EAAQ,aAAa,cAGjCE,IAAgB,6BAA6BD,CAAS;AAC5D,MAAIE,IAAQ,SAAS,cAA+BD,CAAa;AAgBjE,MAfKC,MACHA,IAAQ,SAAS,cAAc,gBAAgB,GAC/CA,EAAM,YAAYF,GASlB,SAAS,KAAK,YAAYE,CAAK,IAI7BA,EAAM,aAAa,GAAG;AACxB,UAAMC,IAAa,CAAC,GAAGD,EAAM,iBAA6B,UAAU,CAAC,EAAE,OAAO,CAACE,MAAMA,EAAE,IAAI;AAC3F,IAAID,EAAW,UAAUD,EAAM,gBAC7BG,IAAAF,EAAW,CAAC,MAAZ,QAAAE,EAAe;AAAA,EAEnB;AAGA,QAAMC,IAAU,SAAS,cAAc,UAAU;AACjD,SAAAA,EAAQ,UAAUP,EAAQ,WAAW,WACrCO,EAAQ,WAAWP,EAAQ,YAAY,KACvCO,EAAQ,WAAW,IACnBA,EAAQ,cAAcP,EAAQ,SAG9BO,EAAQ,iBAAiB,iBAAiB,MAAM;AAC9C,IAAAA,EAAQ,OAAA;AAAA,EACV,CAAC,GAEDJ,EAAM,YAAYI,CAAO,GACzBA,EAAQ,KAAA,GAEDA;AACT;"}