@helixui/library 3.4.0 → 3.4.1-next.125
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.
- package/dist/components/hx-button-group/hx-button-group.d.ts +9 -0
- package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
- package/dist/components/hx-button-group/index.js +1 -1
- package/dist/components/hx-card/hx-card.d.ts +68 -0
- package/dist/components/hx-card/hx-card.d.ts.map +1 -1
- package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
- package/dist/components/hx-card/index.js +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-checkbox-group/index.js +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/index.js +1 -1
- package/dist/components/hx-drawer/index.js +1 -1
- package/dist/components/hx-dropdown/index.js +1 -1
- package/dist/components/hx-list/index.js +1 -1
- package/dist/components/hx-menu/index.js +1 -1
- package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
- package/dist/components/hx-meter/index.js +1 -1
- package/dist/components/hx-overflow-menu/index.js +1 -1
- package/dist/components/hx-popover/index.js +1 -1
- package/dist/components/hx-progress-bar/index.js +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-select/index.js +1 -1
- package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
- package/dist/components/hx-spinner/index.js +1 -1
- package/dist/components/hx-split-button/index.js +1 -1
- package/dist/components/hx-stat/index.js +1 -1
- package/dist/components/hx-switch/index.js +1 -1
- package/dist/components/hx-table/hx-td.d.ts.map +1 -1
- package/dist/components/hx-table/hx-th.d.ts +9 -0
- package/dist/components/hx-table/hx-th.d.ts.map +1 -1
- package/dist/components/hx-table/index.js +1 -1
- package/dist/components/hx-tabs/index.js +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toggle-button/index.js +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/css/helix-all.css +14 -1
- package/dist/css/helix-core.css +14 -1
- package/dist/css/hx-card.css +14 -1
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +1 -1
- package/dist/index.js +27 -27
- package/dist/shared/aria-idref-DCuEaknC.js +131 -0
- package/dist/shared/{aria-idref-CxvyzfQS.js.map → aria-idref-DCuEaknC.js.map} +1 -1
- package/dist/shared/{hx-button-group-DcHP5MBv.js → hx-button-group-4NUBpkyC.js} +22 -22
- package/dist/shared/{hx-button-group-DcHP5MBv.js.map → hx-button-group-4NUBpkyC.js.map} +1 -1
- package/dist/shared/{hx-card-qNAM2QNV.js → hx-card-CswtnYvj.js} +142 -85
- package/dist/shared/hx-card-CswtnYvj.js.map +1 -0
- package/dist/shared/{hx-checkbox-C48KYKFq.js → hx-checkbox-CYd0YV_u.js} +2 -2
- package/dist/shared/{hx-checkbox-C48KYKFq.js.map → hx-checkbox-CYd0YV_u.js.map} +1 -1
- package/dist/shared/{hx-checkbox-group-BJIAX3zU.js → hx-checkbox-group-D5piJLY8.js} +2 -2
- package/dist/shared/{hx-checkbox-group-BJIAX3zU.js.map → hx-checkbox-group-D5piJLY8.js.map} +1 -1
- package/dist/shared/{hx-color-picker-Dk4cBwYQ.js → hx-color-picker-DBwJzT5f.js} +2 -2
- package/dist/shared/{hx-color-picker-Dk4cBwYQ.js.map → hx-color-picker-DBwJzT5f.js.map} +1 -1
- package/dist/shared/{hx-combobox-BTLO9qiK.js → hx-combobox-NgJaLbs2.js} +2 -2
- package/dist/shared/{hx-combobox-BTLO9qiK.js.map → hx-combobox-NgJaLbs2.js.map} +1 -1
- package/dist/shared/{hx-date-picker-CiR7FVnR.js → hx-date-picker-B49yo4Vm.js} +2 -2
- package/dist/shared/{hx-date-picker-CiR7FVnR.js.map → hx-date-picker-B49yo4Vm.js.map} +1 -1
- package/dist/shared/{hx-dialog-AOZpHSuF.js → hx-dialog-B4weoj_1.js} +2 -2
- package/dist/shared/{hx-dialog-AOZpHSuF.js.map → hx-dialog-B4weoj_1.js.map} +1 -1
- package/dist/shared/{hx-drawer-DH6CdAN1.js → hx-drawer-D81tb4BD.js} +2 -2
- package/dist/shared/{hx-drawer-DH6CdAN1.js.map → hx-drawer-D81tb4BD.js.map} +1 -1
- package/dist/shared/{hx-dropdown-DiLd40Lm.js → hx-dropdown-D626S2ZG.js} +2 -2
- package/dist/shared/{hx-dropdown-DiLd40Lm.js.map → hx-dropdown-D626S2ZG.js.map} +1 -1
- package/dist/shared/{hx-list-De66EtAP.js → hx-list-Bp8HeLHh.js} +2 -2
- package/dist/shared/{hx-list-De66EtAP.js.map → hx-list-Bp8HeLHh.js.map} +1 -1
- package/dist/shared/{hx-menu-divider-BjiRIWKq.js → hx-menu-divider-A6Guuzi_.js} +2 -2
- package/dist/shared/{hx-menu-divider-BjiRIWKq.js.map → hx-menu-divider-A6Guuzi_.js.map} +1 -1
- package/dist/shared/{hx-meter-BJdh6nrF.js → hx-meter-BnpmF3Vx.js} +57 -36
- package/dist/shared/{hx-meter-BJdh6nrF.js.map → hx-meter-BnpmF3Vx.js.map} +1 -1
- package/dist/shared/{hx-overflow-menu-BQ4fiMYu.js → hx-overflow-menu-DFjJAziP.js} +2 -2
- package/dist/shared/{hx-overflow-menu-BQ4fiMYu.js.map → hx-overflow-menu-DFjJAziP.js.map} +1 -1
- package/dist/shared/{hx-popover-B9W8-tC0.js → hx-popover-BAlAFOH9.js} +2 -2
- package/dist/shared/{hx-popover-B9W8-tC0.js.map → hx-popover-BAlAFOH9.js.map} +1 -1
- package/dist/shared/{hx-progress-bar-C8nDMdYa.js → hx-progress-bar-CYz9U721.js} +2 -2
- package/dist/shared/{hx-progress-bar-C8nDMdYa.js.map → hx-progress-bar-CYz9U721.js.map} +1 -1
- package/dist/shared/{hx-radio-Z1lV1zTO.js → hx-radio-C7eTj5YI.js} +2 -2
- package/dist/shared/{hx-radio-Z1lV1zTO.js.map → hx-radio-C7eTj5YI.js.map} +1 -1
- package/dist/shared/{hx-select-D18CnJ0e.js → hx-select-DahFehiZ.js} +2 -2
- package/dist/shared/{hx-select-D18CnJ0e.js.map → hx-select-DahFehiZ.js.map} +1 -1
- package/dist/shared/{hx-spinner-BB0h2hKZ.js → hx-spinner-3qBp4jeN.js} +11 -11
- package/dist/shared/{hx-spinner-BB0h2hKZ.js.map → hx-spinner-3qBp4jeN.js.map} +1 -1
- package/dist/shared/{hx-split-button-BoABoEm5.js → hx-split-button-Ddle8iVx.js} +2 -2
- package/dist/shared/{hx-split-button-BoABoEm5.js.map → hx-split-button-Ddle8iVx.js.map} +1 -1
- package/dist/shared/{hx-stat-Dtf9lz-O.js → hx-stat-Gtw_SpK8.js} +2 -2
- package/dist/shared/{hx-stat-Dtf9lz-O.js.map → hx-stat-Gtw_SpK8.js.map} +1 -1
- package/dist/shared/{hx-switch-B6kr-EwE.js → hx-switch-TvKGvZJz.js} +2 -2
- package/dist/shared/{hx-switch-B6kr-EwE.js.map → hx-switch-TvKGvZJz.js.map} +1 -1
- package/dist/shared/{hx-tab-panel-BQtBXKLD.js → hx-tab-panel-Cu--8psg.js} +2 -2
- package/dist/shared/{hx-tab-panel-BQtBXKLD.js.map → hx-tab-panel-Cu--8psg.js.map} +1 -1
- package/dist/shared/{hx-td-BGkFOJEK.js → hx-td-BPsb6OaG.js} +141 -138
- package/dist/shared/hx-td-BPsb6OaG.js.map +1 -0
- package/dist/shared/{hx-time-picker-iwCD7rzW.js → hx-time-picker-Bo7FWzmf.js} +2 -2
- package/dist/shared/{hx-time-picker-iwCD7rzW.js.map → hx-time-picker-Bo7FWzmf.js.map} +1 -1
- package/dist/shared/{hx-toggle-button-BQ81EDkl.js → hx-toggle-button-DwBers3A.js} +2 -2
- package/dist/shared/{hx-toggle-button-BQ81EDkl.js.map → hx-toggle-button-DwBers3A.js.map} +1 -1
- package/dist/shared/{hx-tree-item-CHrUhuZL.js → hx-tree-item-CXyspGxI.js} +2 -2
- package/dist/shared/{hx-tree-item-CHrUhuZL.js.map → hx-tree-item-CXyspGxI.js.map} +1 -1
- package/dist/utils/aria-idref.d.ts.map +1 -1
- package/figma-inventory.json +2 -2
- package/package.json +2 -2
- package/dist/shared/aria-idref-CxvyzfQS.js +0 -126
- package/dist/shared/hx-card-qNAM2QNV.js.map +0 -1
- package/dist/shared/hx-td-BGkFOJEK.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hx-toggle-button-BQ81EDkl.js","sources":["../../src/components/hx-toggle-button/hx-toggle-button.styles.ts","../../src/components/hx-toggle-button/hx-toggle-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixToggleButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Base Button ─── */\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-toggle-button-border-color, transparent);\n border-radius: var(--hx-toggle-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toggle-button-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-toggle-button-color, var(--hx-color-text-on-primary, #ffffff));\n font-family: var(--hx-toggle-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-toggle-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n }\n\n /*\n * Host-focus path: on the modern (IDL element-references) render branch the\n * host is the tabbable surface (tabindex=0) and the inner <button> is\n * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'\n * so keyboard users still see a visible affordance. Codex round-11 P1.\n */\n :host(:focus-visible) .button {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /*\n * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner\n * <button> is the tab target. Native :focus-visible drives the ring.\n */\n .button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .button:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .button:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n /* ─── Size Variants ─── */\n\n /* WCAG 2.5.5 (healthcare mandate): minimum 44px touch target for sm variant.\n min-height uses --hx-touch-target-min to guarantee the interactive area\n meets the threshold even though the visual size token is smaller. */\n .button--sm {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n .button--md {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .button--lg {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Style Variants ─── */\n\n .button--primary {\n --hx-toggle-button-bg: var(--hx-color-primary-500, #429797);\n --hx-toggle-button-color: var(--hx-color-text-on-primary, #ffffff);\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * secondary/ghost paint primary text on the surface (white). primary-500\n * (#429797) on white = 3.43:1 — fails AA at body sizes. shift to\n * primary-600 (#0F7078) = 6.06:1 — AA pass. border keeps primary-500\n * for the brand affordance (3:1 non-text contrast still met).\n */\n .button--secondary {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n }\n\n .button--secondary:hover {\n --hx-toggle-button-bg: var(--hx-color-primary-50, #ebf8f8);\n }\n\n .button--tertiary {\n --hx-toggle-button-bg: var(--hx-color-surface-sunken, #ebeee9);\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--tertiary:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--ghost {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--ghost:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--outline {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: var(--hx-color-border-strong, #66787b);\n }\n\n .button--outline:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n /* ─── Pressed State ─── */\n\n /*\n * Primary: already uses solid primary bg; pressed deepens to primary-700\n * to give clear visual feedback without introducing a new color.\n *\n * AA fix: text.on-primary (= neutral-900 #0D1825) on primary-700 (#0F6363)\n * = 2.54:1 — fails AA. Pin fg at neutral-0 for the darker pressed fill\n * (neutral-0 on primary-700 = 7.03:1, AAA pass). Mirrors hx-toast\n * precedent (commit 300e21ab0) and hx-button hover treatment.\n * Note: secondary.pressed below uses primary-500 and stays at 5.20:1 —\n * leave it alone.\n */\n .button--primary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-700, #0f6363));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-neutral-0, #ffffff)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * Secondary: unpressed is outlined/transparent; pressed fills with primary bg\n * so the state change is immediately legible.\n */\n .button--secondary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-500, #429797));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-on-primary, #ffffff)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-500, #429797);\n }\n\n /* Tertiary pressed: use primary-100 bg + primary-700 text + border for WCAG 3:1 non-text contrast. */\n .button--tertiary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n box-shadow: inset 0 0 0 1px var(--hx-color-primary-600, #0f7078);\n }\n\n /* Ghost pressed: subtle neutral fill, matching hover behavior as a baseline. */\n .button--ghost.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /* Outline pressed: fills with a neutral tint, darkens the border, and adds an inset shadow for WCAG 3:1 non-text contrast. */\n .button--outline.button--pressed {\n --hx-toggle-button-bg: var(\n --hx-toggle-button-pressed-bg,\n var(--hx-color-surface-sunken, #ebeee9)\n );\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-primary, #0d1825)\n );\n --hx-toggle-button-border-color: var(--hx-color-text-muted, #4a5362);\n box-shadow: inset 0 0 0 1px var(--hx-color-neutral-500, #66787b);\n }\n\n /* ─── Disabled ─── */\n\n .button[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Prefix / Suffix / Label ─── */\n\n .button__prefix,\n .button__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .button__label {\n flex: 1 1 auto;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .button {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .button {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n :host(:focus-visible) .button,\n .button:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .button--pressed {\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n box-shadow: none;\n }\n\n .button[disabled] {\n background-color: ButtonFace;\n color: GrayText;\n border-color: GrayText;\n opacity: 1;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToggleButtonStyles } from './hx-toggle-button.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\n/** Detail for the hx-toggle event dispatched by hx-toggle-button. */\nexport interface HxToggleDetail {\n pressed: boolean;\n}\n\n/**\n * A two-state toggle button that communicates a pressed/unpressed status to\n * assistive technology via `aria-pressed`. Supports multiple visual variants\n * and sizes, prefix/suffix slots, full ElementInternals form association, and\n * a distinct pressed visual state for every variant.\n *\n * @summary Two-state toggle button with pressed/unpressed ARIA semantics.\n *\n * @tag hx-toggle-button\n *\n * @slot - Default slot for the button label text or content.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Icon or content rendered after the label.\n *\n * @fires {CustomEvent<{pressed: boolean}>} hx-toggle - Dispatched when the\n * toggle state changes. Not dispatched when the button is disabled.\n *\n * @csspart button - The native `<button>` element.\n * @csspart label - The label text wrapper span.\n * @csspart prefix - The prefix slot container span.\n * @csspart suffix - The suffix slot container span.\n *\n * @cssprop [--hx-toggle-button-bg=var(--hx-color-primary-500)] - Button background color.\n * @cssprop [--hx-toggle-button-color=var(--hx-color-neutral-0)] - Button text color.\n * @cssprop [--hx-toggle-button-border-color=transparent] - Button border color.\n * @cssprop [--hx-toggle-button-border-radius=var(--hx-border-radius-md)] - Button border radius.\n * @cssprop [--hx-toggle-button-font-family=var(--hx-font-family-sans)] - Button font family.\n * @cssprop [--hx-toggle-button-font-weight=var(--hx-font-weight-semibold)] - Button font weight.\n * @cssprop [--hx-toggle-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-toggle-button-pressed-bg=var(--hx-color-primary-500)] - Background when pressed (variant-specific fallback applies).\n * @cssprop [--hx-toggle-button-pressed-color=var(--hx-color-neutral-0)] - Text color when pressed (variant-specific fallback applies).\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-filter-brightness-hover] - CSS filter.\n * @cssprop [--hx-filter-brightness-active] - CSS filter.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-color-primary-700] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-color-neutral-50] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n */\n@customElement('hx-toggle-button')\nexport class HelixToggleButton extends HelixElement {\n static override styles = [helixToggleButtonStyles, forcedColorsInteractive];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n /** @internal */\n @query('slot:not([name])') private _defaultSlot!: HTMLSlotElement | null;\n\n // ─── Public Properties ───\n\n /**\n * Whether the toggle button is in the pressed state.\n * Reflected as an attribute so CSS selectors like `:host([pressed])` work.\n * @attr pressed\n */\n @property({ type: Boolean, reflect: true })\n pressed = false;\n\n /**\n * Visual style variant of the button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline' = 'secondary';\n\n /**\n * Size of the button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the button is disabled. Prevents all interaction and form actions.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Form field name submitted via ElementInternals when the button is pressed.\n * @attr name\n */\n @property({ type: String })\n name: string | undefined = undefined;\n\n /**\n * Form field value submitted via ElementInternals when the button is pressed.\n * @attr value\n */\n @property({ type: String })\n value: string | undefined = undefined;\n\n /**\n * Accessible label forwarded to the inner `<button>` as `aria-label`.\n * Required for icon-only toggle buttons where no visible text is present.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * When true, the button must be in the pressed state for the form to be submitted.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n // ─── Form API ───\n\n /** Returns the ValidityState object. */\n override get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** Returns the current validation message. */\n override get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Checks whether the button satisfies its constraints. */\n checkValidity(): boolean {\n return this._internals.checkValidity();\n }\n\n /** Reports validity and shows the browser's constraint validation UI. */\n reportValidity(): boolean {\n return this._internals.reportValidity();\n }\n\n /**\n * Handle for the shared IDREF observer. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Default-slot text content captured for use as the host's accessible name\n * when no explicit `label`/`aria-label`/`aria-labelledby` is supplied.\n * Codex round-1 finding #9.\n * @internal\n */\n @state() private _slotLabelText: string = '';\n\n /** No-IDL-ref fallback tokens applied to the inner button. @internal */\n @state() private _fallbackAriaLabelledBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaDescribedBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaLabel: string | null = null;\n\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the render-time branch between the modern path (host is the\n * announced surface, inner button is `aria-hidden + tabindex=-1`) and the\n * fallback path (inner button is the announced surface, host is demoted).\n * Codex round-2 finding #2.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n\n /**\n * Tracks whether the host's `tabindex` is managed by the component itself\n * (vs. set explicitly by a consumer). Codex round-14 P2: a consumer-supplied\n * `tabindex` (e.g. roving-tabindex toolbar pattern with `tabindex=\"-1\"`)\n * must survive disabled flips and re-renders. Only re-assert tabindex in\n * `updated()` when the component originally claimed it.\n * @internal\n */\n private _internalTabindexManaged = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Detect platform support for IDL element references. Codex round-2\n // finding #2: drives the render-time branch between modern (host\n // announced) and fallback (inner button announced) paths.\n this._supportsIdrefRefs = supportsIdrefElementReferences(this._internals);\n // Seed root-independent semantics from the moment of connection so AT\n // sees the toggle role + pressed state before the first paint.\n this._syncHostAriaSemantics();\n // Codex round-1 finding #1: host is the canonical announced surface on\n // modern browsers, so the inner `<button>` is demoted via\n // `aria-hidden + tabindex=-1`.\n // Codex round-2 finding #2: on no-IDL-ref browsers the inner button is\n // the announced surface (it carries native button + aria-pressed), so\n // the host is demoted to `tabindex=-1` and lets the inner button own\n // tab order + activation.\n // Codex round-14 P2: only claim ownership of `tabindex` when no consumer\n // value is present. Consumers using roving-tabindex toolbar patterns\n // must be able to set `tabindex=\"-1\"` on the host without it being\n // clobbered on every disabled flip. Note we still claim ownership when\n // disabled — the initial value is `-1` to keep the host out of tab order\n // and `updated()` re-asserts the appropriate value when disabled flips.\n if (!this.hasAttribute('tabindex')) {\n this._internalTabindexManaged = true;\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('click', this._handleHostClickRouted);\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('click', this._handleHostClickRouted);\n // Codex round-13 P2: tear down the assigned-node text observer so a\n // detached host does not receive mutation callbacks from nodes that may\n // outlive it (e.g. lifted out of the slot but kept in the document).\n this._slotTextObserver?.disconnect();\n this._slotTextObserver = null;\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n /**\n * Host-level keydown handler. Active only on the modern path; on the\n * no-IDL-ref fallback the inner `<button>` owns native Space/Enter\n * activation. Codex round-2 finding #2.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n if (e.target !== this) return;\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n this._invokeToggle();\n }\n };\n\n /**\n * Host-level click router. The inner `<button>` is `aria-hidden + tabindex=-1`\n * on modern browsers but still receives clicks via mouse activation; toggling\n * is handled by the inner `_handleClick`. Host-level clicks (composed path\n * origin === host) only come from AT activation or programmatic triggers,\n * so we route those to the toggle pipeline.\n *\n * Codex round-2 finding #2: on no-IDL-ref browsers the inner button is the\n * announced surface so this host-level routing is a no-op — AT activation\n * lands on the inner button directly.\n * @internal\n */\n private _handleHostClickRouted = (e: MouseEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n // Only fire when the host itself originated the click — inner-button\n // clicks bubble through here too but are handled by `_handleClick`.\n const path = e.composedPath();\n if (path[0] !== this) return;\n this._invokeToggle();\n };\n\n /** @internal */\n private _invokeToggle(): void {\n this.pressed = !this.pressed;\n this._syncFormValue();\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n }\n\n /**\n * Moves focus to the announced toggle-button surface. Codex round-1 finding\n * `#1` made the host the canonical focus target on modern engines so AT\n * announces a single widget. Round-7 finding `#9` extends that contract to\n * the no-IDL-ref fallback: when the host is demoted (`tabindex=-1`,\n * role/state cleared on `internals`) the inner `<button>` owns the announced\n * semantics and tab order, so programmatic `focus()` must redirect there —\n * otherwise scripted focus and error recovery land on the demoted host on\n * unsupported engines.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n super.focus(options);\n return;\n }\n this.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"button\"]')?.focus(options);\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n\n // Track default-slot text content so it can serve as the accessible\n // name when no explicit label is set. Codex round-1 finding #9.\n this._captureSlotLabelText();\n // Codex round-13 P2: also observe in-place text mutations on assigned\n // nodes so framework-driven `Mute` → `Unmute` rewrites refresh the\n // cached label without requiring the consumer to swap the node.\n this._installSlotTextObserver();\n\n if (!this.label) {\n const slot = this._defaultSlot;\n const hasSlotText = slot\n ? slot.assignedNodes({ flatten: true }).some((n) => n.textContent?.trim())\n : false;\n if (!hasSlotText) {\n console.warn(\n '[hx-toggle-button] No accessible label found. Set the `label` attribute or provide slot text content for WCAG 4.1.2 compliance.',\n );\n }\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n if (\n changedProperties.has('pressed') ||\n changedProperties.has('value') ||\n changedProperties.has('required')\n ) {\n this._syncFormValue();\n }\n\n if (\n changedProperties.has('disabled') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_supportsIdrefRefs')\n ) {\n // Codex round-2 finding #2: align host tabindex with the chosen\n // announced surface. On no-IDL-ref browsers the inner button owns\n // tab order, so re-enabling the host should leave it `tabindex=-1`.\n // Codex round-14 P2: only re-assert when the component owns tabindex.\n // Consumer-managed values (e.g. roving-tabindex toolbar with `-1`) must\n // not be overwritten on disabled flips or supports-flag transitions.\n if (this._internalTabindexManaged) {\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n }\n\n // Host-elevated ARIA semantics — see _syncHostAriaSemantics.\n this._syncHostAriaSemantics();\n }\n\n /**\n * Reads the default slot's flattened text content into `_slotLabelText`.\n * Called from `firstUpdated()` and `slotchange` so host-canonical semantics\n * pick up slotted label text. Codex round-1 finding #9.\n * @internal\n */\n private _captureSlotLabelText(): void {\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotLabelText = '';\n return;\n }\n const text = slot\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent ?? '')\n .join(' ')\n .trim();\n this._slotLabelText = text;\n }\n\n /**\n * Watches assigned default-slot nodes for in-place text mutations so the\n * cached `_slotLabelText` (and thus `internals.ariaLabel`) stays in sync\n * when a framework rewrites textContent of an already-assigned node without\n * replacing it. `slotchange` does NOT fire for those mutations, so a\n * separate observer is required. Codex round-13 P2.\n * @internal\n */\n private _slotTextObserver: MutationObserver | null = null;\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * default-slot nodes. Disconnects any prior observer first so detached\n * nodes stop firing into a torn-down host.\n * @internal\n */\n private _installSlotTextObserver(): void {\n this._slotTextObserver?.disconnect();\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotTextObserver = null;\n return;\n }\n const observer = new MutationObserver(() => {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes({ flatten: true }).forEach((node) => {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n });\n this._slotTextObserver = observer;\n }\n\n /** @internal */\n private _handleDefaultSlotChange(): void {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n // Re-tune the in-place text observer over the new assigned-node set\n // (codex round-13 P2).\n this._installSlotTextObserver();\n }\n\n /**\n * Mirrors toggle-button semantics onto the host via ElementInternals so that\n * consumer-supplied `aria-label`, `aria-labelledby`, and `aria-describedby`\n * on `<hx-toggle-button>` reach the announced control. The codex aria-group-2\n * finding identified that the inner shadow `<button>` was the only carrier of\n * the toggle role + pressed state, leaving host-level IDREF tokens stranded\n * across the shadow boundary.\n *\n * The shadow `<button>` keeps `aria-pressed`/`aria-label` mirrored for\n * backwards-compat with existing tests and for browsers without IDL element\n * references; the host is the canonical announced surface.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const externalLabelTokens = this.getAttribute('aria-labelledby');\n const externalDescTokens = this.getAttribute('aria-describedby');\n const labelEls = resolveIdrefTokens(this, externalLabelTokens);\n const descEls = resolveIdrefTokens(this, externalDescTokens);\n // Codex round-35 finding (CR major): `aria-labelledby` is only \"effective\"\n // when at least one IDREF resolves. A typo or transiently-missing target\n // must NOT erase the visible label — fall back to label/slot text so a\n // visibly-labeled toggle never becomes unnamed.\n const hasEffectiveLabelledBy = labelEls.length > 0;\n let resolvedLabel: string | null;\n if (hostAriaLabel) {\n resolvedLabel = hostAriaLabel;\n } else if (hasEffectiveLabelledBy) {\n resolvedLabel = null;\n } else if (this.label) {\n resolvedLabel = this.label;\n } else {\n // Codex round-1 finding #9: default-slot text becomes the accessible\n // name when no explicit label is provided. Without this, slotted text\n // never reaches the host's announced surface.\n resolvedLabel = this._slotLabelText || null;\n }\n\n // Codex round-2 finding #2: branch on platform support. Modern path —\n // host carries `role=button` + aria-pressed via ElementInternals.\n // Fallback path — inner native `<button>` is the announced surface; clear\n // host role/state on internals so AT does not double-announce.\n if (this._supportsIdrefRefs) {\n // ─── Modern path ───\n internals.role = 'button';\n internals.ariaPressed = this.pressed ? 'true' : 'false';\n internals.ariaDisabled = this.disabled ? 'true' : 'false';\n // Codex round-1 finding #6: drive aria-invalid from the live ValidityState\n // so a required-but-unpressed toggle is announced as invalid even before\n // any visible affordance renders. `_updateValidity()` calls this method\n // synchronously after every `setValidity()`.\n internals.ariaInvalid = !internals.validity.valid ? 'true' : 'false';\n internals.ariaLabel = resolvedLabel;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n ariaDescribedByElements: Element[] | null;\n };\n const refsInternals = internals as InternalsWithRefs;\n\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n refsInternals.ariaDescribedByElements = descEls.length > 0 ? descEls : null;\n // Clear fallbacks when IDL refs are available.\n this._fallbackAriaLabelledBy = null;\n this._fallbackAriaDescribedBy = null;\n this._fallbackAriaLabel = null;\n } else {\n // ─── Fallback path: inner button is the announced surface ───\n // Round-2 finding #2: round-1 set host role/state via internals AND\n // mirrored aria-* onto the `aria-hidden` inner button — making the\n // mirrored attributes inert. The fix is to clear host role/state and\n // let the inner native `<button>` (rendered without aria-hidden, with\n // `tabindex=0`, with aria-pressed) carry semantics natively.\n internals.role = null;\n internals.ariaPressed = null;\n internals.ariaDisabled = null;\n internals.ariaInvalid = null;\n internals.ariaLabel = null;\n\n // Codex round-36 (medium): gate the fallback label tokens on the\n // *effective* labelledby contract. Mirroring broken consumer tokens to\n // the inner button on legacy engines erases the accessible name —\n // exactly the bug the modern path now defends against. When tokens\n // don't resolve, fall through to `_fallbackAriaLabel` (resolvedLabel)\n // so the slot/property still names the announced surface.\n this._fallbackAriaLabelledBy = hasEffectiveLabelledBy ? externalLabelTokens : null;\n this._fallbackAriaDescribedBy = externalDescTokens || null;\n this._fallbackAriaLabel = resolvedLabel;\n }\n }\n\n protected override _onFormReset(): void {\n this.pressed = false;\n }\n\n protected override _onFormStateRestore(\n state: string | File | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n this.pressed = typeof state === 'string' && state === 'pressed';\n }\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _syncFormValue(): void {\n if (this.pressed && this.value !== undefined) {\n // Pass explicit state 'pressed' so formStateRestoreCallback can reliably detect it.\n this._internals.setFormValue(this.value, 'pressed');\n } else {\n this._internals.setFormValue(null);\n }\n this._updateValidity();\n }\n\n /** @internal */\n private _updateValidity(): void {\n if (this.required && !this.pressed) {\n // Codex round-17 P2: anchor validity UI to the announced surface. On\n // the modern path the host is the canonical announced/focus surface\n // (the inner button is `aria-hidden + tabindex=-1`), so passing the\n // host avoids `reportValidity()` landing focus on a hidden node. On\n // the fallback path the inner button is the announced surface.\n const anchor: HTMLElement | undefined = this._supportsIdrefRefs\n ? this\n : (this.shadowRoot?.querySelector<HTMLElement>('[part=\"button\"]') ?? undefined);\n this._internals.setValidity(\n { valueMissing: true },\n 'Please activate this toggle button.',\n anchor,\n );\n } else {\n this._internals.setValidity({});\n }\n // Codex round-1 finding #6: keep `internals.ariaInvalid` aligned with the\n // current `ValidityState`.\n this._syncHostAriaSemantics();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.pressed = !this.pressed;\n this._syncFormValue();\n\n /**\n * Dispatched when the toggle state changes.\n * @event hx-toggle\n */\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n\n // Codex round-12 P2: on the modern path the host owns role=\"button\" and\n // tabindex=0; the inner <button tabindex=\"-1\"> is aria-hidden. Native\n // click activation on a `<button>` still focuses it, which would leave\n // `document.activeElement` and AT focus on a hidden node. Move focus to\n // the host so the announced surface is also the focus target.\n if (this._supportsIdrefRefs) {\n this.focus();\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderInner() {\n return html`\n <span part=\"prefix\" class=\"button__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"button__label\">\n <slot @slotchange=${this._handleDefaultSlotChange}></slot>\n </span>\n <span part=\"suffix\" class=\"button__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const classes = {\n button: true,\n [`button--${this.variant}`]: true,\n [`button--${this.size}`]: true,\n 'button--pressed': this.pressed,\n };\n\n // Codex round-2 finding #2: branch the inner button on platform support.\n // Modern path — host announced, inner button is `aria-hidden + tabindex=-1`.\n // Fallback path — inner native `<button>` is announced (NO aria-hidden,\n // tabindex=0) so consumer-mirrored aria-* attributes resolve through a\n // visible accessibility-tree node and AT can name + activate it natively.\n const innerIsAnnounced = !this._supportsIdrefRefs;\n const innerTabIndex = innerIsAnnounced && !this.disabled ? '0' : '-1';\n // Round-1 finding #8: on no-IDL-ref browsers mirror host aria tokens onto\n // the inner button so it carries an accessible name. On modern browsers\n // we still mirror `label` onto the inner button for non-AT consumers\n // (testing, devtools) — does not affect announced semantics.\n const innerAriaLabel = this._fallbackAriaLabel ?? this.label ?? undefined;\n const innerAriaLabelledBy = this._fallbackAriaLabelledBy ?? undefined;\n const innerAriaDescribedBy = this._fallbackAriaDescribedBy ?? undefined;\n\n return html`\n <button\n part=\"button\"\n class=${classMap(classes)}\n ?disabled=${this.disabled}\n type=\"button\"\n tabindex=${innerTabIndex}\n aria-pressed=${this.pressed ? 'true' : 'false'}\n aria-label=${ifDefined(innerAriaLabel)}\n aria-labelledby=${ifDefined(innerAriaLabelledBy)}\n aria-describedby=${ifDefined(innerAriaDescribedBy)}\n aria-hidden=${innerIsAnnounced ? nothing : 'true'}\n @click=${this._handleClick}\n >\n ${this._renderInner()}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toggle-button': HelixToggleButton;\n }\n}\n"],"names":["helixToggleButtonStyles","css","HelixToggleButton","HelixElement","e","supportsIdrefElementReferences","enabledTabIndex","installAriaIdrefMirror","_a","_b","options","changedProperties","slot","n","text","observer","node","internals","hostAriaLabel","externalLabelTokens","externalDescTokens","labelEls","resolveIdrefTokens","descEls","hasEffectiveLabelledBy","resolvedLabel","refsInternals","state","_mode","disabled","anchor","html","classes","innerIsAnnounced","innerTabIndex","innerAriaLabel","innerAriaLabelledBy","innerAriaDescribedBy","classMap","ifDefined","nothing","forcedColorsInteractive","__decorateClass","query","property","customElement"],"mappings":";;;;;;;AAEO,MAAMA,IAA0BC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
|
1
|
+
{"version":3,"file":"hx-toggle-button-DwBers3A.js","sources":["../../src/components/hx-toggle-button/hx-toggle-button.styles.ts","../../src/components/hx-toggle-button/hx-toggle-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixToggleButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Base Button ─── */\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-toggle-button-border-color, transparent);\n border-radius: var(--hx-toggle-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toggle-button-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-toggle-button-color, var(--hx-color-text-on-primary, #ffffff));\n font-family: var(--hx-toggle-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-toggle-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n }\n\n /*\n * Host-focus path: on the modern (IDL element-references) render branch the\n * host is the tabbable surface (tabindex=0) and the inner <button> is\n * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'\n * so keyboard users still see a visible affordance. Codex round-11 P1.\n */\n :host(:focus-visible) .button {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /*\n * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner\n * <button> is the tab target. Native :focus-visible drives the ring.\n */\n .button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .button:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .button:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n /* ─── Size Variants ─── */\n\n /* WCAG 2.5.5 (healthcare mandate): minimum 44px touch target for sm variant.\n min-height uses --hx-touch-target-min to guarantee the interactive area\n meets the threshold even though the visual size token is smaller. */\n .button--sm {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n .button--md {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .button--lg {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Style Variants ─── */\n\n .button--primary {\n --hx-toggle-button-bg: var(--hx-color-primary-500, #429797);\n --hx-toggle-button-color: var(--hx-color-text-on-primary, #ffffff);\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * secondary/ghost paint primary text on the surface (white). primary-500\n * (#429797) on white = 3.43:1 — fails AA at body sizes. shift to\n * primary-600 (#0F7078) = 6.06:1 — AA pass. border keeps primary-500\n * for the brand affordance (3:1 non-text contrast still met).\n */\n .button--secondary {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n }\n\n .button--secondary:hover {\n --hx-toggle-button-bg: var(--hx-color-primary-50, #ebf8f8);\n }\n\n .button--tertiary {\n --hx-toggle-button-bg: var(--hx-color-surface-sunken, #ebeee9);\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--tertiary:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--ghost {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-primary-600, #0f7078);\n --hx-toggle-button-border-color: transparent;\n }\n\n .button--ghost:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n .button--outline {\n --hx-toggle-button-bg: transparent;\n --hx-toggle-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-toggle-button-border-color: var(--hx-color-border-strong, #66787b);\n }\n\n .button--outline:hover {\n --hx-toggle-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n }\n\n /* ─── Pressed State ─── */\n\n /*\n * Primary: already uses solid primary bg; pressed deepens to primary-700\n * to give clear visual feedback without introducing a new color.\n *\n * AA fix: text.on-primary (= neutral-900 #0D1825) on primary-700 (#0F6363)\n * = 2.54:1 — fails AA. Pin fg at neutral-0 for the darker pressed fill\n * (neutral-0 on primary-700 = 7.03:1, AAA pass). Mirrors hx-toast\n * precedent (commit 300e21ab0) and hx-button hover treatment.\n * Note: secondary.pressed below uses primary-500 and stays at 5.20:1 —\n * leave it alone.\n */\n .button--primary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-700, #0f6363));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-neutral-0, #ffffff)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /*\n * Secondary: unpressed is outlined/transparent; pressed fills with primary bg\n * so the state change is immediately legible.\n */\n .button--secondary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-500, #429797));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-on-primary, #ffffff)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-500, #429797);\n }\n\n /* Tertiary pressed: use primary-100 bg + primary-700 text + border for WCAG 3:1 non-text contrast. */\n .button--tertiary.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: var(--hx-color-primary-600, #0f7078);\n box-shadow: inset 0 0 0 1px var(--hx-color-primary-600, #0f7078);\n }\n\n /* Ghost pressed: subtle neutral fill, matching hover behavior as a baseline. */\n .button--ghost.button--pressed {\n --hx-toggle-button-bg: var(--hx-toggle-button-pressed-bg, var(--hx-color-primary-100, #dbf0f0));\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-primary-700, #0f6363)\n );\n --hx-toggle-button-border-color: transparent;\n }\n\n /* Outline pressed: fills with a neutral tint, darkens the border, and adds an inset shadow for WCAG 3:1 non-text contrast. */\n .button--outline.button--pressed {\n --hx-toggle-button-bg: var(\n --hx-toggle-button-pressed-bg,\n var(--hx-color-surface-sunken, #ebeee9)\n );\n --hx-toggle-button-color: var(\n --hx-toggle-button-pressed-color,\n var(--hx-color-text-primary, #0d1825)\n );\n --hx-toggle-button-border-color: var(--hx-color-text-muted, #4a5362);\n box-shadow: inset 0 0 0 1px var(--hx-color-neutral-500, #66787b);\n }\n\n /* ─── Disabled ─── */\n\n .button[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Prefix / Suffix / Label ─── */\n\n .button__prefix,\n .button__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .button__label {\n flex: 1 1 auto;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .button {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .button {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n :host(:focus-visible) .button,\n .button:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .button--pressed {\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n box-shadow: none;\n }\n\n .button[disabled] {\n background-color: ButtonFace;\n color: GrayText;\n border-color: GrayText;\n opacity: 1;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToggleButtonStyles } from './hx-toggle-button.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\n/** Detail for the hx-toggle event dispatched by hx-toggle-button. */\nexport interface HxToggleDetail {\n pressed: boolean;\n}\n\n/**\n * A two-state toggle button that communicates a pressed/unpressed status to\n * assistive technology via `aria-pressed`. Supports multiple visual variants\n * and sizes, prefix/suffix slots, full ElementInternals form association, and\n * a distinct pressed visual state for every variant.\n *\n * @summary Two-state toggle button with pressed/unpressed ARIA semantics.\n *\n * @tag hx-toggle-button\n *\n * @slot - Default slot for the button label text or content.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Icon or content rendered after the label.\n *\n * @fires {CustomEvent<{pressed: boolean}>} hx-toggle - Dispatched when the\n * toggle state changes. Not dispatched when the button is disabled.\n *\n * @csspart button - The native `<button>` element.\n * @csspart label - The label text wrapper span.\n * @csspart prefix - The prefix slot container span.\n * @csspart suffix - The suffix slot container span.\n *\n * @cssprop [--hx-toggle-button-bg=var(--hx-color-primary-500)] - Button background color.\n * @cssprop [--hx-toggle-button-color=var(--hx-color-neutral-0)] - Button text color.\n * @cssprop [--hx-toggle-button-border-color=transparent] - Button border color.\n * @cssprop [--hx-toggle-button-border-radius=var(--hx-border-radius-md)] - Button border radius.\n * @cssprop [--hx-toggle-button-font-family=var(--hx-font-family-sans)] - Button font family.\n * @cssprop [--hx-toggle-button-font-weight=var(--hx-font-weight-semibold)] - Button font weight.\n * @cssprop [--hx-toggle-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-toggle-button-pressed-bg=var(--hx-color-primary-500)] - Background when pressed (variant-specific fallback applies).\n * @cssprop [--hx-toggle-button-pressed-color=var(--hx-color-neutral-0)] - Text color when pressed (variant-specific fallback applies).\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-filter-brightness-hover] - CSS filter.\n * @cssprop [--hx-filter-brightness-active] - CSS filter.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-color-primary-700] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-color-neutral-50] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n */\n@customElement('hx-toggle-button')\nexport class HelixToggleButton extends HelixElement {\n static override styles = [helixToggleButtonStyles, forcedColorsInteractive];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n /** @internal */\n @query('slot:not([name])') private _defaultSlot!: HTMLSlotElement | null;\n\n // ─── Public Properties ───\n\n /**\n * Whether the toggle button is in the pressed state.\n * Reflected as an attribute so CSS selectors like `:host([pressed])` work.\n * @attr pressed\n */\n @property({ type: Boolean, reflect: true })\n pressed = false;\n\n /**\n * Visual style variant of the button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline' = 'secondary';\n\n /**\n * Size of the button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the button is disabled. Prevents all interaction and form actions.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Form field name submitted via ElementInternals when the button is pressed.\n * @attr name\n */\n @property({ type: String })\n name: string | undefined = undefined;\n\n /**\n * Form field value submitted via ElementInternals when the button is pressed.\n * @attr value\n */\n @property({ type: String })\n value: string | undefined = undefined;\n\n /**\n * Accessible label forwarded to the inner `<button>` as `aria-label`.\n * Required for icon-only toggle buttons where no visible text is present.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * When true, the button must be in the pressed state for the form to be submitted.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n // ─── Form API ───\n\n /** Returns the ValidityState object. */\n override get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** Returns the current validation message. */\n override get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Checks whether the button satisfies its constraints. */\n checkValidity(): boolean {\n return this._internals.checkValidity();\n }\n\n /** Reports validity and shows the browser's constraint validation UI. */\n reportValidity(): boolean {\n return this._internals.reportValidity();\n }\n\n /**\n * Handle for the shared IDREF observer. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Default-slot text content captured for use as the host's accessible name\n * when no explicit `label`/`aria-label`/`aria-labelledby` is supplied.\n * Codex round-1 finding #9.\n * @internal\n */\n @state() private _slotLabelText: string = '';\n\n /** No-IDL-ref fallback tokens applied to the inner button. @internal */\n @state() private _fallbackAriaLabelledBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaDescribedBy: string | null = null;\n /** @internal */\n @state() private _fallbackAriaLabel: string | null = null;\n\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the render-time branch between the modern path (host is the\n * announced surface, inner button is `aria-hidden + tabindex=-1`) and the\n * fallback path (inner button is the announced surface, host is demoted).\n * Codex round-2 finding #2.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n\n /**\n * Tracks whether the host's `tabindex` is managed by the component itself\n * (vs. set explicitly by a consumer). Codex round-14 P2: a consumer-supplied\n * `tabindex` (e.g. roving-tabindex toolbar pattern with `tabindex=\"-1\"`)\n * must survive disabled flips and re-renders. Only re-assert tabindex in\n * `updated()` when the component originally claimed it.\n * @internal\n */\n private _internalTabindexManaged = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Detect platform support for IDL element references. Codex round-2\n // finding #2: drives the render-time branch between modern (host\n // announced) and fallback (inner button announced) paths.\n this._supportsIdrefRefs = supportsIdrefElementReferences(this._internals);\n // Seed root-independent semantics from the moment of connection so AT\n // sees the toggle role + pressed state before the first paint.\n this._syncHostAriaSemantics();\n // Codex round-1 finding #1: host is the canonical announced surface on\n // modern browsers, so the inner `<button>` is demoted via\n // `aria-hidden + tabindex=-1`.\n // Codex round-2 finding #2: on no-IDL-ref browsers the inner button is\n // the announced surface (it carries native button + aria-pressed), so\n // the host is demoted to `tabindex=-1` and lets the inner button own\n // tab order + activation.\n // Codex round-14 P2: only claim ownership of `tabindex` when no consumer\n // value is present. Consumers using roving-tabindex toolbar patterns\n // must be able to set `tabindex=\"-1\"` on the host without it being\n // clobbered on every disabled flip. Note we still claim ownership when\n // disabled — the initial value is `-1` to keep the host out of tab order\n // and `updated()` re-asserts the appropriate value when disabled flips.\n if (!this.hasAttribute('tabindex')) {\n this._internalTabindexManaged = true;\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('click', this._handleHostClickRouted);\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('click', this._handleHostClickRouted);\n // Codex round-13 P2: tear down the assigned-node text observer so a\n // detached host does not receive mutation callbacks from nodes that may\n // outlive it (e.g. lifted out of the slot but kept in the document).\n this._slotTextObserver?.disconnect();\n this._slotTextObserver = null;\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n /**\n * Host-level keydown handler. Active only on the modern path; on the\n * no-IDL-ref fallback the inner `<button>` owns native Space/Enter\n * activation. Codex round-2 finding #2.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n if (e.target !== this) return;\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n this._invokeToggle();\n }\n };\n\n /**\n * Host-level click router. The inner `<button>` is `aria-hidden + tabindex=-1`\n * on modern browsers but still receives clicks via mouse activation; toggling\n * is handled by the inner `_handleClick`. Host-level clicks (composed path\n * origin === host) only come from AT activation or programmatic triggers,\n * so we route those to the toggle pipeline.\n *\n * Codex round-2 finding #2: on no-IDL-ref browsers the inner button is the\n * announced surface so this host-level routing is a no-op — AT activation\n * lands on the inner button directly.\n * @internal\n */\n private _handleHostClickRouted = (e: MouseEvent): void => {\n if (this.disabled) return;\n if (!this._supportsIdrefRefs) return;\n // Only fire when the host itself originated the click — inner-button\n // clicks bubble through here too but are handled by `_handleClick`.\n const path = e.composedPath();\n if (path[0] !== this) return;\n this._invokeToggle();\n };\n\n /** @internal */\n private _invokeToggle(): void {\n this.pressed = !this.pressed;\n this._syncFormValue();\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n }\n\n /**\n * Moves focus to the announced toggle-button surface. Codex round-1 finding\n * `#1` made the host the canonical focus target on modern engines so AT\n * announces a single widget. Round-7 finding `#9` extends that contract to\n * the no-IDL-ref fallback: when the host is demoted (`tabindex=-1`,\n * role/state cleared on `internals`) the inner `<button>` owns the announced\n * semantics and tab order, so programmatic `focus()` must redirect there —\n * otherwise scripted focus and error recovery land on the demoted host on\n * unsupported engines.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n super.focus(options);\n return;\n }\n this.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"button\"]')?.focus(options);\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n\n // Track default-slot text content so it can serve as the accessible\n // name when no explicit label is set. Codex round-1 finding #9.\n this._captureSlotLabelText();\n // Codex round-13 P2: also observe in-place text mutations on assigned\n // nodes so framework-driven `Mute` → `Unmute` rewrites refresh the\n // cached label without requiring the consumer to swap the node.\n this._installSlotTextObserver();\n\n if (!this.label) {\n const slot = this._defaultSlot;\n const hasSlotText = slot\n ? slot.assignedNodes({ flatten: true }).some((n) => n.textContent?.trim())\n : false;\n if (!hasSlotText) {\n console.warn(\n '[hx-toggle-button] No accessible label found. Set the `label` attribute or provide slot text content for WCAG 4.1.2 compliance.',\n );\n }\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n if (\n changedProperties.has('pressed') ||\n changedProperties.has('value') ||\n changedProperties.has('required')\n ) {\n this._syncFormValue();\n }\n\n if (\n changedProperties.has('disabled') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_supportsIdrefRefs')\n ) {\n // Codex round-2 finding #2: align host tabindex with the chosen\n // announced surface. On no-IDL-ref browsers the inner button owns\n // tab order, so re-enabling the host should leave it `tabindex=-1`.\n // Codex round-14 P2: only re-assert when the component owns tabindex.\n // Consumer-managed values (e.g. roving-tabindex toolbar with `-1`) must\n // not be overwritten on disabled flips or supports-flag transitions.\n if (this._internalTabindexManaged) {\n const enabledTabIndex = this._supportsIdrefRefs ? '0' : '-1';\n this.setAttribute('tabindex', this.disabled ? '-1' : enabledTabIndex);\n }\n }\n\n // Host-elevated ARIA semantics — see _syncHostAriaSemantics.\n this._syncHostAriaSemantics();\n }\n\n /**\n * Reads the default slot's flattened text content into `_slotLabelText`.\n * Called from `firstUpdated()` and `slotchange` so host-canonical semantics\n * pick up slotted label text. Codex round-1 finding #9.\n * @internal\n */\n private _captureSlotLabelText(): void {\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotLabelText = '';\n return;\n }\n const text = slot\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent ?? '')\n .join(' ')\n .trim();\n this._slotLabelText = text;\n }\n\n /**\n * Watches assigned default-slot nodes for in-place text mutations so the\n * cached `_slotLabelText` (and thus `internals.ariaLabel`) stays in sync\n * when a framework rewrites textContent of an already-assigned node without\n * replacing it. `slotchange` does NOT fire for those mutations, so a\n * separate observer is required. Codex round-13 P2.\n * @internal\n */\n private _slotTextObserver: MutationObserver | null = null;\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * default-slot nodes. Disconnects any prior observer first so detached\n * nodes stop firing into a torn-down host.\n * @internal\n */\n private _installSlotTextObserver(): void {\n this._slotTextObserver?.disconnect();\n const slot = this._defaultSlot;\n if (!slot) {\n this._slotTextObserver = null;\n return;\n }\n const observer = new MutationObserver(() => {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes({ flatten: true }).forEach((node) => {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n });\n this._slotTextObserver = observer;\n }\n\n /** @internal */\n private _handleDefaultSlotChange(): void {\n this._captureSlotLabelText();\n this._syncHostAriaSemantics();\n // Re-tune the in-place text observer over the new assigned-node set\n // (codex round-13 P2).\n this._installSlotTextObserver();\n }\n\n /**\n * Mirrors toggle-button semantics onto the host via ElementInternals so that\n * consumer-supplied `aria-label`, `aria-labelledby`, and `aria-describedby`\n * on `<hx-toggle-button>` reach the announced control. The codex aria-group-2\n * finding identified that the inner shadow `<button>` was the only carrier of\n * the toggle role + pressed state, leaving host-level IDREF tokens stranded\n * across the shadow boundary.\n *\n * The shadow `<button>` keeps `aria-pressed`/`aria-label` mirrored for\n * backwards-compat with existing tests and for browsers without IDL element\n * references; the host is the canonical announced surface.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const externalLabelTokens = this.getAttribute('aria-labelledby');\n const externalDescTokens = this.getAttribute('aria-describedby');\n const labelEls = resolveIdrefTokens(this, externalLabelTokens);\n const descEls = resolveIdrefTokens(this, externalDescTokens);\n // Codex round-35 finding (CR major): `aria-labelledby` is only \"effective\"\n // when at least one IDREF resolves. A typo or transiently-missing target\n // must NOT erase the visible label — fall back to label/slot text so a\n // visibly-labeled toggle never becomes unnamed.\n const hasEffectiveLabelledBy = labelEls.length > 0;\n let resolvedLabel: string | null;\n if (hostAriaLabel) {\n resolvedLabel = hostAriaLabel;\n } else if (hasEffectiveLabelledBy) {\n resolvedLabel = null;\n } else if (this.label) {\n resolvedLabel = this.label;\n } else {\n // Codex round-1 finding #9: default-slot text becomes the accessible\n // name when no explicit label is provided. Without this, slotted text\n // never reaches the host's announced surface.\n resolvedLabel = this._slotLabelText || null;\n }\n\n // Codex round-2 finding #2: branch on platform support. Modern path —\n // host carries `role=button` + aria-pressed via ElementInternals.\n // Fallback path — inner native `<button>` is the announced surface; clear\n // host role/state on internals so AT does not double-announce.\n if (this._supportsIdrefRefs) {\n // ─── Modern path ───\n internals.role = 'button';\n internals.ariaPressed = this.pressed ? 'true' : 'false';\n internals.ariaDisabled = this.disabled ? 'true' : 'false';\n // Codex round-1 finding #6: drive aria-invalid from the live ValidityState\n // so a required-but-unpressed toggle is announced as invalid even before\n // any visible affordance renders. `_updateValidity()` calls this method\n // synchronously after every `setValidity()`.\n internals.ariaInvalid = !internals.validity.valid ? 'true' : 'false';\n internals.ariaLabel = resolvedLabel;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n ariaDescribedByElements: Element[] | null;\n };\n const refsInternals = internals as InternalsWithRefs;\n\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n refsInternals.ariaDescribedByElements = descEls.length > 0 ? descEls : null;\n // Clear fallbacks when IDL refs are available.\n this._fallbackAriaLabelledBy = null;\n this._fallbackAriaDescribedBy = null;\n this._fallbackAriaLabel = null;\n } else {\n // ─── Fallback path: inner button is the announced surface ───\n // Round-2 finding #2: round-1 set host role/state via internals AND\n // mirrored aria-* onto the `aria-hidden` inner button — making the\n // mirrored attributes inert. The fix is to clear host role/state and\n // let the inner native `<button>` (rendered without aria-hidden, with\n // `tabindex=0`, with aria-pressed) carry semantics natively.\n internals.role = null;\n internals.ariaPressed = null;\n internals.ariaDisabled = null;\n internals.ariaInvalid = null;\n internals.ariaLabel = null;\n\n // Codex round-36 (medium): gate the fallback label tokens on the\n // *effective* labelledby contract. Mirroring broken consumer tokens to\n // the inner button on legacy engines erases the accessible name —\n // exactly the bug the modern path now defends against. When tokens\n // don't resolve, fall through to `_fallbackAriaLabel` (resolvedLabel)\n // so the slot/property still names the announced surface.\n this._fallbackAriaLabelledBy = hasEffectiveLabelledBy ? externalLabelTokens : null;\n this._fallbackAriaDescribedBy = externalDescTokens || null;\n this._fallbackAriaLabel = resolvedLabel;\n }\n }\n\n protected override _onFormReset(): void {\n this.pressed = false;\n }\n\n protected override _onFormStateRestore(\n state: string | File | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n this.pressed = typeof state === 'string' && state === 'pressed';\n }\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _syncFormValue(): void {\n if (this.pressed && this.value !== undefined) {\n // Pass explicit state 'pressed' so formStateRestoreCallback can reliably detect it.\n this._internals.setFormValue(this.value, 'pressed');\n } else {\n this._internals.setFormValue(null);\n }\n this._updateValidity();\n }\n\n /** @internal */\n private _updateValidity(): void {\n if (this.required && !this.pressed) {\n // Codex round-17 P2: anchor validity UI to the announced surface. On\n // the modern path the host is the canonical announced/focus surface\n // (the inner button is `aria-hidden + tabindex=-1`), so passing the\n // host avoids `reportValidity()` landing focus on a hidden node. On\n // the fallback path the inner button is the announced surface.\n const anchor: HTMLElement | undefined = this._supportsIdrefRefs\n ? this\n : (this.shadowRoot?.querySelector<HTMLElement>('[part=\"button\"]') ?? undefined);\n this._internals.setValidity(\n { valueMissing: true },\n 'Please activate this toggle button.',\n anchor,\n );\n } else {\n this._internals.setValidity({});\n }\n // Codex round-1 finding #6: keep `internals.ariaInvalid` aligned with the\n // current `ValidityState`.\n this._syncHostAriaSemantics();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.pressed = !this.pressed;\n this._syncFormValue();\n\n /**\n * Dispatched when the toggle state changes.\n * @event hx-toggle\n */\n this.dispatchEvent(\n new CustomEvent<{ pressed: boolean }>('hx-toggle', {\n bubbles: true,\n composed: true,\n detail: { pressed: this.pressed },\n }),\n );\n\n // Codex round-12 P2: on the modern path the host owns role=\"button\" and\n // tabindex=0; the inner <button tabindex=\"-1\"> is aria-hidden. Native\n // click activation on a `<button>` still focuses it, which would leave\n // `document.activeElement` and AT focus on a hidden node. Move focus to\n // the host so the announced surface is also the focus target.\n if (this._supportsIdrefRefs) {\n this.focus();\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderInner() {\n return html`\n <span part=\"prefix\" class=\"button__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"button__label\">\n <slot @slotchange=${this._handleDefaultSlotChange}></slot>\n </span>\n <span part=\"suffix\" class=\"button__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const classes = {\n button: true,\n [`button--${this.variant}`]: true,\n [`button--${this.size}`]: true,\n 'button--pressed': this.pressed,\n };\n\n // Codex round-2 finding #2: branch the inner button on platform support.\n // Modern path — host announced, inner button is `aria-hidden + tabindex=-1`.\n // Fallback path — inner native `<button>` is announced (NO aria-hidden,\n // tabindex=0) so consumer-mirrored aria-* attributes resolve through a\n // visible accessibility-tree node and AT can name + activate it natively.\n const innerIsAnnounced = !this._supportsIdrefRefs;\n const innerTabIndex = innerIsAnnounced && !this.disabled ? '0' : '-1';\n // Round-1 finding #8: on no-IDL-ref browsers mirror host aria tokens onto\n // the inner button so it carries an accessible name. On modern browsers\n // we still mirror `label` onto the inner button for non-AT consumers\n // (testing, devtools) — does not affect announced semantics.\n const innerAriaLabel = this._fallbackAriaLabel ?? this.label ?? undefined;\n const innerAriaLabelledBy = this._fallbackAriaLabelledBy ?? undefined;\n const innerAriaDescribedBy = this._fallbackAriaDescribedBy ?? undefined;\n\n return html`\n <button\n part=\"button\"\n class=${classMap(classes)}\n ?disabled=${this.disabled}\n type=\"button\"\n tabindex=${innerTabIndex}\n aria-pressed=${this.pressed ? 'true' : 'false'}\n aria-label=${ifDefined(innerAriaLabel)}\n aria-labelledby=${ifDefined(innerAriaLabelledBy)}\n aria-describedby=${ifDefined(innerAriaDescribedBy)}\n aria-hidden=${innerIsAnnounced ? nothing : 'true'}\n @click=${this._handleClick}\n >\n ${this._renderInner()}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toggle-button': HelixToggleButton;\n }\n}\n"],"names":["helixToggleButtonStyles","css","HelixToggleButton","HelixElement","e","supportsIdrefElementReferences","enabledTabIndex","installAriaIdrefMirror","_a","_b","options","changedProperties","slot","n","text","observer","node","internals","hostAriaLabel","externalLabelTokens","externalDescTokens","labelEls","resolveIdrefTokens","descEls","hasEffectiveLabelledBy","resolvedLabel","refsInternals","state","_mode","disabled","anchor","html","classes","innerIsAnnounced","innerTabIndex","innerAriaLabel","innerAriaLabelledBy","innerAriaDescribedBy","classMap","ifDefined","nothing","forcedColorsInteractive","__decorateClass","query","property","customElement"],"mappings":";;;;;;;AAEO,MAAMA,IAA0BC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css as x, html as f, nothing as u } from "lit";
|
|
2
2
|
import { property as m, state as c, customElement as g, query as E } from "lit/decorators.js";
|
|
3
3
|
import { a as I } from "./forced-colors-CTEDFRGa.js";
|
|
4
|
-
import { s as y, i as w, r as S } from "./aria-idref-
|
|
4
|
+
import { s as y, i as w, r as S } from "./aria-idref-DCuEaknC.js";
|
|
5
5
|
import { f as C } from "./aria-flatten-DY6v2vah.js";
|
|
6
6
|
import { H as A } from "./helix-element-BNEYeiys.js";
|
|
7
7
|
import { classMap as k } from "lit/directives/class-map.js";
|
|
@@ -922,4 +922,4 @@ export {
|
|
|
922
922
|
o as H,
|
|
923
923
|
d as a
|
|
924
924
|
};
|
|
925
|
-
//# sourceMappingURL=hx-tree-item-
|
|
925
|
+
//# sourceMappingURL=hx-tree-item-CXyspGxI.js.map
|