@helixui/library 3.2.0-next.89 → 3.2.0-next.94
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 +30 -8
- 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 +19 -4
- 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-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/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/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/index.js +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 +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-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 +134 -152
- package/dist/css/helix-core.css +56 -15
- package/dist/css/helix-data.css +7 -14
- package/dist/css/helix-feedback.css +4 -5
- package/dist/css/helix-forms.css +42 -52
- package/dist/css/helix-layout.css +2 -8
- package/dist/css/helix-navigation.css +12 -33
- package/dist/css/helix-overlay.css +3 -12
- package/dist/css/helix-tokens.css +17 -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 +52 -5
- package/dist/css/hx-card.css +1 -4
- package/dist/css/hx-checkbox.css +2 -2
- package/dist/css/hx-clinical-status.css +2 -4
- package/dist/css/hx-code-snippet.css +4 -4
- package/dist/css/hx-color-picker.css +3 -13
- package/dist/css/hx-combobox.css +4 -4
- 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 +1 -1
- 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 +2 -2
- package/dist/css/hx-side-nav.css +4 -4
- 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 +4 -4
- package/dist/css/hx-textarea.css +2 -2
- package/dist/css/hx-time-picker.css +3 -3
- 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 +28 -25
- package/dist/index.js +42 -42
- 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-D3Royxqp.js → hx-button-D3gC-OJb.js} +74 -27
- package/dist/shared/hx-button-D3gC-OJb.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-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-CJrFeyz0.js} +5 -5
- package/dist/shared/{hx-code-snippet-CJ0FbQYG.js.map → hx-code-snippet-CJrFeyz0.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-M1yregCS.js} +5 -5
- package/dist/shared/{hx-combobox-DaA5dBC4.js.map → hx-combobox-M1yregCS.js.map} +1 -1
- 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-B4L_Nkm-.js} +11 -11
- package/dist/shared/{hx-file-upload-zTDbjsRw.js.map → hx-file-upload-B4L_Nkm-.js.map} +1 -1
- 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-C9zXD1zK.js → hx-nav-item-DH2tXcj1.js} +7 -7
- package/dist/shared/{hx-nav-item-C9zXD1zK.js.map → hx-nav-item-DH2tXcj1.js.map} +1 -1
- 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-zfIRr9qM.js} +3 -3
- package/dist/shared/{hx-select-vgaBo1Ai.js.map → hx-select-zfIRr9qM.js.map} +1 -1
- 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-ClrrmoE1.js → hx-text-input-Bn7Gn8CI.js} +5 -5
- 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/figma-inventory.json +47 -8
- package/package.json +2 -2
- package/dist/shared/hx-accordion-cnKg4_la.js.map +0 -1
- package/dist/shared/hx-button-D3Royxqp.js.map +0 -1
- package/dist/shared/hx-card-CU1QnjNb.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-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-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-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-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-ClrrmoE1.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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-split-panel-BVG1VWNT.js","sources":["../../src/components/hx-split-panel/hx-split-panel.styles.ts","../../src/components/hx-split-panel/hx-split-panel.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSplitPanelStyles = css`\n :host {\n display: flex;\n --_divider-size: var(--hx-split-panel-divider-size, 4px);\n --_divider-color: var(--hx-split-panel-divider-color, var(--hx-color-border-default, #d6dbd5));\n --_divider-hover-color: var(\n --hx-split-panel-divider-hover-color,\n var(--hx-color-primary-500, #429797)\n );\n overflow: hidden;\n }\n\n :host([orientation='horizontal']) {\n flex-direction: row;\n width: 100%;\n height: 100%;\n }\n\n :host([orientation='vertical']) {\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .panel {\n overflow: auto;\n min-width: 0;\n min-height: 0;\n }\n\n .panel--start {\n flex-shrink: 0;\n }\n\n .panel--end {\n flex: 1;\n }\n\n :host([orientation='horizontal']) .panel--start {\n height: 100%;\n }\n\n :host([orientation='vertical']) .panel--start {\n width: 100%;\n }\n\n /* ─── Divider Track (flex child wrapper) ─── */\n\n .divider-track {\n flex-shrink: 0;\n position: relative;\n overflow: visible;\n display: flex;\n align-items: stretch;\n }\n\n :host([orientation='horizontal']) .divider-track {\n width: var(--_divider-size);\n height: 100%;\n }\n\n :host([orientation='vertical']) .divider-track {\n width: 100%;\n height: var(--_divider-size);\n }\n\n /* ─── Divider (separator role — no interactive children) ─── */\n\n .divider {\n flex: 1;\n background-color: var(--_divider-color);\n cursor: col-resize;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n }\n\n :host([orientation='horizontal']) .divider {\n cursor: col-resize;\n }\n\n :host([orientation='vertical']) .divider {\n cursor: row-resize;\n }\n\n .divider:hover,\n .divider:focus-visible {\n background-color: var(--_divider-hover-color);\n }\n\n .divider:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-split-panel-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--_divider-hover-color) 30%, transparent);\n }\n\n :host([disabled]) .divider {\n cursor: default;\n pointer-events: none;\n }\n\n :host([disabled]) .divider:hover,\n :host([disabled]) .divider:focus-visible {\n background-color: var(--_divider-color);\n outline: none;\n box-shadow: none;\n }\n\n /* ─── Collapse Controls (siblings of separator, not children) ─── */\n\n .collapse-controls {\n position: absolute;\n top: 50%;\n inset-inline-start: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n z-index: 2;\n pointer-events: auto;\n }\n\n :host([orientation='vertical']) .collapse-controls {\n flex-direction: row;\n }\n\n .collapse-btn {\n background: var(--_divider-hover-color);\n border: 2px solid var(--hx-color-surface-default);\n color: var(--hx-color-surface-default);\n width: var(--hx-size-5, 1.25rem);\n height: var(--hx-size-5, 1.25rem);\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--hx-split-panel-btn-icon-size, 0.5rem);\n padding: 0;\n line-height: 1;\n flex-shrink: 0;\n /* WCAG 2.5.5: minimum 44×44px touch target via transparent hit-area */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n .collapse-btn:hover {\n filter: brightness(1.1);\n }\n\n .collapse-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-split-panel-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .divider {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .divider {\n background-color: CanvasText;\n }\n\n .collapse-btn {\n border-color: ButtonText;\n color: ButtonText;\n background: Canvas;\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 { styleMap } from 'lit/directives/style-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixSplitPanelStyles } from './hx-split-panel.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\n\n/**\n * A resizable two-pane layout with a draggable divider.\n *\n * @summary Resizable split panel with start and end panes.\n *\n * @tag hx-split-panel\n *\n * @slot start - The first (start) panel content.\n * @slot end - The second (end) panel content.\n *\n * @csspart start - The start panel container.\n * @csspart divider - The draggable divider element.\n * @csspart end - The end panel container.\n *\n * @fires hx-reposition - Fired when the divider is moved. Detail: `{ position: number }`.\n *\n * @cssprop [--hx-split-panel-divider-size=4px] - Width (horizontal) or height (vertical) of the divider.\n * @cssprop [--hx-split-panel-divider-color=var(--hx-color-neutral-200)] - Default divider color.\n * @cssprop [--hx-split-panel-divider-hover-color=var(--hx-color-primary-500)] - Divider color on hover/focus.\n *\n * @example Drupal Twig usage:\n * ```twig\n * <hx-split-panel\n * position=\"50\"\n * orientation=\"horizontal\"\n * min=\"10\"\n * max=\"90\"\n * collapsible\n * >\n * <div slot=\"start\">{{ start_content }}</div>\n * <div slot=\"end\">{{ end_content }}</div>\n * </hx-split-panel>\n *\n * Attribute-settable: position, position-in-pixels, orientation, disabled, min, max, collapsible, collapsed\n * JS-only (complex types): snap (use .snap=${[25, 50, 75]} in Lit templates,\n * or snap=\"[25,50,75]\" as JSON string in Twig)\n * ```\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-split-panel-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-size-5] - Size token.\n * @cssprop [--hx-split-panel-btn-icon-size=0.5rem] - CSS custom property.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n */\n@customElement('hx-split-panel')\nexport class HelixSplitPanel extends HelixElement {\n static override styles = [helixSplitPanelStyles, forcedColorsInteractive];\n\n /**\n * Position of the divider as a percentage (0–100) of the start panel.\n * @attr position\n */\n @property({ type: Number, reflect: true })\n position = 50;\n\n /**\n * Position of the divider in pixels (alternative to `position`).\n * When set, takes precedence over `position` until the host is measured.\n * @attr position-in-pixels\n */\n @property({ type: Number, attribute: 'position-in-pixels' })\n positionInPixels: number | undefined;\n\n /**\n * Orientation of the split.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Minimum position as a percentage (0–100). Prevents full collapse of start panel.\n * @attr min\n */\n @property({ type: Number, reflect: true })\n min = 0;\n\n /**\n * Maximum position as a percentage (0–100). Prevents full expansion of start panel.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Snap points as an array of percentages. The divider snaps to the\n * nearest point within a 5% threshold.\n * Accepts JSON array string in HTML: snap=\"[25, 50, 75]\"\n * @attr snap\n */\n @property({\n attribute: 'snap',\n converter: {\n fromAttribute(value: string | null): number[] {\n if (!value) return [];\n try {\n const parsed = JSON.parse(value) as unknown;\n if (Array.isArray(parsed)) return (parsed as unknown[]).map(Number);\n return [];\n } catch {\n return value\n .split(',')\n .map((s) => Number(s.trim()))\n .filter((n) => !isNaN(n));\n }\n },\n toAttribute(value: number[]): string {\n return JSON.stringify(value);\n },\n },\n })\n snap: number[] = [];\n\n /**\n * When true, the divider cannot be dragged.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * When true, collapse/expand buttons appear on the divider.\n * @attr collapsible\n */\n @property({ type: Boolean, reflect: true })\n collapsible = false;\n\n /**\n * Which panel is collapsed: 'start', 'end', or null (not collapsed).\n * @attr collapsed\n */\n @property({ type: String, reflect: true })\n collapsed: 'start' | 'end' | null = null;\n\n /**\n * Accessible label for the divider separator element.\n * @attr resize-label\n */\n @property({ attribute: 'resize-label' })\n resizeLabel = 'Resize panels';\n\n /**\n * Accessible label for the button that collapses the start panel.\n * @attr collapse-start-label\n */\n @property({ attribute: 'collapse-start-label' })\n collapseStartLabel = 'Collapse start panel';\n\n /**\n * Accessible label for the button that collapses the end panel.\n * @attr collapse-end-label\n */\n @property({ attribute: 'collapse-end-label' })\n collapseEndLabel = 'Collapse end panel';\n\n /**\n * The resolved (clamped + snapped) position used for rendering and ARIA.\n * Derived from `position` in `willUpdate` to avoid mutating a reflected\n * `@property` inside the update lifecycle (which would trigger a re-entrant\n * update cycle).\n * @internal\n */\n @state() private _resolvedPosition = 50;\n\n /**\n * Whether the user is currently dragging the divider.\n * @internal\n */\n private _dragging = false;\n /**\n * The pointer coordinate (clientX or clientY) at the start of a drag gesture.\n * @internal\n */\n private _dragStart = 0;\n /**\n * The divider position percentage at the moment a drag gesture begins, used to compute deltas.\n * @internal\n */\n private _positionAtDragStart = 0;\n /**\n * The position saved before a collapse occurs, restored when the panel is expanded.\n * @internal\n */\n private _positionBeforeCollapse = 50;\n /**\n * Cached container width measured once at drag start to avoid layout thrash on every pointermove.\n * @internal\n */\n private _cachedContainerWidth = 0;\n /**\n * Cached container height measured once at drag start to avoid layout thrash on every pointermove.\n * @internal\n */\n private _cachedContainerHeight = 0;\n\n /** @internal */\n private _clamp(value: number): number {\n return Math.min(this.max, Math.max(this.min, value));\n }\n\n /** @internal */\n private _snapToPoint(value: number): number {\n if (!this.snap.length) return value;\n const threshold = 5;\n for (const point of this.snap) {\n if (Math.abs(value - point) <= threshold) return point;\n }\n return value;\n }\n\n /** @internal */\n private _setPosition(percent: number): void {\n const clamped = this._clamp(this._snapToPoint(percent));\n if (clamped === this._resolvedPosition) return;\n this._resolvedPosition = clamped;\n this.position = clamped;\n this.dispatchEvent(\n new CustomEvent<{ position: number }>('hx-reposition', {\n detail: { position: this._resolvedPosition },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n /** @internal */\n private _getHostSize(): number {\n if (this.orientation === 'horizontal') {\n return this.offsetWidth;\n }\n return this.offsetHeight;\n }\n\n /**\n * Initiates a drag gesture when the divider receives a pointerdown event.\n * @internal\n */\n private _onPointerDown = (e: PointerEvent): void => {\n if (this.disabled) return;\n const divider = e.currentTarget as HTMLElement;\n divider.setPointerCapture(e.pointerId);\n this._dragging = true;\n this._dragStart = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n this._positionAtDragStart = this._resolvedPosition;\n // Cache container dimensions once at drag start to avoid forced layout on every pointermove\n this._cachedContainerWidth = this.offsetWidth;\n this._cachedContainerHeight = this.offsetHeight;\n e.preventDefault();\n };\n\n /**\n * Updates the divider position during an active drag gesture.\n * @internal\n */\n private _onPointerMove = (e: PointerEvent): void => {\n if (!this._dragging) return;\n const current = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n const delta = current - this._dragStart;\n const hostSize =\n this.orientation === 'horizontal' ? this._cachedContainerWidth : this._cachedContainerHeight;\n if (hostSize === 0) return;\n const deltaPercent = (delta / hostSize) * 100;\n this._setPosition(this._positionAtDragStart + deltaPercent);\n };\n\n /**\n * Ends the drag gesture when the pointer is released.\n * @internal\n */\n private _onPointerUp = (): void => {\n this._dragging = false;\n this._cachedContainerWidth = 0;\n this._cachedContainerHeight = 0;\n };\n\n /**\n * Handles keyboard navigation on the divider — arrow keys adjust position, Home/End jump to min/max.\n * @internal\n */\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n switch (e.key) {\n case 'ArrowLeft':\n case 'ArrowUp':\n e.preventDefault();\n this._setPosition(this._resolvedPosition - 1);\n break;\n case 'ArrowRight':\n case 'ArrowDown':\n e.preventDefault();\n this._setPosition(this._resolvedPosition + 1);\n break;\n case 'PageUp':\n e.preventDefault();\n this._setPosition(this._resolvedPosition + 10);\n break;\n case 'PageDown':\n e.preventDefault();\n this._setPosition(this._resolvedPosition - 10);\n break;\n case 'Home':\n e.preventDefault();\n this._setPosition(this.min);\n break;\n case 'End':\n e.preventDefault();\n this._setPosition(this.max);\n break;\n }\n };\n\n /**\n * Collapses the start panel by setting `collapsed` to `'start'`.\n * @internal\n */\n private _collapseStart = (): void => {\n this.collapsed = 'start';\n };\n\n /**\n * Collapses the end panel by setting `collapsed` to `'end'`.\n * @internal\n */\n private _collapseEnd = (): void => {\n this.collapsed = 'end';\n };\n\n /**\n * Expands a collapsed panel by resetting `collapsed` to null.\n * @internal\n */\n private _expand = (): void => {\n this.collapsed = null;\n };\n\n protected override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n\n let handled = false;\n\n if (changedProperties.has('collapsed')) {\n const prev = changedProperties.get('collapsed');\n\n if (this.collapsed === 'start') {\n if (prev === null || prev === undefined)\n this._positionBeforeCollapse = this._resolvedPosition;\n this._resolvedPosition = this._clamp(this._snapToPoint(this.min));\n handled = true;\n } else if (this.collapsed === 'end') {\n if (prev === null || prev === undefined)\n this._positionBeforeCollapse = this._resolvedPosition;\n this._resolvedPosition = this._clamp(this._snapToPoint(this.max));\n handled = true;\n } else if (this.collapsed === null && prev !== null && prev !== undefined) {\n this._resolvedPosition = this._clamp(this._snapToPoint(this._positionBeforeCollapse));\n handled = true;\n }\n }\n\n if (\n !handled &&\n (changedProperties.has('position') ||\n changedProperties.has('min') ||\n changedProperties.has('max') ||\n changedProperties.has('snap'))\n ) {\n this._resolvedPosition = this._clamp(this._snapToPoint(this.position));\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (this.position !== this._resolvedPosition) {\n this.position = this._resolvedPosition;\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.positionInPixels !== undefined) {\n // Convert pixel position to percentage after first paint\n if (typeof requestAnimationFrame !== 'undefined') {\n requestAnimationFrame(() => {\n if (this.positionInPixels !== undefined) {\n const hostSize = this._getHostSize();\n if (hostSize > 0) {\n this._setPosition((this.positionInPixels / hostSize) * 100);\n }\n }\n });\n }\n }\n }\n\n /** @internal */\n private _startPanelStyleMap(): Record<string, string> {\n if (this.orientation === 'horizontal') {\n return { width: `${this._resolvedPosition}%` };\n }\n return { height: `${this._resolvedPosition}%` };\n }\n\n override render() {\n return html`\n <div part=\"start\" class=\"panel panel--start\" style=${styleMap(this._startPanelStyleMap())}>\n <slot name=\"start\"></slot>\n </div>\n <div class=\"divider-track\">\n <div\n part=\"divider\"\n class=\"divider\"\n role=\"separator\"\n aria-label=${this.resizeLabel}\n aria-orientation=${this.orientation === 'horizontal' ? 'vertical' : 'horizontal'}\n aria-valuenow=${this._resolvedPosition}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-disabled=${this.disabled ? 'true' : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n @pointerdown=${this._onPointerDown}\n @pointermove=${this._onPointerMove}\n @pointerup=${this._onPointerUp}\n @keydown=${this._onKeyDown}\n ></div>\n ${this.collapsible\n ? this.collapsed\n ? html`<div class=\"collapse-controls\">\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=${`Expand ${this.collapsed} panel`}\n @click=${this._expand}\n >\n ${this.collapsed === 'start' ? '▶' : '◀'}\n </button>\n </div>`\n : html`<div class=\"collapse-controls\">\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=${this.collapseStartLabel}\n @click=${this._collapseStart}\n >\n ◀\n </button>\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=${this.collapseEndLabel}\n @click=${this._collapseEnd}\n >\n ▶\n </button>\n </div>`\n : nothing}\n </div>\n <div part=\"end\" class=\"panel panel--end\">\n <slot name=\"end\"></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-split-panel': HelixSplitPanel;\n }\n}\n"],"names":["helixSplitPanelStyles","css","HelixSplitPanel","HelixElement","e","delta","hostSize","deltaPercent","value","threshold","point","percent","clamped","changedProperties","handled","prev","html","styleMap","nothing","forcedColorsInteractive","__decorateClass","property","parsed","s","n","state","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-step-DL3PbOzm.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(\n --hx-steps-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\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 svg {\n width: var(--hx-steps-indicator-icon-size, 1rem);\n height: 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-primary-500, #429797));\n background-color: var(--hx-steps-active-bg, var(--hx-color-primary-500, #429797));\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 { 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 <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n <span class=\"sr-only\">Complete</span>\n `;\n }\n\n /** @internal */\n private _renderXMark() {\n return html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-td-1zwTFLRw.js","sources":["../../src/components/hx-table/hx-table.styles.ts","../../src/components/hx-table/hx-table.ts","../../src/components/hx-table/hx-thead.ts","../../src/components/hx-table/hx-tbody.ts","../../src/components/hx-table/hx-tfoot.ts","../../src/components/hx-table/hx-tr.ts","../../src/components/hx-table/hx-th.ts","../../src/components/hx-table/hx-td.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTableStyles = css`\n :host {\n display: block;\n overflow-x: auto;\n font-family: var(--hx-table-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n /* ─── Scroll Wrapper ─── */\n\n .table-wrapper {\n min-width: 0;\n width: 100%;\n }\n\n /* ─── Table ─── */\n\n table {\n border-collapse: collapse;\n border-spacing: 0;\n }\n\n :host([full-width]) table {\n width: 100%;\n }\n\n /* ─── Caption ─── */\n\n caption {\n caption-side: top;\n text-align: start;\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n color: var(--hx-table-header-color, var(--hx-color-text-strong, #202b39));\n font-size: var(--hx-font-size-md, 1rem);\n }\n\n /* ─── Slotted sub-component styling ─── */\n\n /*\n * ::slotted() only matches DIRECT slot assignees. hx-table's direct\n * slot children are hx-thead, hx-tbody, and hx-tfoot — never hx-tr,\n * hx-th, or hx-td. CSS custom properties inherit through shadow DOM\n * boundaries, so variables set on section elements cascade to their\n * slotted row and cell descendants automatically.\n */\n\n /* Header background via CSS vars that cascade through display:contents */\n ::slotted(hx-thead) {\n --_hx-table-cell-bg: var(--hx-table-header-bg, var(--hx-color-surface-raised, #f5f8f3));\n }\n\n /* Striped variant: set stripe signal on hx-tbody (direct slotted child) so hx-tbody can apply to even rows */\n :host([variant='striped']) ::slotted(hx-tbody) {\n --_hx-table-row-stripe-bg: var(--hx-table-stripe-bg, var(--hx-color-surface-raised, #f5f8f3));\n }\n\n /* Hover variant: set hover bg variable on direct slotted section elements */\n :host([variant='hover']) ::slotted(hx-tbody),\n :host([variant='hover']) ::slotted(hx-thead),\n :host([variant='striped']) ::slotted(hx-tbody),\n :host([variant='striped']) ::slotted(hx-thead),\n :host([variant='default']) ::slotted(hx-tbody),\n :host([variant='default']) ::slotted(hx-thead) {\n --_hx-table-row-hover-bg: var(--hx-table-row-hover-bg, var(--hx-color-surface-raised, #f5f8f3));\n }\n\n /* Compact variant: reduced padding signal set on section elements that cascade to cells */\n :host([variant='compact']) ::slotted(hx-thead),\n :host([variant='compact']) ::slotted(hx-tbody),\n :host([variant='compact']) ::slotted(hx-tfoot) {\n --_hx-table-cell-padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Sticky Header ─── */\n\n :host([sticky-header]) ::slotted(hx-thead) {\n --_hx-table-th-position: sticky;\n --_hx-table-th-top: 0;\n --_hx-table-th-z-index: 1;\n --_hx-table-th-bg: var(--hx-table-header-bg, var(--hx-color-surface-raised, #f5f8f3));\n }\n\n /* ─── Focus ─── */\n\n ::slotted(:focus-visible) {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797));\n outline-offset: var(--hx-focus-ring-offset, -2px);\n }\n\n /* ─── Responsive Mobile Card Layout ─── */\n\n @media (max-width: 768px) {\n .table-wrapper {\n overflow-x: visible;\n }\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n ::slotted(*) {\n transition: none !important;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n table {\n border: 1px solid CanvasText;\n }\n }\n`;\n\n/**\n * Styles shared by sub-components (hx-th, hx-td) for cell layout.\n * Exported so sub-components can import them directly.\n */\nexport const helixTableCellBaseStyles = css`\n :host {\n display: contents;\n }\n`;\n\nexport const helixTableRowBaseStyles = css`\n :host {\n display: contents;\n }\n`;\n\nexport const helixTableSectionBaseStyles = css`\n :host {\n display: contents;\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 { HelixElement } from '../../base/index.js';\nimport { helixTableStyles } from './hx-table.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A semantic table container with variant styling and accessibility support.\n * Compose with `hx-thead`, `hx-tbody`, `hx-tfoot`, `hx-tr`, `hx-th`, and `hx-td`.\n *\n * @summary Semantic HTML table with variant styling, sticky header, and responsive layout.\n *\n * @tag hx-table\n *\n * @slot - Default slot for `hx-thead`, `hx-tbody`, and `hx-tfoot` sub-components.\n * @slot caption - Custom caption content rendered inside the `<caption>` element.\n *\n * @csspart table - The `<table>` element.\n * @csspart caption - The `<caption>` element.\n *\n * @cssprop [--hx-table-border-color=var(--hx-color-neutral-200, #D6DBD5)] - Cell border color.\n * @cssprop [--hx-table-header-bg=var(--hx-color-neutral-50, #F5F8F3)] - Header row background.\n * @cssprop [--hx-table-header-color=var(--hx-color-neutral-700, #313E4B)] - Header text color.\n * @cssprop [--hx-table-cell-color=var(--hx-color-neutral-900, #0D1825)] - Cell text color.\n * @cssprop [--hx-table-row-hover-bg=var(--hx-color-neutral-50, #F5F8F3)] - Row hover background.\n * @cssprop [--hx-table-stripe-bg=var(--hx-color-neutral-50, #F5F8F3)] - Striped row background.\n * @cssprop [--hx-table-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-color-neutral-50] - Color.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n */\n@customElement('hx-table')\nexport class HelixTable extends HelixElement {\n static override styles = [helixTableStyles, forcedColorsSurface];\n\n // ─── Public Properties ───\n\n /**\n * Accessible name for the table (WCAG 4.1.2 requirement).\n * Exposed via `aria-label` on the `<table>` element.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Visible caption text. When set, renders a `<caption>` element.\n * Use the `caption` slot for richer caption content.\n * @attr caption\n */\n @property({ type: String })\n caption = '';\n\n /**\n * Visual variant that controls row styling.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'striped' | 'hover' | 'compact' = 'default';\n\n /**\n * When true, the header row stays fixed while the table body scrolls.\n * @attr sticky-header\n */\n @property({ type: Boolean, reflect: true, attribute: 'sticky-header' })\n stickyHeader = false;\n\n /**\n * When true, the table expands to fill 100% of its container width.\n * @attr full-width\n */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n fullWidth = true;\n\n // ─── Internal State ───\n\n /** @internal */\n @state() private _hasCaptionSlot = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._hasCaptionSlot = this.querySelector('[slot=\"caption\"]') !== null;\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n // WCAG 4.1.2: warn when neither label nor caption provides an accessible name.\n // A table without an accessible name cannot be identified by screen reader users.\n if (!this.label && !this.caption && !this._hasCaptionSlot) {\n devWarn(\n 'hx-table',\n 'No accessible name provided. Set the `label` or `caption` attribute, or use the `caption` slot, so screen readers can identify this table (WCAG 4.1.2 Name, Role, Value).',\n );\n }\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (changed.has('label') && !this.label && changed.get('label') !== undefined) {\n devWarn(\n 'hx-table',\n 'No accessible name provided. Set the `label` attribute so screen readers can identify this table (WCAG 4.1.2).',\n );\n }\n }\n\n /** @internal */\n private _onCaptionSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasCaptionSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Render ───\n\n override render() {\n const hasCaption = this.caption || this._hasCaptionSlot;\n\n return html`\n <div class=\"table-wrapper\">\n <!-- role=\"table\" is required: sub-components use display:contents which can confuse assistive technology in Shadow DOM -->\n <table part=\"table\" role=\"table\" aria-label=${this.label || nothing}>\n ${hasCaption\n ? html`<caption part=\"caption\">\n <slot name=\"caption\" @slotchange=${this._onCaptionSlotChange}>${this.caption}</slot>\n </caption>`\n : nothing}\n <slot></slot>\n </table>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-table': HelixTable;\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 { helixTableSectionBaseStyles } from './hx-table.styles.js';\n\n/**\n * Semantic table head section. Must be a direct child of `hx-table`.\n * Contains `hx-tr` rows with `hx-th` header cells.\n *\n * @summary Table head section (`<thead>`) for use inside `hx-table`.\n *\n * @tag hx-thead\n *\n * @slot - Default slot for `hx-tr` elements.\n *\n * @csspart thead - The `<thead>` element.\n */\n@customElement('hx-thead')\nexport class HelixTableHead extends HelixElement {\n static override styles = [helixTableSectionBaseStyles];\n\n override render() {\n return html`<thead part=\"thead\" role=\"rowgroup\">\n <slot></slot>\n </thead>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-thead': HelixTableHead;\n }\n}\n","import { html, css } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\n\n/**\n * Semantic table body section. Must be a direct child of `hx-table`.\n * Contains `hx-tr` rows with `hx-td` data cells.\n *\n * @summary Table body section (`<tbody>`) for use inside `hx-table`.\n *\n * @tag hx-tbody\n *\n * @slot - Default slot for `hx-tr` elements.\n *\n * @csspart tbody - The `<tbody>` element.\n */\n@customElement('hx-tbody')\nexport class HelixTableBody extends HelixElement {\n static override styles = [\n css`\n :host {\n display: contents;\n }\n\n /*\n * Striped rows: only applies when the parent hx-table sets\n * --_hx-table-row-stripe-bg (via variant=\"striped\"). Falls back\n * to transparent so non-striped variants are unaffected.\n */\n ::slotted(hx-tr:nth-child(even)) {\n --_hx-table-row-bg: var(--_hx-table-row-stripe-bg, transparent);\n }\n `,\n ];\n\n override render() {\n return html`<tbody part=\"tbody\" role=\"rowgroup\">\n <slot></slot>\n </tbody>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tbody': HelixTableBody;\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 { helixTableSectionBaseStyles } from './hx-table.styles.js';\n\n/**\n * Semantic table foot section. Must be a direct child of `hx-table`.\n * Typically contains summary or totals rows.\n *\n * @summary Table foot section (`<tfoot>`) for use inside `hx-table`.\n *\n * @tag hx-tfoot\n *\n * @slot - Default slot for `hx-tr` elements.\n *\n * @csspart tfoot - The `<tfoot>` element.\n */\n@customElement('hx-tfoot')\nexport class HelixTableFoot extends HelixElement {\n static override styles = [helixTableSectionBaseStyles];\n\n override render() {\n return html`<tfoot part=\"tfoot\" role=\"rowgroup\">\n <slot></slot>\n </tfoot>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tfoot': HelixTableFoot;\n }\n}\n","import { html, nothing, css } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\n\n/**\n * Semantic table row. Must be a child of `hx-thead`, `hx-tbody`, or `hx-tfoot`.\n * Contains `hx-th` or `hx-td` cells.\n *\n * @summary Table row (`<tr>`) for use inside `hx-thead`, `hx-tbody`, or `hx-tfoot`.\n *\n * @tag hx-tr\n *\n * @slot - Default slot for `hx-th` and `hx-td` elements.\n *\n * @csspart row - The `<tr>` element.\n */\n@customElement('hx-tr')\nexport class HelixTableRow extends HelixElement {\n static override styles = [\n css`\n :host {\n display: contents;\n }\n\n tr {\n background-color: var(--_hx-table-row-bg, transparent);\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n tr:hover {\n background-color: var(--_hx-table-row-hover-bg, var(--hx-table-row-hover-bg, transparent));\n }\n\n :host([selected]) tr {\n background-color: var(--hx-table-row-selected-bg, var(--hx-color-primary-50, #ebf8f8));\n }\n\n :host([disabled]) tr {\n opacity: 0.5;\n pointer-events: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n tr {\n transition: none;\n }\n }\n `,\n ];\n\n /**\n * When true, marks the row as selected and applies selected styling.\n * @attr selected\n */\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n /**\n * When true, the row is visually disabled and non-interactive.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n override render() {\n return html`\n <tr\n part=\"row\"\n role=\"row\"\n aria-selected=${this.selected ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n >\n <slot></slot>\n </tr>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tr': HelixTableRow;\n }\n}\n","import { html, nothing, css } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\n\n/**\n * Detail type for `hx-sort` events dispatched from `hx-th`.\n */\nexport interface HxTableSortDetail {\n direction: 'asc' | 'desc';\n}\n\n/**\n * Semantic table header cell. Must be a child of `hx-tr`.\n * Supports sortable columns with accessible sort state.\n *\n * @summary Table header cell (`<th>`) with optional sort support.\n *\n * @tag hx-th\n *\n * @slot - Default slot for header label content.\n *\n * @fires {CustomEvent<HxTableSortDetail>} hx-sort - Dispatched when a sortable header is activated.\n *\n * @csspart header - The `<th>` element.\n * @csspart sort-icon - The sort indicator icon `<span>` inside sortable headers.\n */\n@customElement('hx-th')\nexport class HelixTableHeader extends HelixElement {\n static override styles = [\n css`\n :host {\n display: contents;\n }\n\n th {\n padding: var(--_hx-table-cell-padding, var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem));\n text-align: left;\n font-weight: var(--hx-font-weight-semibold, 600);\n color: var(--hx-table-header-color, var(--hx-color-neutral-700, #313e4b));\n background-color: var(\n --_hx-table-cell-bg,\n var(--hx-table-header-bg, var(--hx-color-neutral-50, #f5f8f3))\n );\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-table-border-color, var(--hx-color-neutral-200, #d6dbd5));\n white-space: nowrap;\n vertical-align: middle;\n position: var(--_hx-table-th-position, static);\n top: var(--_hx-table-th-top, auto);\n z-index: var(--_hx-table-th-z-index, auto);\n }\n\n :host([sortable]) th {\n cursor: pointer;\n }\n\n /* ─── Sort Button ─── */\n\n .sort-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-weight: inherit;\n color: inherit;\n cursor: pointer;\n white-space: nowrap;\n width: 100%;\n }\n\n .sort-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 2px);\n }\n\n /* ─── Sort Icon ─── */\n\n .sort-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n opacity: 0.4;\n transition:\n opacity var(--hx-transition-fast, 150ms ease),\n transform var(--hx-transition-fast, 150ms ease);\n }\n\n .sort-icon--active {\n opacity: 1;\n color: var(--hx-color-primary-500, #429797);\n }\n\n .sort-icon--desc {\n transform: rotate(180deg);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sort-icon {\n transition: none;\n }\n }\n\n /* ─── Mobile card layout ─── */\n\n @media (max-width: 768px) {\n /*\n * Visually hide the header cell on mobile while keeping it in the\n * accessibility tree. Screen readers can then associate column\n * headers with data cells via the semantic table structure\n * (scope=\"col\", role=\"columnheader\"), satisfying WCAG 2.1 AA.\n * Using display:none would remove headers from the a11y tree entirely.\n */\n th {\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 `,\n ];\n\n /**\n * When true, the header renders a sort button and emits `hx-sort` on activation.\n * @attr sortable\n */\n @property({ type: Boolean, reflect: true })\n sortable = false;\n\n /**\n * Current sort direction. Reflected for CSS targeting.\n * @attr sort-direction\n */\n @property({ type: String, reflect: true, attribute: 'sort-direction' })\n sortDirection: 'asc' | 'desc' | 'none' = 'none';\n\n /**\n * The `scope` attribute for the underlying `<th>` element.\n * @attr scope\n */\n @property({ type: String })\n scope: 'col' | 'row' | 'colgroup' | 'rowgroup' = 'col';\n\n /**\n * Number of columns this header spans.\n * @attr colspan\n */\n @property({ type: Number })\n colspan = 0;\n\n /**\n * Number of rows this header spans.\n * @attr rowspan\n */\n @property({ type: Number })\n rowspan = 0;\n\n // ─── Event Handlers ───\n\n /** @internal */\n private _handleSort(): void {\n const next: 'asc' | 'desc' = this.sortDirection === 'asc' ? 'desc' : 'asc';\n this.sortDirection = next;\n this.dispatchEvent(\n new CustomEvent<HxTableSortDetail>('hx-sort', {\n bubbles: true,\n composed: true,\n detail: { direction: next },\n }),\n );\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderSortIcon() {\n const isActive = this.sortDirection !== 'none';\n const iconClass = [\n 'sort-icon',\n isActive ? 'sort-icon--active' : '',\n this.sortDirection === 'desc' ? 'sort-icon--desc' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return html`\n <span part=\"sort-icon\" class=${iconClass} aria-hidden=\"true\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n width=\"16\"\n height=\"16\"\n >\n <path d=\"M8 3L5 7h6L8 3zM8 13l3-4H5l3 4z\" fill-rule=\"evenodd\" />\n </svg>\n </span>\n `;\n }\n\n /** @internal */\n private _ariaSort(): 'ascending' | 'descending' | 'none' | typeof nothing {\n if (!this.sortable) return nothing;\n if (this.sortDirection === 'asc') return 'ascending';\n if (this.sortDirection === 'desc') return 'descending';\n return 'none';\n }\n\n /** @internal */\n private _sortLabel(): string {\n if (this.sortDirection === 'asc') return 'Sort descending';\n if (this.sortDirection === 'desc') return 'Sort ascending';\n return 'Sort';\n }\n\n override render() {\n return html`\n <th\n part=\"header\"\n role=\"columnheader\"\n scope=${this.scope}\n colspan=${ifDefined(this.colspan > 0 ? this.colspan : undefined)}\n rowspan=${ifDefined(this.rowspan > 0 ? this.rowspan : undefined)}\n aria-sort=${this._ariaSort()}\n >\n ${this.sortable\n ? html`\n <button class=\"sort-btn\" @click=${this._handleSort} aria-label=${this._sortLabel()}>\n <slot></slot>\n ${this._renderSortIcon()}\n </button>\n `\n : html`<slot></slot>`}\n </th>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-th': HelixTableHeader;\n }\n}\n","import { html, css } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\n\n/**\n * Semantic table data cell. Must be a child of `hx-tr`.\n *\n * @summary Table data cell (`<td>`) for use inside `hx-tr`.\n *\n * @tag hx-td\n *\n * @slot - Default slot for cell content.\n *\n * @csspart cell - The `<td>` element.\n *\n * @cssprop [--hx-table-cell-color=var(--hx-color-neutral-900, #0D1825)] - Cell text color.\n */\n@customElement('hx-td')\nexport class HelixTableCell extends HelixElement {\n static override styles = [\n css`\n :host {\n display: contents;\n }\n\n td {\n padding: var(--_hx-table-cell-padding, var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem));\n text-align: left;\n color: var(--hx-table-cell-color, var(--hx-color-neutral-900, #0d1825));\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-table-border-color, var(--hx-color-neutral-200, #d6dbd5));\n vertical-align: middle;\n }\n\n :host([align='center']) td {\n text-align: center;\n }\n\n :host([align='right']) td {\n text-align: right;\n }\n\n td:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797));\n outline-offset: var(--hx-focus-ring-offset, -2px);\n border-radius: var(--hx-border-radius-sm, 2px);\n }\n\n /* ─── Mobile card layout ─── */\n\n @media (max-width: 768px) {\n :host {\n display: block;\n }\n\n td {\n display: block;\n text-align: right;\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n border-bottom: none;\n position: relative;\n }\n\n td::before {\n content: attr(data-label);\n font-weight: var(--hx-font-weight-semibold, 600);\n float: left;\n color: var(--hx-table-header-color, var(--hx-color-neutral-700, #313e4b));\n }\n }\n `,\n ];\n\n /**\n * Horizontal alignment for cell content.\n * @attr align\n */\n @property({ type: String, reflect: true })\n align: 'left' | 'center' | 'right' = 'left';\n\n /**\n * Number of columns this cell spans.\n * @attr colspan\n */\n @property({ type: Number })\n colspan = 0;\n\n /**\n * Number of rows this cell spans.\n * @attr rowspan\n */\n @property({ type: Number })\n rowspan = 0;\n\n /**\n * Column header label for this cell. Forwarded as `data-label` on the native `<td>` for\n * the mobile card layout (`td::before { content: attr(data-label) }`) and as `aria-label`\n * so screen readers identify the column when the header row is hidden.\n * @attr label\n */\n @property({ type: String, attribute: 'label' })\n label = '';\n\n override render() {\n return html`\n <td\n part=\"cell\"\n role=\"cell\"\n data-label=${ifDefined(this.label || undefined)}\n colspan=${ifDefined(this.colspan > 0 ? this.colspan : undefined)}\n rowspan=${ifDefined(this.rowspan > 0 ? this.rowspan : undefined)}\n >\n <slot></slot>\n </td>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-td': HelixTableCell;\n }\n}\n"],"names":["helixTableStyles","css","helixTableSectionBaseStyles","HelixTable","HelixElement","changedProperties","changed","slot","hasCaption","html","nothing","forcedColorsSurface","__decorateClass","property","state","customElement","HelixTableHead","HelixTableBody","HelixTableFoot","HelixTableRow","HelixTableHeader","next","iconClass","ifDefined","HelixTableCell"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-text-input-ClrrmoE1.js","sources":["../../src/mixins/FocusMixin.ts","../../src/components/hx-text-input/hx-text-input.styles.ts","../../src/components/hx-text-input/hx-text-input.ts"],"sourcesContent":["import { LitElement, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\n/**\n * Mixin constructor type — must use `any[]` args per TypeScript mixin requirements (TS2545).\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Constructor<T = object> = new (...args: any[]) => T;\n\n/**\n * The public interface added by FocusMixin.\n * Consumers can use this type for typed references.\n *\n * @public\n */\nexport interface FocusMixinInterface {\n /** True when the component host has focus (including descendant focus). */\n readonly focused: boolean;\n /** True when focus arrived via keyboard (not pointer). */\n readonly focusedVisible: boolean;\n}\n\n/**\n * FocusMixin — standardized focus delegation for HELiX web components.\n *\n * Modeled after Lion's `FocusMixin` and Material Web's `mixinDelegatesAria`.\n * Provides:\n * - `_focusableNode` getter for subclasses to declare the inner focusable element\n * - `focused` reflected attribute as a styling hook for `:host([focused])`\n * - `focusedVisible` reflected attribute for keyboard-only focus rings\n * - Delegated `focus()` / `blur()` routing to the inner element\n * - Autofocus support after first render\n *\n * ### Usage\n *\n * ```ts\n * class MyInput extends FocusMixin(HelixElement) {\n * @query('input') private _input: HTMLInputElement | undefined;\n *\n * protected override get _focusableNode(): HTMLElement | null {\n * return this._input ?? null;\n * }\n * }\n * ```\n *\n * @param superClass - A Lit element constructor to mix into\n * @returns A new class with focus management capabilities\n *\n * @public\n */\nexport const FocusMixin = <T extends Constructor<LitElement>>(superClass: T) => {\n class FocusMixinClass extends superClass implements FocusMixinInterface {\n /**\n * True when the component or any of its descendants has focus.\n * Reflects to attribute `focused` for CSS selector use.\n *\n * @attr focused\n */\n @property({ type: Boolean, reflect: true })\n focused = false;\n\n /**\n * True when focus was reached via keyboard navigation (Tab / Shift+Tab)\n * rather than pointer interaction. Reflects to attribute `focused-visible`\n * for rendering keyboard-only focus rings.\n *\n * @attr focused-visible\n */\n @property({ type: Boolean, reflect: true, attribute: 'focused-visible' })\n focusedVisible = false;\n\n /** @internal — whether a `focus()` call was queued before first render */\n private _focusPending = false;\n\n /**\n * @internal — tracks whether the most recent interaction toward this\n * element was via pointer (true) or keyboard (false).\n *\n * Set to false on `pointerdown` so that the subsequent `focusin` can\n * determine it is not keyboard-initiated.\n */\n private _lastInteractionWasPointer = false;\n\n /**\n * Returns the inner focusable element that `focus()` and `blur()` will\n * delegate to. Subclasses MUST override this getter.\n *\n * @returns The inner focusable element, or `null` if not yet rendered.\n * @internal\n */\n protected get _focusableNode(): HTMLElement | null {\n return null;\n }\n\n /**\n * Delegates focus to the inner focusable element.\n * If the element has not yet rendered, queues the focus call for\n * `firstUpdated`.\n */\n override focus(options?: FocusOptions): void {\n const node = this._focusableNode;\n if (node !== null) {\n node.focus(options);\n } else {\n this._focusPending = true;\n }\n }\n\n /** Delegates blur to the inner focusable element. */\n override blur(): void {\n this._focusableNode?.blur();\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('focusin', this._handleFocusIn);\n this.addEventListener('focusout', this._handleFocusOut);\n this.addEventListener('pointerdown', this._handlePointerDown);\n this.addEventListener('keydown', this._handleKeyDown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('focusin', this._handleFocusIn);\n this.removeEventListener('focusout', this._handleFocusOut);\n this.removeEventListener('pointerdown', this._handlePointerDown);\n this.removeEventListener('keydown', this._handleKeyDown);\n }\n\n override firstUpdated(changedProperties: PropertyValues): void {\n super.firstUpdated(changedProperties);\n\n // Honour the native `autofocus` attribute after the first render cycle\n if (this.hasAttribute('autofocus')) {\n this.focus();\n }\n\n // Flush any focus() call that arrived before the shadow DOM was stamped\n if (this._focusPending) {\n this._focusPending = false;\n this.focus();\n }\n }\n\n // ─── Private Event Handlers ────────────────────────────────────────────────\n\n /** @internal */\n private _handleFocusIn = (): void => {\n this.focused = true;\n // focusedVisible is true only when focus arrived via keyboard\n this.focusedVisible = !this._lastInteractionWasPointer;\n };\n\n /** @internal */\n private _handleFocusOut = (): void => {\n this.focused = false;\n this.focusedVisible = false;\n // Reset for the next interaction cycle\n this._lastInteractionWasPointer = false;\n };\n\n /**\n * Marks the next focusin as pointer-initiated.\n * @internal\n */\n private _handlePointerDown = (): void => {\n this._lastInteractionWasPointer = true;\n };\n\n /**\n * Ensures that keyboard navigation (Tab / Shift+Tab arriving from outside)\n * is correctly flagged as keyboard-initiated even when no prior `pointerdown`\n * fired on this element.\n *\n * This fires BEFORE `focusin` so the flag is in the correct state when\n * `_handleFocusIn` runs.\n * @internal\n */\n private _handleKeyDown = (): void => {\n this._lastInteractionWasPointer = false;\n };\n }\n\n return FocusMixinClass as unknown as T & Constructor<FocusMixinInterface>;\n};\n","import { css } from 'lit';\n\n/**\n * hx-text-input styles.\n *\n * Component-tier tokens introduced in 3.2.0 — every visual property exposes\n * `--hx-text-input-*` overrides while preserving backward-compatible\n * `--hx-input-*` aliases that earlier consumers may already use.\n *\n * Two-level var() fallback pattern is canonical:\n * var(--hx-text-input-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (primary-600=#0F7078,\n * neutral-200=#D6DBD5, etc.) introduced in the same release.\n */\nexport const helixTextInputStyles = css`\n :host {\n display: block;\n\n /* ─── Component tokens (3.2.0) ──────────────────────────────────── */\n\n /* Surface */\n --_text-input-bg: var(\n --hx-text-input-bg,\n var(--hx-input-bg, var(--hx-color-surface-default, #ffffff))\n );\n --_text-input-color: var(\n --hx-text-input-color,\n var(--hx-input-color, var(--hx-color-text-strong, #202b39))\n );\n --_text-input-placeholder-color: var(\n --hx-text-input-placeholder-color,\n var(--hx-color-text-placeholder, #66787b)\n );\n\n /* Border */\n --_text-input-border-color: var(\n --hx-text-input-border-color,\n var(--hx-input-border-color, var(--hx-color-border-strong, #8e9c98))\n );\n --_text-input-border-color-hover: var(\n --hx-text-input-border-color-hover,\n var(--hx-color-border-strong, #8e9c98)\n );\n --_text-input-border-color-focus: var(\n --hx-text-input-border-color-focus,\n var(\n --hx-input-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))\n )\n );\n --_text-input-border-color-invalid: var(\n --hx-text-input-border-color-invalid,\n var(--hx-input-error-color, var(--hx-color-error-600, #c92a2a))\n );\n --_text-input-border-width: var(--hx-text-input-border-width, var(--hx-border-width-thin, 1px));\n --_text-input-border-radius: var(\n --hx-text-input-border-radius,\n var(--hx-input-border-radius, var(--hx-border-radius-md, 0.375rem))\n );\n\n /* Spacing */\n --_text-input-padding-x: var(--hx-text-input-padding-x, var(--hx-space-3, 0.75rem));\n --_text-input-padding-y: var(--hx-text-input-padding-y, var(--hx-space-2, 0.5rem));\n\n /* Typography */\n --_text-input-font-family: var(\n --hx-text-input-font-family,\n var(--hx-input-font-family, var(--hx-font-family-sans, sans-serif))\n );\n --_text-input-font-size: var(--hx-text-input-font-size, var(--hx-font-size-md, 1rem));\n\n /* Focus ring */\n --_text-input-focus-ring-color: var(\n --hx-text-input-focus-ring-color,\n var(\n --hx-input-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))\n )\n );\n --_text-input-focus-ring-width: var(\n --hx-text-input-focus-ring-width,\n var(--hx-focus-ring-width, 2px)\n );\n --_text-input-focus-ring-offset: var(\n --hx-text-input-focus-ring-offset,\n var(--hx-focus-ring-offset, 0px)\n );\n\n /* Disabled */\n --_text-input-disabled-bg: var(\n --hx-text-input-disabled-bg,\n var(--hx-color-surface-sunken, #ebeee9)\n );\n --_text-input-disabled-color: var(\n --hx-text-input-disabled-color,\n var(--hx-color-text-disabled, #8e9c98)\n );\n\n /* Label / help / error */\n --_text-input-label-color: var(\n --hx-text-input-label-color,\n var(--hx-input-label-color, var(--hx-color-text-strong, #202b39))\n );\n --_text-input-help-text-color: var(\n --hx-text-input-help-text-color,\n var(--hx-color-text-muted, #4a5362)\n );\n --_text-input-error-color: var(\n --hx-text-input-error-color,\n var(--hx-input-error-color, var(--hx-color-error-text, #c92a2a))\n );\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n\n /*\n * Attribute-based focus hooks set by FocusMixin.\n * :host([focused]) — fires whenever the component or any descendant has focus.\n * :host([focused-visible]) — fires only for keyboard-initiated focus.\n * These complement the :focus-within rules on .field__input-wrapper and are\n * exposed as theming hooks for consumers who target the host element.\n */\n :host([focused]) .field__input-wrapper,\n :host([focused-visible]) .field__input-wrapper {\n border-color: var(--_text-input-border-color-focus);\n box-shadow: 0 0 0 var(--_text-input-focus-ring-width)\n color-mix(\n in srgb,\n var(--_text-input-border-color-focus) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n * {\n box-sizing: border-box;\n }\n\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--_text-input-font-family);\n }\n\n /* ─── Label ─── */\n\n .field__label-wrapper {\n display: contents;\n }\n\n .field__label {\n display: flex;\n align-items: baseline;\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-medium, 500);\n color: var(--_text-input-label-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__required-marker {\n color: var(--_text-input-error-color);\n font-weight: var(--hx-font-weight-bold, 700);\n }\n\n /* ─── Input Wrapper ─── */\n\n .field__input-wrapper {\n display: flex;\n align-items: center;\n border: var(--_text-input-border-width) solid var(--_text-input-border-color);\n border-radius: var(--_text-input-border-radius);\n background-color: var(--_text-input-bg);\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n overflow: hidden;\n }\n\n .field__input-wrapper:hover {\n border-color: var(--_text-input-border-color-hover);\n }\n\n .field__input-wrapper:focus-within {\n border-color: var(--_text-input-border-color-focus);\n box-shadow: 0 0 0 var(--_text-input-focus-ring-width)\n color-mix(\n in srgb,\n var(--_text-input-border-color-focus) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n /* ─── Error State ─── */\n\n .field--error .field__input-wrapper {\n border-color: var(--_text-input-border-color-invalid);\n }\n\n .field--error .field__input-wrapper:focus-within {\n border-color: var(--_text-input-border-color-invalid);\n box-shadow: 0 0 0 var(--_text-input-focus-ring-width)\n color-mix(\n in srgb,\n var(--_text-input-border-color-invalid) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n /* ─── Slots (Prefix / Suffix) ─── */\n\n .field__prefix,\n .field__suffix {\n display: flex;\n align-items: center;\n color: var(--hx-color-text-muted, #4a5362);\n flex-shrink: 0;\n }\n\n /* Only add padding when slot has content — avoids phantom space on empty slots */\n .field__prefix--filled {\n padding: 0 var(--_text-input-padding-x);\n }\n\n .field__suffix--filled {\n padding: 0 var(--_text-input-padding-x);\n }\n\n /* ─── Native Input ─── */\n\n .field__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n padding: var(--_text-input-padding-y) var(--_text-input-padding-x);\n font-family: inherit;\n font-size: var(--_text-input-font-size);\n color: var(--_text-input-color);\n line-height: var(--hx-line-height-normal, 1.5);\n min-height: var(--hx-size-10, 2.5rem);\n width: 100%;\n }\n\n .field__input::placeholder {\n color: var(--_text-input-placeholder-color);\n }\n\n .field__input:focus-visible {\n outline: none; /* wrapper ring handles keyboard focus indication */\n }\n\n .field__input:disabled {\n cursor: not-allowed;\n background-color: var(--_text-input-disabled-bg);\n color: var(--_text-input-disabled-color);\n }\n\n :host([disabled]) .field__input-wrapper {\n background-color: var(--_text-input-disabled-bg);\n }\n\n /* ─── Size Variants ─── */\n\n .field--size-sm .field__input {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n min-height: var(--hx-size-8, 2rem);\n font-size: var(--hx-text-input-sm-font-size, var(--hx-input-sm-font-size, 0.875rem));\n }\n\n .field--size-md .field__input {\n /* md is the default — no overrides needed */\n }\n\n .field--size-lg .field__input {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n min-height: var(--hx-size-12, 3rem);\n font-size: var(--hx-text-input-lg-font-size, var(--hx-input-lg-font-size, 1.125rem));\n }\n\n /* ─── Help Text & Error Messages ─── */\n\n .field__help-text {\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--_text-input-help-text-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__error {\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--_text-input-error-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .field__input-wrapper {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ───\n *\n * Bespoke block — sole owner of forced-colors deference for hx-text-input.\n * Covers wrapper/input/placeholder/focus/disabled/error/label/help-text;\n * strictly more than forcedColorsField. The mixin is intentionally NOT\n * composed (XOR rule — see styles/forced-colors.ts COMPOSITION RULES).\n */\n\n @media (forced-colors: active) {\n .field__input-wrapper {\n forced-color-adjust: none;\n background-color: Field;\n color: FieldText;\n border: 2px solid ButtonText;\n }\n\n .field__input {\n color: FieldText;\n }\n\n .field__input::placeholder {\n color: GrayText;\n }\n\n .field__input-wrapper:focus-within {\n border-color: Highlight;\n box-shadow: none;\n }\n\n .field__input:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: -3px;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n\n :host([disabled]) .field__input-wrapper {\n border-color: GrayText;\n color: GrayText;\n }\n\n :host([disabled]) .field__input {\n color: GrayText;\n }\n\n .field--error .field__input-wrapper {\n border-color: LinkText;\n }\n\n .field__label {\n color: CanvasText;\n }\n\n .field__help-text {\n color: GrayText;\n }\n\n .field__error {\n color: LinkText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { live } from 'lit/directives/live.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FocusMixin } from '../../mixins/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixTextInputStyles } from './hx-text-input.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n// Module-level counter for stable, SSR-compatible IDs (avoids Math.random() hydration mismatch)\nconst _nextTextInputId = createIdCounter('hx-text-input');\n\n/** Detail for hx-input and hx-change events dispatched by hx-text-input. */\nexport interface HxTextInputDetail {\n value: string;\n}\n\n/**\n * A text input component with label, validation, and form association.\n * Supports accessible labeling via `label` property, `aria-label` attribute, or the `label` slot.\n * Uses `aria-invalid` and `aria-describedby` on the native input for screen reader support. Native `required` provides implicit aria-required mapping per HTML-AAM.\n * Error messages are announced via `role=\"alert\"`. Keyboard navigation follows native input behavior.\n *\n * @summary Form-associated text input with built-in label, error, and help text.\n *\n * @tag hx-text-input\n *\n * @slot label - Custom label content (overrides the label property). Use for Drupal Form API rendered labels.\n * @slot prefix - Content rendered before the input (e.g., icon).\n * @slot suffix - Content rendered after the input (e.g., icon or button).\n * @slot help-text - Custom help text content (overrides the helpText property).\n * @slot error - Custom error content (overrides the error property). Use for Drupal Form API rendered errors.\n *\n * @fires {CustomEvent<{value: string}>} hx-input - Dispatched on every keystroke as the user types.\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when the input loses focus after its value changed.\n *\n * @csspart field - The outer field container.\n * @csspart label - The label element.\n * @csspart input-wrapper - The wrapper around prefix, input, and suffix.\n * @csspart input - The native input element.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n *\n * @cssprop [--hx-input-bg=var(--hx-color-surface-default)] - Input background color.\n * @cssprop [--hx-input-color=var(--hx-color-text-strong)] - Input text color.\n * @cssprop [--hx-input-border-color=var(--hx-color-border-strong)] - Input border color.\n * @cssprop [--hx-input-border-radius=var(--hx-border-radius-md)] - Input border radius.\n * @cssprop [--hx-input-font-family=var(--hx-font-family-sans)] - Input font family.\n * @cssprop [--hx-input-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-input-error-color=var(--hx-color-error-text)] - Error state color.\n * @cssprop [--hx-input-label-color=var(--hx-color-text-strong)] - Label text color.\n * @cssprop [--hx-input-sm-font-size=0.875rem] - Font size for the sm size variant.\n * @cssprop [--hx-input-lg-font-size=1.125rem] - Font size for the lg size variant.\n *\n * @cssprop [--hx-text-input-border-width=var(--hx-border-width-thin)] - Outer border-width override (canonical hx-{tag}-* prefix; sits above --hx-input-* aliases in the cascade).\n * @cssprop [--hx-text-input-padding-x=var(--hx-space-3)] - Outer horizontal padding override.\n * @cssprop [--hx-text-input-padding-y=var(--hx-space-2)] - Outer vertical padding override.\n * @cssprop [--hx-text-input-font-size=var(--hx-font-size-md)] - Outer font-size override.\n * @cssprop [--hx-text-input-sm-font-size] - Outer sm-variant font-size override (falls through to --hx-input-sm-font-size).\n * @cssprop [--hx-text-input-lg-font-size] - Outer lg-variant font-size override (falls through to --hx-input-lg-font-size).\n *\n * @cssprop [--hx-color-surface-default] - Resting field surface (semantic).\n * @cssprop [--hx-color-text-strong] - Resting input text + label color (semantic).\n * @cssprop [--hx-color-border-strong] - Resting border color (semantic).\n * @cssprop [--hx-color-error-text] - Error state text + border color (semantic).\n * @cssprop [--hx-color-error-600] - Error border primitive fallback inside the focus-state cascade.\n */\n@customElement('hx-text-input')\nexport class HelixTextInput extends FocusMixin(FormMixin(HelixElement)) {\n // 3.2.1: forced-colors deference is owned by the bespoke @media block in\n // hx-text-input.styles.ts (covers wrapper/input/placeholder/focus/disabled/\n // error/label/help-text — strictly more than the shared mixin). XOR rule:\n // do NOT also compose forcedColorsField — overlapping selectors inside the\n // same media query create a fragile specificity war.\n static override styles = [helixTextInputStyles];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n // ─── Properties ───\n\n /**\n * The visible label text for the input.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown when the input is empty.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the input.\n * @attr value\n * @remarks When `null` is passed programmatically, Lit coerces it to an empty string.\n * This is expected behavior — the input treats null as equivalent to an empty string value.\n */\n @property({ type: String })\n value = '';\n\n /**\n * The type of the native input element.\n * @attr type\n */\n @property({ type: String })\n type: 'text' | 'email' | 'password' | 'tel' | 'url' | 'search' | 'number' | 'date' = 'text';\n\n /**\n * Whether the input is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the input is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Error message to display. When set, the input enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the input for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * The name of the input, used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element. The value is forwarded to the\n * internal native input's `aria-label`.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because form\n * inputs with associated labels delegate accessible naming via `<label>`\n * association and `aria-labelledby`, not host-level ARIA delegation. The\n * `accessible-label` attribute is a fallback for label-free usage.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n /**\n * Whether the input is read-only.\n * @attr readonly\n */\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n /**\n * Minimum number of characters allowed.\n * @attr minlength\n */\n @property({ type: Number })\n minlength: number | undefined = undefined;\n\n /**\n * Maximum number of characters allowed.\n * @attr maxlength\n */\n @property({ type: Number })\n maxlength: number | undefined = undefined;\n\n /**\n * A regular expression pattern the value must match for form validation.\n * @attr pattern\n */\n @property({ type: String })\n pattern = '';\n\n /**\n * Hint for the browser's autocomplete feature. Accepts standard HTML autocomplete values.\n * @attr autocomplete\n */\n @property({ type: String })\n autocomplete = '';\n\n /**\n * Validation message shown when the field is required but empty.\n * @attr required-message\n */\n @property({ attribute: 'required-message' })\n requiredMessage = 'This field is required.';\n\n /**\n * Visual size of the input field.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n // ─── Internal References ───\n\n /** @internal */\n @query('.field__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── FocusMixin integration ───\n\n /**\n * Declares the inner focusable element for FocusMixin delegation.\n * @internal\n */\n protected get _focusableNode(): HTMLElement | null {\n return this._input ?? null;\n }\n\n // ─── Slot Tracking ───\n\n /** @internal */\n @state() private _hasLabelSlot = false;\n /** @internal */\n @state() private _hasErrorSlot = false;\n /** @internal */\n @state() private _hasPrefixSlot = false;\n /** @internal */\n @state() private _hasSuffixSlot = false;\n /** @internal */\n @state() private _hasHelpTextSlot = false;\n\n /** @internal */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasLabelSlot = slot.assignedElements().length > 0;\n if (this._hasLabelSlot) {\n const slottedLabel = slot.assignedElements()[0];\n if (slottedLabel && !slottedLabel.id) {\n slottedLabel.id = `${this._inputId}-slotted-label`;\n }\n }\n }\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasErrorSlot = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _handlePrefixSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasPrefixSlot = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _handleSuffixSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSuffixSlot = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _handleHelpTextSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHelpTextSlot = slot.assignedElements().length > 0;\n }\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('value')) {\n this._internals.setFormValue(this.value);\n }\n if (\n (changedProperties.has('value') || changedProperties.has('type')) &&\n this.type === 'number' &&\n this.value !== '' &&\n isNaN(Number(this.value))\n ) {\n devWarn(\n 'hx-text-input',\n `type=\"number\" received non-numeric value \"${this.value}\". Browser will display empty input.`,\n );\n }\n }\n\n // ─── Form Integration ───\n\n /** Returns the associated form element, if any. */\n override get form(): HTMLFormElement | null {\n return this._internals.form;\n }\n\n /** Returns the validation message. */\n override get validationMessage(): string {\n return this._internals.validationMessage;\n }\n\n /** Returns the ValidityState object. */\n override get validity(): ValidityState {\n return this._internals.validity;\n }\n\n /** @internal */\n _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.requiredMessage,\n this._input,\n );\n } else if (\n this.minlength !== undefined &&\n this.value.length > 0 &&\n this.value.length < this.minlength\n ) {\n this._internals.setValidity(\n { tooShort: true },\n this.error || `Please lengthen this text to ${this.minlength} characters or more.`,\n this._input,\n );\n } else if (this.maxlength !== undefined && this.value.length > this.maxlength) {\n this._internals.setValidity(\n { tooLong: true },\n this.error || `Please shorten this text to ${this.maxlength} characters or fewer.`,\n this._input,\n );\n } else {\n this._internals.setValidity({});\n }\n }\n\n // ─── Form Lifecycle Hooks ───\n\n protected override _onFormReset(): void {\n this.value = '';\n this._internals.setFormValue('');\n this._resetInteractionState();\n }\n\n protected override _onFormStateRestore(\n state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n this.value = state;\n }\n }\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n const target = e.target as HTMLInputElement;\n this.value = target.value;\n this._internals.setFormValue(this.value);\n this._handleInteractionInput();\n\n /**\n * Dispatched on every keystroke as the user types.\n * @event hx-input\n */\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-input', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleChange(e: Event): void {\n const target = e.target as HTMLInputElement;\n this.value = target.value;\n this._internals.setFormValue(this.value);\n this._handleInteractionBlur();\n\n /**\n * Dispatched when the input loses focus after its value changed.\n * @event hx-change\n */\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Public Methods ───\n\n /** Selects all text in the input. */\n select(): void {\n this._input?.select();\n }\n\n // ─── Render ───\n\n /** @internal */\n private _inputId = _nextTextInputId();\n /** @internal */\n private _helpTextId = `${this._inputId}-help`;\n /** @internal */\n private _errorId = `${this._inputId}-error`;\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n [`field--size-${this.size}`]: true,\n };\n\n const describedBy =\n [\n hasError ? this._errorId : null,\n this.helpText || this._hasHelpTextSlot ? this._helpTextId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <div class=\"field__label-wrapper\">\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>\n ${this.label\n ? html`\n <label part=\"label\" class=\"field__label\" for=${this._inputId}>\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>\n `\n : nothing}\n </slot>\n </div>\n\n <div part=\"input-wrapper\" class=\"field__input-wrapper\">\n <span\n class=${classMap({\n field__prefix: true,\n 'field__prefix--filled': this._hasPrefixSlot,\n })}\n >\n <slot name=\"prefix\" @slotchange=${this._handlePrefixSlotChange}></slot>\n </span>\n\n <input\n part=\"input\"\n class=\"field__input\"\n id=${this._inputId}\n type=${this.type}\n .value=${live(this.value)}\n placeholder=${ifDefined(this.placeholder || undefined)}\n ?required=${this.required}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n name=${ifDefined(this.name || undefined)}\n minlength=${ifDefined(this.minlength)}\n maxlength=${ifDefined(this.maxlength)}\n pattern=${ifDefined(this.pattern || undefined)}\n autocomplete=${ifDefined(this.autocomplete || undefined)}\n aria-label=${ifDefined(this.accessibleLabel || undefined)}\n aria-labelledby=${ifDefined(\n this._hasLabelSlot ? `${this._inputId}-slotted-label` : undefined,\n )}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n @input=${this._handleInput}\n @change=${this._handleChange}\n />\n\n <span\n class=${classMap({\n field__suffix: true,\n 'field__suffix--filled': this._hasSuffixSlot,\n })}\n >\n <slot name=\"suffix\" @slotchange=${this._handleSuffixSlotChange}></slot>\n </span>\n </div>\n\n ${hasError\n ? html`<div\n part=\"error\"\n class=\"field__error\"\n id=${this._errorId}\n role=\"alert\"\n aria-atomic=\"true\"\n >\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}>${this.error}</slot>\n </div>`\n : html`<slot name=\"error\" @slotchange=${this._handleErrorSlotChange}></slot>`}\n ${this._hasHelpTextSlot\n ? html`\n <div part=\"help-text\" class=\"field__help-text\" id=${this._helpTextId}>\n <slot name=\"help-text\" @slotchange=${this._handleHelpTextSlotChange}>\n ${this.helpText}\n </slot>\n </div>\n `\n : this.helpText && !hasError\n ? html`\n <div part=\"help-text\" class=\"field__help-text\" id=${this._helpTextId}>\n <slot name=\"help-text\" @slotchange=${this._handleHelpTextSlotChange}>\n ${this.helpText}\n </slot>\n </div>\n `\n : html`<slot name=\"help-text\" @slotchange=${this._handleHelpTextSlotChange}></slot>`}\n </div>\n `;\n }\n}\n\n/**\n * Per-component event map for type-safe addEventListener on hx-text-input.\n * The `hx-change` detail is `{ value: string }` only — no `checked` property.\n */\nexport interface HxTextInputEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n 'hx-change': CustomEvent<{ value: string }>;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-text-input': HelixTextInput;\n }\n interface HTMLElementEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n }\n}\n\n/** Primary type alias for hx-text-input */\nexport type HxTextInput = HelixTextInput;\n"],"names":["FocusMixin","superClass","FocusMixinClass","options","node","_a","changedProperties","__decorateClass","property","helixTextInputStyles","css","_nextTextInputId","createIdCounter","HelixTextInput","FormMixin","HelixElement","slot","slottedLabel","devWarn","state","_mode","disabled","target","hasError","fieldClasses","describedBy","html","classMap","nothing","live","ifDefined","query","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-top-nav-CchPYaiV.js","sources":["../../src/components/hx-top-nav/hx-top-nav.styles.ts","../../src/components/hx-top-nav/hx-top-nav.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTopNavStyles = css`\n /* ─── Host ─── */\n\n :host {\n display: block;\n }\n\n /* ─── Header wrapper (landmark) ─── */\n\n header {\n display: block;\n margin: 0;\n padding: 0;\n }\n\n /* ─── Sticky mode ─── */\n\n :host([sticky]) .nav {\n position: sticky;\n top: 0;\n /* Fallback 1000 is appropriate for sticky navbars (below modals ~1300, above content) */\n z-index: var(--hx-top-nav-z-index, var(--hx-z-index-sticky, 1000));\n }\n\n /* ─── Nav container ─── */\n\n .nav {\n background-color: var(--hx-top-nav-bg, var(--hx-color-surface-default, #ffffff));\n color: var(--hx-top-nav-color, var(--hx-color-text-strong, #202b39));\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-top-nav-border-color, var(--hx-color-border-default, #d6dbd5));\n font-family: var(--hx-top-nav-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n /* ─── Bar row (always visible) ─── */\n\n .nav__bar {\n display: flex;\n align-items: center;\n min-height: var(--hx-top-nav-height, var(--hx-space-16, 4rem));\n padding-inline: var(--hx-top-nav-padding-x, var(--hx-space-6, 1.5rem));\n gap: var(--hx-space-4, 1rem);\n }\n\n /* ─── Logo ─── */\n\n .nav__logo {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n /* ─── Mobile toggle (hamburger) ─── */\n\n .mobile-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-inline-start: auto;\n /* var(--hx-space-3, 0.75rem) padding + 24px icon = 48×48px touch target (exceeds WCAG 2.5.5 44×44px) */\n padding: var(--hx-space-3, 0.75rem);\n background: transparent;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n color: var(--hx-top-nav-toggle-color, var(--hx-color-text-strong, #202b39));\n cursor: pointer;\n line-height: 0;\n }\n\n .mobile-toggle:hover {\n background: var(--hx-top-nav-toggle-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n }\n\n .mobile-toggle:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-top-nav-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .mobile-toggle__icon {\n width: var(--hx-space-6, 1.5rem);\n height: var(--hx-space-6, 1.5rem);\n }\n\n /* ─── Collapsible panel (mobile) ─── */\n\n .nav__collapsible {\n display: none;\n flex-direction: column;\n width: 100%;\n padding-block: var(--hx-space-3, 0.75rem);\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-top-nav-border-color, var(--hx-color-border-default, #d6dbd5));\n }\n\n .nav__collapsible--open {\n display: flex;\n animation: hx-mobile-nav-open var(--hx-duration-fast, 100ms) ease-out;\n }\n\n /* ─── Menu and actions in collapsible (mobile) ─── */\n\n .nav__menu,\n .nav__actions {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n padding-inline: var(--hx-top-nav-padding-x, var(--hx-space-6, 1.5rem));\n }\n\n .nav__actions {\n margin-top: var(--hx-space-3, 0.75rem);\n padding-top: var(--hx-space-3, 0.75rem);\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-top-nav-border-color, var(--hx-color-border-default, #d6dbd5));\n }\n\n /* ─── Desktop breakpoint ─── */\n\n /* NOTE: CSS @media queries do not support custom properties.\n This value corresponds to --hx-breakpoint-md (768px). */\n @media (min-width: 768px) {\n /* Make nav a flex row so bar and collapsible sit side-by-side */\n .nav {\n display: flex;\n align-items: center;\n padding-inline: var(--hx-top-nav-padding-x, var(--hx-space-6, 1.5rem));\n }\n\n .nav__bar {\n flex-shrink: 0;\n padding-inline: 0;\n min-height: var(--hx-top-nav-height, var(--hx-space-16, 4rem));\n }\n\n /* Hide hamburger on desktop */\n .mobile-toggle {\n display: none;\n }\n\n /* Collapsible becomes a standard inline flex row */\n .nav__collapsible {\n display: flex;\n flex-direction: row;\n align-items: center;\n flex: 1;\n padding-block: 0;\n border-top: none;\n margin-inline-start: auto;\n gap: var(--hx-space-4, 1rem);\n animation: none;\n }\n\n /* Override open modifier — always visible on desktop regardless of state */\n .nav__collapsible--open {\n display: flex;\n animation: none;\n }\n\n /* Menu grows to fill available space */\n .nav__menu {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n flex: 1;\n padding-inline: 0;\n }\n\n /* Actions sit at the far right */\n .nav__actions {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n margin-top: 0;\n padding-top: 0;\n padding-inline: 0;\n border-top: none;\n flex-shrink: 0;\n }\n }\n\n /* ─── Mobile menu open animation ─── */\n\n @keyframes hx-mobile-nav-open {\n from {\n opacity: 0;\n transform: translateY(-0.25rem);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n /* ─── Reduced motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .nav__collapsible--open {\n animation: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .nav {\n border-bottom-color: CanvasText;\n }\n\n .mobile-toggle {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n\n .nav__collapsible {\n border-top-color: CanvasText;\n }\n\n .nav__actions {\n border-top-color: CanvasText;\n }\n }\n`;\n","import { html, svg } 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 { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixTopNavStyles } from './hx-top-nav.styles.js';\n\n/**\n * Top-of-page site navigation bar with logo, menu items, and utility area.\n * Supports sticky positioning, responsive hamburger menu, and full slot-driven\n * content composition for Drupal and other CMS consumers.\n *\n * @summary Site-level navigation bar with logo, nav items, and action slots.\n *\n * @tag hx-top-nav\n *\n * @slot logo - Brand area rendered on the left side.\n * @slot - Default slot for primary navigation items rendered in the center.\n * IMPORTANT: Do NOT place a `<nav>` element in this slot — the component\n * already renders a `<nav>` landmark internally. Use a `<div>` or bare links.\n * @slot actions - Utility area rendered on the right side (search, user menu, etc.).\n *\n * @fires {CustomEvent<{open: boolean}>} hx-mobile-toggle - Dispatched when the\n * hamburger button is toggled. Detail contains the new open state.\n *\n * @csspart header - The outer `<header>` landmark element.\n * @csspart nav - The `<nav>` element inside the header.\n * @csspart logo - The logo slot container.\n * @csspart menu - The primary navigation slot container.\n * @csspart actions - The actions slot container.\n * @csspart mobile-toggle - The hamburger toggle button.\n *\n * @cssprop [--hx-top-nav-bg=var(--hx-color-neutral-0)] - Navigation bar background color.\n * @cssprop [--hx-top-nav-color=var(--hx-color-neutral-800)] - Navigation bar text color.\n * @cssprop [--hx-top-nav-border-color=var(--hx-color-neutral-200)] - Bottom border color.\n * @cssprop [--hx-top-nav-height=var(--hx-space-16)] - Navigation bar height.\n * @cssprop [--hx-top-nav-padding-x=var(--hx-space-6)] - Horizontal padding.\n * @cssprop [--hx-top-nav-z-index=var(--hx-z-index-sticky)] - Z-index for sticky mode.\n * @cssprop [--hx-top-nav-toggle-color=var(--hx-color-neutral-700)] - Hamburger icon color.\n * @cssprop [--hx-top-nav-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-z-index-sticky] - Z-index layer.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-space-16] - Spacing token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-duration-fast] - Animation duration.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-width-thin] - Width.\n */\n@customElement('hx-top-nav')\nexport class HelixTopNav extends HelixElement {\n static override styles = [helixTopNavStyles, forcedColorsInteractive];\n\n // ─── Public Properties ───\n\n /**\n * When true, the navigation bar sticks to the top of the viewport during scroll.\n * @attr sticky\n */\n @property({ type: Boolean, reflect: true })\n sticky = false;\n\n /**\n * Accessible label applied to the `<nav>` element via `aria-label`.\n * @attr label\n */\n @property({ type: String })\n label = 'Site Navigation';\n\n // ─── Private State ───\n\n /** Whether the mobile collapsible menu is currently open. */\n /** @internal */\n @state() private _mobileOpen = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('keydown', this._handleKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleKeydown);\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleMobileToggle(): void {\n this._mobileOpen = !this._mobileOpen;\n\n /**\n * Dispatched when the hamburger button is toggled.\n * @event hx-mobile-toggle\n */\n this.dispatchEvent(\n new CustomEvent<{ open: boolean }>('hx-mobile-toggle', {\n bubbles: true,\n composed: true,\n detail: { open: this._mobileOpen },\n }),\n );\n\n if (this._mobileOpen) {\n // Move focus to first truly interactive element in the default slot (WCAG 2.4.3).\n // A plain HTMLElement (e.g. <div>) is not keyboard-reachable; we must find a\n // focusable descendant to avoid trapping focus on a non-interactive node.\n void this.updateComplete.then(() => {\n const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), [tabindex=\"0\"]';\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n const assigned = slot?.assignedElements({ flatten: true }) ?? [];\n let firstFocusable: HTMLElement | null = null;\n for (const el of assigned) {\n if (!(el instanceof HTMLElement)) continue;\n if (el.matches(FOCUSABLE_SELECTOR)) {\n firstFocusable = el;\n break;\n }\n const found = el.querySelector<HTMLElement>(FOCUSABLE_SELECTOR);\n if (found) {\n firstFocusable = found;\n break;\n }\n }\n firstFocusable?.focus();\n });\n }\n }\n\n /** @internal */\n private _handleKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && this._mobileOpen) {\n this._mobileOpen = false;\n this.dispatchEvent(\n new CustomEvent<{ open: boolean }>('hx-mobile-toggle', {\n bubbles: true,\n composed: true,\n detail: { open: false },\n }),\n );\n // Return focus to the toggle button after Lit re-render completes\n void this.updateComplete.then(() => {\n this.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"mobile-toggle\"]')?.focus();\n });\n }\n };\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderHamburgerIcon() {\n return html`\n <svg\n class=\"mobile-toggle__icon\"\n aria-hidden=\"true\"\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 ${this._mobileOpen\n ? svg`\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n `\n : svg`\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"></line>\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"></line>\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\"></line>\n `}\n </svg>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const menuClasses = {\n nav__collapsible: true,\n 'nav__collapsible--open': this._mobileOpen,\n };\n\n return html`\n <header part=\"header\">\n <nav part=\"nav\" class=\"nav\" aria-label=${this.label}>\n <div class=\"nav__bar\">\n <div part=\"logo\" class=\"nav__logo\">\n <slot name=\"logo\"></slot>\n </div>\n\n <button\n part=\"mobile-toggle\"\n class=\"mobile-toggle\"\n type=\"button\"\n aria-expanded=${String(this._mobileOpen)}\n aria-controls=\"nav-menu\"\n aria-label=${this._mobileOpen ? 'Close navigation' : 'Open navigation'}\n @click=${this._handleMobileToggle}\n >\n ${this._renderHamburgerIcon()}\n </button>\n </div>\n\n <div id=\"nav-menu\" class=${classMap(menuClasses)}>\n <div part=\"menu\" class=\"nav__menu\">\n <slot></slot>\n </div>\n\n <div part=\"actions\" class=\"nav__actions\">\n <slot name=\"actions\"></slot>\n </div>\n </div>\n </nav>\n </header>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-top-nav': HelixTopNav;\n }\n}\n"],"names":["helixTopNavStyles","css","HelixTopNav","HelixElement","e","_b","_a","FOCUSABLE_SELECTOR","slot","assigned","firstFocusable","el","found","html","svg","menuClasses","classMap","forcedColorsInteractive","__decorateClass","property","state","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAoBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC6D1B,IAAMC,IAAN,cAA0BC,EAAa;AAAA,EA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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-tree-item-DtMC3DTa.js","sources":["../../src/components/hx-tree-view/hx-tree-view.styles.ts","../../src/components/hx-tree-view/hx-tree-view.ts","../../src/components/hx-tree-view/hx-tree-item.styles.ts","../../src/components/hx-tree-view/hx-tree-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTreeViewStyles = css`\n :host {\n display: block;\n contain: layout style;\n font-family: var(--hx-tree-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n * {\n box-sizing: border-box;\n }\n\n .tree {\n display: block;\n outline: none;\n }\n\n .tree:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .tree:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixTreeViewStyles } from './hx-tree-view.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport type { HelixTreeItem, HxTreeItemSelectDetail } from './hx-tree-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/** Selection mode for the tree. */\nexport type TreeSelection = 'none' | 'single' | 'multiple';\n\n/** Detail type for the `hx-select` event. */\nexport interface HxSelectDetail {\n /** The tree item that was selected or deselected. */\n item: HelixTreeItem;\n /** Whether the item is now selected. */\n selected: boolean;\n}\n\n/**\n * A hierarchical tree component for navigating nested data structures.\n * Used in healthcare applications for org charts, ICD-10 code hierarchies, and department navigation.\n *\n * Implements WAI-ARIA tree view pattern with `role=\"tree\"` on the container\n * and `role=\"treeitem\"` on each item. Supports `aria-label` via the `label` property\n * for screen reader identification. Full keyboard navigation: Arrow keys for movement,\n * Enter/Space for selection, Home/End for first/last item.\n *\n * ## Scale Limits\n *\n * This component renders all tree items simultaneously in the DOM. It is suitable for\n * trees with up to ~500 visible items. For large taxonomies (e.g., ICD-10 with 70,000+\n * codes), use async/lazy loading: only render top-level nodes initially and populate\n * child nodes on `hx-select` or expand events. The component exposes the `expanded`\n * property on `hx-tree-item` for programmatic control of subtrees, enabling consumer-level\n * virtualization strategies without requiring changes to this component.\n *\n * @summary Hierarchical tree view with expand/collapse and keyboard navigation.\n *\n * @tag hx-tree-view\n *\n * @slot - Default slot for hx-tree-item elements.\n *\n * @fires {CustomEvent<HxSelectDetail>} hx-select - Dispatched when a tree item is selected or deselected.\n *\n * @csspart tree - The tree container element with role=\"tree\".\n *\n * @cssprop [--hx-tree-font-family=var(--hx-font-family-sans)] - Tree font family.\n * @cssprop [--hx-font-family-sans] - Font family.\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-border-radius-sm] - CSS custom property.\n */\n@customElement('hx-tree-view')\nexport class HelixTreeView extends HelixElement {\n static override styles = [helixTreeViewStyles, forcedColorsSurface];\n\n // ─── Properties ───\n\n /**\n * Accessible label for the tree. Applied as `aria-label` on the tree container.\n * Provides context to screen readers about the tree's purpose.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Selection mode for the tree.\n * - `none` — items cannot be selected\n * - `single` — only one item can be selected at a time\n * - `multiple` — multiple items can be selected\n * @attr selection\n */\n @property({ type: String, reflect: true })\n selection: 'none' | 'single' | 'multiple' = 'none';\n\n // ─── Internal State ───\n\n /** @internal */\n @state() private _currentIndex = 0;\n\n /** Tracks whether the tree has any visible items, to decide the container tabindex. */\n /** @internal */\n @state() private _hasVisibleItems = false;\n\n // ─── Visible items cache ───\n\n /**\n * Cached flat list of visible items (depth-first, respects collapsed nodes).\n * Set to null to invalidate; rebuilt on next access.\n * @internal\n */\n private _cachedVisibleItems: HelixTreeItem[] | null = null;\n\n /**\n * Invalidate the visible-items cache. Call after any expand/collapse or structural change.\n * @internal\n */\n private _invalidateVisibleItemsCache(): void {\n this._cachedVisibleItems = null;\n }\n\n // ─── Internal Helpers ───\n\n /**\n * Returns a flat ordered list of all visible (not inside a collapsed item) hx-tree-items\n * in depth-first order. Result is cached; invalidated on expand/collapse/slotchange.\n */\n /** @internal */\n private _getVisibleItems(): HelixTreeItem[] {\n if (!this._cachedVisibleItems) {\n this._cachedVisibleItems = this._collectVisibleItems(this);\n }\n return this._cachedVisibleItems;\n }\n\n /** @internal */\n private _collectVisibleItems(container: Element): HelixTreeItem[] {\n const items: HelixTreeItem[] = [];\n for (const child of Array.from(container.children)) {\n if (child.tagName.toLowerCase() === 'hx-tree-item') {\n const item = child as HelixTreeItem;\n items.push(item);\n if (item.expanded) {\n items.push(...this._collectVisibleItems(item));\n }\n } else {\n items.push(...this._collectVisibleItems(child));\n }\n }\n return items;\n }\n\n /** @internal */\n private _getSelectedItems(): HelixTreeItem[] {\n return Array.from(this.querySelectorAll<HelixTreeItem>('hx-tree-item[selected]'));\n }\n\n /**\n * Updates the roving tabindex across all visible items so that only the\n * item at `activeIndex` has `tabindex=\"0\"`. All others receive `tabindex=\"-1\"`.\n * This is called whenever the active item changes (navigation, initial render).\n */\n /** @internal */\n private _updateRovingTabindex(items: HelixTreeItem[], activeIndex: number): void {\n items.forEach((item, i) => {\n item.setRovingActive(i === activeIndex);\n });\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n const clamped = Math.max(0, Math.min(index, items.length - 1));\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n items[clamped]?.focus();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleTreeItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const event = e as CustomEvent<HxTreeItemSelectDetail>;\n const item = event.detail.item;\n\n if (this.selection === 'none') return;\n\n if (this.selection === 'single') {\n const wasSelected = item.selected;\n this._getSelectedItems().forEach((i) => {\n i.selected = false;\n });\n item.selected = !wasSelected;\n } else if (this.selection === 'multiple') {\n item.selected = !item.selected;\n }\n\n this.dispatchEvent(\n new CustomEvent<HxSelectDetail>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item, selected: item.selected },\n }),\n );\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n\n let currentIndex = this._currentIndex;\n const focused = document.activeElement;\n\n for (let i = 0; i < items.length; i++) {\n if (items[i] === focused || items[i]?.shadowRoot?.activeElement) {\n currentIndex = i;\n break;\n }\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n // Intentional design: wrap-around from last to first item provides\n // a continuous navigation loop, consistent with the component's\n // circular keyboard navigation model.\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._focusItem(next);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n // Intentional design: wrap-around from first to last item (see ArrowDown note).\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._focusItem(prev);\n break;\n }\n case 'ArrowLeft': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.expanded && currentItem.hasChildItems) {\n currentItem.expanded = false;\n this._invalidateVisibleItemsCache();\n } else {\n const parentItem = currentItem.parentElement?.closest('hx-tree-item') as\n | HelixTreeItem\n | undefined;\n if (parentItem) {\n const parentIndex = items.indexOf(parentItem);\n if (parentIndex >= 0) {\n this._focusItem(parentIndex);\n }\n }\n }\n break;\n }\n case 'ArrowRight': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.hasChildItems) {\n if (!currentItem.expanded) {\n currentItem.expanded = true;\n this._invalidateVisibleItemsCache();\n } else {\n this._focusItem(currentIndex + 1);\n }\n }\n break;\n }\n case 'Home': {\n e.preventDefault();\n this._focusItem(0);\n break;\n }\n case 'End': {\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n }\n default: {\n // WAI-ARIA APG typeahead: a printable character moves focus to the next visible\n // item whose label starts with that character (case-insensitive).\n if (e.key.length === 1) {\n e.preventDefault();\n const matchIndex = this._findTypeaheadMatch(e.key.toLowerCase(), currentIndex);\n if (matchIndex !== -1) {\n this._focusItem(matchIndex);\n }\n }\n break;\n }\n }\n }\n\n /**\n * Finds the next visible item (starting after `currentIndex`, wrapping around) whose\n * label text begins with the given lowercase character. Returns -1 if no match.\n * @internal\n */\n private _findTypeaheadMatch(char: string, currentIndex: number): number {\n const items = this._getVisibleItems();\n if (items.length === 0) return -1;\n for (let i = 1; i <= items.length; i++) {\n const index = (currentIndex + i) % items.length;\n const item = items[index];\n if (item && item.labelText.toLowerCase().startsWith(char)) {\n return index;\n }\n }\n return -1;\n }\n\n /** @internal */\n private _handleFocusIn(e: FocusEvent): void {\n // With roving tabindex, the tree container (tabindex=\"-1\") should only receive\n // focus when the tree is empty. If focus does land on the container (e.g. the\n // tree is empty or programmatic focus), redirect to the active item if present.\n if (e.target === e.currentTarget) {\n const items = this._getVisibleItems();\n if (items.length > 0) {\n this._focusItem(this._currentIndex);\n }\n }\n }\n\n /**\n * Compute and push ARIA position metadata (level, posInSet, setSize, selectable) to all\n * direct hx-tree-item children of a container in a single O(n) pass.\n * Each item also recurses for its own children, building the full tree in O(total-items) total.\n * @internal\n */\n private _updateAriaMetadataForContainer(container: Element, level: number): void {\n const selectable = this.selection === 'single' || this.selection === 'multiple';\n const children = Array.from(container.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n ) as HelixTreeItem[];\n const setSize = children.length;\n children.forEach((item, index) => {\n item.setAriaMetadata(level, index + 1, setSize, selectable);\n // Recurse into child items so the full tree is updated in one traversal\n this._updateAriaMetadataForContainer(item, level + 1);\n });\n }\n\n /**\n * Initializes the roving tabindex after items are first slotted in.\n * Ensures the active item (index 0 by default) has tabindex=\"0\" from the start,\n * so a Tab into the tree lands directly on the first item without a redirect.\n * Also updates `_hasVisibleItems` so the container tabindex re-renders correctly.\n * Pushes O(n) ARIA metadata to all items to replace the O(n^2) per-item ancestor walk.\n */\n /** @internal */\n private _handleSlotChange(): void {\n this._invalidateVisibleItemsCache();\n // Push ARIA metadata from parent in a single O(n) traversal\n this._updateAriaMetadataForContainer(this, 1);\n const items = this._getVisibleItems();\n this._hasVisibleItems = items.length > 0;\n if (items.length === 0) return;\n // Clamp _currentIndex in case items were removed.\n const clamped = Math.min(this._currentIndex, items.length - 1);\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n }\n\n // ─── Lifecycle ───\n\n override firstUpdated(): void {\n if (!this.label) {\n devWarn(\n 'hx-tree-view',\n 'No accessible label provided. Set the `label` attribute on hx-tree-view so screen readers can identify this tree (WCAG 4.1.2).',\n );\n }\n }\n\n // ─── Render ───\n\n override render() {\n // Roving tabindex pattern (WCAG 2.4.3 Fix):\n // The tree container is NOT a Tab stop (tabindex=\"-1\"). Tab focus goes\n // directly to the active item, which carries tabindex=\"0\". The container\n // is only a landing target (tabindex=\"0\") when the tree is empty.\n const containerTabindex = this._hasVisibleItems ? '-1' : '0';\n\n return html`\n <div\n part=\"tree\"\n class=\"tree\"\n role=\"tree\"\n tabindex=${containerTabindex}\n aria-label=${this.label || 'Tree'}\n aria-multiselectable=${this.selection === 'none'\n ? nothing\n : this.selection === 'multiple'\n ? 'true'\n : 'false'}\n @hx-tree-item-select=${this._handleTreeItemSelect}\n @keydown=${this._handleKeyDown}\n @focusin=${this._handleFocusIn}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-view': HelixTreeView;\n }\n}\n\n/** Canonical type alias for HelixTreeView. Use this when typing hx-tree-view element references. */\nexport type HxTreeView = HelixTreeView;\n","import { css } from 'lit';\n\nexport const helixTreeItemStyles = css`\n :host {\n display: block;\n contain: layout style;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Item Container ─── */\n\n .item {\n display: block;\n }\n\n /* ─── Item Row ─── */\n\n .item-row {\n display: flex;\n align-items: center;\n min-height: var(--hx-touch-target-min, 44px);\n gap: var(--hx-tree-item-gap, var(--hx-space-2, 0.5rem));\n padding: var(--hx-tree-item-padding-y, var(--hx-space-2, 0.5rem))\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem));\n padding-inline-start: calc(\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem)) + var(--_indent-level, 0) *\n var(--hx-tree-indent-size, 1.5rem)\n );\n border-radius: var(--hx-tree-item-border-radius, var(--hx-border-radius-sm, 0.25rem));\n cursor: pointer;\n outline: none;\n color: var(--hx-tree-item-color, var(--hx-color-neutral-900, #0d1825));\n font-family: var(--hx-tree-item-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-tree-item-font-size, var(--hx-font-size-sm, 0.875rem));\n line-height: var(--hx-line-height-normal, 1.5);\n transition: background-color var(--hx-transition-fast, 150ms ease);\n user-select: none;\n }\n\n .item-row:hover {\n background-color: var(--hx-tree-item-hover-bg, var(--hx-color-neutral-100, #ebeee9));\n }\n\n .item-row:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-tree-item-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\n outline-offset: var(--hx-focus-ring-offset, -2px);\n }\n\n /* ─── Selected State ─── */\n\n :host([selected]) .item-row {\n background-color: var(--hx-tree-item-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n color: var(--hx-tree-item-selected-color, var(--hx-color-primary-800, #07494a));\n }\n\n :host([selected]) .item-row:hover {\n background-color: var(--hx-tree-item-selected-hover-bg, var(--hx-color-primary-200, #bce1e1));\n }\n\n /* ─── Disabled State ─── */\n\n :host([disabled]) .item-row {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ─── Expand Icon ─── */\n\n .expand-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n }\n\n .expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n padding: 0;\n border: none;\n background: transparent;\n color: var(--hx-tree-item-expand-icon-color, var(--hx-color-neutral-500, #66787b));\n cursor: pointer;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n transition: transform var(--hx-transition-fast, 150ms ease);\n pointer-events: auto;\n }\n\n .expand-btn:hover {\n background-color: var(\n --hx-tree-item-expand-hover-bg,\n var(--hx-overlay-black-6, rgba(0, 0, 0, 0.06))\n );\n }\n\n .expand-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-tree-item-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500, #429797))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .expand-btn svg {\n width: var(--hx-space-3, 0.75rem);\n height: var(--hx-space-3, 0.75rem);\n stroke: currentColor;\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n :host([expanded]) .expand-btn svg {\n transform: rotate(90deg);\n }\n\n .expand-placeholder {\n display: block;\n width: var(--hx-space-4, 1rem);\n flex-shrink: 0;\n }\n\n /* ─── Icon Slot ─── */\n\n .item-icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--hx-tree-item-icon-color, var(--hx-color-neutral-500, #66787b));\n }\n\n .item-icon:empty {\n display: none;\n }\n\n /* ─── Label ─── */\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* ─── Children (animated) ─── */\n\n .children {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--hx-transition-base, 200ms ease);\n --_indent-level: calc(var(--_indent-level, 0) + 1);\n }\n\n .children--expanded {\n grid-template-rows: 1fr;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .item-row,\n .expand-btn,\n .expand-btn svg,\n .children {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .item-row:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: -2px;\n }\n\n .expand-btn:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n :host([selected]) .item-row {\n outline: 2px solid Highlight;\n }\n }\n\n .children-inner {\n overflow: hidden;\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 { helixTreeItemStyles } from './hx-tree-item.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\n\n/** Detail type for the `hx-tree-item-select` event. */\nexport interface HxTreeItemSelectDetail {\n /** The tree item that was selected or activated. */\n item: HelixTreeItem;\n}\n\n/**\n * A tree item used within an hx-tree-view component.\n * Supports expand/collapse, selection, keyboard navigation, and icon/children slots.\n *\n * @summary Individual item within an hx-tree-view hierarchical tree.\n *\n * @tag hx-tree-item\n *\n * @slot - Default slot for the item label content. This text is also used to label the children group.\n * @slot icon - Custom icon shown before the label.\n * @slot children - Nested hx-tree-item elements for sub-tree.\n *\n * @csspart item - The outer item container.\n * @csspart row - The interactive item row (contains expand icon, icon slot, and label).\n * @csspart expand-icon - The expand/collapse toggle button.\n * @csspart label - The label text content area.\n * @csspart children - The children container.\n *\n * @cssprop [--hx-tree-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-tree-item-hover-bg=var(--hx-color-neutral-100)] - Hover background color.\n * @cssprop [--hx-tree-item-selected-bg=var(--hx-color-primary-100)] - Selected background color.\n * @cssprop [--hx-tree-item-selected-color=var(--hx-color-primary-800)] - Selected text color.\n * @cssprop [--hx-tree-item-padding-x=var(--hx-space-2)] - Horizontal padding.\n * @cssprop [--hx-tree-item-padding-y=var(--hx-space-1)] - Vertical padding.\n * @cssprop [--hx-tree-indent-size=1.5rem] - Indentation size per level.\n *\n * @fires {CustomEvent<HxTreeItemSelectDetail>} hx-tree-item-select - Dispatched when this item is clicked or activated via keyboard.\n */\n@customElement('hx-tree-item')\nexport class HelixTreeItem extends HelixElement {\n static override styles = [helixTreeItemStyles, forcedColorsSurface];\n\n // ─── Properties ───\n\n /**\n * Whether the item is expanded (showing children).\n * @attr expanded\n */\n @property({ type: Boolean, reflect: true })\n expanded = false;\n\n /**\n * Whether the item is selected.\n * @attr selected\n */\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n /**\n * Whether the item is disabled (non-interactive).\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether any elements are assigned to the children slot, controlling expand icon visibility.\n * @internal\n */\n @state() private _hasChildren = false;\n\n /**\n * Whether this item is the roving-tabindex active item in the tree.\n * @internal\n */\n @state() private _rovingActive = false;\n\n /**\n * Text content from the default slot, used to label the children group for screen readers.\n * @internal\n */\n @state() private _labelText = '';\n\n /**\n * Cached ARIA position metadata. Computed once on connect and on slotchange\n * of the parent container, avoiding repeated DOM traversal on every render.\n * @internal\n */\n @state() private _level = 1;\n /**\n * One-based position of this item within its sibling set, set as aria-posinset.\n * @internal\n */\n @state() private _posInSet = 1;\n /**\n * Total count of sibling hx-tree-item elements at the same level, set as aria-setsize.\n * @internal\n */\n @state() private _setSize = 1;\n /**\n * Whether the owning hx-tree-view supports item selection (single or multiple mode).\n * @internal\n */\n @state() private _selectable = false;\n\n /** @internal */\n @query('.item-row') private _itemRowEl!: HTMLElement | null;\n\n // ─── Computed ARIA ───\n\n /**\n * Whether this item has slotted children.\n * @returns True if one or more elements are assigned to the children slot.\n */\n get hasChildItems(): boolean {\n return this._hasChildren;\n }\n\n /**\n * The text content of the item's label slot, used for typeahead keyboard navigation.\n * Returns an empty string until the label slot has been assigned.\n */\n get labelText(): string {\n return this._labelText;\n }\n\n /**\n * Recompute all cached ARIA metadata in a single DOM pass.\n * Called on connect, slotchange, and whenever structural context may change.\n * @internal\n */\n private _updateAriaMetadata(): void {\n // Compute nesting level by counting ancestor hx-tree-item elements.\n let level = 1;\n let el: Element | null = this.parentElement;\n while (el) {\n if (el.tagName.toLowerCase() === 'hx-tree-item') level++;\n el = el.parentElement;\n }\n this._level = level;\n\n // Compute position-in-set and set-size from sibling hx-tree-item elements.\n const parent = this.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n );\n this._posInSet = siblings.indexOf(this) + 1;\n this._setSize = siblings.length;\n } else {\n this._posInSet = 1;\n this._setSize = 1;\n }\n\n // Determine if the owning tree supports selection.\n const tree = this.closest('hx-tree-view');\n if (tree) {\n const selection = tree.getAttribute('selection');\n this._selectable = selection === 'single' || selection === 'multiple';\n } else {\n this._selectable = false;\n }\n }\n\n /**\n * Set ARIA position metadata from the parent hx-tree-view in a single O(n) pass.\n * Calling this avoids the O(n^2) ancestor-walk + sibling-iteration in _updateAriaMetadata\n * when the parent already knows the layout.\n * @internal\n */\n setAriaMetadata(level: number, posInSet: number, setSize: number, selectable: boolean): void {\n this._level = level;\n this._posInSet = posInSet;\n this._setSize = setSize;\n this._selectable = selectable;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._updateAriaMetadata();\n }\n\n // ─── Children Detection ───\n\n /**\n * Updates _hasChildren and recomputes ARIA metadata when the children slot assignment changes.\n * @internal\n */\n private _handleChildrenSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasChildren = slot.assignedElements().length > 0;\n this._updateAriaMetadata();\n }\n\n /**\n * Captures the text content from the default (label) slot for use on the children group label.\n * @internal\n */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const nodes = slot.assignedNodes({ flatten: true });\n this._labelText = nodes\n .map((n) => n.textContent ?? '')\n .join('')\n .trim();\n }\n\n // ─── Event Handlers ───\n\n /**\n * Toggles the expanded state when the expand/collapse button is clicked, stopping event propagation.\n * @internal\n */\n private _handleExpandClick(e: Event): void {\n e.stopPropagation();\n if (this.disabled) return;\n this.expanded = !this.expanded;\n }\n\n /**\n * Dispatches the hx-tree-item-select event when the item is activated via click or keyboard.\n * @internal\n */\n private _handleRowClick(): void {\n if (this.disabled) return;\n this.dispatchEvent(\n new CustomEvent<HxTreeItemSelectDetail>('hx-tree-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n\n /**\n * Handles keyboard interaction for the tree item, including expand/collapse, activation, and delegation of list-navigation keys to the parent tree.\n * @internal\n */\n private _handleKeyDown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n switch (e.key) {\n case 'ArrowRight':\n e.preventDefault();\n if (this._hasChildren && !this.expanded) {\n this.expanded = true;\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (this._hasChildren && this.expanded) {\n this.expanded = false;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n this._handleRowClick();\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n case 'Home':\n case 'End':\n // Bubble up to hx-tree-view for navigation\n break;\n }\n }\n\n // ─── Public API ───\n\n /**\n * Sets the roving tabindex state for this item.\n * When `active` is true, the item row gets `tabindex=\"0\"` making it the\n * Tab-reachable item in the tree. All other items should be set to false.\n * Called by the parent hx-tree-view to manage the roving tabindex pattern.\n */\n setRovingActive(active: boolean): void {\n this._rovingActive = active;\n }\n\n /** Focus this item's interactive row element. */\n override focus(): void {\n this._itemRowEl?.focus();\n }\n\n // ─── Render ───\n\n /**\n * Renders the expand/collapse chevron button, or a placeholder span when the item has no children.\n * @internal\n */\n private _renderExpandIcon() {\n if (!this._hasChildren) {\n return html`<span class=\"expand-placeholder\" aria-hidden=\"true\"></span>`;\n }\n return html`\n <button\n part=\"expand-icon\"\n class=\"expand-btn\"\n tabindex=\"-1\"\n aria-label=\"${this.expanded ? 'Collapse' : 'Expand'}\"\n @click=${this._handleExpandClick}\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <polyline points=\"6 4 10 8 6 12\" />\n </svg>\n </button>\n `;\n }\n\n override render() {\n const ariaExpanded = this._hasChildren ? String(this.expanded) : nothing;\n const ariaSelected = this._selectable ? String(this.selected) : nothing;\n\n return html`\n <div part=\"item\" class=\"item\">\n <div\n part=\"row\"\n class=\"item-row\"\n role=\"treeitem\"\n tabindex=${this._rovingActive ? '0' : '-1'}\n aria-expanded=${ariaExpanded}\n aria-selected=${ariaSelected}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-level=${this._level}\n aria-posinset=${this._posInSet}\n aria-setsize=${this._setSize}\n @click=${this._handleRowClick}\n @keydown=${this._handleKeyDown}\n >\n ${this._renderExpandIcon()}\n <span class=\"item-icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"item-label\">\n <slot @slotchange=${this._handleLabelSlotChange}></slot>\n </span>\n </div>\n <div\n part=\"children\"\n class=${classMap({ children: true, 'children--expanded': this.expanded })}\n role=\"group\"\n aria-label=${this._labelText ? `${this._labelText} children` : 'children'}\n aria-hidden=${!this.expanded || nothing}\n >\n <div class=\"children-inner\">\n <slot name=\"children\" @slotchange=${this._handleChildrenSlotChange}></slot>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-item': HelixTreeItem;\n }\n}\n\n/** Canonical type alias for HelixTreeItem. Use this when typing hx-tree-item element references. */\nexport type HxTreeItem = HelixTreeItem;\n"],"names":["helixTreeViewStyles","css","HelixTreeView","HelixElement","container","items","child","item","activeIndex","i","index","clamped","_a","wasSelected","currentIndex","focused","_b","next","prev","currentItem","parentItem","_c","parentIndex","matchIndex","char","level","selectable","children","c","setSize","containerTabindex","html","nothing","forcedColorsSurface","__decorateClass","property","state","customElement","helixTreeItemStyles","HelixTreeItem","el","parent","siblings","tree","selection","posInSet","slot","nodes","n","active","ariaExpanded","ariaSelected","classMap","query"],"mappings":"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"}
|