@helixui/library 3.1.0-next.72 → 3.2.0-next.100
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/custom-elements.json +165 -328
- 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/index.js +1 -1
- package/dist/components/hx-banner/index.js +1 -1
- package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/index.js +1 -1
- package/dist/components/hx-button/hx-button.d.ts +44 -49
- package/dist/components/hx-button/hx-button.d.ts.map +1 -1
- package/dist/components/hx-button/hx-button.styles.d.ts.map +1 -1
- package/dist/components/hx-button/index.js +1 -1
- package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
- package/dist/components/hx-card/index.js +1 -1
- package/dist/components/hx-carousel/index.js +1 -1
- package/dist/components/hx-checkbox/index.js +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-code-snippet/hx-code-snippet.styles.d.ts.map +1 -1
- package/dist/components/hx-code-snippet/index.js +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-data-table/hx-data-table.styles.d.ts.map +1 -1
- package/dist/components/hx-data-table/index.js +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/hx-dialog.styles.d.ts.map +1 -1
- package/dist/components/hx-dialog/index.js +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-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-icon-button/hx-icon-button.styles.d.ts.map +1 -1
- package/dist/components/hx-icon-button/index.js +1 -1
- package/dist/components/hx-link/index.js +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-meter/hx-meter.styles.d.ts.map +1 -1
- package/dist/components/hx-meter/index.js +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-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-pagination/hx-pagination.styles.d.ts.map +1 -1
- package/dist/components/hx-pagination/index.js +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-popover/hx-popover.styles.d.ts.map +1 -1
- package/dist/components/hx-popover/index.js +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-rating/index.js +1 -1
- package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
- package/dist/components/hx-select/index.js +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.d.ts +7 -5
- 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 +9 -23
- 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/index.js +1 -1
- package/dist/components/hx-split-button/hx-split-button.d.ts +1 -1
- package/dist/components/hx-split-button/index.js +1 -1
- package/dist/components/hx-split-panel/hx-split-panel.styles.d.ts.map +1 -1
- package/dist/components/hx-split-panel/index.js +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-switch/index.js +1 -1
- package/dist/components/hx-table/hx-table.styles.d.ts.map +1 -1
- package/dist/components/hx-table/index.js +1 -1
- package/dist/components/hx-tabs/index.js +1 -1
- package/dist/components/hx-text-input/hx-text-input.d.ts +18 -35
- package/dist/components/hx-text-input/hx-text-input.d.ts.map +1 -1
- package/dist/components/hx-text-input/index.js +1 -1
- package/dist/components/hx-textarea/index.js +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toast/hx-toast.d.ts +12 -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-toggle-button/index.js +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.styles.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/css/helix-all.css +289 -237
- package/dist/css/helix-core.css +147 -53
- package/dist/css/helix-data.css +9 -14
- package/dist/css/helix-feedback.css +30 -20
- package/dist/css/helix-forms.css +53 -73
- package/dist/css/helix-layout.css +2 -8
- package/dist/css/helix-media.css +3 -3
- package/dist/css/helix-navigation.css +34 -41
- package/dist/css/helix-overlay.css +3 -12
- package/dist/css/helix-tokens.css +60 -5
- package/dist/css/helix-utility.css +5 -5
- package/dist/css/hx-alert.css +1 -1
- package/dist/css/hx-banner.css +2 -2
- package/dist/css/hx-button.css +143 -43
- package/dist/css/hx-card.css +1 -4
- package/dist/css/hx-carousel.css +3 -3
- package/dist/css/hx-checkbox.css +2 -2
- package/dist/css/hx-clinical-status.css +2 -4
- package/dist/css/hx-code-snippet.css +6 -4
- package/dist/css/hx-color-picker.css +3 -13
- package/dist/css/hx-combobox.css +7 -7
- package/dist/css/hx-data-table.css +2 -8
- package/dist/css/hx-date-picker.css +7 -7
- package/dist/css/hx-dialog.css +1 -4
- package/dist/css/hx-drawer.css +1 -4
- package/dist/css/hx-file-upload.css +4 -13
- package/dist/css/hx-icon-button.css +2 -5
- package/dist/css/hx-link.css +1 -1
- package/dist/css/hx-meter.css +1 -2
- package/dist/css/hx-nav.css +2 -8
- package/dist/css/hx-overflow-menu.css +2 -8
- package/dist/css/hx-pagination.css +2 -8
- package/dist/css/hx-phi-field.css +1 -4
- package/dist/css/hx-popover.css +1 -4
- package/dist/css/hx-rating.css +3 -3
- package/dist/css/hx-select.css +3 -4
- package/dist/css/hx-side-nav.css +26 -12
- package/dist/css/hx-slider.css +4 -4
- package/dist/css/hx-split-button.css +5 -5
- package/dist/css/hx-split-panel.css +2 -8
- package/dist/css/hx-switch.css +3 -3
- package/dist/css/hx-table.css +1 -2
- package/dist/css/hx-text-input.css +8 -8
- package/dist/css/hx-textarea.css +2 -2
- package/dist/css/hx-time-picker.css +3 -3
- package/dist/css/hx-toast.css +26 -15
- package/dist/css/hx-toggle-button.css +4 -4
- package/dist/css/hx-top-nav.css +1 -4
- package/dist/css/hx-tree-view.css +1 -1
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +60 -46
- package/dist/index.js +44 -44
- package/dist/shared/{hx-accordion-cnKg4_la.js → hx-accordion-ZVzgDzTG.js} +4 -5
- package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -0
- package/dist/shared/{hx-alert-BZH8iHQf.js → hx-alert-C597yHpD.js} +2 -2
- package/dist/shared/{hx-alert-BZH8iHQf.js.map → hx-alert-C597yHpD.js.map} +1 -1
- package/dist/shared/{hx-banner-DT7Zn9Bo.js → hx-banner-Cxd7eFUP.js} +3 -3
- package/dist/shared/{hx-banner-DT7Zn9Bo.js.map → hx-banner-Cxd7eFUP.js.map} +1 -1
- package/dist/shared/{hx-breadcrumb-item-COeYcB2x.js → hx-breadcrumb-item-3tKppF9h.js} +2 -5
- package/dist/shared/{hx-breadcrumb-item-COeYcB2x.js.map → hx-breadcrumb-item-3tKppF9h.js.map} +1 -1
- package/dist/shared/{hx-button-modUSOpY.js → hx-button-9OUjJnk7.js} +167 -68
- package/dist/shared/hx-button-9OUjJnk7.js.map +1 -0
- package/dist/shared/{hx-card-CU1QnjNb.js → hx-card-qNAM2QNV.js} +6 -9
- package/dist/shared/hx-card-qNAM2QNV.js.map +1 -0
- package/dist/shared/{hx-carousel-item-BaE4hpLl.js → hx-carousel-item-z1Lc24op.js} +4 -4
- package/dist/shared/hx-carousel-item-z1Lc24op.js.map +1 -0
- package/dist/shared/{hx-checkbox-C46TyXhM.js → hx-checkbox-DBD-gMoz.js} +3 -3
- package/dist/shared/{hx-checkbox-C46TyXhM.js.map → hx-checkbox-DBD-gMoz.js.map} +1 -1
- package/dist/shared/{hx-clinical-status-BmSjfSEN.js → hx-clinical-status-D3XQIOqX.js} +3 -5
- package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +1 -0
- package/dist/shared/{hx-code-snippet-CJ0FbQYG.js → hx-code-snippet-B26RM1_C.js} +10 -8
- package/dist/shared/{hx-code-snippet-CJ0FbQYG.js.map → hx-code-snippet-B26RM1_C.js.map} +1 -1
- package/dist/shared/{hx-color-picker-DiDLZyvK.js → hx-color-picker-uRc865FJ.js} +23 -33
- package/dist/shared/hx-color-picker-uRc865FJ.js.map +1 -0
- package/dist/shared/{hx-combobox-DaA5dBC4.js → hx-combobox-ClhNRAS5.js} +8 -8
- package/dist/shared/hx-combobox-ClhNRAS5.js.map +1 -0
- package/dist/shared/{hx-data-table-Cq3t86Ic.js → hx-data-table-CLqVqdxr.js} +3 -9
- package/dist/shared/hx-data-table-CLqVqdxr.js.map +1 -0
- package/dist/shared/{hx-date-picker-DMqRQNSB.js → hx-date-picker-BJm7Yrda.js} +8 -8
- package/dist/shared/{hx-date-picker-DMqRQNSB.js.map → hx-date-picker-BJm7Yrda.js.map} +1 -1
- package/dist/shared/{hx-dialog-eIS8tcDm.js → hx-dialog-DRN_1-Y-.js} +2 -5
- package/dist/shared/hx-dialog-DRN_1-Y-.js.map +1 -0
- package/dist/shared/{hx-drawer-DDhDz7RI.js → hx-drawer-Y1Ui2IWJ.js} +2 -5
- package/dist/shared/hx-drawer-Y1Ui2IWJ.js.map +1 -0
- package/dist/shared/{hx-file-upload-zTDbjsRw.js → hx-file-upload-D3rKROK5.js} +17 -26
- package/dist/shared/hx-file-upload-D3rKROK5.js.map +1 -0
- package/dist/shared/{hx-icon-button-BmV97nqz.js → hx-icon-button-CGNdQSFM.js} +3 -6
- package/dist/shared/hx-icon-button-CGNdQSFM.js.map +1 -0
- package/dist/shared/{hx-link-DmiV-mPw.js → hx-link-9Ig2DW6L.js} +5 -5
- package/dist/shared/{hx-link-DmiV-mPw.js.map → hx-link-9Ig2DW6L.js.map} +1 -1
- package/dist/shared/{hx-menu-divider-j__TZjH2.js → hx-menu-divider-C2omnPtj.js} +2 -5
- package/dist/shared/hx-menu-divider-C2omnPtj.js.map +1 -0
- package/dist/shared/{hx-meter-Cm7k_Ro8.js → hx-meter-BPscsw5t.js} +2 -3
- package/dist/shared/hx-meter-BPscsw5t.js.map +1 -0
- package/dist/shared/{hx-nav-item-D8xHLVOs.js → hx-nav-item-CqbO5-T5.js} +140 -90
- package/dist/shared/hx-nav-item-CqbO5-T5.js.map +1 -0
- package/dist/shared/{hx-nav-LoyEKZQC.js → hx-nav-ldFM3Fle.js} +37 -43
- package/dist/shared/hx-nav-ldFM3Fle.js.map +1 -0
- package/dist/shared/{hx-overflow-menu-BmKyAp5D.js → hx-overflow-menu-DCLsdIBy.js} +3 -9
- package/dist/shared/hx-overflow-menu-DCLsdIBy.js.map +1 -0
- package/dist/shared/{hx-pagination-Dqw5dorC.js → hx-pagination-C7y8GVyU.js} +54 -60
- package/dist/shared/hx-pagination-C7y8GVyU.js.map +1 -0
- package/dist/shared/{hx-phi-field-Bf9TdtC1.js → hx-phi-field-C19oxlrr.js} +2 -5
- package/dist/shared/hx-phi-field-C19oxlrr.js.map +1 -0
- package/dist/shared/{hx-popover-B93rTAfr.js → hx-popover-B-FP3-wW.js} +8 -11
- package/dist/shared/hx-popover-B-FP3-wW.js.map +1 -0
- package/dist/shared/{hx-radio-N8xgDd_5.js → hx-radio-dFjUAost.js} +4 -4
- package/dist/shared/{hx-radio-N8xgDd_5.js.map → hx-radio-dFjUAost.js.map} +1 -1
- package/dist/shared/{hx-rating-i2FL1WUN.js → hx-rating-CGtsejNf.js} +4 -4
- package/dist/shared/{hx-rating-i2FL1WUN.js.map → hx-rating-CGtsejNf.js.map} +1 -1
- package/dist/shared/{hx-select-vgaBo1Ai.js → hx-select-Bf4usFts.js} +4 -5
- package/dist/shared/hx-select-Bf4usFts.js.map +1 -0
- package/dist/shared/{hx-slider-ydBamYhd.js → hx-slider-m0aEClH1.js} +5 -5
- package/dist/shared/{hx-slider-ydBamYhd.js.map → hx-slider-m0aEClH1.js.map} +1 -1
- package/dist/shared/{hx-split-button-BeMsmS6N.js → hx-split-button-BxDFfx4D.js} +6 -6
- package/dist/shared/{hx-split-button-BeMsmS6N.js.map → hx-split-button-BxDFfx4D.js.map} +1 -1
- package/dist/shared/{hx-split-panel-BVG1VWNT.js → hx-split-panel-B-u0Z3mm.js} +3 -9
- package/dist/shared/hx-split-panel-B-u0Z3mm.js.map +1 -0
- package/dist/shared/{hx-step-DL3PbOzm.js → hx-step-R2rjp1fT.js} +2 -5
- package/dist/shared/hx-step-R2rjp1fT.js.map +1 -0
- package/dist/shared/{hx-switch-Dougzsgp.js → hx-switch-DvAW4YY-.js} +4 -4
- package/dist/shared/{hx-switch-Dougzsgp.js.map → hx-switch-DvAW4YY-.js.map} +1 -1
- package/dist/shared/{hx-tab-panel-CbkO9VKu.js → hx-tab-panel-SWOEHuJc.js} +3 -3
- package/dist/shared/{hx-tab-panel-CbkO9VKu.js.map → hx-tab-panel-SWOEHuJc.js.map} +1 -1
- package/dist/shared/{hx-td-1zwTFLRw.js → hx-td-DnnEMIuA.js} +2 -3
- package/dist/shared/hx-td-DnnEMIuA.js.map +1 -0
- package/dist/shared/{hx-text-input-B-caO5fI.js → hx-text-input-Bn7Gn8CI.js} +24 -25
- package/dist/shared/hx-text-input-Bn7Gn8CI.js.map +1 -0
- package/dist/shared/{hx-textarea-D9O4U8cb.js → hx-textarea-Jx1xnhgv.js} +7 -7
- package/dist/shared/{hx-textarea-D9O4U8cb.js.map → hx-textarea-Jx1xnhgv.js.map} +1 -1
- package/dist/shared/{hx-time-picker-m0z4nFB-.js → hx-time-picker-BoEIZwzv.js} +4 -4
- package/dist/shared/{hx-time-picker-m0z4nFB-.js.map → hx-time-picker-BoEIZwzv.js.map} +1 -1
- package/dist/shared/{hx-toggle-button-Dd8clXB4.js → hx-toggle-button-DPAIh_Xo.js} +24 -24
- package/dist/shared/{hx-toggle-button-Dd8clXB4.js.map → hx-toggle-button-DPAIh_Xo.js.map} +1 -1
- package/dist/shared/{hx-top-nav-CchPYaiV.js → hx-top-nav-DP6OFS8C.js} +11 -14
- package/dist/shared/hx-top-nav-DP6OFS8C.js.map +1 -0
- package/dist/shared/{hx-tree-item-DtMC3DTa.js → hx-tree-item-Dt0Ozqyr.js} +4 -10
- package/dist/shared/hx-tree-item-Dt0Ozqyr.js.map +1 -0
- package/dist/shared/{toast-factory-DvDRAh0l.js → toast-factory-YSznocIV.js} +66 -56
- package/dist/shared/toast-factory-YSznocIV.js.map +1 -0
- package/figma-inventory.json +292 -444
- package/package.json +2 -2
- package/dist/shared/hx-accordion-cnKg4_la.js.map +0 -1
- package/dist/shared/hx-button-modUSOpY.js.map +0 -1
- package/dist/shared/hx-card-CU1QnjNb.js.map +0 -1
- package/dist/shared/hx-carousel-item-BaE4hpLl.js.map +0 -1
- package/dist/shared/hx-clinical-status-BmSjfSEN.js.map +0 -1
- package/dist/shared/hx-color-picker-DiDLZyvK.js.map +0 -1
- package/dist/shared/hx-combobox-DaA5dBC4.js.map +0 -1
- package/dist/shared/hx-data-table-Cq3t86Ic.js.map +0 -1
- package/dist/shared/hx-dialog-eIS8tcDm.js.map +0 -1
- package/dist/shared/hx-drawer-DDhDz7RI.js.map +0 -1
- package/dist/shared/hx-file-upload-zTDbjsRw.js.map +0 -1
- package/dist/shared/hx-icon-button-BmV97nqz.js.map +0 -1
- package/dist/shared/hx-menu-divider-j__TZjH2.js.map +0 -1
- package/dist/shared/hx-meter-Cm7k_Ro8.js.map +0 -1
- package/dist/shared/hx-nav-LoyEKZQC.js.map +0 -1
- package/dist/shared/hx-nav-item-D8xHLVOs.js.map +0 -1
- package/dist/shared/hx-overflow-menu-BmKyAp5D.js.map +0 -1
- package/dist/shared/hx-pagination-Dqw5dorC.js.map +0 -1
- package/dist/shared/hx-phi-field-Bf9TdtC1.js.map +0 -1
- package/dist/shared/hx-popover-B93rTAfr.js.map +0 -1
- package/dist/shared/hx-select-vgaBo1Ai.js.map +0 -1
- package/dist/shared/hx-split-panel-BVG1VWNT.js.map +0 -1
- package/dist/shared/hx-step-DL3PbOzm.js.map +0 -1
- package/dist/shared/hx-td-1zwTFLRw.js.map +0 -1
- package/dist/shared/hx-text-input-B-caO5fI.js.map +0 -1
- package/dist/shared/hx-top-nav-CchPYaiV.js.map +0 -1
- package/dist/shared/hx-tree-item-DtMC3DTa.js.map +0 -1
- package/dist/shared/toast-factory-DvDRAh0l.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-menu-divider-C2omnPtj.js","sources":["../../src/components/hx-menu/hx-menu.styles.ts","../../src/components/hx-menu/hx-menu.ts","../../src/components/hx-menu/hx-menu-item.styles.ts","../../src/components/hx-menu/hx-menu-item.ts","../../src/components/hx-menu/hx-menu-divider.styles.ts","../../src/components/hx-menu/hx-menu-divider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMenuStyles = css`\n :host {\n display: block;\n }\n\n .menu {\n display: flex;\n flex-direction: column;\n padding: var(--hx-space-1, 0.25rem);\n background: var(--hx-menu-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-menu-border-color, var(--hx-color-border-default, #d6dbd5));\n border-radius: var(--hx-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-menu-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n min-width: var(--hx-menu-min-width, 10rem);\n max-height: var(--hx-menu-max-height, 20rem);\n overflow-y: auto;\n outline: none;\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu {\n background-color: Canvas;\n border: 2px solid CanvasText;\n }\n }\n`;\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuStyles } from './hx-menu.styles.js';\nimport type { HelixMenuItem } from './hx-menu-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A menu container that manages keyboard navigation over a list of menu items.\n * Use with `hx-menu-item` and `hx-menu-divider`.\n *\n * @summary Context/action menu with keyboard-navigable items.\n *\n * @tag hx-menu\n *\n * @slot - Default slot for hx-menu-item and hx-menu-divider elements.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-select - Dispatched when an item is selected.\n * @fires {CustomEvent<void>} hx-close - Dispatched when Escape is pressed.\n *\n * @csspart base - The root menu element.\n *\n * @cssprop [--hx-menu-bg=var(--hx-color-neutral-0)] - Menu background color.\n * @cssprop [--hx-menu-border-color=var(--hx-color-neutral-200)] - Menu border color.\n * @cssprop [--hx-menu-border-radius=var(--hx-border-radius-md)] - Menu border radius.\n * @cssprop [--hx-menu-shadow] - Menu box shadow.\n * @cssprop [--hx-menu-min-width=10rem] - Minimum menu width.\n * @cssprop [--hx-menu-max-height=20rem] - Maximum menu height before vertical scroll is activated.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-shadow-md] - Box shadow.\n */\n@customElement('hx-menu')\nexport class HelixMenu extends HelixElement {\n static override styles = [helixMenuStyles, forcedColorsInteractive];\n\n /**\n * Accessible label for the menu. Rendered as `aria-label` on the inner\n * `role=\"menu\"` element when set.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Index of the currently focused menu item within the list of enabled items.\n * @internal\n */\n private _focusedIndex = -1;\n\n /**\n * Accumulated character buffer for typeahead search within menu items.\n * @internal\n */\n private _typeaheadBuffer = '';\n\n /**\n * Timer handle that clears the typeahead buffer after a period of inactivity.\n * @internal\n */\n private _typeaheadTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** @internal */\n private _getItems(): HelixMenuItem[] {\n return Array.from(this.querySelectorAll<HelixMenuItem>('hx-menu-item')).filter(\n (item) => !item.disabled && !item.loading,\n );\n }\n\n /**\n * Synchronize roving tabindex across all enabled items.\n * Only the active item (or first item if none active) gets tabindex=0.\n */\n /** @internal */\n private _syncRovingTabIndex(): void {\n const items = this._getItems();\n const activeIndex = this._focusedIndex >= 0 ? this._focusedIndex : 0;\n items.forEach((item, i) => {\n item.setRovingTabIndex(i === activeIndex ? 0 : -1);\n });\n }\n\n /** Focus the first menu item. */\n focusFirst(): void {\n const items = this._getItems();\n const first = items[0];\n if (first !== undefined) {\n this._focusedIndex = 0;\n this._syncRovingTabIndex();\n first.focus();\n }\n }\n\n /** Focus the last menu item. */\n focusLast(): void {\n const items = this._getItems();\n const last = items[items.length - 1];\n if (last !== undefined) {\n this._focusedIndex = items.length - 1;\n this._syncRovingTabIndex();\n last.focus();\n }\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getItems();\n if (items.length === 0) return;\n this._focusedIndex = Math.max(0, Math.min(index, items.length - 1));\n this._syncRovingTabIndex();\n const target = items[this._focusedIndex];\n if (target !== undefined) target.focus();\n }\n\n /** @internal */\n private _updateFocusedIndex(): void {\n const items = this._getItems();\n const active = this.shadowRoot?.activeElement ?? document.activeElement;\n // Find the active item by checking if any item's shadow root contains the active element\n const idx = items.findIndex((item) => item.matches(':focus-within') || item === active);\n if (idx !== -1) this._focusedIndex = idx;\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n this._updateFocusedIndex();\n const items = this._getItems();\n if (items.length === 0) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this._focusItem(this._focusedIndex + 1 < items.length ? this._focusedIndex + 1 : 0);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._focusItem(this._focusedIndex > 0 ? this._focusedIndex - 1 : items.length - 1);\n break;\n case 'Home':\n e.preventDefault();\n this._focusItem(0);\n break;\n case 'End':\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n case 'Escape':\n e.preventDefault();\n this.dispatchEvent(new CustomEvent<void>('hx-close', { bubbles: true, composed: true }));\n break;\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 /** @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 const match = items.findIndex((item) => {\n if (item.disabled || item.hasAttribute('disabled')) return false;\n const text = item.textContent?.trim().toLowerCase() ?? '';\n return text.startsWith(this._typeaheadBuffer);\n });\n\n if (match !== -1) {\n this._focusItem(match);\n }\n }\n\n /** @internal */\n private _handleSlotChange(e: Event): void {\n const slot = e.target;\n if (!(slot instanceof HTMLSlotElement)) return;\n const validTags = new Set(['hx-menu-item', 'hx-menu-divider']);\n const invalid = slot\n .assignedElements()\n .filter((el) => !validTags.has(el.tagName.toLowerCase()));\n if (invalid.length > 0) {\n devWarn(\n 'hx-menu',\n `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n // Initialize roving tabindex when items are slotted\n this._syncRovingTabIndex();\n }\n\n /** @internal */\n private _handleItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem; value: string }>).detail;\n const items = this._getItems();\n this._focusedIndex = items.indexOf(detail.item);\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item: detail.item, value: detail.value },\n }),\n );\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = null;\n }\n }\n\n override firstUpdated(): void {\n if (!this.label) {\n devWarn(\n 'hx-menu',\n 'No accessible label provided. Set the `label` attribute on hx-menu so screen readers can identify this menu (WCAG 4.1.2).',\n );\n }\n }\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=\"menu\"\n role=\"menu\"\n aria-label=${this.label || 'Menu'}\n @keydown=${this._handleKeyDown}\n @hx-item-select=${this._handleItemSelect}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu': HelixMenu;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuItemStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n .menu-item {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n min-height: var(--hx-touch-target-min, 44px);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n cursor: pointer;\n color: var(--hx-menu-item-color, var(--hx-color-text-primary, #0d1825));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-family: var(--hx-menu-item-font-family, var(--hx-font-family-sans, sans-serif));\n line-height: var(--hx-line-height-tight, 1.25);\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n background: none;\n width: 100%;\n box-sizing: border-box;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: var(--hx-menu-item-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n }\n\n .menu-item:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);\n }\n\n .menu-item__prefix,\n .menu-item__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .menu-item__label {\n flex: 1 1 auto;\n }\n\n .menu-item__checked-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n width: 1em;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item--checked .menu-item__checked-icon {\n opacity: 1;\n }\n\n .menu-item__submenu-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n }\n\n .menu-item__spinner {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n animation: hx-menu-spin var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n @keyframes hx-menu-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item {\n transition: none;\n }\n\n .menu-item__checked-icon {\n transition: none;\n }\n\n .menu-item__spinner {\n animation: none;\n opacity: var(--hx-opacity-muted, 0.6);\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-item {\n forced-color-adjust: none;\n color: CanvasText;\n background-color: Canvas;\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .menu-item:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: -2px;\n }\n\n :host([disabled]) .menu-item {\n color: GrayText;\n opacity: 1;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuItemStyles } from './hx-menu-item.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A single interactive item for use inside `hx-menu`. Supports normal, checkbox,\n * and radio types, loading state, prefix/suffix slots, and submenu nesting.\n * Use `aria-label` on the parent `hx-menu` to provide an accessible name.\n *\n * @summary Interactive item within an hx-menu.\n *\n * @tag hx-menu-item\n *\n * @slot - Default slot for the item label.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Shortcut text or icon rendered after the label.\n * @slot submenu - A nested hx-menu for submenu content.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-item-select - Dispatched when the item is activated via click, Enter, or Space.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-open - Dispatched when ArrowRight is pressed on an item with a submenu.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-close - Dispatched when ArrowLeft is pressed on an item, signaling the parent to close the submenu and return focus.\n *\n * @csspart base - The root item element.\n * @csspart prefix - Prefix slot wrapper.\n * @csspart label - Label slot wrapper.\n * @csspart suffix - Suffix slot wrapper.\n * @csspart submenu-icon - The chevron icon indicating a submenu.\n * @csspart checked-icon - The checkmark icon for checkbox-type items.\n *\n * @cssprop [--hx-menu-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-menu-item-hover-bg=var(--hx-color-neutral-100)] - Item hover/focus background.\n */\n@customElement('hx-menu-item')\nexport class HelixMenuItem extends HelixElement {\n static override styles = [helixMenuItemStyles, forcedColorsInteractive];\n\n /**\n * @internal Managed by parent hx-menu for roving tabindex.\n * Only the active item in the menu has tabindex=0; all others have -1.\n */\n @state()\n private _rovingTabIndex = -1;\n\n /** @internal Set the roving tabindex value. Called by parent hx-menu. */\n setRovingTabIndex(value: number): void {\n this._rovingTabIndex = value;\n }\n\n /** Set whether the nested submenu is open. Called by the component managing submenu visibility. */\n setSubmenuOpen(open: boolean): void {\n this._submenuOpen = open;\n }\n\n /**\n * The value associated with this item, emitted in the hx-select event.\n * @attr value\n */\n @property({ type: String })\n value = '';\n\n /**\n * Whether the item is disabled. Prevents interaction and event dispatch.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Whether the item is checked. Only meaningful when type=\"checkbox\".\n * @attr checked\n */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /**\n * The type of menu item. \"checkbox\" renders a checkmark and toggles checked state.\n * \"radio\" renders a checkmark and emits selection for radio-group behavior.\n * @attr type\n */\n @property({ type: String, reflect: true })\n type: 'normal' | 'checkbox' | 'radio' = 'normal';\n\n /**\n * Whether the item is in a loading state. Shows a spinner and prevents interaction.\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /** @internal */\n @state()\n private _hasSubmenu = false;\n\n /** @internal Tracks whether the nested submenu is currently open. */\n @state()\n private _submenuOpen = false;\n\n /** @internal */\n @query('.menu-item') private _menuItemEl!: HTMLElement | null;\n\n /** Focus the inner interactive element. */\n override focus(options?: FocusOptions): void {\n this._menuItemEl?.focus(options);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // WCAG 4.1.2: menuitem role is only valid inside a role=\"menu\" or role=\"menubar\" container.\n // Check the closest ancestor with a menu role.\n const menuHost = this.closest('hx-menu, hx-split-button, [role=\"menu\"], [role=\"menubar\"]');\n if (!menuHost) {\n devWarn(\n 'hx-menu-item',\n 'hx-menu-item must be used inside an hx-menu or an element with role=\"menu\". ' +\n 'An orphaned menuitem violates WCAG 1.3.1 (Info and Relationships).',\n );\n }\n }\n\n /** @internal */\n private _handleSubmenuSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _activate(): void {\n if (this.disabled || this.loading) return;\n\n if (this.type === 'checkbox') {\n this.checked = !this.checked;\n } else if (this.type === 'radio') {\n const menu = this.closest('hx-menu');\n if (menu) {\n menu\n .querySelectorAll<HelixMenuItem>(':scope > hx-menu-item[type=\"radio\"]')\n .forEach((sibling) => {\n sibling.checked = sibling === this;\n });\n } else {\n this.checked = true;\n }\n }\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this, value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled || this.loading) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n this._activate();\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._activate();\n return;\n }\n\n if (e.key === 'ArrowRight' && this._hasSubmenu) {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-open', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n return;\n }\n\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-close', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n }\n\n /** @internal */\n private _renderCheckedIcon() {\n return html`\n <span part=\"checked-icon\" class=\"menu-item__checked-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSubmenuIcon() {\n return html`\n <span part=\"submenu-icon\" class=\"menu-item__submenu-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSpinner() {\n return html`\n <svg class=\"menu-item__spinner\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"3\" opacity=\"0.3\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n />\n </svg>\n `;\n }\n\n /** @internal */\n private _getRole(): string {\n switch (this.type) {\n case 'checkbox':\n return 'menuitemcheckbox';\n case 'radio':\n return 'menuitemradio';\n default:\n return 'menuitem';\n }\n }\n\n override render() {\n const role = this._getRole();\n const hasCheckableRole = this.type === 'checkbox' || this.type === 'radio';\n const classes = {\n 'menu-item': true,\n 'menu-item--checked': this.checked,\n };\n\n return html`\n <div\n part=\"base\"\n class=${classMap(classes)}\n role=${role}\n tabindex=${this.disabled ? '-1' : String(this._rovingTabIndex)}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-checked=${hasCheckableRole ? (this.checked ? 'true' : 'false') : nothing}\n aria-haspopup=${this._hasSubmenu ? 'menu' : nothing}\n aria-expanded=${this._hasSubmenu ? (this._submenuOpen ? 'true' : 'false') : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n @click=${this._handleClick}\n @keydown=${this._handleKeyDown}\n >\n ${this.loading ? this._renderSpinner() : nothing}\n ${hasCheckableRole ? this._renderCheckedIcon() : nothing}\n <span part=\"prefix\" class=\"menu-item__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"menu-item__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"menu-item__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n ${this._hasSubmenu ? this._renderSubmenuIcon() : nothing}\n <slot name=\"submenu\" @slotchange=${this._handleSubmenuSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-item': HelixMenuItem;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuDividerStyles = css`\n :host {\n display: block;\n }\n\n .menu-divider {\n height: var(--hx-border-width-thin, 1px);\n background-color: var(--hx-menu-divider-color, var(--hx-color-border-default, #d6dbd5));\n margin: var(--hx-space-1, 0.25rem) calc(-1 * var(--hx-space-1, 0.25rem));\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-divider {\n background-color: GrayText;\n }\n }\n`;\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuDividerStyles } from './hx-menu-divider.styles.js';\n\n/**\n * A visual separator for grouping items within an `hx-menu`.\n *\n * @summary Horizontal divider between menu sections.\n *\n * @tag hx-menu-divider\n *\n * @csspart base - The root separator element.\n *\n * @cssprop [--hx-menu-divider-color=var(--hx-color-neutral-200)] - Divider line color.\n */\n@customElement('hx-menu-divider')\nexport class HelixMenuDivider extends HelixElement {\n static override styles = [helixMenuDividerStyles, forcedColorsInteractive];\n\n override render() {\n return html`<div\n part=\"base\"\n class=\"menu-divider\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n ></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-divider': HelixMenuDivider;\n }\n}\n"],"names":["helixMenuStyles","css","HelixMenu","HelixElement","item","items","activeIndex","i","first","last","index","target","active","_a","idx","char","match","slot","validTags","invalid","el","devWarn","detail","html","forcedColorsInteractive","__decorateClass","property","customElement","helixMenuItemStyles","HelixMenuItem","value","open","options","menu","sibling","role","hasCheckableRole","classes","classMap","nothing","state","query","helixMenuDividerStyles","HelixMenuDivider"],"mappings":"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"}
|
|
@@ -20,8 +20,7 @@ const S = x`
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.meter:focus-visible {
|
|
23
|
-
outline: var(--hx-focus-ring-width, 2px) solid
|
|
24
|
-
var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797));
|
|
23
|
+
outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);
|
|
25
24
|
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -252,4 +251,4 @@ a = n([
|
|
|
252
251
|
export {
|
|
253
252
|
a as H
|
|
254
253
|
};
|
|
255
|
-
//# sourceMappingURL=hx-meter-
|
|
254
|
+
//# sourceMappingURL=hx-meter-BPscsw5t.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-meter-BPscsw5t.js","sources":["../../src/components/hx-meter/hx-meter.styles.ts","../../src/components/hx-meter/hx-meter.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMeterStyles = css`\n :host {\n display: block;\n width: 100%;\n }\n\n .meter {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n outline: none;\n border-radius: var(--hx-border-radius-md, 0.375rem);\n }\n\n .meter:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .meter__label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-meter-label-color, var(--hx-color-neutral-700, #313e4b));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .meter__track {\n position: relative;\n width: 100%;\n height: var(--hx-meter-track-height, var(--hx-space-2, 0.5rem));\n background-color: var(--hx-meter-track-color, var(--hx-color-neutral-200, #d6dbd5));\n border-radius: var(--hx-meter-track-radius, var(--hx-border-radius-full, 9999px));\n overflow: hidden;\n }\n\n .meter__indicator {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n height: 100%;\n width: 100%;\n border-radius: inherit;\n background-color: var(--_indicator-color);\n transform-origin: left center;\n transform: scaleX(var(--_value-ratio, 0));\n transition:\n transform var(--hx-transition-fast, 150ms ease),\n background-color var(--hx-transition-fast, 150ms ease);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .meter__indicator {\n transition: none;\n }\n }\n\n /* ─── Default (no thresholds configured) ─── */\n\n :host {\n --_indicator-color: var(--hx-meter-indicator-color, var(--hx-color-primary-500, #429797));\n }\n\n /* ─── Semantic state colors ─── */\n\n :host([data-state='optimum']) {\n --_indicator-color: var(--hx-meter-color-optimum, var(--hx-color-success-500, #3b9e58));\n }\n\n :host([data-state='warning']) {\n --_indicator-color: var(--hx-meter-color-warning, var(--hx-color-warning-500, #c2711c));\n }\n\n :host([data-state='danger']) {\n --_indicator-color: var(--hx-meter-color-danger, var(--hx-color-error-500, #e5493e));\n }\n\n /* ─── State Label (WCAG 1.4.1) ─── */\n /* Visible text label rendered below the track when a semantic state is active. */\n /* Ensures the meter state is not conveyed by fill color alone. */\n /* aria-hidden=\"true\" because aria-valuetext already includes the state for AT. */\n\n .meter__state-label {\n font-size: var(--hx-font-size-xs, 0.75rem);\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-tight, 1.25);\n font-family: var(--hx-meter-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n .meter__state-label[data-state='optimum'] {\n color: var(--hx-meter-color-optimum, var(--hx-color-success-700, #146831));\n }\n\n .meter__state-label[data-state='warning'] {\n color: var(--hx-meter-color-warning, var(--hx-color-warning-700, #804605));\n }\n\n .meter__state-label[data-state='danger'] {\n color: var(--hx-meter-color-danger, var(--hx-color-error-700, #a21312));\n }\n\n /* ─── Native meter hidden (we use custom rendering) ─── */\n\n .meter__native {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .meter__track {\n border: 1px solid CanvasText;\n }\n\n .meter__indicator {\n forced-color-adjust: none;\n background-color: Highlight;\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 { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixMeterStyles } from './hx-meter.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\n\ntype MeterState = 'optimum' | 'warning' | 'danger' | 'default';\n\nconst _nextMeterId = createIdCounter('hx-meter');\n\n/**\n * A scalar measurement within a known range — e.g., disk usage, health score,\n * or any numeric value with defined min/max bounds. Supports low/high/optimum\n * threshold markers for semantic color feedback.\n *\n * @summary Scalar measurement gauge within a defined range.\n *\n * @tag hx-meter\n *\n * @slot label - Visible label rendered above the meter track. When using this\n * slot without the `label` attribute, the accessible name is derived from the\n * slot content via `aria-labelledby`. The `label` attribute is NOT required\n * when slot content is provided — the component detects slot content and\n * switches to `aria-labelledby` automatically.\n *\n * @csspart base - The outer wrapper element.\n * @csspart track - The unfilled track bar element.\n * @csspart indicator - The filled bar indicating the current value.\n * @csspart label - The label wrapper element.\n *\n * @cssprop [--hx-meter-track-height] - Height of the track bar.\n * @cssprop [--hx-meter-track-color] - Background color of the unfilled track.\n * @cssprop [--hx-meter-track-radius] - Border radius of the track.\n * @cssprop [--hx-meter-indicator-color] - Default filled bar color (no thresholds).\n * @cssprop [--hx-meter-color-optimum] - Color when value is in the optimum zone.\n * @cssprop [--hx-meter-color-warning] - Color when value is in a warning zone.\n * @cssprop [--hx-meter-color-danger] - Color when value is in the danger zone.\n * @cssprop [--hx-meter-label-color] - Label text color.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-success-500] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-meter-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-color-success-700] - Color.\n * @cssprop [--hx-color-warning-700] - Color.\n * @cssprop [--hx-color-error-700] - Color.\n */\n@customElement('hx-meter')\nexport class HelixMeter extends HelixElement {\n static override styles = [helixMeterStyles, forcedColorsSurface];\n\n /** @internal */\n private _uid = _nextMeterId();\n\n /**\n * Current value of the meter.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value = 0;\n\n /**\n * Minimum value of the range.\n * @attr min\n */\n @property({ type: Number, reflect: true })\n min = 0;\n\n /**\n * Maximum value of the range.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Threshold below which the value is considered suboptimal (lower range warning).\n * @attr low\n */\n @property({ type: Number, reflect: true })\n low?: number;\n\n /**\n * Threshold above which the value is considered suboptimal (upper range warning).\n * @attr high\n */\n @property({ type: Number, reflect: true })\n high?: number;\n\n /**\n * The optimal value within the range. Used to determine which zone is \"good\".\n * @attr optimum\n */\n @property({ type: Number, reflect: true })\n optimum?: number;\n\n /**\n * Accessible label for the meter. Used as the visible label text and as\n * the source for `aria-labelledby`. When only slot content is provided\n * (no `label` attribute), the slot content is used for the accessible name.\n * @attr label\n */\n @property({ type: String })\n label?: string;\n\n /** @internal */\n @state()\n private _hasSlotContent = false;\n\n /** @internal */\n private _clampedValue(): number {\n return Math.min(Math.max(this.value, this.min), this.max);\n }\n\n /** @internal */\n private _percentage(): number {\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((this._clampedValue() - this.min) / range) * 100;\n }\n\n /** @internal */\n private _resolveState(): MeterState {\n const v = this._clampedValue();\n const hasLow = this.low !== undefined;\n const hasHigh = this.high !== undefined;\n const hasOptimum = this.optimum !== undefined;\n\n if (!hasLow && !hasHigh && !hasOptimum) return 'default';\n\n // When hasLow/hasHigh/hasOptimum are true, the corresponding property is defined.\n // Use nullish coalescing to satisfy the type checker while preserving the runtime logic.\n const lowVal = this.low ?? 0;\n const highVal = this.high ?? this.max;\n const inLowZone = hasLow && v < lowVal;\n const inHighZone = hasHigh && v > highVal;\n const inMiddleZone = !inLowZone && !inHighZone;\n\n if (!hasOptimum) {\n if (inLowZone || inHighZone) return 'warning';\n return 'optimum';\n }\n\n const opt = this.optimum ?? this.min;\n const optimumInLow = hasLow && opt < lowVal;\n const optimumInHigh = hasHigh && opt > highVal;\n const optimumInMiddle = !optimumInLow && !optimumInHigh;\n\n if (optimumInMiddle) {\n if (inMiddleZone) return 'optimum';\n return 'warning';\n } else if (optimumInLow) {\n if (inLowZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n } else {\n // optimumInHigh\n if (inHighZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n }\n }\n\n /** @internal */\n private _onLabelSlotChange(e: Event) {\n const slot = e.target as HTMLSlotElement;\n this._hasSlotContent = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // Set data-state on host so :host([data-state]) CSS selectors work\n this.dataset['state'] = this._resolveState();\n // Set --_value-ratio for GPU-compositable scaleX() transform on indicator\n const ratio = this._percentage() / 100;\n this.style.setProperty('--_value-ratio', String(Math.max(0, Math.min(1, ratio))));\n }\n\n // ─── WCAG 1.4.1: State label map ───\n // The indicator bar color alone is insufficient for color-blind users.\n // A visible state label is rendered below the track when a semantic state\n // (optimum/warning/danger) is active, providing a non-color visual cue.\n // aria-valuetext already embeds the state for AT users.\n\n /** @internal */\n private static readonly _STATE_LABELS: Partial<Record<MeterState, string>> = {\n optimum: 'Optimum',\n warning: 'Warning',\n danger: 'Danger',\n };\n\n override render() {\n const state = this._resolveState();\n const clampedValue = this._clampedValue();\n const stateLabel = state !== 'default' ? ` — ${state}` : '';\n const ariaValuetext = `${clampedValue} of ${this.max}${stateLabel}`;\n const hasVisibleLabel = this.label !== undefined || this._hasSlotContent;\n const visibleStateLabel = HelixMeter._STATE_LABELS[state];\n\n return html`\n <div\n part=\"base\"\n class=\"meter\"\n role=\"meter\"\n tabindex=\"0\"\n aria-valuenow=${clampedValue}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-valuetext=${ariaValuetext}\n aria-label=${ifDefined(!hasVisibleLabel ? `${clampedValue} of ${this.max}` : undefined)}\n aria-labelledby=${ifDefined(hasVisibleLabel ? `${this._uid}-label` : undefined)}\n >\n <span\n id=${`${this._uid}-label`}\n part=\"label\"\n class=\"meter__label\"\n ?hidden=${!hasVisibleLabel}\n >\n <slot name=\"label\" @slotchange=${this._onLabelSlotChange}>${this.label ?? ''}</slot>\n </span>\n <div class=\"meter__track\" part=\"track\">\n <div part=\"indicator\" class=\"meter__indicator\"></div>\n </div>\n ${visibleStateLabel\n ? html`<span class=\"meter__state-label\" data-state=${state} aria-hidden=\"true\"\n >${visibleStateLabel}</span\n >`\n : nothing}\n <meter\n class=\"meter__native\"\n value=${clampedValue}\n min=${this.min}\n max=${this.max}\n low=${ifDefined(this.low)}\n high=${ifDefined(this.high)}\n optimum=${ifDefined(this.optimum)}\n aria-hidden=\"true\"\n tabindex=\"-1\"\n ></meter>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-meter': HelixMeter;\n }\n}\n"],"names":["helixMeterStyles","css","_nextMeterId","createIdCounter","HelixMeter","HelixElement","range","v","hasLow","hasHigh","hasOptimum","lowVal","highVal","inLowZone","inHighZone","inMiddleZone","opt","optimumInLow","optimumInHigh","slot","changedProperties","ratio","state","clampedValue","stateLabel","ariaValuetext","hasVisibleLabel","visibleStateLabel","html","ifDefined","nothing","forcedColorsSurface","__decorateClass","property","customElement"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { css as A, html as c, nothing as h } from "lit";
|
|
2
|
-
import { property as p, customElement as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const D = A`
|
|
2
|
+
import { property as p, customElement as T, state as $ } from "lit/decorators.js";
|
|
3
|
+
import { H as I } from "./helix-element-BNEYeiys.js";
|
|
4
|
+
import { c as E } from "./id-counter-DuX8vsui.js";
|
|
5
|
+
const S = A`
|
|
7
6
|
:host {
|
|
8
7
|
display: block;
|
|
9
8
|
height: 100%;
|
|
@@ -13,7 +12,7 @@ const D = A`
|
|
|
13
12
|
and evaluates their text against the page white background, producing
|
|
14
13
|
false-positive color-contrast violations (WCAG 2.1 AA). */
|
|
15
14
|
background-color: var(--hx-side-nav-bg, var(--hx-color-surface-inverse, #0d1825));
|
|
16
|
-
color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #
|
|
15
|
+
color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #ffffff));
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
* {
|
|
@@ -28,11 +27,14 @@ const D = A`
|
|
|
28
27
|
height: 100%;
|
|
29
28
|
width: var(--hx-side-nav-width, 16rem);
|
|
30
29
|
background-color: var(--hx-side-nav-bg, var(--hx-color-surface-inverse, #0d1825));
|
|
31
|
-
color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #
|
|
30
|
+
color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #ffffff));
|
|
32
31
|
transition: width var(--hx-transition-normal, 300ms) ease;
|
|
33
32
|
overflow: hidden;
|
|
34
33
|
border-inline-end: var(--hx-border-width-thin, 1px) solid
|
|
35
|
-
var(
|
|
34
|
+
var(
|
|
35
|
+
--hx-side-nav-border-color,
|
|
36
|
+
var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
|
|
37
|
+
);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/* ─── Collapsed State ─── */
|
|
@@ -50,7 +52,10 @@ const D = A`
|
|
|
50
52
|
flex-shrink: 0;
|
|
51
53
|
min-height: var(--hx-space-14, 3.5rem);
|
|
52
54
|
border-bottom: var(--hx-border-width-thin, 1px) solid
|
|
53
|
-
var(
|
|
55
|
+
var(
|
|
56
|
+
--hx-side-nav-border-color,
|
|
57
|
+
var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
|
|
58
|
+
);
|
|
54
59
|
overflow: hidden;
|
|
55
60
|
}
|
|
56
61
|
|
|
@@ -77,7 +82,10 @@ const D = A`
|
|
|
77
82
|
flex-shrink: 0;
|
|
78
83
|
min-height: var(--hx-space-14, 3.5rem);
|
|
79
84
|
border-top: var(--hx-border-width-thin, 1px) solid
|
|
80
|
-
var(
|
|
85
|
+
var(
|
|
86
|
+
--hx-side-nav-border-color,
|
|
87
|
+
var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
|
|
88
|
+
);
|
|
81
89
|
overflow: hidden;
|
|
82
90
|
}
|
|
83
91
|
|
|
@@ -100,7 +108,7 @@ const D = A`
|
|
|
100
108
|
border: none;
|
|
101
109
|
border-radius: var(--hx-border-radius-sm, 0.25rem);
|
|
102
110
|
background: transparent;
|
|
103
|
-
color: var(--hx-side-nav-toggle-color, var(--hx-color-text-inverse, #
|
|
111
|
+
color: var(--hx-side-nav-toggle-color, var(--hx-color-text-inverse, #ffffff));
|
|
104
112
|
cursor: pointer;
|
|
105
113
|
transition:
|
|
106
114
|
background-color var(--hx-transition-fast, 150ms) ease,
|
|
@@ -109,10 +117,10 @@ const D = A`
|
|
|
109
117
|
|
|
110
118
|
.side-nav__toggle:hover {
|
|
111
119
|
background-color: var(
|
|
112
|
-
--hx-
|
|
120
|
+
--hx-color-border-on-dark-subtle,
|
|
113
121
|
rgba(255, 255, 255, 0.1)
|
|
114
122
|
); /* fallback for browsers without color-mix() */
|
|
115
|
-
color: var(--hx-color-text-inverse, #
|
|
123
|
+
color: var(--hx-side-nav-toggle-hover-color, var(--hx-color-text-inverse, #ffffff));
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
@supports (color: color-mix(in srgb, red 50%, blue)) {
|
|
@@ -123,10 +131,7 @@ const D = A`
|
|
|
123
131
|
|
|
124
132
|
.side-nav__toggle:focus-visible {
|
|
125
133
|
outline: var(--hx-focus-ring-width, 2px) solid
|
|
126
|
-
var(
|
|
127
|
-
--hx-side-nav-focus-ring-color,
|
|
128
|
-
var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))
|
|
129
|
-
);
|
|
134
|
+
var(--hx-side-nav-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
|
|
130
135
|
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
131
136
|
}
|
|
132
137
|
|
|
@@ -172,22 +177,30 @@ const D = A`
|
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
.side-nav__toggle {
|
|
180
|
+
forced-color-adjust: none;
|
|
181
|
+
background-color: ButtonFace;
|
|
175
182
|
color: ButtonText;
|
|
176
183
|
border: 1px solid ButtonText;
|
|
177
184
|
}
|
|
178
185
|
|
|
186
|
+
.side-nav__toggle:hover {
|
|
187
|
+
background-color: Highlight;
|
|
188
|
+
color: HighlightText;
|
|
189
|
+
border-color: Highlight;
|
|
190
|
+
}
|
|
191
|
+
|
|
179
192
|
.side-nav__toggle:focus-visible {
|
|
180
193
|
outline: 3px solid Highlight;
|
|
181
194
|
outline-offset: 2px;
|
|
182
195
|
}
|
|
183
196
|
}
|
|
184
197
|
`;
|
|
185
|
-
var
|
|
186
|
-
for (var t = i > 1 ? void 0 : i ?
|
|
187
|
-
(n = e[l]) && (t = (i ? n(
|
|
188
|
-
return i && t &&
|
|
198
|
+
var H = Object.defineProperty, B = Object.getOwnPropertyDescriptor, u = (e, o, a, i) => {
|
|
199
|
+
for (var t = i > 1 ? void 0 : i ? B(o, a) : o, l = e.length - 1, n; l >= 0; l--)
|
|
200
|
+
(n = e[l]) && (t = (i ? n(o, a, t) : n(t)) || t);
|
|
201
|
+
return i && t && H(o, a, t), t;
|
|
189
202
|
};
|
|
190
|
-
let x = class extends
|
|
203
|
+
let x = class extends I {
|
|
191
204
|
constructor() {
|
|
192
205
|
super(...arguments), this.collapsed = !1, this.label = "Main Navigation";
|
|
193
206
|
}
|
|
@@ -203,11 +216,11 @@ let x = class extends E {
|
|
|
203
216
|
*/
|
|
204
217
|
/** @internal */
|
|
205
218
|
_propagateCollapsedToChildren() {
|
|
206
|
-
var
|
|
207
|
-
const e = (
|
|
219
|
+
var a;
|
|
220
|
+
const e = (a = this.shadowRoot) == null ? void 0 : a.querySelector("slot:not([name])");
|
|
208
221
|
if (!e) return;
|
|
209
|
-
const
|
|
210
|
-
for (const i of
|
|
222
|
+
const o = e.assignedElements({ flatten: !0 }).filter((i) => i.tagName.toLowerCase() === "hx-nav-item");
|
|
223
|
+
for (const i of o)
|
|
211
224
|
i instanceof HTMLElement && (this.collapsed ? i.setAttribute("data-collapsed", "") : i.removeAttribute("data-collapsed"));
|
|
212
225
|
}
|
|
213
226
|
/**
|
|
@@ -227,18 +240,18 @@ let x = class extends E {
|
|
|
227
240
|
*/
|
|
228
241
|
/** @internal */
|
|
229
242
|
_handleKeydown(e) {
|
|
230
|
-
var b, w, y,
|
|
243
|
+
var b, w, y, k, C;
|
|
231
244
|
if (!["ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft", "Home", "End"].includes(e.key)) return;
|
|
232
|
-
const
|
|
233
|
-
if (!
|
|
234
|
-
const i =
|
|
235
|
-
(
|
|
245
|
+
const a = (b = this.shadowRoot) == null ? void 0 : b.querySelector("slot:not([name])");
|
|
246
|
+
if (!a) return;
|
|
247
|
+
const i = a.assignedElements({ flatten: !0 }).filter(
|
|
248
|
+
(r) => r.tagName.toLowerCase() === "hx-nav-item" && !r.hasAttribute("disabled")
|
|
236
249
|
);
|
|
237
250
|
if (i.length === 0) return;
|
|
238
251
|
const t = [];
|
|
239
|
-
for (const
|
|
240
|
-
if (t.push(
|
|
241
|
-
const s = (w =
|
|
252
|
+
for (const r of i)
|
|
253
|
+
if (t.push(r), r.hasAttribute("expanded")) {
|
|
254
|
+
const s = (w = r.shadowRoot) == null ? void 0 : w.querySelector('slot[name="children"]');
|
|
242
255
|
if (s) {
|
|
243
256
|
const g = s.assignedElements({ flatten: !0 }).filter(
|
|
244
257
|
(m) => m.tagName.toLowerCase() === "hx-nav-item" && !m.hasAttribute("disabled")
|
|
@@ -249,22 +262,22 @@ let x = class extends E {
|
|
|
249
262
|
if (t.length === 0) return;
|
|
250
263
|
const l = document.activeElement;
|
|
251
264
|
let n = -1;
|
|
252
|
-
for (let
|
|
253
|
-
const s = t[
|
|
265
|
+
for (let r = 0; r < t.length; r++) {
|
|
266
|
+
const s = t[r];
|
|
254
267
|
if (s && (s === l || s.contains(l) || ((y = s.shadowRoot) == null ? void 0 : y.contains(l)) === !0)) {
|
|
255
|
-
n =
|
|
268
|
+
n = r;
|
|
256
269
|
break;
|
|
257
270
|
}
|
|
258
271
|
}
|
|
259
272
|
if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
260
273
|
e.preventDefault();
|
|
261
|
-
const
|
|
262
|
-
if (!
|
|
274
|
+
const r = n >= 0 ? t[n] : null;
|
|
275
|
+
if (!r) return;
|
|
263
276
|
if (e.key === "ArrowRight") {
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
else if (
|
|
267
|
-
const s = (
|
|
277
|
+
if (r.hasAttribute("expanded") === !1 && r.querySelector('[slot="children"]'))
|
|
278
|
+
r.setAttribute("expanded", ""), r.expanded = !0;
|
|
279
|
+
else if (r.hasAttribute("expanded")) {
|
|
280
|
+
const s = (k = r.shadowRoot) == null ? void 0 : k.querySelector('slot[name="children"]');
|
|
268
281
|
if (s) {
|
|
269
282
|
const g = s.assignedElements({ flatten: !0 }).find(
|
|
270
283
|
(m) => m.tagName.toLowerCase() === "hx-nav-item" && !m.hasAttribute("disabled")
|
|
@@ -275,10 +288,10 @@ let x = class extends E {
|
|
|
275
288
|
}
|
|
276
289
|
}
|
|
277
290
|
}
|
|
278
|
-
} else if (
|
|
279
|
-
|
|
291
|
+
} else if (r.hasAttribute("expanded"))
|
|
292
|
+
r.removeAttribute("expanded"), r.expanded = !1;
|
|
280
293
|
else {
|
|
281
|
-
const s =
|
|
294
|
+
const s = r.closest("hx-nav-item:not(:scope)") ?? ((C = r.parentElement) == null ? void 0 : C.closest("hx-nav-item")) ?? null;
|
|
282
295
|
s && !s.hasAttribute("disabled") && s.focus();
|
|
283
296
|
}
|
|
284
297
|
return;
|
|
@@ -342,7 +355,7 @@ let x = class extends E {
|
|
|
342
355
|
`;
|
|
343
356
|
}
|
|
344
357
|
};
|
|
345
|
-
x.styles = [
|
|
358
|
+
x.styles = [S];
|
|
346
359
|
u([
|
|
347
360
|
p({ type: Boolean, reflect: !0 })
|
|
348
361
|
], x.prototype, "collapsed", 2);
|
|
@@ -350,9 +363,9 @@ u([
|
|
|
350
363
|
p({ type: String })
|
|
351
364
|
], x.prototype, "label", 2);
|
|
352
365
|
x = u([
|
|
353
|
-
|
|
366
|
+
T("hx-side-nav")
|
|
354
367
|
], x);
|
|
355
|
-
const
|
|
368
|
+
const N = A`
|
|
356
369
|
:host {
|
|
357
370
|
display: block;
|
|
358
371
|
/* The host background must be a concrete color so that axe-core can
|
|
@@ -427,10 +440,7 @@ const B = A`
|
|
|
427
440
|
|
|
428
441
|
.nav-item__link:focus-visible {
|
|
429
442
|
outline: var(--hx-focus-ring-width, 2px) solid
|
|
430
|
-
var(
|
|
431
|
-
--hx-nav-item-focus-ring-color,
|
|
432
|
-
var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))
|
|
433
|
-
);
|
|
443
|
+
var(--hx-nav-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
|
|
434
444
|
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
435
445
|
}
|
|
436
446
|
|
|
@@ -438,16 +448,25 @@ const B = A`
|
|
|
438
448
|
|
|
439
449
|
:host([active]) .nav-item__link {
|
|
440
450
|
/* Active state sits on the darker primary-600 (#0F7078) fill. White text
|
|
441
|
-
(#ffffff) on primary-600 = 5.
|
|
451
|
+
(#ffffff) on primary-600 = 5.82:1 WCAG AA pass. text-on-primary now
|
|
442
452
|
resolves to neutral-900 (intended for the lighter primary-500 surface)
|
|
443
|
-
which would fail here
|
|
444
|
-
|
|
445
|
-
|
|
453
|
+
which would fail here. text.on-primary-strong holds at neutral-0 across
|
|
454
|
+
modes (no dark flip) so the active fg stays AA. 3.2.1: routed through
|
|
455
|
+
the action.* / on-{role}-strong semantic tier per token-cascade
|
|
456
|
+
remediation (no more bare primary-600 / neutral-0 consumption). */
|
|
457
|
+
background-color: var(
|
|
458
|
+
--hx-nav-item-active-bg,
|
|
459
|
+
var(--hx-color-action-primary-bg-hover, #0f7078)
|
|
460
|
+
);
|
|
461
|
+
color: var(--hx-nav-item-active-color, var(--hx-color-text-on-primary-strong, #ffffff));
|
|
446
462
|
}
|
|
447
463
|
|
|
448
464
|
:host([active]) .nav-item__link:hover {
|
|
449
|
-
/* text
|
|
450
|
-
background-color: var(
|
|
465
|
+
/* text.on-primary-strong (#ffffff) on primary-700 (#0F6363) = WCAG AA ✓ */
|
|
466
|
+
background-color: var(
|
|
467
|
+
--hx-nav-item-active-hover-bg,
|
|
468
|
+
var(--hx-color-action-primary-bg-active, #0f6363)
|
|
469
|
+
);
|
|
451
470
|
}
|
|
452
471
|
|
|
453
472
|
/* ─── Disabled State ─── */
|
|
@@ -538,9 +557,10 @@ const B = A`
|
|
|
538
557
|
top: 50%;
|
|
539
558
|
transform: translateY(-50%);
|
|
540
559
|
/* tooltip is an inverted surface — flips per mode via surface-inverse /
|
|
541
|
-
text-inverse.
|
|
542
|
-
|
|
543
|
-
color: var(--hx-color-
|
|
560
|
+
text-inverse. 3.2.1: wrapped with component-tier slots so consumers can
|
|
561
|
+
theme tooltip surface/text without overriding the global semantics. */
|
|
562
|
+
background-color: var(--hx-nav-item-tooltip-bg, var(--hx-color-surface-inverse, #0d1825));
|
|
563
|
+
color: var(--hx-nav-item-tooltip-color, var(--hx-color-text-inverse, #ffffff));
|
|
544
564
|
padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);
|
|
545
565
|
border-radius: var(--hx-border-radius-sm, 0.25rem);
|
|
546
566
|
font-size: var(--hx-font-size-xs, 0.75rem);
|
|
@@ -603,8 +623,38 @@ const B = A`
|
|
|
603
623
|
/* ─── Forced Colors (Windows High Contrast) ─── */
|
|
604
624
|
|
|
605
625
|
@media (forced-colors: active) {
|
|
606
|
-
|
|
607
|
-
|
|
626
|
+
/*
|
|
627
|
+
* Bespoke block — sole owner of forced-colors deference for hx-nav-item
|
|
628
|
+
* (the forcedColorsInteractive mixin is intentionally NOT composed; XOR
|
|
629
|
+
* rule in styles/forced-colors.ts). Mirrors the mixin's interactive
|
|
630
|
+
* contract (ButtonFace / ButtonText / Highlight on hover, GrayText on
|
|
631
|
+
* disabled) for the .nav-item__link interactive surface, then layers the
|
|
632
|
+
* component-specific active-state border and tooltip border on top.
|
|
633
|
+
*/
|
|
634
|
+
.nav-item__link {
|
|
635
|
+
forced-color-adjust: none;
|
|
636
|
+
background-color: ButtonFace;
|
|
637
|
+
color: ButtonText;
|
|
638
|
+
border: 1px solid ButtonText;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.nav-item__link:hover {
|
|
642
|
+
background-color: Highlight;
|
|
643
|
+
color: HighlightText;
|
|
644
|
+
border-color: Highlight;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
:host([disabled]) {
|
|
648
|
+
opacity: 1;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
:host([disabled]) .nav-item__link {
|
|
652
|
+
color: GrayText;
|
|
653
|
+
border-color: GrayText;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
:host([active]:not([disabled])) .nav-item__link {
|
|
657
|
+
border-color: Highlight;
|
|
608
658
|
}
|
|
609
659
|
|
|
610
660
|
.nav-item__link:focus-visible {
|
|
@@ -617,22 +667,22 @@ const B = A`
|
|
|
617
667
|
}
|
|
618
668
|
}
|
|
619
669
|
`;
|
|
620
|
-
var
|
|
621
|
-
for (var t = i > 1 ? void 0 : i ? j(
|
|
622
|
-
(n = e[l]) && (t = (i ? n(
|
|
623
|
-
return i && t &&
|
|
670
|
+
var D = Object.defineProperty, j = Object.getOwnPropertyDescriptor, v = (e, o, a, i) => {
|
|
671
|
+
for (var t = i > 1 ? void 0 : i ? j(o, a) : o, l = e.length - 1, n; l >= 0; l--)
|
|
672
|
+
(n = e[l]) && (t = (i ? n(o, a, t) : n(t)) || t);
|
|
673
|
+
return i && t && D(o, a, t), t;
|
|
624
674
|
};
|
|
625
|
-
const
|
|
626
|
-
let d = class extends
|
|
675
|
+
const L = E("hx-nav-item");
|
|
676
|
+
let d = class extends I {
|
|
627
677
|
constructor() {
|
|
628
|
-
super(...arguments), this._tooltipId = `${
|
|
678
|
+
super(...arguments), this._tooltipId = `${L()}-tooltip`, this.href = "", this.active = !1, this.expanded = !1, this.disabled = !1, this._hasChildren = !1, this._isCollapsed = !1;
|
|
629
679
|
}
|
|
630
680
|
// ─── Attribute Observer ───
|
|
631
681
|
static get observedAttributes() {
|
|
632
682
|
return [...super.observedAttributes, "data-collapsed"];
|
|
633
683
|
}
|
|
634
|
-
attributeChangedCallback(e,
|
|
635
|
-
super.attributeChangedCallback(e,
|
|
684
|
+
attributeChangedCallback(e, o, a) {
|
|
685
|
+
super.attributeChangedCallback(e, o, a), e === "data-collapsed" && (this._isCollapsed = a !== null);
|
|
636
686
|
}
|
|
637
687
|
// ─── Public API ───
|
|
638
688
|
/**
|
|
@@ -642,22 +692,22 @@ let d = class extends E {
|
|
|
642
692
|
* direct shadowRoot queries.
|
|
643
693
|
*/
|
|
644
694
|
focus(e) {
|
|
645
|
-
var
|
|
646
|
-
const
|
|
647
|
-
|
|
695
|
+
var a;
|
|
696
|
+
const o = (a = this.shadowRoot) == null ? void 0 : a.querySelector('[part="link"]');
|
|
697
|
+
o ? o.focus(e) : super.focus(e);
|
|
648
698
|
}
|
|
649
699
|
// ─── Slot Change Handler ───
|
|
650
700
|
/** @internal */
|
|
651
701
|
_onChildrenSlotChange(e) {
|
|
652
|
-
const
|
|
653
|
-
this._hasChildren =
|
|
702
|
+
const o = e.target;
|
|
703
|
+
this._hasChildren = o.assignedNodes({ flatten: !0 }).length > 0;
|
|
654
704
|
}
|
|
655
705
|
// ─── Private Helpers ───
|
|
656
706
|
/** @internal */
|
|
657
707
|
_getDirectText() {
|
|
658
708
|
return Array.from(this.childNodes).filter((e) => e.nodeType === Node.TEXT_NODE).map((e) => {
|
|
659
|
-
var
|
|
660
|
-
return ((
|
|
709
|
+
var o;
|
|
710
|
+
return ((o = e.textContent) == null ? void 0 : o.trim()) ?? "";
|
|
661
711
|
}).filter(Boolean).join(" ");
|
|
662
712
|
}
|
|
663
713
|
/** @internal */
|
|
@@ -676,7 +726,7 @@ let d = class extends E {
|
|
|
676
726
|
}
|
|
677
727
|
// ─── Render ───
|
|
678
728
|
render() {
|
|
679
|
-
const e = this._getDirectText(),
|
|
729
|
+
const e = this._getDirectText(), o = c`
|
|
680
730
|
<span part="icon" class="nav-item__icon">
|
|
681
731
|
<slot name="icon"></slot>
|
|
682
732
|
</span>
|
|
@@ -688,7 +738,7 @@ let d = class extends E {
|
|
|
688
738
|
</span>
|
|
689
739
|
${this._hasChildren ? this._renderExpandArrow() : h}
|
|
690
740
|
${this._isCollapsed ? c`<span id=${this._tooltipId} class="nav-item__tooltip" role="tooltip">${e}</span>` : h}
|
|
691
|
-
`,
|
|
741
|
+
`, a = this.href && !this._hasChildren ? c`<a
|
|
692
742
|
part="link"
|
|
693
743
|
class="nav-item__link"
|
|
694
744
|
href=${this.href}
|
|
@@ -697,7 +747,7 @@ let d = class extends E {
|
|
|
697
747
|
aria-describedby=${this._isCollapsed ? this._tooltipId : h}
|
|
698
748
|
tabindex=${this.disabled ? "-1" : "0"}
|
|
699
749
|
>
|
|
700
|
-
${
|
|
750
|
+
${o}
|
|
701
751
|
</a>` : c`<button
|
|
702
752
|
part="link"
|
|
703
753
|
class="nav-item__link"
|
|
@@ -707,11 +757,11 @@ let d = class extends E {
|
|
|
707
757
|
tabindex=${this.disabled ? "-1" : "0"}
|
|
708
758
|
@click=${this._handleToggle}
|
|
709
759
|
>
|
|
710
|
-
${
|
|
760
|
+
${o}
|
|
711
761
|
</button>`;
|
|
712
762
|
return c`
|
|
713
763
|
<div class="nav-item">
|
|
714
|
-
${
|
|
764
|
+
${a}
|
|
715
765
|
<div part="children" class="nav-item__children" role="group">
|
|
716
766
|
<div class="nav-item__children-inner">
|
|
717
767
|
<slot name="children" @slotchange=${this._onChildrenSlotChange}></slot>
|
|
@@ -721,7 +771,7 @@ let d = class extends E {
|
|
|
721
771
|
`;
|
|
722
772
|
}
|
|
723
773
|
};
|
|
724
|
-
d.styles = [
|
|
774
|
+
d.styles = [N];
|
|
725
775
|
v([
|
|
726
776
|
p({ type: String })
|
|
727
777
|
], d.prototype, "href", 2);
|
|
@@ -735,16 +785,16 @@ v([
|
|
|
735
785
|
p({ type: Boolean, reflect: !0 })
|
|
736
786
|
], d.prototype, "disabled", 2);
|
|
737
787
|
v([
|
|
738
|
-
|
|
788
|
+
$()
|
|
739
789
|
], d.prototype, "_hasChildren", 2);
|
|
740
790
|
v([
|
|
741
|
-
|
|
791
|
+
$()
|
|
742
792
|
], d.prototype, "_isCollapsed", 2);
|
|
743
793
|
d = v([
|
|
744
|
-
|
|
794
|
+
T("hx-nav-item")
|
|
745
795
|
], d);
|
|
746
796
|
export {
|
|
747
797
|
d as H,
|
|
748
798
|
x as a
|
|
749
799
|
};
|
|
750
|
-
//# sourceMappingURL=hx-nav-item-
|
|
800
|
+
//# sourceMappingURL=hx-nav-item-CqbO5-T5.js.map
|