@helixui/library 3.8.0 → 3.9.0-next.150
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/README.md +41 -0
- package/aaa-verdicts.json +2036 -0
- package/custom-elements.json +532 -569
- package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
- package/dist/components/hx-accordion/hx-accordion-item.styles.d.ts.map +1 -1
- package/dist/components/hx-accordion/index.js +1 -1
- package/dist/components/hx-alert/hx-alert.d.ts +0 -8
- package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
- package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
- package/dist/components/hx-alert/index.js +1 -1
- package/dist/components/hx-avatar/hx-avatar.d.ts +4 -1
- package/dist/components/hx-avatar/hx-avatar.d.ts.map +1 -1
- package/dist/components/hx-avatar/hx-avatar.styles.d.ts.map +1 -1
- package/dist/components/hx-avatar/index.js +1 -1
- package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
- package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
- package/dist/components/hx-badge/index.js +1 -1
- package/dist/components/hx-banner/hx-banner.d.ts +0 -8
- package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
- package/dist/components/hx-banner/hx-banner.styles.d.ts.map +1 -1
- package/dist/components/hx-banner/index.js +1 -1
- package/dist/components/hx-carousel/hx-carousel.d.ts.map +1 -1
- package/dist/components/hx-carousel/hx-carousel.styles.d.ts.map +1 -1
- package/dist/components/hx-carousel/index.js +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +7 -9
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
- package/dist/components/hx-clinical-status/hx-clinical-status.styles.d.ts.map +1 -1
- package/dist/components/hx-clinical-status/index.js +1 -1
- package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
- package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
- package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
- package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
- package/dist/components/hx-drawer/index.js +1 -1
- package/dist/components/hx-dropdown/hx-dropdown.styles.d.ts.map +1 -1
- package/dist/components/hx-dropdown/index.js +1 -1
- package/dist/components/hx-file-upload/hx-file-upload.d.ts +28 -0
- package/dist/components/hx-file-upload/hx-file-upload.d.ts.map +1 -1
- package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
- package/dist/components/hx-file-upload/index.js +1 -1
- package/dist/components/hx-help-text/hx-help-text.d.ts.map +1 -1
- package/dist/components/hx-help-text/hx-help-text.styles.d.ts.map +1 -1
- package/dist/components/hx-help-text/index.js +1 -1
- package/dist/components/hx-icon/hx-icon.d.ts +108 -12
- package/dist/components/hx-icon/hx-icon.d.ts.map +1 -1
- package/dist/components/hx-icon/hx-icon.styles.d.ts.map +1 -1
- package/dist/components/hx-icon/index.js +1 -1
- package/dist/components/hx-link/hx-link.d.ts.map +1 -1
- package/dist/components/hx-link/hx-link.styles.d.ts.map +1 -1
- package/dist/components/hx-link/index.js +1 -1
- package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
- package/dist/components/hx-menu/index.js +1 -1
- package/dist/components/hx-nav/hx-nav.d.ts.map +1 -1
- package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
- package/dist/components/hx-nav/index.js +1 -1
- package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
- package/dist/components/hx-number-input/hx-number-input.styles.d.ts.map +1 -1
- package/dist/components/hx-number-input/index.js +1 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +5 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
- package/dist/components/hx-overflow-menu/index.js +1 -1
- package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
- package/dist/components/hx-phi-field/hx-phi-field.styles.d.ts.map +1 -1
- package/dist/components/hx-phi-field/index.js +1 -1
- package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-rating/hx-rating.d.ts.map +1 -1
- package/dist/components/hx-rating/hx-rating.styles.d.ts.map +1 -1
- package/dist/components/hx-rating/index.js +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
- package/dist/components/hx-side-nav/index.js +1 -1
- package/dist/components/hx-slider/hx-slider.d.ts +28 -0
- package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
- package/dist/components/hx-slider/index.js +1 -1
- package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
- package/dist/components/hx-split-button/hx-split-button.styles.d.ts.map +1 -1
- package/dist/components/hx-split-button/index.js +1 -1
- package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
- package/dist/components/hx-stat/hx-stat.styles.d.ts.map +1 -1
- package/dist/components/hx-stat/index.js +1 -1
- package/dist/components/hx-steps/hx-step.d.ts.map +1 -1
- package/dist/components/hx-steps/hx-step.styles.d.ts.map +1 -1
- package/dist/components/hx-steps/index.js +1 -1
- package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
- package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
- package/dist/components/hx-tag/index.js +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toast/hx-toast.d.ts +0 -8
- package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
- package/dist/components/hx-toast/hx-toast.styles.d.ts.map +1 -1
- package/dist/components/hx-toast/index.js +1 -1
- package/dist/components/hx-top-nav/hx-top-nav.d.ts.map +1 -1
- package/dist/components/hx-top-nav/hx-top-nav.styles.d.ts.map +1 -1
- package/dist/components/hx-top-nav/index.js +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/css/helix-all.css +116 -54
- package/dist/css/helix-core.css +19 -4
- package/dist/css/helix-feedback.css +15 -18
- package/dist/css/helix-forms.css +39 -12
- package/dist/css/helix-media.css +6 -3
- package/dist/css/helix-navigation.css +16 -7
- package/dist/css/helix-overlay.css +10 -0
- package/dist/css/helix-tokens.css +3 -2
- package/dist/css/helix-utility.css +5 -0
- package/dist/css/hx-alert.css +4 -8
- package/dist/css/hx-avatar.css +1 -2
- package/dist/css/hx-badge.css +5 -0
- package/dist/css/hx-banner.css +4 -8
- package/dist/css/hx-carousel.css +6 -3
- package/dist/css/hx-checkbox.css +4 -9
- package/dist/css/hx-clinical-status.css +4 -7
- package/dist/css/hx-combobox.css +8 -0
- package/dist/css/hx-date-picker.css +5 -0
- package/dist/css/hx-drawer.css +5 -0
- package/dist/css/hx-dropdown.css +5 -0
- package/dist/css/hx-file-upload.css +4 -0
- package/dist/css/hx-help-text.css +5 -0
- package/dist/css/hx-icon.css +7 -0
- package/dist/css/hx-link.css +1 -2
- package/dist/css/hx-nav.css +7 -0
- package/dist/css/hx-number-input.css +2 -3
- package/dist/css/hx-overflow-menu.css +5 -0
- package/dist/css/hx-phi-field.css +2 -3
- package/dist/css/hx-rating.css +6 -0
- package/dist/css/hx-side-nav.css +3 -5
- package/dist/css/hx-split-button.css +5 -0
- package/dist/css/hx-stat.css +1 -2
- package/dist/css/hx-tag.css +5 -0
- package/dist/css/hx-time-picker.css +5 -0
- package/dist/css/hx-toast.css +6 -0
- package/dist/css/hx-top-nav.css +1 -2
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +4 -1
- package/dist/index.js +33 -33
- package/dist/shared/{hx-accordion-ZVzgDzTG.js → hx-accordion-DR--Ev4t.js} +48 -54
- package/dist/shared/hx-accordion-DR--Ev4t.js.map +1 -0
- package/dist/shared/{hx-alert-Bto8-TIi.js → hx-alert-C0axS32J.js} +40 -79
- package/dist/shared/hx-alert-C0axS32J.js.map +1 -0
- package/dist/shared/{hx-avatar-C9hOmlAb.js → hx-avatar-ChAYWnK8.js} +22 -24
- package/dist/shared/hx-avatar-ChAYWnK8.js.map +1 -0
- package/dist/shared/{hx-badge-DFL35nzi.js → hx-badge-vX-1cuLA.js} +16 -11
- package/dist/shared/hx-badge-vX-1cuLA.js.map +1 -0
- package/dist/shared/{hx-banner-fpRnciIO.js → hx-banner-PbHwFNSb.js} +51 -90
- package/dist/shared/hx-banner-PbHwFNSb.js.map +1 -0
- package/dist/shared/{hx-carousel-item-z1Lc24op.js → hx-carousel-item-BVIKgQ4i.js} +72 -102
- package/dist/shared/hx-carousel-item-BVIKgQ4i.js.map +1 -0
- package/dist/shared/{hx-checkbox-DcgyGS9V.js → hx-checkbox-DDSXXhps.js} +31 -38
- package/dist/shared/hx-checkbox-DDSXXhps.js.map +1 -0
- package/dist/shared/{hx-clinical-status-D3XQIOqX.js → hx-clinical-status-ZSVEc3Qg.js} +68 -87
- package/dist/shared/hx-clinical-status-ZSVEc3Qg.js.map +1 -0
- package/dist/shared/{hx-combobox-NgJaLbs2.js → hx-combobox-Be-mqOv4.js} +35 -45
- package/dist/shared/hx-combobox-Be-mqOv4.js.map +1 -0
- package/dist/shared/{hx-date-picker-0PtEav0K.js → hx-date-picker-CziP3Hm1.js} +15 -22
- package/dist/shared/hx-date-picker-CziP3Hm1.js.map +1 -0
- package/dist/shared/{hx-drawer-CM_upadk.js → hx-drawer-BlU2oX8-.js} +32 -36
- package/dist/shared/hx-drawer-BlU2oX8-.js.map +1 -0
- package/dist/shared/{hx-dropdown-xHwTJecv.js → hx-dropdown-DREqpIpm.js} +16 -11
- package/dist/shared/hx-dropdown-DREqpIpm.js.map +1 -0
- package/dist/shared/{hx-file-upload-D3rKROK5.js → hx-file-upload-CU5QGZSP.js} +137 -80
- package/dist/shared/hx-file-upload-CU5QGZSP.js.map +1 -0
- package/dist/shared/hx-help-text-CNaZ82LT.js +137 -0
- package/dist/shared/hx-help-text-CNaZ82LT.js.map +1 -0
- package/dist/shared/hx-icon-bxz9eB9a.js +386 -0
- package/dist/shared/hx-icon-bxz9eB9a.js.map +1 -0
- package/dist/shared/{hx-link-CMnZRUtQ.js → hx-link-BURSdYLp.js} +19 -26
- package/dist/shared/hx-link-BURSdYLp.js.map +1 -0
- package/dist/shared/{hx-menu-divider-A6Guuzi_.js → hx-menu-divider-g0grbWV9.js} +19 -31
- package/dist/shared/hx-menu-divider-g0grbWV9.js.map +1 -0
- package/dist/shared/{hx-nav-ChMTfn7o.js → hx-nav-GTsAZGOx.js} +46 -59
- package/dist/shared/hx-nav-GTsAZGOx.js.map +1 -0
- package/dist/shared/{hx-nav-item-ClN17f1y.js → hx-nav-item-CxE7Mp3M.js} +62 -64
- package/dist/shared/hx-nav-item-CxE7Mp3M.js.map +1 -0
- package/dist/shared/{hx-number-input-MggsT7F0.js → hx-number-input-Bvyc9kOi.js} +48 -53
- package/dist/shared/hx-number-input-Bvyc9kOi.js.map +1 -0
- package/dist/shared/{hx-overflow-menu-DFjJAziP.js → hx-overflow-menu-LrTteeR1.js} +32 -39
- package/dist/shared/hx-overflow-menu-LrTteeR1.js.map +1 -0
- package/dist/shared/{hx-phi-field-C19oxlrr.js → hx-phi-field-sZt_rYIL.js} +46 -66
- package/dist/shared/hx-phi-field-sZt_rYIL.js.map +1 -0
- package/dist/shared/{hx-radio-BY4zpwdh.js → hx-radio-BD_c9NJy.js} +51 -56
- package/dist/shared/{hx-radio-BY4zpwdh.js.map → hx-radio-BD_c9NJy.js.map} +1 -1
- package/dist/shared/{hx-rating-C3QP53k9.js → hx-rating-BGK4AxvI.js} +45 -71
- package/dist/shared/hx-rating-BGK4AxvI.js.map +1 -0
- package/dist/shared/{hx-slider-Blmv_rwS.js → hx-slider-CkOk5BCY.js} +83 -23
- package/dist/shared/{hx-slider-Blmv_rwS.js.map → hx-slider-CkOk5BCY.js.map} +1 -1
- package/dist/shared/{hx-split-button-CdNz1XAu.js → hx-split-button-Bg9FHrFK.js} +12 -16
- package/dist/shared/hx-split-button-Bg9FHrFK.js.map +1 -0
- package/dist/shared/{hx-stat-Gtw_SpK8.js → hx-stat-wKxbyep6.js} +22 -55
- package/dist/shared/hx-stat-wKxbyep6.js.map +1 -0
- package/dist/shared/{hx-step-CUzliIK_.js → hx-step-CyGQAuiB.js} +5 -25
- package/dist/shared/hx-step-CyGQAuiB.js.map +1 -0
- package/dist/shared/{hx-tag-C5aCUpVi.js → hx-tag-BqO6HY6V.js} +26 -21
- package/dist/shared/hx-tag-BqO6HY6V.js.map +1 -0
- package/dist/shared/{hx-time-picker-DfJkBwcX.js → hx-time-picker-if5Cl0Ei.js} +32 -38
- package/dist/shared/hx-time-picker-if5Cl0Ei.js.map +1 -0
- package/dist/shared/{hx-top-nav-CsTxOtVI.js → hx-top-nav-vP6oDWMV.js} +24 -38
- package/dist/shared/hx-top-nav-vP6oDWMV.js.map +1 -0
- package/dist/shared/{hx-tree-item-CXyspGxI.js → hx-tree-item-D8hwKd5m.js} +54 -57
- package/dist/shared/hx-tree-item-D8hwKd5m.js.map +1 -0
- package/dist/shared/{toast-factory-Dht3pVsw.js → toast-factory-DgnbFxVs.js} +127 -153
- package/dist/shared/toast-factory-DgnbFxVs.js.map +1 -0
- package/figma-inventory.json +283 -304
- package/package.json +8 -4
- package/dist/shared/hx-accordion-ZVzgDzTG.js.map +0 -1
- package/dist/shared/hx-alert-Bto8-TIi.js.map +0 -1
- package/dist/shared/hx-avatar-C9hOmlAb.js.map +0 -1
- package/dist/shared/hx-badge-DFL35nzi.js.map +0 -1
- package/dist/shared/hx-banner-fpRnciIO.js.map +0 -1
- package/dist/shared/hx-carousel-item-z1Lc24op.js.map +0 -1
- package/dist/shared/hx-checkbox-DcgyGS9V.js.map +0 -1
- package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +0 -1
- package/dist/shared/hx-combobox-NgJaLbs2.js.map +0 -1
- package/dist/shared/hx-date-picker-0PtEav0K.js.map +0 -1
- package/dist/shared/hx-drawer-CM_upadk.js.map +0 -1
- package/dist/shared/hx-dropdown-xHwTJecv.js.map +0 -1
- package/dist/shared/hx-file-upload-D3rKROK5.js.map +0 -1
- package/dist/shared/hx-help-text-Xb2Yr8x2.js +0 -156
- package/dist/shared/hx-help-text-Xb2Yr8x2.js.map +0 -1
- package/dist/shared/hx-icon-fuVm4-bk.js +0 -283
- package/dist/shared/hx-icon-fuVm4-bk.js.map +0 -1
- package/dist/shared/hx-link-CMnZRUtQ.js.map +0 -1
- package/dist/shared/hx-menu-divider-A6Guuzi_.js.map +0 -1
- package/dist/shared/hx-nav-ChMTfn7o.js.map +0 -1
- package/dist/shared/hx-nav-item-ClN17f1y.js.map +0 -1
- package/dist/shared/hx-number-input-MggsT7F0.js.map +0 -1
- package/dist/shared/hx-overflow-menu-DFjJAziP.js.map +0 -1
- package/dist/shared/hx-phi-field-C19oxlrr.js.map +0 -1
- package/dist/shared/hx-rating-C3QP53k9.js.map +0 -1
- package/dist/shared/hx-split-button-CdNz1XAu.js.map +0 -1
- package/dist/shared/hx-stat-Gtw_SpK8.js.map +0 -1
- package/dist/shared/hx-step-CUzliIK_.js.map +0 -1
- package/dist/shared/hx-tag-C5aCUpVi.js.map +0 -1
- package/dist/shared/hx-time-picker-DfJkBwcX.js.map +0 -1
- package/dist/shared/hx-top-nav-CsTxOtVI.js.map +0 -1
- package/dist/shared/hx-tree-item-CXyspGxI.js.map +0 -1
- package/dist/shared/toast-factory-Dht3pVsw.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-split-button-Bg9FHrFK.js","sources":["../../src/components/hx-split-button/hx-split-button.styles.ts","../../src/components/hx-split-button/hx-split-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSplitButtonStyles = css`\n :host {\n display: inline-block;\n position: relative;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Container ─── */\n\n .split-button {\n display: inline-flex;\n align-items: stretch;\n position: relative;\n }\n\n /* ─── Primary Button ─── */\n\n .split-button__primary {\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-split-button-border-color, transparent);\n border-inline-end: none;\n border-radius: var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0 0\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-split-button-color, var(--hx-color-text-on-primary, #ffffff));\n font-family: var(--hx-split-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-split-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 flex: 1 1 auto;\n }\n\n .split-button__primary:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__primary:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__primary:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__primary[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Button ─── */\n\n .split-button__trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);\n border-inline-start: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-divider-color, var(--hx-color-primary-900, #0b3232));\n border-radius: 0 var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem))\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0;\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-split-button-color, var(--hx-color-text-on-primary, #ffffff));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n user-select: none;\n -webkit-user-select: none;\n }\n\n .split-button__trigger:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__trigger:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__trigger:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__trigger[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Icon ─── */\n\n .split-button__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .split-button__chevron--open {\n transform: rotate(180deg);\n }\n\n /* hx-icon glyph sizing for the migrated chevron (12x8 → 12px). */\n .split-button__chevron-glyph {\n --hx-icon-size: 12px;\n }\n\n /* ─── Size Variants ─── */\n\n /* sm */\n .split-button--sm .split-button__primary {\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-size-8, 2rem);\n }\n\n .split-button--sm .split-button__trigger {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n /* md — WCAG 2.5.5 AAA Target Size (Enhanced): 44×44 minimum.\n Bound to --hx-touch-target-min so the default md variant clears the\n AAA-strict floor without requiring consumers to opt into sm or lg. */\n .split-button--md .split-button__primary {\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-touch-target-min, 2.75rem);\n }\n\n .split-button--md .split-button__trigger {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n /* WCAG 2.5.5 (Enhanced) AAA — chevron trigger must clear 44×44 in\n BOTH dimensions. Without min-width, the trigger collapses to its\n icon width (~38 px) and fails the brand-theme matrix audit. */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n /* lg */\n .split-button--lg .split-button__primary {\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 .split-button--lg .split-button__trigger {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Variant: primary ─── */\n\n /* Primary resting — bind through action.primary.bg (resolves to primary-600\n across all 6 brands) coordinated with text.on-primary. Inline fallback\n #0d1825 matches text.on-primary's resolved primitive (neutral-900) so a\n cold-start without semantic tokens paints AA-tuned dark-on-teal (5.20:1)\n rather than white-on-teal (3.43:1 fail). Mirrors hx-button precedent\n (hx-button.styles.ts ~line 88) and Phase C structural fix. */\n .split-button--primary .split-button__primary,\n .split-button--primary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-action-primary-bg, #429797);\n --hx-split-button-color: var(--hx-color-text-on-primary, #0d1825);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-900, #0b3232);\n }\n\n /* primary:hover — lift to action.primary.bg-hover (primary-700) with\n text.on-primary-strong (neutral-0). Replaces the universal brightness(0.9)\n filter which would degrade contrast on the resting pair. */\n .split-button--primary .split-button__primary:hover,\n .split-button--primary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-action-primary-bg-hover, #0f7078);\n --hx-split-button-color: var(--hx-color-text-on-primary-strong, #ffffff);\n filter: none;\n }\n\n /* ─── Variant: secondary ─── */\n\n .split-button--secondary .split-button__primary,\n .split-button--secondary .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #429797);\n --hx-split-button-border-color: var(--hx-color-primary-500, #429797);\n --hx-split-button-divider-color: var(--hx-color-primary-300, #97cdcc);\n }\n\n .split-button--secondary .split-button__primary:hover,\n .split-button--secondary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-primary-50, #ebf8f8);\n filter: none;\n }\n\n /* ─── Variant: tertiary ─── */\n\n .split-button--tertiary .split-button__primary,\n .split-button--tertiary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-surface-sunken, #ebeee9);\n --hx-split-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-border-default, #d6dbd5);\n }\n\n .split-button--tertiary .split-button__primary:hover,\n .split-button--tertiary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n filter: none;\n }\n\n /* ─── Variant: danger ─── */\n\n .split-button--danger .split-button__primary,\n .split-button--danger .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-error-500, #e5493e);\n --hx-split-button-color: var(--hx-color-text-on-error, #ffffff);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-error-400, #fc7264);\n }\n\n /* danger:hover — on-error tokens are tuned for error-500. error-600 drops\n the pair to 2.25:1 (AA fail). Pin fg at neutral-0 to keep the darker\n hover fill legible. Mirrors hx-toast precedent (commit 300e21ab0). */\n .split-button--danger .split-button__primary:hover,\n .split-button--danger .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-error-600, #c92a2a);\n --hx-split-button-color: var(--hx-color-neutral-0, #ffffff);\n filter: none;\n }\n\n /* ─── Variant: ghost ─── */\n\n .split-button--ghost .split-button__primary,\n .split-button--ghost .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #429797);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-200, #bce1e1);\n }\n\n .split-button--ghost .split-button__primary:hover,\n .split-button--ghost .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n filter: none;\n }\n\n /* ─── Variant: outline ─── */\n\n .split-button--outline .split-button__primary,\n .split-button--outline .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-text-primary, #0d1825);\n --hx-split-button-border-color: var(--hx-color-border-strong, #66787b);\n --hx-split-button-divider-color: var(--hx-color-border-default, #d6dbd5);\n }\n\n .split-button--outline .split-button__primary:hover,\n .split-button--outline .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-surface-raised, #f5f8f3);\n filter: none;\n }\n\n /* ─── Dropdown Menu Panel ─── */\n\n @keyframes hx-split-button-menu-open {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .split-button__menu {\n display: none;\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n inset-inline-end: 0;\n min-width: 100%;\n max-height: var(--hx-split-button-menu-max-height, 18rem);\n overflow-y: auto;\n background-color: var(--hx-split-button-menu-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-menu-border-color, var(--hx-color-border-default, #d6dbd5));\n border-radius: var(--hx-split-button-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-split-button-menu-shadow,\n 0 4px 6px -1px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1)),\n 0 2px 4px -2px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1))\n );\n padding: var(--hx-space-1, 0.25rem);\n z-index: var(--hx-z-index-dropdown, 1000);\n }\n\n .split-button__menu--open {\n display: block;\n animation: hx-split-button-menu-open var(--hx-transition-fast, 150ms ease);\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .split-button__primary,\n .split-button__trigger,\n .split-button__chevron {\n transition: none;\n }\n\n .split-button__menu--open {\n animation: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .split-button__primary,\n .split-button__trigger {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n .split-button__primary:focus-visible,\n .split-button__trigger:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .split-button__primary[disabled],\n .split-button__trigger[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 .split-button__menu {\n background-color: Canvas;\n border: 2px solid CanvasText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport '../hx-icon/hx-icon.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixSplitButtonStyles } from './hx-split-button.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport type { HelixMenuItem } from '../hx-menu/hx-menu-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport { getMenuItemTypeaheadLabel } from '../../utils/menu-label.js';\nimport { findClosestMenuAncestor } from '../../utils/menu-tree.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\nconst _nextSplitButtonId = createIdCounter('hx-split-button');\n\n/**\n * A split button combining a primary action button with an attached dropdown\n * menu for secondary actions. Implements the ARIA menu button pattern for\n * full keyboard and screen reader support.\n *\n * ## Architecture Note: Composite host with two interactive children (Group 5b)\n *\n * The host wraps a primary `<button>`, a dropdown trigger `<button>`, and a\n * panel `<div role=\"menu\">` — three ARIA-bearing surfaces that cannot all\n * collapse onto the host. Group 5b keeps role placement on the inner\n * elements (consistent with `hx-overflow-menu`). The host carries no role.\n *\n * What Group 5b adds:\n * - **Host-attribute label mirror** via `installAriaIdrefMirror`: consumer\n * `aria-label` / `aria-labelledby` on the host flow to the inner primary\n * button's `aria-label`. Replaces the legacy `accessible-label` shim,\n * which was a workaround for ARIAMixin shadowing on the host. The shim\n * is preserved with a one-time devWarn for one minor version of back-\n * compat; new code should use the standard `aria-label` attribute.\n * - **Roving tabindex** on slotted `hx-menu-item` children inside the\n * panel. Only the focused item carries `tabindex=0`; arrow key\n * navigation rewrites the tabindex map via `_applyRovingTabIndex()`.\n * `setRovingTabIndex` is the same setter used by `hx-menu` for cross-\n * family pattern alignment.\n * - **First-character typeahead** with 500ms timeout matching `hx-menu`.\n *\n * @summary Primary action button with attached dropdown menu for secondary actions.\n *\n * @tag hx-split-button\n *\n * @slot - Primary button label text.\n * @slot menu - `hx-menu-item` children rendered in the dropdown panel.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the primary button is clicked and is not disabled.\n * @fires {CustomEvent<{value: string; label: string}>} hx-select - Dispatched when\n * a menu item is selected from the dropdown.\n *\n * @csspart button - The primary action button element.\n * @csspart trigger - The dropdown trigger button element.\n * @csspart menu - The dropdown menu panel.\n *\n * @cssprop [--hx-split-button-menu-max-height=18rem] - Maximum height of the dropdown menu panel before scrolling.\n * @cssprop [--hx-split-button-bg=var(--hx-color-primary-500)] - Background color for both buttons.\n * @cssprop [--hx-split-button-color=var(--hx-color-neutral-0)] - Text/icon color for both buttons.\n * @cssprop [--hx-split-button-border-color=transparent] - Border color.\n * @cssprop [--hx-split-button-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-split-button-divider-color=var(--hx-color-primary-900)] - Color of the divider between primary and trigger.\n * @cssprop [--hx-split-button-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-split-button-font-weight=var(--hx-font-weight-semibold)] - Font weight.\n * @cssprop [--hx-split-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-split-button-menu-bg=var(--hx-color-neutral-0)] - Dropdown menu background.\n * @cssprop [--hx-split-button-menu-border-color=var(--hx-color-neutral-200)] - Dropdown menu border color.\n * @cssprop [--hx-split-button-menu-border-radius=var(--hx-border-radius-md)] - Dropdown menu border radius.\n * @cssprop [--hx-split-button-menu-shadow] - Dropdown menu box shadow.\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-space-1] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-size-8] - Size token.\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-300] - Color.\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-300] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-error-400] - Color.\n * @cssprop [--hx-color-error-600] - Color.\n * @cssprop [--hx-color-primary-200] - Color.\n * @cssprop [--hx-color-neutral-50] - Color.\n * @cssprop [--hx-overlay-black-10] - Overlay color.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @aaa-certified 2026-05-08\n * @aaa-criteria 1.4.6, 1.4.9, 2.1.3, 2.3.3, 2.4.12, 2.4.13, 2.5.5, 3.2.5, 3.3.6, forced-colors, apg-keyboard\n * @aaa-audit src/components/hx-split-button/AAA-AUDIT.md\n * @keyboard-contract activate=Enter,Space; disabled-suppresses=true\n * @aria-pattern button\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/button/\n * @forced-colors-supported true\n * @stability stable\n * @since 3.7.0\n * @form-associated false\n * @theme-aware true\n * @brand-aware true\n * @drupal-sdc-eligible true\n * @react-wrapper-status complete\n * @figma-component-name hx-split-button\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-split-button')\nexport class HelixSplitButton extends HelixElement {\n static override styles = [helixSplitButtonStyles, forcedColorsInteractive];\n\n // ─── Internal References ───\n\n /**\n * Reference to the dropdown menu panel element, used for positioning and focus management.\n * @internal\n */\n @query('.split-button__menu')\n private _menuPanel: HTMLElement | undefined;\n\n /**\n * Reference to the dropdown trigger button element, used to return focus after menu closes.\n * @internal\n */\n @query('.split-button__trigger')\n private _triggerButton: HTMLButtonElement | undefined;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether the dropdown menu is currently open.\n * @internal\n */\n @state() private _open = false;\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant of the split button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';\n\n /**\n * Size of the split 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 split button is disabled. Both the primary button and the\n * trigger are disabled when this is true.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Primary button label text. When set, overrides the default slot content.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * @deprecated Use the standard host `aria-label` attribute instead. Group\n * 5b replaces the `accessible-label` shim with a host-attribute mirror\n * driven by `installAriaIdrefMirror` — consumer host `aria-label` /\n * `aria-labelledby` flow to the inner primary button's `aria-label`,\n * which is the same composed-tree result as the legacy shim without\n * the ARIAMixin shadowing concern.\n *\n * The attribute remains observed for one minor version so existing\n * consumers do not regress; setting it logs a devWarn pointing them to\n * the standard `aria-label` path.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel = '';\n\n /**\n * Accessible label for the dropdown trigger button. Override for localization.\n * @attr label-trigger\n */\n @property({ type: String, attribute: 'label-trigger' })\n labelTrigger = 'More actions';\n\n /**\n * Accessible label for the dropdown menu panel. Override for localization.\n * @attr label-menu\n */\n @property({ type: String, attribute: 'label-menu' })\n labelMenu = 'Secondary actions';\n\n // ─── Unique IDs ───\n\n /**\n * Stable unique ID for the dropdown menu panel element, used to wire aria-controls on the trigger button.\n * @internal\n */\n private readonly _menuId = `${_nextSplitButtonId()}-menu`;\n\n // ─── Host-attribute label mirror state ───\n\n /**\n * Resolved accessible name for the primary action button — written to\n * the inner primary button's `aria-label` on render. AccName 1.2 §4.3.1\n * precedence: host `aria-labelledby` (resolved IDREFs, flattened) >\n * host `aria-label` > deprecated `accessible-label` (with devWarn) >\n * `label` property > slotted text content (no aria-label set when this\n * branch is taken so AT walks the inner content for the name).\n * @internal\n */\n @state() private _resolvedPrimaryLabel: string | null = null;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n // ─── Roving tabindex + typeahead state ───\n\n /** @internal */\n private _rovingIndex = -1;\n\n /** @internal */\n private _typeaheadBuffer = '';\n\n /** @internal */\n private _typeaheadTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('click', this._handleOutsideClick);\n document.addEventListener('keydown', this._handleDocumentKeydown);\n this._syncResolvedPrimaryLabel();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncResolvedPrimaryLabel();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this._handleOutsideClick);\n document.removeEventListener('keydown', this._handleDocumentKeydown);\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = null;\n }\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n if (changedProperties.has('label') || changedProperties.has('accessibleLabel')) {\n this._syncResolvedPrimaryLabel();\n }\n }\n\n /**\n * Resolve the primary button's accessible name from host attributes\n * and (deprecated) properties. See `_resolvedPrimaryLabel` jsdoc for\n * precedence rules.\n * @internal\n */\n private _syncResolvedPrimaryLabel(): void {\n const liveLabelledBy = this.getAttribute('aria-labelledby');\n const consumerLabelEls = resolveIdrefTokens(this, liveLabelledBy);\n\n // CodeRabbit MUST-FIX: AccName 1.2 §4.3.2 — `aria-labelledby` references\n // their target text content REGARDLESS of visibility. The previous\n // outer visibility filter dropped legitimate accessible names from\n // visually-hidden labels. `flattenAccName` already handles aria-hidden\n // subtree pruning per §4.3.10.\n const flattenedFromIdrefs = consumerLabelEls\n .map((el) => flattenAccName(el))\n .filter((t) => t.length > 0)\n .join(' ')\n .replace(/\\s+/g, ' ')\n .trim();\n\n const liveAriaLabel = this.getAttribute('aria-label');\n const hostAriaLabel = liveAriaLabel !== null ? liveAriaLabel.trim() : '';\n\n let resolved: string | null = null;\n if (flattenedFromIdrefs) {\n resolved = flattenedFromIdrefs;\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n } else if (this.accessibleLabel) {\n // Deprecated path — emit a one-time devWarn pointing consumers at\n // the standard aria-label flow.\n if (!this._deprecatedAccessibleLabelWarned) {\n this._deprecatedAccessibleLabelWarned = true;\n devWarn(\n 'hx-split-button',\n '`accessible-label` is deprecated; use the standard `aria-label` attribute on hx-split-button instead. The shim continues to work in this minor version but will be removed in a future release.',\n );\n }\n resolved = this.accessibleLabel;\n } else if (this.label) {\n resolved = this.label;\n } else {\n // No explicit name supplied — leave aria-label off the primary\n // button so AT walks the slotted content for the accessible name.\n resolved = null;\n }\n\n this._resolvedPrimaryLabel = resolved;\n }\n\n /** @internal */\n private _deprecatedAccessibleLabelWarned = false;\n\n // ─── Outside-click / document keydown ───\n\n /** @internal */\n private readonly _handleOutsideClick = (e: MouseEvent): void => {\n if (!this._open) return;\n const target = e.target as Node;\n if (!this.contains(target) && target !== this) {\n this._closeMenu();\n }\n };\n\n /** @internal */\n private readonly _handleDocumentKeydown = (e: KeyboardEvent): void => {\n if (!this._open) return;\n if (e.key === 'Tab') {\n this._closeMenu();\n }\n };\n\n // ─── Primary Button Handlers ───\n\n /** @internal */\n private _handlePrimaryClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n /**\n * Dispatched when the primary button is clicked.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n }\n\n /** @internal */\n private _handlePrimaryKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Trigger Button Handlers ───\n\n /** @internal */\n private _handleTriggerClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n // Stop propagation so _handleOutsideClick does not immediately close.\n e.stopPropagation();\n this._toggleMenu();\n }\n\n /** @internal */\n private _handleTriggerKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Menu Key Navigation ───\n\n /** @internal */\n private _handleMenuKeydown(e: KeyboardEvent): void {\n const items = this._getMenuItems();\n if (items.length === 0) return;\n\n // document.activeElement returns the hx-menu-item host element when\n // host-canonical (post-Group-5b) — matches items[] directly. On the\n // legacy fallback path, focus delegates to the inner div but\n // document.activeElement still resolves to the host so the same\n // index works.\n const currentIndex = items.findIndex((item) => item === document.activeElement);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._focusMenuItem(items, next);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._focusMenuItem(items, prev);\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._closeMenu();\n this._triggerButton?.focus();\n break;\n }\n case 'Home': {\n e.preventDefault();\n this._focusMenuItem(items, 0);\n break;\n }\n case 'End': {\n e.preventDefault();\n this._focusMenuItem(items, items.length - 1);\n break;\n }\n default: {\n if (e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n this._handleTypeahead(e.key, items);\n }\n break;\n }\n }\n }\n\n /** @internal */\n private _focusMenuItem(items: HelixMenuItem[], index: number): void {\n this._rovingIndex = index;\n this._applyRovingTabIndex(items);\n items[index]?.focus();\n }\n\n /**\n * Roving tabindex: only the focused item carries tabindex=0; the rest\n * are tabindex=-1. Tab from the panel exits the menu via document\n * keydown (line ~_handleDocumentKeydown), so the closing-Tab path\n * remains correct.\n * @internal\n */\n private _applyRovingTabIndex(items: HelixMenuItem[]): void {\n items.forEach((item, i) => {\n item.setRovingTabIndex(i === this._rovingIndex ? 0 : -1);\n });\n }\n\n /** @internal */\n private _handleTypeahead(char: string, items: HelixMenuItem[]): void {\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n }\n this._typeaheadBuffer += char.toLowerCase();\n this._typeaheadTimer = setTimeout(() => {\n this._typeaheadBuffer = '';\n this._typeaheadTimer = null;\n }, 500);\n\n // Codex push-gate round-7 finding 3: shared submenu-aware label\n // extractor — see hx-menu / hx-dropdown for rationale.\n const match = items.findIndex((item) => {\n const text = getMenuItemTypeaheadLabel(item).toLowerCase();\n return text.startsWith(this._typeaheadBuffer);\n });\n\n if (match !== -1) {\n this._focusMenuItem(items, match);\n }\n }\n\n // ─── Menu Item Selection ───\n\n /** @internal */\n private _handleMenuItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const custom = e as CustomEvent<{ item: HelixMenuItem; value: string }>;\n this._closeMenu();\n this._triggerButton?.focus();\n\n const item = custom.detail.item;\n const label = item?.textContent?.trim() ?? '';\n\n /**\n * Dispatched when a menu item is selected.\n * @event hx-select\n */\n this.dispatchEvent(\n new CustomEvent<{ value: string; label: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { value: custom.detail.value, label },\n }),\n );\n }\n\n /**\n * Bubbled `hx-item-submenu-open` from a slotted `hx-menu-item` host.\n * Codex push-gate round-9 P1: when slotted `hx-menu-item`s open / close\n * a nested submenu inside this menu panel (no enclosing `hx-menu`), the\n * events fly past with no handler. Match the round-4\n * `hx-menu._handleSubmenuOpen` shape so APG behaviour holds. Defer to\n * an inner `hx-menu` when present (it owns the toggle). Otherwise this\n * panel is the enclosing menu surface — call `setSubmenuOpen(true)` on\n * the dispatching item and focus its first nested child.\n * @internal\n */\n private _handleMenuSubmenuOpen = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem }>).detail;\n const item = detail?.item;\n if (!item) return;\n if (findClosestMenuAncestor(item) !== null) return;\n queueMicrotask(() => {\n if (e.defaultPrevented) return;\n item.setSubmenuOpen(true);\n void item.updateComplete\n .then(() => {\n const submenuSlot =\n item.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"submenu\"]');\n const nested = submenuSlot\n ?.assignedElements({ flatten: true })\n .find((el) => el.tagName.toLowerCase() === 'hx-menu') as\n | (HTMLElement & { focusFirst?: () => void })\n | undefined;\n nested?.focusFirst?.();\n })\n .catch(() => undefined);\n });\n };\n\n /**\n * Bubbled `hx-item-submenu-close` from a slotted `hx-menu-item` host.\n * Codex push-gate round-9 P1: when an inner `hx-menu` (a nested\n * submenu) handles its own close, the event still bubbles through this\n * panel — defer in that case so the panel stays open. When the\n * dispatching item is top-level inside this panel (no enclosing\n * `hx-menu`), there is no parent submenu to collapse, so close the\n * composite's menu and return focus to the trigger button.\n * @internal\n */\n private _handleMenuSubmenuClose = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem }>).detail;\n const item = detail?.item;\n if (!item) return;\n if (findClosestMenuAncestor(item) !== null) return;\n if (e.defaultPrevented) return;\n this._closeMenu();\n this._triggerButton?.focus();\n };\n\n // ─── Menu Helpers ───\n\n /** @internal */\n private _openMenu(): void {\n if (this._open) return;\n this._open = true;\n // Focus the first enabled menu item after the panel renders;\n // initialize roving tabindex so Tab from outside lands on the same\n // item that has visual focus.\n void this.updateComplete\n .then(() => {\n const items = this._getMenuItems();\n this._rovingIndex = items.length > 0 ? 0 : -1;\n this._applyRovingTabIndex(items);\n items[0]?.focus();\n })\n .catch(() => undefined);\n }\n\n /** @internal */\n private _closeMenu(): void {\n this._open = false;\n }\n\n /** @internal */\n private _toggleMenu(): void {\n if (this._open) {\n this._closeMenu();\n } else {\n this._openMenu();\n }\n }\n\n /**\n * Returns the enabled hx-menu-item host elements assigned to the `menu` slot.\n * HelixMenuItem overrides focus() to delegate to its inner element, so calling\n * .focus() on hosts works correctly. document.activeElement returns the host\n * element when the inner shadow element has focus, enabling correct index tracking.\n */\n /** @internal */\n private _getMenuItems(): HelixMenuItem[] {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"menu\"]');\n if (!slot) return [];\n\n return slot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HelixMenuItem =>\n el.tagName.toLowerCase() === 'hx-menu-item' && !(el as HelixMenuItem).disabled,\n );\n }\n\n // ─── Render ───\n\n override render() {\n const containerClasses = {\n 'split-button': true,\n [`split-button--${this.variant}`]: true,\n [`split-button--${this.size}`]: true,\n };\n\n const menuClasses = {\n 'split-button__menu': true,\n 'split-button__menu--open': this._open,\n };\n\n const chevronClasses = {\n 'split-button__chevron': true,\n 'split-button__chevron--open': this._open,\n };\n\n return html`\n <div class=${classMap(containerClasses)}>\n <!-- Primary action button -->\n <button\n part=\"button\"\n class=\"split-button__primary\"\n ?disabled=${this.disabled}\n type=\"button\"\n aria-label=${this._resolvedPrimaryLabel ?? nothing}\n @click=${this._handlePrimaryClick}\n @keydown=${this._handlePrimaryKeydown}\n >\n ${this.label !== undefined ? this.label : html`<slot></slot>`}\n </button>\n\n <!-- Dropdown trigger button -->\n <button\n part=\"trigger\"\n class=\"split-button__trigger\"\n ?disabled=${this.disabled}\n aria-haspopup=\"menu\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._menuId}\n aria-label=${this.labelTrigger}\n type=\"button\"\n @click=${this._handleTriggerClick}\n @keydown=${this._handleTriggerKeydown}\n >\n <span class=${classMap(chevronClasses)} aria-hidden=\"true\">\n <hx-icon\n class=\"split-button__chevron-glyph\"\n library=\"helix\"\n name=\"chevron-down\"\n aria-hidden=\"true\"\n ></hx-icon>\n </span>\n </button>\n\n <!-- Dropdown menu panel -->\n <div\n part=\"menu\"\n id=${this._menuId}\n class=${classMap(menuClasses)}\n role=\"menu\"\n aria-label=${this.labelMenu}\n @keydown=${this._handleMenuKeydown}\n @hx-item-select=${this._handleMenuItemSelect}\n @hx-item-submenu-open=${this._handleMenuSubmenuOpen}\n @hx-item-submenu-close=${this._handleMenuSubmenuClose}\n >\n <slot name=\"menu\"></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-split-button': HelixSplitButton;\n }\n}\n"],"names":["helixSplitButtonStyles","css","_nextSplitButtonId","createIdCounter","HelixSplitButton","HelixElement","e","target","detail","item","findClosestMenuAncestor","submenuSlot","_a","nested","el","_b","installAriaIdrefMirror","changedProperties","liveLabelledBy","flattenedFromIdrefs","resolveIdrefTokens","flattenAccName","t","liveAriaLabel","hostAriaLabel","resolved","items","currentIndex","next","prev","index","i","char","match","getMenuItemTypeaheadLabel","custom","label","slot","containerClasses","menuClasses","chevronClasses","html","classMap","nothing","forcedColorsInteractive","__decorateClass","query","state","property","customElement"],"mappings":";;;;;;;;;AAEO,MAAMA,IAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { css as v, html as
|
|
1
|
+
import { css as v, html as c, nothing as p } from "lit";
|
|
2
2
|
import { property as h, state as _, customElement as m } from "lit/decorators.js";
|
|
3
3
|
import { classMap as x } from "lit/directives/class-map.js";
|
|
4
4
|
import { a as b } from "./forced-colors-CTEDFRGa.js";
|
|
5
|
-
import { s as g, i as
|
|
5
|
+
import { s as g, i as y, r as w } from "./aria-idref-DCuEaknC.js";
|
|
6
6
|
import { f as z } from "./aria-flatten-DY6v2vah.js";
|
|
7
7
|
import { H as I } from "./helix-element-BNEYeiys.js";
|
|
8
8
|
const $ = v`
|
|
@@ -101,8 +101,7 @@ const $ = v`
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
.stat__trend-arrow {
|
|
104
|
-
|
|
105
|
-
height: 0.75em;
|
|
104
|
+
--hx-icon-size: 0.75em;
|
|
106
105
|
flex-shrink: 0;
|
|
107
106
|
}
|
|
108
107
|
|
|
@@ -159,10 +158,10 @@ const $ = v`
|
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
160
|
`;
|
|
162
|
-
var S = Object.defineProperty,
|
|
163
|
-
for (var
|
|
164
|
-
(l = t[o]) && (
|
|
165
|
-
return r &&
|
|
161
|
+
var S = Object.defineProperty, T = Object.getOwnPropertyDescriptor, n = (t, e, s, r) => {
|
|
162
|
+
for (var a = r > 1 ? void 0 : r ? T(e, s) : e, o = t.length - 1, l; o >= 0; o--)
|
|
163
|
+
(l = t[o]) && (a = (r ? l(e, s, a) : l(a)) || a);
|
|
164
|
+
return r && a && S(e, s, a), a;
|
|
166
165
|
};
|
|
167
166
|
let i = class extends I {
|
|
168
167
|
constructor() {
|
|
@@ -174,7 +173,7 @@ let i = class extends I {
|
|
|
174
173
|
const t = this.getAttribute("size");
|
|
175
174
|
t !== null && !this.hasAttribute("hx-size") && (this.size = t);
|
|
176
175
|
const e = this.constructor;
|
|
177
|
-
this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : g(this._internals), this._syncHostAriaSemantics(), this._ariaMirror =
|
|
176
|
+
this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : g(this._internals), this._syncHostAriaSemantics(), this._ariaMirror = y(this, () => {
|
|
178
177
|
this._syncHostAriaSemantics();
|
|
179
178
|
});
|
|
180
179
|
}
|
|
@@ -184,8 +183,8 @@ let i = class extends I {
|
|
|
184
183
|
}
|
|
185
184
|
updated(t) {
|
|
186
185
|
super.updated(t);
|
|
187
|
-
const e = t.has("value") || t.has("label"),
|
|
188
|
-
e && !
|
|
186
|
+
const e = t.has("value") || t.has("label"), s = this.value.trim().length > 0, r = this.label.trim().length > 0;
|
|
187
|
+
e && !s && !r && !this._hasWarnedUnnamed && (this._hasWarnedUnnamed = !0), (s || r) && (this._hasWarnedUnnamed = !1), (t.has("value") || t.has("label") || t.has("trend") || t.has("labelTrend")) && this._syncHostAriaSemantics();
|
|
189
188
|
}
|
|
190
189
|
/**
|
|
191
190
|
* Mirror group semantics onto the host. The default group label is
|
|
@@ -195,16 +194,16 @@ let i = class extends I {
|
|
|
195
194
|
* @internal
|
|
196
195
|
*/
|
|
197
196
|
_syncHostAriaSemantics() {
|
|
198
|
-
var
|
|
197
|
+
var d;
|
|
199
198
|
const t = this._internals, e = this.value && this.label ? `${this.value}: ${this.label}` : this.value || this.label || "";
|
|
200
199
|
this._supportsIdrefRefs ? t.role = "group" : (t.role = null, t.ariaLabel = null);
|
|
201
|
-
const
|
|
200
|
+
const s = ((d = this.getAttribute("aria-label")) == null ? void 0 : d.trim()) || "", r = this.getAttribute("aria-labelledby"), a = w(this, r), o = a.length > 0;
|
|
202
201
|
if (this._supportsIdrefRefs) {
|
|
203
202
|
const f = t;
|
|
204
|
-
f.ariaLabelledByElements = o ?
|
|
203
|
+
f.ariaLabelledByElements = o ? a : null;
|
|
205
204
|
}
|
|
206
205
|
let l = "";
|
|
207
|
-
o ? (l =
|
|
206
|
+
o ? (l = a.map((u) => z(u)).filter(Boolean).join(" ") || s || e, this._supportsIdrefRefs && (t.ariaLabel = null)) : s ? (l = s, this._supportsIdrefRefs && (t.ariaLabel = s)) : e ? (l = e, this._supportsIdrefRefs && (t.ariaLabel = e)) : (l = "", this._supportsIdrefRefs && (t.ariaLabel = null)), this._resolvedAccessibleName !== l && (this._resolvedAccessibleName = l, this._supportsIdrefRefs || this.requestUpdate());
|
|
208
207
|
}
|
|
209
208
|
/** @internal */
|
|
210
209
|
_onIconSlotChange(t) {
|
|
@@ -214,54 +213,22 @@ let i = class extends I {
|
|
|
214
213
|
// ─── Render Helpers ───
|
|
215
214
|
/** @internal */
|
|
216
215
|
_renderTrendArrow(t) {
|
|
217
|
-
return t === "up" ?
|
|
218
|
-
<svg
|
|
219
|
-
class="stat__trend-arrow"
|
|
220
|
-
aria-hidden="true"
|
|
221
|
-
viewBox="0 0 12 12"
|
|
222
|
-
fill="none"
|
|
223
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
224
|
-
>
|
|
225
|
-
<path
|
|
226
|
-
d="M6 10V2M6 2L2 6M6 2L10 6"
|
|
227
|
-
stroke="currentColor"
|
|
228
|
-
stroke-width="1.5"
|
|
229
|
-
stroke-linecap="round"
|
|
230
|
-
stroke-linejoin="round"
|
|
231
|
-
/>
|
|
232
|
-
</svg>
|
|
233
|
-
` : d`
|
|
234
|
-
<svg
|
|
235
|
-
class="stat__trend-arrow"
|
|
236
|
-
aria-hidden="true"
|
|
237
|
-
viewBox="0 0 12 12"
|
|
238
|
-
fill="none"
|
|
239
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
240
|
-
>
|
|
241
|
-
<path
|
|
242
|
-
d="M6 2V10M6 10L2 6M6 10L10 6"
|
|
243
|
-
stroke="currentColor"
|
|
244
|
-
stroke-width="1.5"
|
|
245
|
-
stroke-linecap="round"
|
|
246
|
-
stroke-linejoin="round"
|
|
247
|
-
/>
|
|
248
|
-
</svg>
|
|
249
|
-
`;
|
|
216
|
+
return c` <hx-icon class="stat__trend-arrow" library="helix" name=${t === "up" ? "arrow-up" : "arrow-down"}></hx-icon> `;
|
|
250
217
|
}
|
|
251
218
|
// ─── Render ───
|
|
252
219
|
render() {
|
|
253
220
|
const t = {
|
|
254
221
|
stat: !0,
|
|
255
222
|
[`stat--${this.size}`]: !0
|
|
256
|
-
}, e = this.trend !== "neutral",
|
|
257
|
-
|
|
223
|
+
}, e = this.trend !== "neutral", s = this.value && this.label ? `${this.value}: ${this.label}` : this.value || this.label || p, r = [], a = this.label && this.value ? `${this.label}: ${this.value}` : this.value || this.label || "";
|
|
224
|
+
a && r.push(a), e && r.push(`${this.labelTrend}: ${this.trend}`);
|
|
258
225
|
const o = r.join(", ");
|
|
259
|
-
return
|
|
226
|
+
return c`
|
|
260
227
|
<div
|
|
261
228
|
part="container"
|
|
262
229
|
class=${x(t)}
|
|
263
230
|
role="group"
|
|
264
|
-
aria-label=${
|
|
231
|
+
aria-label=${s}
|
|
265
232
|
>
|
|
266
233
|
<span class="stat__live-region" aria-live="polite" aria-atomic="true">${o}</span>
|
|
267
234
|
<div part="header" class="stat__header">
|
|
@@ -269,7 +236,7 @@ let i = class extends I {
|
|
|
269
236
|
<slot name="icon" @slotchange=${this._onIconSlotChange}></slot>
|
|
270
237
|
</span>
|
|
271
238
|
<span part="value" class="stat__value" aria-hidden="true">${this.value}</span>
|
|
272
|
-
${e ?
|
|
239
|
+
${e ? c`
|
|
273
240
|
<span
|
|
274
241
|
part="trend"
|
|
275
242
|
class="stat__trend stat__trend--${this.trend}"
|
|
@@ -278,7 +245,7 @@ let i = class extends I {
|
|
|
278
245
|
>
|
|
279
246
|
${this._renderTrendArrow(this.trend)}
|
|
280
247
|
</span>
|
|
281
|
-
` :
|
|
248
|
+
` : p}
|
|
282
249
|
</div>
|
|
283
250
|
<span part="label" class="stat__label" aria-hidden="true">${this.label}</span>
|
|
284
251
|
</div>
|
|
@@ -311,4 +278,4 @@ i = n([
|
|
|
311
278
|
export {
|
|
312
279
|
i as H
|
|
313
280
|
};
|
|
314
|
-
//# sourceMappingURL=hx-stat-
|
|
281
|
+
//# sourceMappingURL=hx-stat-wKxbyep6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-stat-wKxbyep6.js","sources":["../../src/components/hx-stat/hx-stat.styles.ts","../../src/components/hx-stat/hx-stat.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixStatStyles = css`\n :host {\n display: block;\n }\n\n .stat {\n display: flex;\n flex-direction: column;\n gap: var(--hx-stat-gap, var(--hx-space-1, 0.25rem));\n font-family: var(--hx-stat-font-family, var(--hx-font-family-sans, sans-serif));\n color: var(--hx-stat-color, var(--hx-color-text-strong, #202b39));\n }\n\n /* ─── Size Variants ─── */\n\n .stat--sm .stat__value {\n font-size: var(--hx-stat-value-font-size-sm, var(--hx-font-size-xl, 1.25rem));\n line-height: var(--hx-line-height-tight, 1.25);\n font-weight: var(--hx-stat-value-font-weight, var(--hx-font-weight-bold, 700));\n }\n\n .stat--sm .stat__label {\n font-size: var(--hx-stat-label-font-size-sm, var(--hx-font-size-xs, 0.75rem));\n }\n\n .stat--md .stat__value {\n font-size: var(--hx-stat-value-font-size-md, var(--hx-font-size-3xl, 1.875rem));\n line-height: var(--hx-line-height-tight, 1.25);\n font-weight: var(--hx-stat-value-font-weight, var(--hx-font-weight-bold, 700));\n }\n\n .stat--md .stat__label {\n font-size: var(--hx-stat-label-font-size-md, var(--hx-font-size-sm, 0.875rem));\n }\n\n .stat--lg .stat__value {\n font-size: var(--hx-stat-value-font-size-lg, var(--hx-font-size-5xl, 3rem));\n line-height: var(--hx-line-height-tight, 1.25);\n font-weight: var(--hx-stat-value-font-weight, var(--hx-font-weight-bold, 700));\n }\n\n .stat--lg .stat__label {\n font-size: var(--hx-stat-label-font-size-lg, var(--hx-font-size-md, 1rem));\n }\n\n /* ─── Value ─── */\n\n .stat__header {\n display: flex;\n align-items: center;\n gap: var(--hx-stat-header-gap, var(--hx-space-2, 0.5rem));\n }\n\n .stat__value {\n color: var(--hx-stat-value-color, var(--hx-color-text-primary, #0d1825));\n }\n\n /* ─── Label ─── */\n\n .stat__label {\n color: var(--hx-stat-label-color, var(--hx-color-text-muted, #4a5362));\n font-weight: var(--hx-font-weight-normal, 400);\n }\n\n /* ─── Icon Slot ─── */\n\n .stat__icon {\n display: flex;\n align-items: center;\n color: var(--hx-stat-icon-color, var(--hx-color-primary-500, #429797));\n flex-shrink: 0;\n }\n\n /* ─── Trend Indicator ─── */\n\n .stat__trend {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n padding: var(--hx-space-0-5, 0.125rem) var(--hx-space-1-5, 0.375rem);\n }\n\n .stat__trend--up {\n color: var(--hx-stat-trend-up-color, var(--hx-color-success-700, #146831));\n background-color: var(--hx-stat-trend-up-bg, var(--hx-color-success-50, #eafaec));\n }\n\n .stat__trend--down {\n color: var(--hx-stat-trend-down-color, var(--hx-color-error-700, #a21312));\n background-color: var(--hx-stat-trend-down-bg, var(--hx-color-error-50, #fff2f0));\n }\n\n .stat__trend-arrow {\n --hx-icon-size: 0.75em;\n flex-shrink: 0;\n }\n\n /* ─── Hidden empty slot wrappers ─── */\n\n [hidden] {\n display: none !important;\n }\n\n /* ─── Visually-hidden live region ─── */\n\n .stat__live-region {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n }\n\n /* ─── Forced Colors (Windows High Contrast Mode) ─── */\n\n @media (forced-colors: active) {\n .stat__trend {\n forced-color-adjust: none;\n }\n\n .stat__value {\n color: CanvasText;\n }\n\n .stat__label {\n color: CanvasText;\n }\n\n .stat__icon {\n color: CanvasText;\n }\n\n .stat__trend--up {\n background: Highlight;\n color: HighlightText;\n border: 1px solid Highlight;\n }\n\n .stat__trend--down {\n background: ButtonText;\n color: ButtonFace;\n border: 1px solid ButtonText;\n }\n\n .stat__trend-arrow {\n color: currentColor;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport '../hx-icon/hx-icon.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixStatStyles } from './hx-stat.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\n\nexport type StatSize = 'sm' | 'md' | 'lg';\nexport type StatTrend = 'up' | 'down' | 'neutral';\n\n/**\n * A static stat display component for presenting key metrics in a healthcare dashboard.\n *\n * Group 7 host-canonical: `role=\"group\"` lives on the **host** via\n * `_internals.role`. The host carries the resolved accessible name so AT\n * walks `<hx-stat>` (role=group, label=\"value: label\") directly. The\n * internal `aria-live=\"polite\"` announcer remains in the shadow tree —\n * `role=\"group\"` does NOT imply a live region, so the announcer is required\n * for value/label/trend update announcements.\n *\n * @summary Displays a labeled metric value with optional trend indicator and icon slot.\n *\n * @tag hx-stat\n *\n * @slot icon - Optional icon displayed alongside the stat value.\n *\n * @csspart container - The outer stat container element.\n * @csspart header - The row containing the value and optional icon.\n * @csspart value - The stat value element.\n * @csspart label - The stat label element.\n * @csspart trend - The trend indicator element (only rendered when trend is not 'neutral').\n * @csspart icon - The icon slot container.\n *\n * @cssprop [--hx-stat-gap=var(--hx-space-1)] - Gap between value and label.\n * @cssprop [--hx-stat-header-gap=var(--hx-space-2)] - Gap between icon and value in the header row.\n * @cssprop [--hx-stat-color=var(--hx-color-neutral-800)] - Default text color.\n * @cssprop [--hx-stat-value-color=var(--hx-color-neutral-900)] - Value text color.\n * @cssprop [--hx-stat-label-color=var(--hx-color-neutral-500)] - Label text color.\n * @cssprop [--hx-stat-icon-color=var(--hx-color-primary-500)] - Icon color.\n * @cssprop [--hx-stat-value-font-weight=var(--hx-font-weight-bold)] - Value font weight.\n * @cssprop [--hx-stat-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-stat-value-font-size-sm=var(--hx-font-size-xl)] - Value font size at sm.\n * @cssprop [--hx-stat-value-font-size-md=var(--hx-font-size-3xl)] - Value font size at md.\n * @cssprop [--hx-stat-value-font-size-lg=var(--hx-font-size-5xl)] - Value font size at lg.\n * @cssprop [--hx-stat-label-font-size-sm=var(--hx-font-size-xs)] - Label font size at sm.\n * @cssprop [--hx-stat-label-font-size-md=var(--hx-font-size-sm)] - Label font size at md.\n * @cssprop [--hx-stat-label-font-size-lg=var(--hx-font-size-md)] - Label font size at lg.\n * @cssprop [--hx-stat-trend-up-color=var(--hx-color-success-700)] - Trend up text color.\n * @cssprop [--hx-stat-trend-up-bg=var(--hx-color-success-50)] - Trend up background color.\n * @cssprop [--hx-stat-trend-down-color=var(--hx-color-error-700)] - Trend down text color.\n * @cssprop [--hx-stat-trend-down-bg=var(--hx-color-error-50)] - Trend down background color.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-font-size-xl] - Font size.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-font-size-3xl] - Font size.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-size-5xl] - Font size.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-font-weight-normal] - Font weight.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-space-0-5] - Spacing token.\n * @cssprop [--hx-space-1-5] - Spacing token.\n * @cssprop [--hx-color-success-700] - Color.\n * @cssprop [--hx-color-success-50] - Color.\n * @cssprop [--hx-color-error-700] - Color.\n * @cssprop [--hx-color-error-50] - Color.\n */\n@customElement('hx-stat')\nexport class HelixStat extends HelixElement {\n static override styles = [helixStatStyles, forcedColorsSurface];\n\n /**\n * Test seam (Group 7 host-canonical migration): see other Group 7 components.\n * Production code MUST NOT touch this field.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n /**\n * The metric label displayed below the value.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * The metric value displayed prominently.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Trend direction indicator. 'neutral' hides the indicator.\n * @attr trend\n */\n @property({ type: String, reflect: true })\n trend: 'up' | 'down' | 'neutral' = 'neutral';\n\n /**\n * Size variant controlling font size.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Prefix label for trend indicator. Override for i18n.\n * @attr label-trend\n */\n @property({ attribute: 'label-trend' }) labelTrend = 'Trend';\n\n /** @internal tracks whether the \"unnamed\" devWarn has already fired this lifecycle */\n private _hasWarnedUnnamed = false;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /** @internal */\n private _resolvedAccessibleName = '';\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-stat', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize as StatSize;\n }\n\n const ctor = this.constructor as typeof HelixStat;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n this._syncHostAriaSemantics();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n const identityChanged = changedProperties.has('value') || changedProperties.has('label');\n const hasValue = this.value.trim().length > 0;\n const hasLabel = this.label.trim().length > 0;\n if (identityChanged && !hasValue && !hasLabel && !this._hasWarnedUnnamed) {\n this._hasWarnedUnnamed = true;\n devWarn(\n 'hx-stat',\n 'Rendering an unnamed hx-stat; provide at least value or label for screen reader accessibility.',\n );\n }\n if (hasValue || hasLabel) {\n this._hasWarnedUnnamed = false;\n }\n\n if (\n changedProperties.has('value') ||\n changedProperties.has('label') ||\n changedProperties.has('trend') ||\n changedProperties.has('labelTrend')\n ) {\n this._syncHostAriaSemantics();\n }\n }\n\n /**\n * Mirror group semantics onto the host. The default group label is\n * `${value}: ${label}` (matching the prior inner-div behaviour). Consumer\n * `aria-label` / `aria-labelledby` on the host take precedence per AccName\n * 1.2 §4.3.1.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n const groupLabel =\n this.value && this.label ? `${this.value}: ${this.label}` : this.value || this.label || '';\n\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n } else {\n internals.role = 'group';\n }\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const consumerLabelledBy = this.getAttribute('aria-labelledby');\n const labelEls = resolveIdrefTokens(this, consumerLabelledBy);\n const hasEffectiveLabelledBy = labelEls.length > 0;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n };\n\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithRefs;\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n }\n\n let resolved = '';\n if (hasEffectiveLabelledBy) {\n const flattened =\n labelEls\n .map((el) => flattenAccName(el))\n .filter(Boolean)\n .join(' ') ||\n hostAriaLabel ||\n groupLabel;\n resolved = flattened;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = hostAriaLabel;\n }\n } else if (groupLabel) {\n resolved = groupLabel;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = groupLabel;\n }\n } else {\n resolved = '';\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = null;\n }\n }\n\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n // ─── Slot Detection ───\n\n /** @internal */\n @state() private _hasIcon = false;\n\n /** @internal */\n private _onIconSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasIcon = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderTrendArrow(trend: 'up' | 'down'): ReturnType<typeof html> {\n const name = trend === 'up' ? 'arrow-up' : 'arrow-down';\n return html` <hx-icon class=\"stat__trend-arrow\" library=\"helix\" name=${name}></hx-icon> `;\n }\n\n // ─── Render ───\n\n override render() {\n const containerClasses = {\n stat: true,\n [`stat--${this.size}`]: true,\n };\n\n const hasTrend = this.trend !== 'neutral';\n\n // WCAG 1.3.1: wrap value and label in a group so screen readers announce them\n // together with a combined accessible name instead of as disconnected text runs.\n const groupLabel =\n this.value && this.label\n ? `${this.value}: ${this.label}`\n : this.value || this.label || nothing;\n\n // Live region text: announces value, label, and trend direction to screen\n // readers when any of those properties change programmatically.\n const liveParts: string[] = [];\n const primary =\n this.label && this.value ? `${this.label}: ${this.value}` : this.value || this.label || '';\n if (primary) liveParts.push(primary);\n if (hasTrend) liveParts.push(`${this.labelTrend}: ${this.trend}`);\n const liveText = liveParts.join(', ');\n\n // Dual-surface (Group 7 hx-progress-ring exemplar): inner div keeps\n // role=\"group\" + aria-label for legacy AT and consumer queries; host\n // adds the cross-shadow IDREF wiring via internals.* in\n // _syncHostAriaSemantics().\n return html`\n <div\n part=\"container\"\n class=${classMap(containerClasses)}\n role=\"group\"\n aria-label=${groupLabel}\n >\n <span class=\"stat__live-region\" aria-live=\"polite\" aria-atomic=\"true\">${liveText}</span>\n <div part=\"header\" class=\"stat__header\">\n <span part=\"icon\" class=\"stat__icon\" ?hidden=${!this._hasIcon}>\n <slot name=\"icon\" @slotchange=${this._onIconSlotChange}></slot>\n </span>\n <span part=\"value\" class=\"stat__value\" aria-hidden=\"true\">${this.value}</span>\n ${hasTrend\n ? html`\n <span\n part=\"trend\"\n class=\"stat__trend stat__trend--${this.trend}\"\n role=\"img\"\n aria-label=\"${this.labelTrend}: ${this.trend}\"\n >\n ${this._renderTrendArrow(this.trend as 'up' | 'down')}\n </span>\n `\n : nothing}\n </div>\n <span part=\"label\" class=\"stat__label\" aria-hidden=\"true\">${this.label}</span>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-stat': HelixStat;\n }\n}\n"],"names":["helixStatStyles","css","HelixStat","HelixElement","legacySize","ctor","supportsIdrefElementReferences","installAriaIdrefMirror","_a","changedProperties","identityChanged","hasValue","hasLabel","internals","groupLabel","hostAriaLabel","consumerLabelledBy","labelEls","resolveIdrefTokens","hasEffectiveLabelledBy","refsInternals","resolved","el","flattenAccName","e","slot","trend","html","containerClasses","hasTrend","nothing","liveParts","primary","liveText","classMap","forcedColorsSurface","__decorateClass","property","state","customElement"],"mappings":"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"}
|
|
@@ -214,9 +214,8 @@ const y = x`
|
|
|
214
214
|
z-index: 1;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
.step__indicator
|
|
218
|
-
|
|
219
|
-
height: var(--hx-steps-indicator-icon-size, 1rem);
|
|
217
|
+
.step__indicator .step__status-glyph {
|
|
218
|
+
--hx-icon-size: var(--hx-steps-indicator-icon-size, 1rem);
|
|
220
219
|
}
|
|
221
220
|
|
|
222
221
|
/* ─── Connector ─── */
|
|
@@ -446,33 +445,14 @@ let o = class extends u {
|
|
|
446
445
|
/** @internal */
|
|
447
446
|
_renderCheckmark() {
|
|
448
447
|
return d`
|
|
449
|
-
<
|
|
450
|
-
aria-hidden="true"
|
|
451
|
-
viewBox="0 0 24 24"
|
|
452
|
-
fill="none"
|
|
453
|
-
stroke="currentColor"
|
|
454
|
-
stroke-width="2.5"
|
|
455
|
-
stroke-linecap="round"
|
|
456
|
-
stroke-linejoin="round"
|
|
457
|
-
>
|
|
458
|
-
<path d="M20 6L9 17l-5-5" />
|
|
459
|
-
</svg>
|
|
448
|
+
<hx-icon class="step__status-glyph" library="helix" name="check" aria-hidden="true"></hx-icon>
|
|
460
449
|
<span class="sr-only">Complete</span>
|
|
461
450
|
`;
|
|
462
451
|
}
|
|
463
452
|
/** @internal */
|
|
464
453
|
_renderXMark() {
|
|
465
454
|
return d`
|
|
466
|
-
<
|
|
467
|
-
aria-hidden="true"
|
|
468
|
-
viewBox="0 0 24 24"
|
|
469
|
-
fill="none"
|
|
470
|
-
stroke="currentColor"
|
|
471
|
-
stroke-width="2.5"
|
|
472
|
-
stroke-linecap="round"
|
|
473
|
-
>
|
|
474
|
-
<path d="M18 6L6 18M6 6l12 12" />
|
|
475
|
-
</svg>
|
|
455
|
+
<hx-icon class="step__status-glyph" library="helix" name="close" aria-hidden="true"></hx-icon>
|
|
476
456
|
<span class="sr-only">Error</span>
|
|
477
457
|
`;
|
|
478
458
|
}
|
|
@@ -530,4 +510,4 @@ export {
|
|
|
530
510
|
o as H,
|
|
531
511
|
h as a
|
|
532
512
|
};
|
|
533
|
-
//# sourceMappingURL=hx-step-
|
|
513
|
+
//# sourceMappingURL=hx-step-CyGQAuiB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-step-CyGQAuiB.js","sources":["../../src/components/hx-steps/hx-steps.styles.ts","../../src/components/hx-steps/hx-steps.ts","../../src/components/hx-steps/hx-step.styles.ts","../../src/components/hx-steps/hx-step.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixStepsStyles = css`\n :host {\n display: block;\n\n /* ─── Size defaults (md) ─── */\n --hx-steps-indicator-size: var(--hx-size-8, 2rem);\n --hx-steps-indicator-font-size: var(--hx-font-size-sm, 0.875rem);\n --hx-steps-indicator-icon-size: var(--hx-size-4, 1rem);\n --hx-steps-label-font-size: var(--hx-font-size-sm, 0.875rem);\n --hx-steps-description-font-size: var(--hx-font-size-xs, 0.75rem);\n\n /* ─── Item layout defaults (horizontal) ─── */\n --hx-steps-item-flex: 1;\n --hx-steps-item-width: auto;\n }\n\n .steps {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n }\n\n /* ─── Orientation: vertical ─── */\n\n :host([orientation='vertical']) {\n --hx-steps-item-flex: initial;\n --hx-steps-item-width: 100%;\n }\n\n :host([orientation='vertical']) .steps {\n flex-direction: column;\n }\n\n /* ─── Size: sm ─── */\n\n :host([size='sm']) {\n --hx-steps-indicator-size: var(--hx-size-6, 1.5rem);\n --hx-steps-indicator-font-size: var(--hx-font-size-xs, 0.75rem);\n --hx-steps-indicator-icon-size: var(--hx-space-3, 0.75rem);\n --hx-steps-label-font-size: var(--hx-font-size-xs, 0.75rem);\n --hx-steps-description-font-size: var(--hx-font-size-xs, 0.75rem);\n }\n\n /* ─── Size: lg ─── */\n\n :host([size='lg']) {\n --hx-steps-indicator-size: var(--hx-size-10, 2.5rem);\n --hx-steps-indicator-font-size: var(--hx-font-size-md, 1rem);\n --hx-steps-indicator-icon-size: var(--hx-size-5, 1.25rem);\n --hx-steps-label-font-size: var(--hx-font-size-md, 1rem);\n --hx-steps-description-font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n /*\n * hx-steps is a layout container — forced-colors state is handled\n * by each hx-step child element's own forced-colors block.\n */\n @media (forced-colors: active) {\n :host {\n forced-color-adjust: auto;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixStepsStyles } from './hx-steps.styles.js';\nimport type { HelixStep } from './hx-step.js';\n\n/**\n * A multi-step wizard / stepper progress indicator. Renders a sequence of\n * `<hx-step>` children as a horizontal or vertical step tracker with connector\n * lines and status-based styling.\n *\n * Provide an `aria-label` on `<hx-steps>` to describe the step process for assistive technology.\n *\n * @summary Multi-step progress indicator container.\n *\n * @tag hx-steps\n *\n * @slot - Default slot for `<hx-step>` elements.\n *\n * @fires {CustomEvent<{step: HelixStep, index: number}>} hx-step-click - Dispatched when\n * a step is clicked. Detail contains the clicked `step` element and its zero-based `index`.\n *\n * @csspart base - The inner wrapper element.\n *\n * @cssprop [--hx-steps-indicator-size=2rem] - Step indicator circle diameter.\n * @cssprop [--hx-steps-connector-color=var(--hx-color-neutral-200)] - Connector line color.\n * @cssprop [--hx-steps-label-color=var(--hx-color-neutral-600)] - Step label text color.\n * @cssprop [--hx-steps-description-color=var(--hx-color-neutral-500)] - Step description color.\n * @cssprop [--hx-steps-indicator-font-size] - Font size for step indicator text.\n * @cssprop [--hx-steps-indicator-icon-size] - Icon size within step indicator.\n * @cssprop [--hx-steps-label-font-size] - Font size for step labels.\n * @cssprop [--hx-steps-description-font-size] - Font size for step description text.\n * @cssprop [--hx-steps-item-flex] - Flex grow/shrink value for step items.\n * @cssprop [--hx-steps-item-width] - Fixed width for step items.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-size-4] - Size token.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-size-6] - Size token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-size-5] - Size token.\n */\n@customElement('hx-steps')\nexport class HelixSteps extends HelixElement {\n static override styles = [helixStepsStyles, forcedColorsInteractive];\n\n // ─── Public Properties ───\n\n /**\n * Layout orientation of the steps.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Size variant of the steps.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Accessible label for the list. Forwarded to the inner list element.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because the\n * `accessible-label` attribute approach avoids the ARIAMixin property conflict\n * without requiring mixin overhead.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-steps', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize as 'sm' | 'md' | 'lg';\n }\n // STEPS-002: WCAG 2.1 SC 4.1.2 — the inner list must have an accessible name.\n // Warn developers when aria-label is missing so the list is not anonymous.\n if (!this.accessibleLabel) {\n devWarn(\n 'hx-steps',\n 'An \"aria-label\" attribute is required to provide an accessible name for the steps list (WCAG 2.1 SC 4.1.2).',\n );\n }\n // WCAG 4.1.2: suppress the host element's implicit ARIA role so only the\n // inner div[role=\"list\"] is announced. Mirrors the hx-action-bar pattern.\n // Without this, the consumer's aria-label attribute on the host causes dual\n // announcement — once for the host element and once for the inner list.\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'none');\n }\n this.addEventListener('hx-step-click-internal', this._handleStepClickInternal);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('hx-step-click-internal', this._handleStepClickInternal);\n }\n\n override firstUpdated(): void {\n this._syncChildren();\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('orientation') || changedProperties.has('size')) {\n this._syncChildren();\n }\n }\n\n // ─── Child Sync ───\n\n /** @internal */\n private _getSteps(): HelixStep[] {\n return Array.from(this.querySelectorAll(':scope > hx-step')) as HelixStep[];\n }\n\n /** @internal */\n private _syncChildren(): void {\n const steps = this._getSteps();\n steps.forEach((step, i) => {\n step.orientation = this.orientation;\n step.size = this.size;\n step.index = i;\n });\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleSlotChange = (): void => {\n this._syncChildren();\n };\n\n /** @internal */\n private _handleStepClickInternal = (e: Event): void => {\n e.stopPropagation();\n const steps = this._getSteps();\n const step = e\n .composedPath()\n .find(\n (el): el is HelixStep => el instanceof Element && el.tagName.toLowerCase() === 'hx-step',\n );\n if (!step) return;\n const index = steps.indexOf(step);\n\n /**\n * Dispatched when a step is clicked.\n * @event hx-step-click\n */\n this.dispatchEvent(\n new CustomEvent<{ step: HelixStep; index: number }>('hx-step-click', {\n bubbles: true,\n composed: true,\n detail: { step, index },\n }),\n );\n };\n\n // ─── Render ───\n\n override render() {\n return html`\n <div part=\"base\" class=\"steps\" role=\"list\" aria-label=${this.accessibleLabel ?? nothing}>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-steps': HelixSteps;\n }\n}\n","import { css } from 'lit';\n\nexport const helixStepStyles = css`\n :host {\n display: flex;\n flex: var(--hx-steps-item-flex, 1);\n width: var(--hx-steps-item-width, auto);\n min-width: 0;\n }\n\n /* ─── Visually Hidden (SR only) ─── */\n\n .sr-only {\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-width: 0;\n }\n\n /* ─── Step Wrapper ─── */\n\n .step {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n cursor: pointer;\n }\n\n /* ─── Focus ─── */\n\n :host(:focus-visible) .step__indicator {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-steps-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Track (indicator + connector) ─── */\n\n .step__track {\n display: flex;\n flex-direction: row;\n align-items: center;\n width: 100%;\n }\n\n /* ─── Indicator ─── */\n\n .step__indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-steps-indicator-size, 2rem);\n height: var(--hx-steps-indicator-size, 2rem);\n border-radius: var(--hx-border-radius-full, 9999px);\n border: var(--hx-border-width-medium, 2px) solid\n var(--hx-steps-indicator-border-color, var(--hx-color-border-strong, #66787b));\n background-color: var(--hx-steps-indicator-bg, var(--hx-color-surface-default, #ffffff));\n color: var(--hx-steps-indicator-color, var(--hx-color-text-muted, #4a5362));\n font-size: var(--hx-steps-indicator-font-size, var(--hx-font-size-sm));\n font-weight: var(--hx-font-weight-semibold);\n font-family: var(--hx-steps-font-family, var(--hx-font-family-sans));\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease);\n position: relative;\n z-index: 1;\n }\n\n .step__indicator .step__status-glyph {\n --hx-icon-size: var(--hx-steps-indicator-icon-size, 1rem);\n }\n\n /* ─── Connector ─── */\n\n .step__connector {\n flex: 1;\n height: var(--hx-steps-connector-thickness, var(--hx-border-width, 2px));\n min-width: 0;\n background-color: var(--hx-steps-connector-color, var(--hx-color-border-default, #d6dbd5));\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n :host(:last-child) .step__connector {\n display: none;\n }\n\n /* ─── Label Area ─── */\n\n .step__label-area {\n text-align: center;\n margin-top: var(--hx-space-2, 0.5rem);\n width: 100%;\n padding: 0 var(--hx-space-1, 0.25rem);\n }\n\n .step__label {\n font-family: var(--hx-steps-font-family, var(--hx-font-family-sans));\n font-size: var(--hx-steps-label-font-size, var(--hx-font-size-sm));\n font-weight: var(--hx-font-weight-medium);\n color: var(--hx-steps-label-color, var(--hx-color-text-secondary, #313e4b));\n line-height: var(--hx-line-height-tight, 1.25);\n }\n\n .step__description {\n font-family: var(--hx-steps-font-family, var(--hx-font-family-sans));\n font-size: var(--hx-steps-description-font-size, var(--hx-font-size-xs));\n color: var(--hx-steps-description-color, var(--hx-color-text-muted, #4a5362));\n margin-top: var(--hx-space-1, 0.25rem);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Status: active ─── */\n\n /* Active: outlined indicator (in-progress) — visually distinct from complete (filled) */\n :host([status='active']) .step__indicator {\n border-color: var(--hx-steps-active-border-color, var(--hx-color-action-primary-bg, #0f7078));\n background-color: var(--hx-steps-active-bg, var(--hx-color-action-primary-bg, #0f7078));\n color: var(--hx-steps-active-color, var(--hx-color-text-on-primary, #ffffff));\n }\n\n :host([status='active']) .step__label {\n color: var(--hx-steps-active-label-color, var(--hx-color-primary-700, #0f6363));\n font-weight: var(--hx-font-weight-semibold);\n }\n\n /* ─── Status: complete ─── */\n\n /* Complete: filled indicator with darker shade — visually distinct from active.\n on-primary tokens are tuned for primary-500. primary-700 + on-primary\n (= neutral-900) drops to 2.54:1 — fails AA for the check icon / step\n number. Pin fg at neutral-0 (7.03:1 on primary-700). Mirrors\n hx-toggle-button pressed treatment. */\n :host([status='complete']) .step__indicator {\n border-color: var(--hx-steps-complete-border-color, var(--hx-color-primary-700, #0f6363));\n background-color: var(--hx-steps-complete-bg, var(--hx-color-primary-700, #0f6363));\n color: var(--hx-steps-complete-color, var(--hx-color-neutral-0, #ffffff));\n }\n\n :host([status='complete']) .step__connector {\n background-color: var(\n --hx-steps-connector-complete-color,\n var(--hx-color-primary-500, #429797)\n );\n }\n\n :host([status='complete']) .step__label {\n color: var(--hx-steps-complete-label-color, var(--hx-color-text-primary, #0d1825));\n }\n\n /* ─── Status: error ─── */\n\n :host([status='error']) .step__indicator {\n border-color: var(--hx-steps-error-border-color, var(--hx-color-error-500, #e5493e));\n background-color: var(--hx-steps-error-bg, var(--hx-color-error-500, #e5493e));\n color: var(--hx-steps-error-color, var(--hx-color-text-on-error, #ffffff));\n }\n\n :host([status='error']) .step__label {\n color: var(--hx-steps-error-label-color, var(--hx-color-error-700, #a21312));\n }\n\n /* ─── Status: disabled ─── */\n\n :host([disabled]) .step {\n cursor: not-allowed;\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n\n :host([disabled]) .step__indicator {\n border-color: var(--hx-steps-disabled-border-color, var(--hx-color-border-default, #d6dbd5));\n background-color: var(--hx-steps-disabled-bg, var(--hx-color-surface-sunken, #ebeee9));\n color: var(--hx-steps-disabled-color, var(--hx-color-text-placeholder, #8e9c98));\n }\n\n /* ─── Vertical Layout ─── */\n\n :host([orientation='vertical']) {\n flex: initial;\n width: 100%;\n }\n\n :host([orientation='vertical']) .step {\n flex-direction: row;\n align-items: flex-start;\n gap: var(--hx-space-3, 0.75rem);\n }\n\n :host([orientation='vertical']) .step__track {\n flex-direction: column;\n align-items: center;\n width: auto;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) .step__connector {\n width: var(--hx-steps-connector-thickness, var(--hx-border-width, 2px));\n height: auto;\n min-height: var(--hx-space-8, 2rem);\n flex: 1;\n }\n\n :host([orientation='vertical']) .step__label-area {\n text-align: start;\n margin-top: 0;\n padding-bottom: var(--hx-space-4, 1rem);\n padding-inline-start: 0;\n }\n\n :host([orientation='vertical']:last-child) .step__label-area {\n padding-bottom: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .step__indicator {\n transition: none;\n }\n\n .step__connector {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .step__indicator {\n border-color: CanvasText;\n }\n\n :host([status='active']) .step__indicator {\n border-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n\n :host([status='complete']) .step__indicator {\n border-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n\n :host([status='error']) .step__indicator {\n border-color: LinkText;\n background-color: LinkText;\n color: HighlightText;\n }\n\n .step__connector {\n background-color: CanvasText;\n }\n\n :host([status='complete']) .step__connector {\n background-color: Highlight;\n }\n\n :host(:focus-visible) .step__indicator {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n }\n`;\n","import { html, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport '../hx-icon/hx-icon.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixStepStyles } from './hx-step.styles.js';\n\n/**\n * An individual step, designed to be used inside an `<hx-steps>` container.\n * Represents a single step in a multi-step wizard or progress indicator.\n *\n * @summary Individual step item within an `<hx-steps>` progress indicator.\n *\n * @tag hx-step\n *\n * @slot icon - Custom icon for the step indicator. Shown when status is `pending` or `active`.\n * @slot label - Step label text. Falls back to the `label` property.\n * @slot description - Step description text. Falls back to the `description` property.\n *\n * @csspart base - The outermost wrapper element.\n * @csspart indicator - The circular step indicator.\n * @csspart connector - The line connecting this step to the next.\n * @csspart label - The step label element.\n * @csspart description - The step description element.\n *\n * @cssprop [--hx-steps-indicator-size=2rem] - Indicator circle diameter.\n * @cssprop [--hx-steps-indicator-font-size=var(--hx-font-size-sm)] - Indicator text size.\n * @cssprop [--hx-steps-indicator-icon-size=1rem] - Indicator icon size.\n * @cssprop [--hx-steps-label-font-size=var(--hx-font-size-sm)] - Label font size.\n * @cssprop [--hx-steps-description-font-size=var(--hx-font-size-xs)] - Description font size.\n * @cssprop [--hx-steps-connector-color=var(--hx-color-neutral-200)] - Connector line color.\n * @cssprop [--hx-steps-connector-complete-color=var(--hx-color-primary-500)] - Connector color when step is complete.\n * @cssprop [--hx-steps-connector-thickness=var(--hx-border-width,2px)] - Connector line thickness.\n * @cssprop [--hx-steps-label-color=var(--hx-color-neutral-600)] - Label text color.\n * @cssprop [--hx-steps-description-color=var(--hx-color-neutral-500)] - Description text color.\n */\n@customElement('hx-step')\nexport class HelixStep extends HelixElement {\n static override styles = [helixStepStyles, forcedColorsInteractive];\n\n // ─── Public Properties ───\n\n /**\n * The step label text.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Current status of the step.\n * @attr status\n */\n @property({ type: String, reflect: true })\n status: 'pending' | 'active' | 'complete' | 'error' = 'pending';\n\n /**\n * Optional description text shown below the label.\n * @attr description\n */\n @property({ type: String, reflect: true })\n description = '';\n\n /**\n * Whether the step is disabled and non-interactive.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── Internal Properties (set by parent hx-steps) ───\n\n /**\n * Layout orientation. Set by the parent `<hx-steps>` container via JS property.\n * Do not set this attribute directly on `<hx-step>` — use the `orientation`\n * property on the parent `<hx-steps>` container instead. The parent will\n * propagate the value to all child steps via `_syncChildren()`.\n * @internal\n */\n @property({ attribute: false })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Size variant. Set by the parent `<hx-steps>` container via JS property.\n * Do not set this attribute directly on `<hx-step>` — use the `size` property\n * on the parent `<hx-steps>` container instead. The parent will propagate the\n * value to all child steps via `_syncChildren()`.\n * @internal\n */\n @property({ attribute: false })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Zero-based index of this step. Set by the parent `<hx-steps>` container.\n * @internal\n */\n @property({ type: Number })\n index = 0;\n\n // ─── Internal State ───\n\n /**\n * Text for the aria-live region, updated on status transitions.\n * Non-reactive: computed in willUpdate() to avoid an extra render cycle.\n * @internal\n */\n private _liveMessage = '';\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'listitem');\n }\n this.setAttribute('tabindex', this.disabled ? '-1' : '0');\n this.addEventListener('keydown', this._handleKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleKeydown);\n }\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n if (changedProperties.has('status')) {\n // STEPS-003: announce status transitions to screen readers via aria-live region.\n // Only announce on transitions (not initial render) by checking the previous value.\n // Using a non-reactive field here avoids scheduling an extra render cycle.\n const prev = changedProperties.get('status');\n if (prev !== undefined) {\n if (this.status === 'complete') {\n this._liveMessage = 'Complete';\n } else if (this.status === 'error') {\n this._liveMessage = 'Error';\n } else {\n this._liveMessage = '';\n }\n }\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('status')) {\n if (this.status === 'active') {\n this.setAttribute('aria-current', 'step');\n } else {\n this.removeAttribute('aria-current');\n }\n }\n if (changedProperties.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('tabindex', '-1');\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.setAttribute('tabindex', '0');\n this.removeAttribute('aria-disabled');\n }\n }\n if (changedProperties.has('orientation')) {\n this.setAttribute('orientation', this.orientation);\n }\n if (changedProperties.has('size')) {\n this.setAttribute('size', this.size);\n }\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleKeydown = (event: KeyboardEvent): void => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this._handleClick();\n }\n };\n\n /** @internal */\n private _handleClick(): void {\n if (this.disabled) {\n return;\n }\n\n /**\n * Internal event dispatched to signal step click to the parent container.\n * @internal\n */\n this.dispatchEvent(\n new CustomEvent<void>('hx-step-click-internal', {\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderCheckmark() {\n return html`\n <hx-icon class=\"step__status-glyph\" library=\"helix\" name=\"check\" aria-hidden=\"true\"></hx-icon>\n <span class=\"sr-only\">Complete</span>\n `;\n }\n\n /** @internal */\n private _renderXMark() {\n return html`\n <hx-icon class=\"step__status-glyph\" library=\"helix\" name=\"close\" aria-hidden=\"true\"></hx-icon>\n <span class=\"sr-only\">Error</span>\n `;\n }\n\n /** @internal */\n private _renderIndicatorContent() {\n if (this.status === 'complete') {\n return this._renderCheckmark();\n }\n if (this.status === 'error') {\n return this._renderXMark();\n }\n return html`<slot name=\"icon\">${this.index + 1}</slot>`;\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <div part=\"base\" class=\"step\" @click=${this._handleClick}>\n <div class=\"step__track\">\n <div part=\"indicator\" class=\"step__indicator\">${this._renderIndicatorContent()}</div>\n <div part=\"connector\" class=\"step__connector\" aria-hidden=\"true\"></div>\n </div>\n <div class=\"step__label-area\">\n <div part=\"label\" class=\"step__label\">\n <slot name=\"label\">${this.label}</slot>\n </div>\n <div part=\"description\" class=\"step__description\">\n <slot name=\"description\">${this.description}</slot>\n </div>\n </div>\n </div>\n <div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\">${this._liveMessage}</div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-step': HelixStep;\n }\n}\n"],"names":["helixStepsStyles","css","HelixSteps","HelixElement","e","steps","step","el","index","legacySize","changedProperties","i","html","nothing","forcedColorsInteractive","__decorateClass","property","customElement","helixStepStyles","HelixStep","event"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { property as n, state as
|
|
3
|
-
import { classMap as
|
|
1
|
+
import { css as p, nothing as x, html as g } from "lit";
|
|
2
|
+
import { property as n, state as d, customElement as f } from "lit/decorators.js";
|
|
3
|
+
import { classMap as c } from "lit/directives/class-map.js";
|
|
4
4
|
import { a as v } from "./forced-colors-CTEDFRGa.js";
|
|
5
5
|
import { H as u } from "./helix-element-BNEYeiys.js";
|
|
6
|
-
const b =
|
|
6
|
+
const b = p`
|
|
7
7
|
:host {
|
|
8
8
|
display: inline-block;
|
|
9
9
|
}
|
|
@@ -184,6 +184,11 @@ const b = f`
|
|
|
184
184
|
border-width: 3px;
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
+
|
|
188
|
+
/* hx-icon glyph sizing for the migrated remove-button SVG. */
|
|
189
|
+
.tag__remove-glyph {
|
|
190
|
+
--hx-icon-size: 10px;
|
|
191
|
+
}
|
|
187
192
|
`;
|
|
188
193
|
var m = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, o = (t, a, s, r) => {
|
|
189
194
|
for (var i = r > 1 ? void 0 : r ? _(a, s) : a, l = t.length - 1, h; l >= 0; l--)
|
|
@@ -237,31 +242,31 @@ let e = class extends u {
|
|
|
237
242
|
tag__suffix: !0,
|
|
238
243
|
"tag__suffix--hidden": !this._hasSuffix
|
|
239
244
|
}, r = this._semanticVariantLabel;
|
|
240
|
-
return
|
|
241
|
-
<span part="base" class=${
|
|
242
|
-
${r ?
|
|
243
|
-
<span part="prefix" class=${
|
|
245
|
+
return g`
|
|
246
|
+
<span part="base" class=${c(t)}>
|
|
247
|
+
${r ? g`<span class="tag__variant-label">${r}: </span>` : x}
|
|
248
|
+
<span part="prefix" class=${c(a)}>
|
|
244
249
|
<slot name="prefix" @slotchange=${this._onPrefixSlotChange}></slot>
|
|
245
250
|
</span>
|
|
246
251
|
<span part="label" class="tag__label">
|
|
247
252
|
<slot @slotchange=${this._onDefaultSlotChange}></slot>
|
|
248
253
|
</span>
|
|
249
|
-
<span part="suffix" class=${
|
|
254
|
+
<span part="suffix" class=${c(s)}>
|
|
250
255
|
<slot name="suffix" @slotchange=${this._onSuffixSlotChange}></slot>
|
|
251
256
|
</span>
|
|
252
|
-
${this.removable ?
|
|
257
|
+
${this.removable ? g`<button
|
|
253
258
|
part="remove-button"
|
|
254
259
|
class="tag__remove-button"
|
|
255
260
|
aria-label=${`Remove ${this._defaultSlotText || "tag"}`}
|
|
256
261
|
?disabled=${this.disabled}
|
|
257
262
|
@click=${this._handleRemove}
|
|
258
263
|
>
|
|
259
|
-
<
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
264
|
+
<hx-icon
|
|
265
|
+
class="tag__remove-glyph"
|
|
266
|
+
library="helix"
|
|
267
|
+
name="close"
|
|
268
|
+
aria-hidden="true"
|
|
269
|
+
></hx-icon>
|
|
265
270
|
</button>` : x}
|
|
266
271
|
</span>
|
|
267
272
|
`;
|
|
@@ -289,18 +294,18 @@ o([
|
|
|
289
294
|
n({ type: Boolean, reflect: !0 })
|
|
290
295
|
], e.prototype, "disabled", 2);
|
|
291
296
|
o([
|
|
292
|
-
|
|
297
|
+
d()
|
|
293
298
|
], e.prototype, "_defaultSlotText", 2);
|
|
294
299
|
o([
|
|
295
|
-
|
|
300
|
+
d()
|
|
296
301
|
], e.prototype, "_hasPrefix", 2);
|
|
297
302
|
o([
|
|
298
|
-
|
|
303
|
+
d()
|
|
299
304
|
], e.prototype, "_hasSuffix", 2);
|
|
300
305
|
e = o([
|
|
301
|
-
|
|
306
|
+
f("hx-tag")
|
|
302
307
|
], e);
|
|
303
308
|
export {
|
|
304
309
|
e as H
|
|
305
310
|
};
|
|
306
|
-
//# sourceMappingURL=hx-tag-
|
|
311
|
+
//# sourceMappingURL=hx-tag-BqO6HY6V.js.map
|