@helixui/library 3.0.0-next.65 → 3.1.0-next.66
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 +6549 -318
- package/dist/components/hx-accordion/hx-accordion.d.ts +3 -0
- package/dist/components/hx-accordion/hx-accordion.d.ts.map +1 -1
- package/dist/components/hx-action-bar/hx-action-bar.d.ts +14 -0
- package/dist/components/hx-action-bar/hx-action-bar.d.ts.map +1 -1
- package/dist/components/hx-action-bar/index.js +1 -1
- package/dist/components/hx-alert/hx-alert.d.ts +36 -0
- package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
- package/dist/components/hx-avatar/hx-avatar.d.ts +17 -0
- package/dist/components/hx-avatar/hx-avatar.d.ts.map +1 -1
- package/dist/components/hx-badge/hx-badge.d.ts +35 -0
- package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
- package/dist/components/hx-banner/hx-banner.d.ts +34 -0
- package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts +3 -0
- package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/index.js +1 -1
- package/dist/components/hx-button/hx-button.d.ts +42 -0
- package/dist/components/hx-button/hx-button.d.ts.map +1 -1
- package/dist/components/hx-button/index.js +1 -1
- package/dist/components/hx-button-group/hx-button-group.d.ts +2 -0
- package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
- package/dist/components/hx-card/hx-card.d.ts +28 -0
- package/dist/components/hx-card/hx-card.d.ts.map +1 -1
- package/dist/components/hx-card/index.js +1 -1
- package/dist/components/hx-carousel/hx-carousel.d.ts +25 -0
- package/dist/components/hx-carousel/hx-carousel.d.ts.map +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.d.ts +31 -0
- package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +14 -0
- package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
- package/dist/components/hx-checkbox-group/index.js +1 -1
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +37 -0
- package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
- package/dist/components/hx-code-snippet/hx-code-snippet.d.ts +35 -0
- package/dist/components/hx-code-snippet/hx-code-snippet.d.ts.map +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.d.ts +29 -0
- package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
- package/dist/components/hx-combobox/hx-combobox.d.ts +49 -0
- package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-container/hx-container.d.ts +5 -0
- package/dist/components/hx-container/hx-container.d.ts.map +1 -1
- package/dist/components/hx-copy-button/hx-copy-button.d.ts +24 -0
- package/dist/components/hx-copy-button/hx-copy-button.d.ts.map +1 -1
- package/dist/components/hx-counter/hx-counter.d.ts +7 -0
- package/dist/components/hx-counter/hx-counter.d.ts.map +1 -1
- package/dist/components/hx-data-table/hx-data-table.d.ts +29 -0
- package/dist/components/hx-data-table/hx-data-table.d.ts.map +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/hx-date-picker.d.ts +44 -0
- package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/hx-dialog.d.ts +31 -0
- package/dist/components/hx-dialog/hx-dialog.d.ts.map +1 -1
- package/dist/components/hx-dialog/index.js +1 -1
- package/dist/components/hx-divider/hx-divider.d.ts +9 -0
- package/dist/components/hx-divider/hx-divider.d.ts.map +1 -1
- package/dist/components/hx-divider/index.js +1 -1
- package/dist/components/hx-drawer/hx-drawer.d.ts +30 -0
- package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
- package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
- package/dist/components/hx-drawer/index.js +1 -1
- package/dist/components/hx-dropdown/hx-dropdown.d.ts +6 -0
- package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
- package/dist/components/hx-dropdown/index.js +1 -1
- package/dist/components/hx-field/hx-field.d.ts +15 -0
- package/dist/components/hx-field/hx-field.d.ts.map +1 -1
- package/dist/components/hx-field/index.js +1 -1
- package/dist/components/hx-field-label/hx-field-label.d.ts +11 -0
- package/dist/components/hx-field-label/hx-field-label.d.ts.map +1 -1
- package/dist/components/hx-field-label/index.js +1 -1
- package/dist/components/hx-file-upload/hx-file-upload.d.ts +35 -0
- package/dist/components/hx-file-upload/hx-file-upload.d.ts.map +1 -1
- package/dist/components/hx-file-upload/index.js +1 -1
- package/dist/components/hx-grid/hx-grid.d.ts +5 -0
- package/dist/components/hx-grid/hx-grid.d.ts.map +1 -1
- package/dist/components/hx-help-text/hx-help-text.d.ts +8 -0
- package/dist/components/hx-help-text/hx-help-text.d.ts.map +1 -1
- package/dist/components/hx-help-text/index.js +1 -1
- package/dist/components/hx-icon/hx-icon.d.ts +5 -0
- package/dist/components/hx-icon/hx-icon.d.ts.map +1 -1
- package/dist/components/hx-icon-button/hx-icon-button.d.ts +27 -0
- package/dist/components/hx-icon-button/hx-icon-button.d.ts.map +1 -1
- package/dist/components/hx-icon-button/index.js +1 -1
- package/dist/components/hx-image/hx-image.d.ts +4 -0
- package/dist/components/hx-image/hx-image.d.ts.map +1 -1
- package/dist/components/hx-link/hx-link.d.ts +15 -0
- package/dist/components/hx-link/hx-link.d.ts.map +1 -1
- package/dist/components/hx-link/index.js +1 -1
- package/dist/components/hx-list/hx-list.d.ts +3 -0
- package/dist/components/hx-list/hx-list.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu.d.ts +6 -0
- package/dist/components/hx-menu/hx-menu.d.ts.map +1 -1
- package/dist/components/hx-menu/index.js +1 -1
- package/dist/components/hx-meter/hx-meter.d.ts +23 -0
- package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
- package/dist/components/hx-nav/hx-nav.d.ts +29 -0
- package/dist/components/hx-nav/hx-nav.d.ts.map +1 -1
- package/dist/components/hx-number-input/hx-number-input.d.ts +34 -0
- package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
- package/dist/components/hx-number-input/index.js +1 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +26 -0
- package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
- package/dist/components/hx-overflow-menu/index.js +1 -1
- package/dist/components/hx-pagination/hx-pagination.d.ts +21 -0
- package/dist/components/hx-pagination/hx-pagination.d.ts.map +1 -1
- package/dist/components/hx-pagination/index.js +1 -1
- package/dist/components/hx-patient-banner/hx-patient-banner.d.ts +23 -0
- package/dist/components/hx-patient-banner/hx-patient-banner.d.ts.map +1 -1
- package/dist/components/hx-phi-field/hx-phi-field.d.ts +14 -0
- package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
- package/dist/components/hx-phi-field/index.js +1 -1
- package/dist/components/hx-popover/hx-popover.d.ts +15 -0
- package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
- package/dist/components/hx-popover/index.js +1 -1
- package/dist/components/hx-popup/hx-popup.d.ts +1 -0
- package/dist/components/hx-popup/hx-popup.d.ts.map +1 -1
- package/dist/components/hx-progress-bar/hx-progress-bar.d.ts +17 -0
- package/dist/components/hx-progress-bar/hx-progress-bar.d.ts.map +1 -1
- package/dist/components/hx-progress-bar/index.js +1 -1
- package/dist/components/hx-progress-ring/hx-progress-ring.d.ts +15 -0
- package/dist/components/hx-progress-ring/hx-progress-ring.d.ts.map +1 -1
- package/dist/components/hx-prose/hx-prose.d.ts +2 -0
- package/dist/components/hx-prose/hx-prose.d.ts.map +1 -1
- package/dist/components/hx-radio-group/hx-radio-group.d.ts +14 -0
- package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-rating/hx-rating.d.ts +13 -0
- package/dist/components/hx-rating/hx-rating.d.ts.map +1 -1
- package/dist/components/hx-select/hx-select.d.ts +43 -0
- package/dist/components/hx-select/hx-select.d.ts.map +1 -1
- package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
- package/dist/components/hx-select/index.js +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-side-nav.d.ts +19 -0
- package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
- package/dist/components/hx-side-nav/index.js +1 -1
- package/dist/components/hx-skeleton/hx-skeleton.d.ts +5 -0
- package/dist/components/hx-skeleton/hx-skeleton.d.ts.map +1 -1
- package/dist/components/hx-slider/hx-slider.d.ts +38 -0
- package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
- package/dist/components/hx-slider/index.js +1 -1
- package/dist/components/hx-spinner/hx-spinner.d.ts +10 -0
- package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
- package/dist/components/hx-split-button/hx-split-button.d.ts +39 -0
- package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
- package/dist/components/hx-split-button/index.js +1 -1
- package/dist/components/hx-split-panel/hx-split-panel.d.ts +12 -0
- package/dist/components/hx-split-panel/hx-split-panel.d.ts.map +1 -1
- package/dist/components/hx-split-panel/index.js +1 -1
- package/dist/components/hx-stack/hx-stack.d.ts +5 -0
- package/dist/components/hx-stack/hx-stack.d.ts.map +1 -1
- package/dist/components/hx-stat/hx-stat.d.ts +24 -0
- package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
- package/dist/components/hx-status-indicator/hx-status-indicator.d.ts +13 -0
- package/dist/components/hx-status-indicator/hx-status-indicator.d.ts.map +1 -1
- package/dist/components/hx-steps/hx-steps.d.ts +15 -0
- package/dist/components/hx-steps/hx-steps.d.ts.map +1 -1
- package/dist/components/hx-structured-list/hx-structured-list.d.ts +7 -0
- package/dist/components/hx-structured-list/hx-structured-list.d.ts.map +1 -1
- package/dist/components/hx-switch/hx-switch.d.ts +42 -0
- package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
- package/dist/components/hx-switch/index.js +1 -1
- package/dist/components/hx-table/hx-table.d.ts +14 -0
- package/dist/components/hx-table/hx-table.d.ts.map +1 -1
- package/dist/components/hx-tabs/hx-tabs.d.ts +4 -0
- package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
- package/dist/components/hx-tag/hx-tag.d.ts +36 -0
- package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
- package/dist/components/hx-text/hx-text.d.ts +22 -0
- package/dist/components/hx-text/hx-text.d.ts.map +1 -1
- package/dist/components/hx-text-input/hx-text-input.d.ts +30 -0
- package/dist/components/hx-text-input/hx-text-input.d.ts.map +1 -1
- package/dist/components/hx-text-input/index.js +1 -1
- package/dist/components/hx-textarea/hx-textarea.d.ts +27 -0
- package/dist/components/hx-textarea/hx-textarea.d.ts.map +1 -1
- package/dist/components/hx-textarea/index.js +1 -1
- package/dist/components/hx-theme/hx-theme.d.ts +3 -0
- package/dist/components/hx-theme/hx-theme.d.ts.map +1 -1
- package/dist/components/hx-theme/index.js +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.d.ts +32 -0
- package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toast/hx-toast.d.ts +24 -0
- package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +35 -0
- package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/index.js +1 -1
- package/dist/components/hx-tooltip/hx-tooltip.d.ts +13 -0
- package/dist/components/hx-tooltip/hx-tooltip.d.ts.map +1 -1
- package/dist/components/hx-tooltip/index.js +1 -1
- package/dist/components/hx-top-nav/hx-top-nav.d.ts +21 -0
- package/dist/components/hx-top-nav/hx-top-nav.d.ts.map +1 -1
- package/dist/components/hx-top-nav/index.js +1 -1
- package/dist/components/hx-tree-view/hx-tree-view.d.ts +6 -0
- package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
- package/dist/css/helix-all.css +263 -253
- package/dist/css/helix-core.css +26 -26
- package/dist/css/helix-data.css +8 -7
- package/dist/css/helix-feedback.css +2 -2
- package/dist/css/helix-forms.css +137 -131
- package/dist/css/helix-layout.css +3 -3
- package/dist/css/helix-navigation.css +35 -35
- package/dist/css/helix-overlay.css +32 -29
- package/dist/css/helix-tokens.css +12 -0
- package/dist/css/helix-utility.css +18 -18
- package/dist/css/hx-action-bar.css +3 -3
- package/dist/css/hx-button.css +10 -10
- package/dist/css/hx-card.css +6 -6
- package/dist/css/hx-checkbox-group.css +2 -2
- package/dist/css/hx-checkbox.css +5 -5
- package/dist/css/hx-combobox.css +13 -13
- package/dist/css/hx-data-table.css +8 -7
- package/dist/css/hx-date-picker.css +20 -20
- package/dist/css/hx-dialog.css +10 -10
- package/dist/css/hx-divider.css +2 -2
- package/dist/css/hx-drawer.css +12 -9
- package/dist/css/hx-dropdown.css +2 -2
- package/dist/css/hx-field-label.css +2 -2
- package/dist/css/hx-field.css +2 -2
- package/dist/css/hx-file-upload.css +11 -11
- package/dist/css/hx-help-text.css +2 -2
- package/dist/css/hx-icon-button.css +6 -6
- package/dist/css/hx-link.css +2 -2
- package/dist/css/hx-menu.css +2 -2
- package/dist/css/hx-number-input.css +12 -12
- package/dist/css/hx-overflow-menu.css +7 -7
- package/dist/css/hx-pagination.css +10 -10
- package/dist/css/hx-phi-field.css +2 -2
- package/dist/css/hx-popover.css +5 -5
- package/dist/css/hx-progress-bar.css +2 -2
- package/dist/css/hx-radio-group.css +2 -2
- package/dist/css/hx-select.css +11 -8
- package/dist/css/hx-side-nav.css +9 -9
- package/dist/css/hx-slider.css +9 -9
- package/dist/css/hx-split-button.css +15 -15
- package/dist/css/hx-split-panel.css +3 -3
- package/dist/css/hx-switch.css +4 -4
- package/dist/css/hx-text-input.css +7 -7
- package/dist/css/hx-textarea.css +7 -7
- package/dist/css/hx-time-picker.css +11 -11
- package/dist/css/hx-toggle-button.css +17 -14
- package/dist/css/hx-tooltip.css +3 -3
- package/dist/css/hx-top-nav.css +7 -7
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +162 -163
- package/dist/index.js +40 -40
- package/dist/shared/hx-accordion-Wt52OOZD.js.map +1 -1
- package/dist/shared/{hx-action-bar-BKMADbHj.js → hx-action-bar-6UzmViHI.js} +4 -4
- package/dist/shared/hx-action-bar-6UzmViHI.js.map +1 -0
- package/dist/shared/hx-alert-D7n94HwI.js.map +1 -1
- package/dist/shared/hx-avatar-iLYzu8MJ.js.map +1 -1
- package/dist/shared/hx-badge-CVCmMPyW.js.map +1 -1
- package/dist/shared/hx-banner-C_He7Tr4.js.map +1 -1
- package/dist/shared/{hx-breadcrumb-item-CldCwD1d.js → hx-breadcrumb-item-BgG5RcmA.js} +3 -3
- package/dist/shared/hx-breadcrumb-item-BgG5RcmA.js.map +1 -0
- package/dist/shared/{hx-button-Ddl-T6T-.js → hx-button-CQZswjtQ.js} +15 -15
- package/dist/shared/hx-button-CQZswjtQ.js.map +1 -0
- package/dist/shared/hx-button-group-BJOGWoMa.js.map +1 -1
- package/dist/shared/{hx-card-ycveujjL.js → hx-card-Dy_FuLfS.js} +23 -23
- package/dist/shared/hx-card-Dy_FuLfS.js.map +1 -0
- package/dist/shared/hx-carousel-item-D_dCv61-.js.map +1 -1
- package/dist/shared/{hx-checkbox-DkkoWoye.js → hx-checkbox-ZKjOF7_3.js} +17 -17
- package/dist/shared/{hx-checkbox-DkkoWoye.js.map → hx-checkbox-ZKjOF7_3.js.map} +1 -1
- package/dist/shared/{hx-checkbox-group-C3poJ-Zw.js → hx-checkbox-group-XjOBHLiP.js} +3 -3
- package/dist/shared/hx-checkbox-group-XjOBHLiP.js.map +1 -0
- package/dist/shared/hx-clinical-status-BS5lcddT.js.map +1 -1
- package/dist/shared/hx-code-snippet-B7wUKzyb.js.map +1 -1
- package/dist/shared/hx-color-picker-DBaKTVLr.js.map +1 -1
- package/dist/shared/{hx-combobox-BmgYT7Ar.js → hx-combobox-DLwnvHVd.js} +17 -17
- package/dist/shared/hx-combobox-DLwnvHVd.js.map +1 -0
- package/dist/shared/hx-container-DVI7sxfX.js.map +1 -1
- package/dist/shared/hx-copy-button-8deNUdwP.js.map +1 -1
- package/dist/shared/hx-counter-CKfl_g8K.js.map +1 -1
- package/dist/shared/{hx-data-table-B6h0RPn0.js → hx-data-table-CnLxo9PH.js} +77 -76
- package/dist/shared/hx-data-table-CnLxo9PH.js.map +1 -0
- package/dist/shared/{hx-date-picker-Dq2Nb68_.js → hx-date-picker-D7H7CsVH.js} +21 -21
- package/dist/shared/hx-date-picker-D7H7CsVH.js.map +1 -0
- package/dist/shared/{hx-dialog-CvIlY0Tc.js → hx-dialog-BW-jetzN.js} +33 -33
- package/dist/shared/hx-dialog-BW-jetzN.js.map +1 -0
- package/dist/shared/{hx-divider-DwpOrzMW.js → hx-divider-CvyUVcp-.js} +13 -13
- package/dist/shared/hx-divider-CvyUVcp-.js.map +1 -0
- package/dist/shared/{hx-drawer-Cx2ZJhBe.js → hx-drawer-BT52I4tk.js} +13 -10
- package/dist/shared/hx-drawer-BT52I4tk.js.map +1 -0
- package/dist/shared/{hx-dropdown-BjDrPUq5.js → hx-dropdown-BpVpL6Dz.js} +3 -3
- package/dist/shared/{hx-dropdown-BjDrPUq5.js.map → hx-dropdown-BpVpL6Dz.js.map} +1 -1
- package/dist/shared/{hx-field-Dp3qQMut.js → hx-field-BX4zE3z5.js} +7 -7
- package/dist/shared/hx-field-BX4zE3z5.js.map +1 -0
- package/dist/shared/{hx-field-label-BC8QViXv.js → hx-field-label-DtJzb1r3.js} +8 -8
- package/dist/shared/hx-field-label-DtJzb1r3.js.map +1 -0
- package/dist/shared/{hx-file-upload-B6Yl1u0i.js → hx-file-upload-BNuepoGn.js} +34 -34
- package/dist/shared/hx-file-upload-BNuepoGn.js.map +1 -0
- package/dist/shared/hx-grid-CXZf3jeK.js.map +1 -1
- package/dist/shared/{hx-help-text-D7eytSim.js → hx-help-text-Br3igJv5.js} +7 -7
- package/dist/shared/hx-help-text-Br3igJv5.js.map +1 -0
- package/dist/shared/hx-icon-CcyDPDYY.js.map +1 -1
- package/dist/shared/{hx-icon-button-BHneqPCU.js → hx-icon-button-CqXH5Wwb.js} +7 -7
- package/dist/shared/hx-icon-button-CqXH5Wwb.js.map +1 -0
- package/dist/shared/hx-image-2gt14zZd.js.map +1 -1
- package/dist/shared/{hx-link-BESrWK8M.js → hx-link-Bem4Gn68.js} +8 -8
- package/dist/shared/hx-link-Bem4Gn68.js.map +1 -0
- package/dist/shared/hx-list-_9qVv02L.js.map +1 -1
- package/dist/shared/{hx-menu-divider-Ck-9Os1t.js → hx-menu-divider-DsHWyPHy.js} +37 -37
- package/dist/shared/hx-menu-divider-DsHWyPHy.js.map +1 -0
- package/dist/shared/hx-meter-TbROk-dw.js.map +1 -1
- package/dist/shared/hx-nav-BcYDmjf7.js.map +1 -1
- package/dist/shared/{hx-nav-item-pqPasRUm.js → hx-nav-item-BTMMQv6c.js} +34 -30
- package/dist/shared/hx-nav-item-BTMMQv6c.js.map +1 -0
- package/dist/shared/{hx-number-input-mOIZ3-46.js → hx-number-input-l6jeaGWW.js} +71 -71
- package/dist/shared/hx-number-input-l6jeaGWW.js.map +1 -0
- package/dist/shared/{hx-overflow-menu-Dprb9lnT.js → hx-overflow-menu-DJ4qpgmi.js} +12 -12
- package/dist/shared/hx-overflow-menu-DJ4qpgmi.js.map +1 -0
- package/dist/shared/{hx-pagination-AguTQjYC.js → hx-pagination-5FeVFIve.js} +64 -64
- package/dist/shared/hx-pagination-5FeVFIve.js.map +1 -0
- package/dist/shared/hx-patient-banner-uE6gqLpT.js.map +1 -1
- package/dist/shared/{hx-phi-field-BC_XowhC.js → hx-phi-field-DxeWcRm9.js} +3 -3
- package/dist/shared/hx-phi-field-DxeWcRm9.js.map +1 -0
- package/dist/shared/{hx-popover-B2_203ct.js → hx-popover-C05QcD9m.js} +6 -6
- package/dist/shared/hx-popover-C05QcD9m.js.map +1 -0
- package/dist/shared/hx-popup-DZXpsJ1R.js.map +1 -1
- package/dist/shared/{hx-progress-bar-KjEkEJLy.js → hx-progress-bar-CJdwAeDg.js} +11 -11
- package/dist/shared/hx-progress-bar-CJdwAeDg.js.map +1 -0
- package/dist/shared/hx-progress-ring-3zMwvrwD.js.map +1 -1
- package/dist/shared/hx-prose-BCtK7YL6.js.map +1 -1
- package/dist/shared/{hx-radio-BBC5qZgE.js → hx-radio-QHrhL908.js} +11 -11
- package/dist/shared/hx-radio-QHrhL908.js.map +1 -0
- package/dist/shared/hx-rating-C3E3ENJb.js.map +1 -1
- package/dist/shared/{hx-select-CixTo7jp.js → hx-select-BuMvRDkY.js} +47 -44
- package/dist/shared/hx-select-BuMvRDkY.js.map +1 -0
- package/dist/shared/hx-skeleton-LxkI0pxr.js.map +1 -1
- package/dist/shared/{hx-slider-DFHuzF3N.js → hx-slider-wcF_oyNJ.js} +41 -41
- package/dist/shared/hx-slider-wcF_oyNJ.js.map +1 -0
- package/dist/shared/hx-spinner-BKjuCdZB.js.map +1 -1
- package/dist/shared/{hx-split-button-CGcJMmCG.js → hx-split-button-CEkQqbF9.js} +32 -32
- package/dist/shared/hx-split-button-CEkQqbF9.js.map +1 -0
- package/dist/shared/{hx-split-panel-C-1R10Mc.js → hx-split-panel-BymHlV5e.js} +4 -4
- package/dist/shared/hx-split-panel-BymHlV5e.js.map +1 -0
- package/dist/shared/hx-stack-DGfcOfWJ.js.map +1 -1
- package/dist/shared/hx-stat-BTpykQAt.js.map +1 -1
- package/dist/shared/hx-status-indicator-X2QEWNFt.js.map +1 -1
- package/dist/shared/hx-step-CRNQlmSo.js.map +1 -1
- package/dist/shared/hx-structured-list-CqNbaEXg.js.map +1 -1
- package/dist/shared/{hx-switch-DqOD9JR7.js → hx-switch-CbunfMHW.js} +5 -5
- package/dist/shared/hx-switch-CbunfMHW.js.map +1 -0
- package/dist/shared/hx-tab-panel-BIzKfW5i.js.map +1 -1
- package/dist/shared/hx-tag-CgnrNnte.js.map +1 -1
- package/dist/shared/hx-td-Bra35cH4.js.map +1 -1
- package/dist/shared/hx-text-DMC2CPlL.js.map +1 -1
- package/dist/shared/{hx-text-input--q0GH78x.js → hx-text-input-eSPVURd5.js} +8 -8
- package/dist/shared/hx-text-input-eSPVURd5.js.map +1 -0
- package/dist/shared/{hx-textarea-CK621vSL.js → hx-textarea-C4DjRmo4.js} +12 -12
- package/dist/shared/hx-textarea-C4DjRmo4.js.map +1 -0
- package/dist/shared/{hx-theme-DfEy-SJA.js → hx-theme-DP4oPU1i.js} +44 -35
- package/dist/shared/hx-theme-DP4oPU1i.js.map +1 -0
- package/dist/shared/{hx-time-picker-tPUfgElQ.js → hx-time-picker-BtbHX7A4.js} +28 -28
- package/dist/shared/hx-time-picker-BtbHX7A4.js.map +1 -0
- package/dist/shared/{hx-toggle-button-L-uBJr-a.js → hx-toggle-button-FOvw-ebx.js} +26 -23
- package/dist/shared/hx-toggle-button-FOvw-ebx.js.map +1 -0
- package/dist/shared/{hx-tooltip-B_zfKvwc.js → hx-tooltip-BoZi2crX.js} +4 -4
- package/dist/shared/hx-tooltip-BoZi2crX.js.map +1 -0
- package/dist/shared/{hx-top-nav-CATbRvIv.js → hx-top-nav-Cd9zvv1B.js} +20 -20
- package/dist/shared/hx-top-nav-Cd9zvv1B.js.map +1 -0
- package/dist/shared/hx-tree-item-A45WCiBu.js.map +1 -1
- package/dist/shared/toast-factory-BPPnG3mM.js.map +1 -1
- package/figma-inventory.json +8526 -511
- package/package.json +2 -2
- package/dist/shared/hx-action-bar-BKMADbHj.js.map +0 -1
- package/dist/shared/hx-breadcrumb-item-CldCwD1d.js.map +0 -1
- package/dist/shared/hx-button-Ddl-T6T-.js.map +0 -1
- package/dist/shared/hx-card-ycveujjL.js.map +0 -1
- package/dist/shared/hx-checkbox-group-C3poJ-Zw.js.map +0 -1
- package/dist/shared/hx-combobox-BmgYT7Ar.js.map +0 -1
- package/dist/shared/hx-data-table-B6h0RPn0.js.map +0 -1
- package/dist/shared/hx-date-picker-Dq2Nb68_.js.map +0 -1
- package/dist/shared/hx-dialog-CvIlY0Tc.js.map +0 -1
- package/dist/shared/hx-divider-DwpOrzMW.js.map +0 -1
- package/dist/shared/hx-drawer-Cx2ZJhBe.js.map +0 -1
- package/dist/shared/hx-field-Dp3qQMut.js.map +0 -1
- package/dist/shared/hx-field-label-BC8QViXv.js.map +0 -1
- package/dist/shared/hx-file-upload-B6Yl1u0i.js.map +0 -1
- package/dist/shared/hx-help-text-D7eytSim.js.map +0 -1
- package/dist/shared/hx-icon-button-BHneqPCU.js.map +0 -1
- package/dist/shared/hx-link-BESrWK8M.js.map +0 -1
- package/dist/shared/hx-menu-divider-Ck-9Os1t.js.map +0 -1
- package/dist/shared/hx-nav-item-pqPasRUm.js.map +0 -1
- package/dist/shared/hx-number-input-mOIZ3-46.js.map +0 -1
- package/dist/shared/hx-overflow-menu-Dprb9lnT.js.map +0 -1
- package/dist/shared/hx-pagination-AguTQjYC.js.map +0 -1
- package/dist/shared/hx-phi-field-BC_XowhC.js.map +0 -1
- package/dist/shared/hx-popover-B2_203ct.js.map +0 -1
- package/dist/shared/hx-progress-bar-KjEkEJLy.js.map +0 -1
- package/dist/shared/hx-radio-BBC5qZgE.js.map +0 -1
- package/dist/shared/hx-select-CixTo7jp.js.map +0 -1
- package/dist/shared/hx-slider-DFHuzF3N.js.map +0 -1
- package/dist/shared/hx-split-button-CGcJMmCG.js.map +0 -1
- package/dist/shared/hx-split-panel-C-1R10Mc.js.map +0 -1
- package/dist/shared/hx-switch-DqOD9JR7.js.map +0 -1
- package/dist/shared/hx-text-input--q0GH78x.js.map +0 -1
- package/dist/shared/hx-textarea-CK621vSL.js.map +0 -1
- package/dist/shared/hx-theme-DfEy-SJA.js.map +0 -1
- package/dist/shared/hx-time-picker-tPUfgElQ.js.map +0 -1
- package/dist/shared/hx-toggle-button-L-uBJr-a.js.map +0 -1
- package/dist/shared/hx-tooltip-B_zfKvwc.js.map +0 -1
- package/dist/shared/hx-top-nav-CATbRvIv.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-file-upload-B6Yl1u0i.js","sources":["../../src/components/hx-file-upload/hx-file-upload.styles.ts","../../src/components/hx-file-upload/hx-file-upload.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixFileUploadStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n\n * {\n box-sizing: border-box;\n }\n\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2, 0.5rem);\n font-family: var(--hx-file-upload-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n /* ─── Label ─── */\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(--hx-color-neutral-700, #334155);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Dropzone ─── */\n\n .dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n min-height: var(--hx-space-32, 8rem);\n padding: var(--hx-space-6, 1.5rem) var(--hx-space-4, 1rem);\n border: var(--hx-border-width-thin, 1px) dashed\n var(--hx-file-upload-dropzone-border-color, var(--hx-color-neutral-300, #cbd5e1));\n border-radius: var(--hx-file-upload-dropzone-border-radius, var(--hx-border-radius-lg, 0.5rem));\n background-color: var(--hx-file-upload-dropzone-bg, var(--hx-color-neutral-50, #f8fafc));\n cursor: pointer;\n text-align: center;\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n background-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n user-select: none;\n color: var(--hx-color-neutral-600, #475569);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n .dropzone:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-file-upload-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-color: var(\n --hx-file-upload-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n }\n\n .dropzone--drag-over {\n border-color: var(--hx-color-primary-500, #2563eb);\n background-color: var(\n --hx-file-upload-dropzone-active-bg,\n color-mix(\n in srgb,\n var(--hx-color-primary-500, #2563eb) 8%,\n var(--hx-color-neutral-0, #ffffff)\n )\n );\n border-style: solid;\n }\n\n .dropzone--error {\n border-color: var(--hx-file-upload-error-color, var(--hx-color-error-500, #dc2626));\n }\n\n @media (prefers-reduced-motion: reduce) {\n .dropzone {\n transition: none;\n }\n }\n\n /* ─── Hidden file input ─── */\n\n .file-input {\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 /* ─── File list ─── */\n\n .file-list {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2, 0.5rem);\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .file-list:empty {\n display: none;\n }\n\n /* ─── File item ─── */\n\n .file-item {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-color-neutral-200, #e2e8f0);\n border-radius: var(--hx-border-radius-md, 0.375rem);\n background-color: var(--hx-color-neutral-0, #ffffff);\n }\n\n .file-item__row {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n }\n\n .file-item__name {\n flex: 1;\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-color-neutral-800, #1e293b);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .file-item__size {\n flex-shrink: 0;\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-color-neutral-500, #64748b);\n }\n\n .file-item__remove {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 44px;\n min-height: 44px;\n padding: var(--hx-space-1, 0.25rem);\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n background: transparent;\n color: var(--hx-color-neutral-500, #64748b);\n cursor: pointer;\n line-height: 1;\n transition:\n color var(--hx-transition-fast, 150ms ease),\n background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .file-item__remove:hover {\n color: var(--hx-file-upload-error-color, var(--hx-color-error-text, #b91c1c));\n background-color: color-mix(in srgb, var(--hx-color-error-500, #dc2626) 8%, transparent);\n }\n\n .file-item__remove:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-file-upload-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .file-item__remove {\n transition: none;\n }\n }\n\n /* ─── Progress bar ─── */\n\n .progress-track {\n width: 100%;\n height: var(--hx-file-upload-progress-height, var(--hx-space-1, 0.25rem));\n background-color: var(--hx-color-neutral-200, #e2e8f0);\n border-radius: var(--hx-border-radius-full, 9999px);\n overflow: hidden;\n }\n\n .progress-bar {\n height: 100%;\n width: 100%;\n background-color: var(--hx-file-upload-progress-color, var(--hx-color-primary-500, #2563eb));\n border-radius: inherit;\n transform-origin: left center;\n transform: scaleX(var(--_progress-ratio, 0));\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none;\n }\n }\n\n /* ─── Screen-reader only utility ─── */\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 /* ─── Error message ─── */\n\n .field__error {\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-file-upload-error-color, var(--hx-color-error-text, #b91c1c));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Forced colors (Windows High Contrast / Forced Colors Mode) ─── */\n\n @media (forced-colors: active) {\n .dropzone {\n border: 2px dashed ButtonText;\n background-color: Canvas;\n color: ButtonText;\n }\n\n .dropzone--drag-over {\n border: 2px solid Highlight;\n outline: none;\n background-color: Canvas;\n }\n\n .dropzone--error {\n border: 2px solid LinkText;\n }\n\n .dropzone:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: 2px;\n }\n\n .progress-bar {\n background: Highlight;\n forced-color-adjust: none;\n }\n\n .file-item__remove:hover {\n outline: 2px solid Highlight;\n background-color: transparent;\n color: ButtonText;\n }\n\n .file-item__remove:focus-visible {\n outline: 2px solid Highlight;\n }\n\n :host([disabled]) .dropzone {\n border-color: GrayText;\n color: GrayText;\n opacity: 1;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { mixinDelegatesAria } from '../../mixins/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixFileUploadStyles } from './hx-file-upload.styles.js';\n\nconst _nextFileUploadId = createIdCounter('hx-file-upload');\n\ninterface FileEntry {\n file: File;\n progress: number;\n}\n\n/** Detail for the hx-upload event dispatched by hx-file-upload. */\nexport interface HxFileUploadDetail {\n files: File[];\n}\n\n/** Detail for the hx-remove event dispatched by hx-file-upload. */\nexport interface HxFileRemoveDetail {\n file: File;\n index: number;\n}\n\n/** Detail for the hx-error event dispatched by hx-file-upload. */\nexport interface HxFileErrorDetail {\n message: string;\n files: File[];\n}\n\n/**\n * A drag-and-drop file upload component with client-side validation,\n * file list management, per-file progress, and native form association.\n *\n * @summary Form-associated file upload dropzone with drag-and-drop, validation, and progress tracking.\n *\n * @tag hx-file-upload\n *\n * @slot - Default dropzone content. Replaces the built-in \"Drag files here or click to browse\" prompt.\n * @slot file-list - Custom file list display. When provided, the built-in file list is hidden.\n *\n * @fires {CustomEvent<{files: File[]}>} hx-upload - Dispatched when valid files are selected via drag-and-drop or the file picker.\n * @fires {CustomEvent<{file: File, index: number}>} hx-remove - Dispatched when a file is removed from the list.\n * @fires {CustomEvent<{message: string, files: File[]}>} hx-error - Dispatched when file validation fails (type or size constraint).\n *\n * @csspart dropzone - The drag-and-drop target area.\n * @csspart file-list - The container wrapping the list of selected files.\n * @csspart file-item - An individual file entry in the list.\n * @csspart progress - The progress bar track for a file item.\n * @csspart label - The visible label element.\n * @csspart error - The error message container below the dropzone.\n *\n * @cssprop [--hx-file-upload-dropzone-bg=var(--hx-color-neutral-50)] - Dropzone background color.\n * @cssprop [--hx-file-upload-dropzone-border-color=var(--hx-color-neutral-300)] - Dropzone border color.\n * @cssprop [--hx-file-upload-dropzone-border-radius=var(--hx-border-radius-lg)] - Dropzone border radius.\n * @cssprop [--hx-file-upload-dropzone-active-bg] - Dropzone background when a file is dragged over.\n * @cssprop [--hx-file-upload-progress-color=var(--hx-color-primary-500)] - Progress bar fill color.\n * @cssprop [--hx-file-upload-error-color=var(--hx-color-error-500)] - Error state and remove-button hover color.\n */\n@customElement('hx-file-upload')\nexport class HelixFileUpload extends FormMixin(mixinDelegatesAria(HelixElement)) {\n static override styles = [helixFileUploadStyles];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n // ─── Properties ───\n\n /**\n * The form field name used during form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Accepted file types as a comma-separated list of MIME types or extensions.\n * Mirrors the native `<input type=\"file\" accept>` attribute.\n * @attr accept\n */\n @property({ type: String })\n accept = '';\n\n /**\n * Maximum allowed file size in bytes. 0 means unlimited.\n * @attr max-size\n */\n @property({ type: Number, attribute: 'max-size' })\n maxSize = 0;\n\n /**\n * Maximum number of files that can be selected. 0 means unlimited.\n * @attr max-files\n */\n @property({ type: Number, attribute: 'max-files' })\n maxFiles = 0;\n\n /**\n * Whether multiple files may be selected at once.\n * @attr multiple\n */\n @property({ type: Boolean })\n multiple = false;\n\n /**\n * Visible label text for the dropzone.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the component is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Error message displayed below the dropzone. Also puts the dropzone in an error visual state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Instructional text shown in the dropzone when no custom slot content is provided.\n * Also used as the accessible label for the dropzone.\n * @attr label-dropzone\n */\n @property({ type: String, attribute: 'label-dropzone' })\n labelDropzone = 'Drag files here or click to browse';\n\n /** Accessible label for the selected files list. */\n @property({ type: String, attribute: 'label-file-list' })\n labelFileList = 'Selected files';\n\n /**\n * Accessible label for the dropzone when no visible label text is provided.\n * Falls back to `label-dropzone` prop value, then a default string.\n *\n * Accepts both `accessible-label` and the standard `aria-label` HTML attribute.\n * `accessible-label` takes precedence when both are set.\n *\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string = '';\n\n /**\n * Returns the effective label for the dropzone, checking accessible-label first,\n * then the aria-label attribute, falling back to empty string.\n * @internal\n */\n private get _effectiveLabel(): string {\n return this.accessibleLabel?.trim() || this.ariaLabel?.trim() || '';\n }\n\n /**\n * Generates upload progress description for screen readers.\n * @param name - file name\n * @param progress - progress percentage 0-100\n */\n @property({ attribute: false })\n labelUploadProgress: (name: string, progress: number) => string = (name, progress) =>\n `Upload progress for ${name}: ${progress}%`;\n\n /**\n * Screen reader announcement when file drag detected. Override for i18n.\n * @attr label-drag-detected\n */\n @property({ attribute: 'label-drag-detected' })\n labelDragDetected = 'File detected. Release to upload.';\n\n // ─── Internal State ───\n\n /** The list of currently selected file entries, each with a file reference and upload progress. @internal */\n @state() private _files: FileEntry[] = [];\n /** Whether a file is currently being dragged over the dropzone. @internal */\n @state() private _dragOver = false;\n /** Whether the named file-list slot contains projected content. @internal */\n @state() private _hasFileListSlot = false;\n\n // ─── Internal References ───\n\n /** Reference to the hidden native file input element used to open the OS file picker. @internal */\n @query('.file-input')\n private _fileInput: HTMLInputElement | null | undefined;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private readonly _baseId = _nextFileUploadId();\n /** @internal */\n private readonly _labelId = `${this._baseId}-label`;\n /** @internal */\n private readonly _errorId = `${this._baseId}-error`;\n /** @internal */\n private readonly _dropzoneId = `${this._baseId}-dropzone`;\n /** @internal */\n private readonly _liveId = `${this._baseId}-live`;\n\n // ─── Slot Handling ───\n\n /** @internal */\n private _handleFileListSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasFileListSlot = slot.assignedElements({ flatten: true }).length > 0;\n }\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('_files' as keyof HelixFileUpload) || changedProperties.has('name')) {\n this._syncFormValue();\n }\n // Force screen reader re-announcement when error text changes (a11y-v3-005)\n if (changedProperties.has('error') && this.error) {\n const errorEl = this.shadowRoot?.querySelector('[role=\"alert\"]');\n if (errorEl) {\n const msg = this.error;\n requestAnimationFrame(() => {\n errorEl.textContent = '';\n requestAnimationFrame(() => {\n errorEl.textContent = msg;\n });\n });\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n protected override _onFormReset(): void {\n this._files = [];\n this._internals.setFormValue(null);\n this._resetInteractionState();\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n /** @internal */\n protected override _onFormStateRestore(\n _state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (_mode === 'restore' || _mode === 'autocomplete') {\n this._files = [];\n this._internals.setFormValue(null);\n }\n }\n\n /** @internal */\n private _syncFormValue(): void {\n if (this._files.length === 0) {\n this._internals.setFormValue(null);\n return;\n }\n\n if (this._files.length === 1) {\n // Single file — pass directly as File (accepted by setFormValue)\n const firstEntry = this._files[0];\n if (firstEntry) {\n this._internals.setFormValue(firstEntry.file);\n }\n return;\n }\n\n // Multiple files — use FormData so all files are submitted under the same name\n const formData = new FormData();\n for (const entry of this._files) {\n formData.append(this.name, entry.file, entry.file.name);\n }\n this._internals.setFormValue(formData);\n }\n\n // ─── Validation ───\n\n /**\n * Validates a file against `accept` and `maxSize` constraints.\n * Returns null on success, or an error message string on failure.\n */\n /** @internal */\n private _validateFile(file: File): string | null {\n if (this.accept) {\n const accepted = this._isAccepted(file);\n if (!accepted) {\n return `\"${file.name}\" has an unsupported file type. Accepted types: ${this.accept}`;\n }\n }\n\n if (this.maxSize > 0 && file.size > this.maxSize) {\n const maxMb = (this.maxSize / (1024 * 1024)).toFixed(1);\n return `\"${file.name}\" exceeds the maximum size of ${maxMb} MB.`;\n }\n\n return null;\n }\n\n /**\n * Checks whether a file is accepted given the `accept` attribute value.\n * Handles MIME types (e.g. \"image/png\"), wildcard MIME types (e.g. \"image/*\"),\n * and extensions (e.g. \".pdf\").\n */\n /** @internal */\n private _isAccepted(file: File): boolean {\n const tokens = this.accept.split(',').map((t) => t.trim().toLowerCase());\n\n for (const token of tokens) {\n if (token.startsWith('.')) {\n // Extension match\n if (file.name.toLowerCase().endsWith(token)) return true;\n } else if (token.endsWith('/*')) {\n // Wildcard MIME type e.g. \"image/*\"\n const baseType = token.slice(0, -2);\n if (file.type.toLowerCase().startsWith(baseType)) return true;\n } else {\n // Exact MIME type\n if (file.type.toLowerCase() === token) return true;\n }\n }\n\n return false;\n }\n\n // ─── File Processing ───\n\n /** @internal */\n private _processFiles(rawFiles: File[]): void {\n if (this.disabled) return;\n\n const candidateFiles = this.multiple ? rawFiles : rawFiles.slice(0, 1);\n const validFiles: File[] = [];\n const invalidFiles: File[] = [];\n const errorMessages: string[] = [];\n\n for (const file of candidateFiles) {\n const validationError = this._validateFile(file);\n if (validationError) {\n invalidFiles.push(file);\n errorMessages.push(validationError);\n } else {\n validFiles.push(file);\n }\n }\n\n if (invalidFiles.length > 0) {\n this.dispatchEvent(\n new CustomEvent<{ message: string; files: File[] }>('hx-error', {\n bubbles: true,\n composed: true,\n detail: { message: errorMessages.join(' '), files: invalidFiles },\n }),\n );\n }\n\n if (validFiles.length === 0) return;\n\n // Enforce maxFiles limit (only in multiple mode — single-file mode always replaces)\n const currentCount = this.multiple ? this._files.length : 0;\n const capacity =\n this.maxFiles > 0 ? Math.max(0, this.maxFiles - currentCount) : validFiles.length;\n const allowedFiles = validFiles.slice(0, capacity);\n\n if (allowedFiles.length === 0 && this.maxFiles > 0) {\n this.dispatchEvent(\n new CustomEvent<{ message: string; files: File[] }>('hx-error', {\n bubbles: true,\n composed: true,\n detail: {\n message: `Maximum of ${this.maxFiles} file${this.maxFiles === 1 ? '' : 's'} allowed.`,\n files: validFiles,\n },\n }),\n );\n return;\n }\n\n if (allowedFiles.length > 0) {\n const newEntries: FileEntry[] = allowedFiles.map((file) => ({ file, progress: 0 }));\n\n if (this.multiple) {\n this._files = [...this._files, ...newEntries];\n } else {\n this._files = newEntries;\n }\n\n this._handleInteractionInput();\n\n this.dispatchEvent(\n new CustomEvent<{ files: File[] }>('hx-upload', {\n bubbles: true,\n composed: true,\n detail: { files: allowedFiles },\n }),\n );\n }\n\n // If remaining valid files were cut by maxFiles, report that too\n const overflow = validFiles.slice(capacity);\n if (overflow.length > 0 && this.maxFiles > 0) {\n this.dispatchEvent(\n new CustomEvent<{ message: string; files: File[] }>('hx-error', {\n bubbles: true,\n composed: true,\n detail: {\n message: `Maximum of ${this.maxFiles} file${this.maxFiles === 1 ? '' : 's'} allowed. ${overflow.length} file${overflow.length === 1 ? ' was' : 's were'} not added.`,\n files: overflow,\n },\n }),\n );\n }\n }\n\n // ─── Public Methods ───\n\n /**\n * Sets the upload progress for a file at the given index.\n * @param index - Zero-based index into the current file list.\n * @param percent - Progress percentage from 0 to 100.\n */\n setProgress(index: number, percent: number): void {\n if (index < 0 || index >= this._files.length) return;\n const clamped = Math.max(0, Math.min(100, percent));\n this._files = this._files.map((entry, i) =>\n i === index ? { ...entry, progress: clamped } : entry,\n );\n }\n\n /**\n * Returns a read-only copy of the currently selected files.\n */\n get files(): File[] {\n return this._files.map((e) => e.file);\n }\n\n // ─── Drag and Drop Handlers ───\n\n /** @internal */\n private _handleDragOver(e: DragEvent): void {\n e.preventDefault();\n if (this.disabled) return;\n this._dragOver = true;\n }\n\n /** @internal */\n private _handleDragLeave(e: DragEvent): void {\n // Only clear drag state when leaving the dropzone entirely\n const target = e.relatedTarget as Node | null;\n if (target && this.contains(target)) return;\n const dropzone = this.shadowRoot?.querySelector('.dropzone');\n if (dropzone && dropzone.contains(target)) return;\n this._dragOver = false;\n }\n\n /** @internal */\n private _handleDrop(e: DragEvent): void {\n e.preventDefault();\n this._dragOver = false;\n if (this.disabled) return;\n\n const dt = e.dataTransfer;\n if (!dt) return;\n\n const rawFiles = Array.from(dt.files);\n if (rawFiles.length === 0) return;\n\n this._processFiles(rawFiles);\n }\n\n // ─── Click / Keyboard Handlers ───\n\n /** @internal */\n private _handleDropzoneClick(): void {\n if (this.disabled) return;\n this._fileInput?.click();\n }\n\n /** @internal */\n private _handleDropzoneKeyDown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._fileInput?.click();\n }\n }\n\n /** @internal */\n private _handleFileInputChange(e: Event): void {\n const input = e.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) return;\n\n const rawFiles = Array.from(input.files);\n // Reset the input so the same file can be re-selected after removal\n input.value = '';\n this._processFiles(rawFiles);\n }\n\n // ─── Remove Handler ───\n\n /** @internal */\n private _handleRemove(index: number): void {\n if (this.disabled) return;\n const entry = this._files[index];\n if (!entry) return;\n\n const removedFile = entry.file;\n this._files = this._files.filter((_, i) => i !== index);\n\n this.dispatchEvent(\n new CustomEvent<{ file: File; index: number }>('hx-remove', {\n bubbles: true,\n composed: true,\n detail: { file: removedFile, index },\n }),\n );\n\n // Restore focus after removal so keyboard users are not stranded.\n this.updateComplete\n .then(() => {\n if (this._files.length === 0) {\n // List is now empty — return focus to the dropzone.\n const dropzone = this.shadowRoot?.querySelector<HTMLElement>('[part=\"dropzone\"]');\n dropzone?.focus();\n } else {\n // Focus the remove button at the same position, or the previous one if\n // the removed item was the last in the list.\n const removeButtons =\n this.shadowRoot?.querySelectorAll<HTMLButtonElement>('.file-item__remove');\n if (removeButtons && removeButtons.length > 0) {\n const targetIndex = index < this._files.length ? index : this._files.length - 1;\n const targetButton = removeButtons[targetIndex];\n if (targetButton) {\n targetButton.focus();\n }\n }\n }\n })\n .catch(() => {\n // Focus restoration is best-effort; ignore errors.\n });\n }\n\n // ─── Formatters ───\n\n /** @internal */\n private _formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderFileList() {\n if (this._hasFileListSlot) return nothing;\n if (this._files.length === 0) return nothing;\n\n return html`\n <ul part=\"file-list\" class=\"file-list\" aria-label=${this.labelFileList}>\n ${repeat(\n this._files,\n (entry) => entry.file.name + entry.file.size,\n (entry, index) => html`\n <li part=\"file-item\" class=\"file-item\">\n <div class=\"file-item__row\">\n <span class=\"file-item__name\" title=${entry.file.name}> ${entry.file.name} </span>\n <span class=\"file-item__size\">${this._formatSize(entry.file.size)}</span>\n <button\n type=\"button\"\n class=\"file-item__remove\"\n aria-label=${`Remove ${entry.file.name}`}\n @click=${() => this._handleRemove(index)}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M1 1L13 13M13 1L1 13\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </div>\n <div\n part=\"progress\"\n class=\"progress-track\"\n role=\"progressbar\"\n aria-valuenow=${entry.progress}\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-label=${this.labelUploadProgress(entry.file.name, entry.progress)}\n >\n <div\n class=\"progress-bar\"\n style=\"--_progress-ratio: ${String(entry.progress / 100)}\"\n ></div>\n </div>\n </li>\n `,\n )}\n </ul>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const hasError = !!this.error;\n\n const dropzoneClasses = {\n dropzone: true,\n 'dropzone--drag-over': this._dragOver,\n 'dropzone--error': hasError,\n };\n\n const dropzoneLabel = this.label ? `${this.label} — ${this.labelDropzone}` : this.labelDropzone;\n\n return html`\n <div class=\"field\">\n ${this.label\n ? html`\n <label part=\"label\" class=\"field__label\" id=${this._labelId} for=${this._dropzoneId}>\n ${this.label}\n </label>\n `\n : nothing}\n\n <div\n part=\"dropzone\"\n class=${classMap(dropzoneClasses)}\n id=${this._dropzoneId}\n role=\"button\"\n tabindex=${this.disabled ? '-1' : '0'}\n aria-label=${ifDefined(this._effectiveLabel || (!this.label ? dropzoneLabel : undefined))}\n aria-labelledby=${ifDefined(\n !this._effectiveLabel && this.label ? this._labelId : undefined,\n )}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(hasError ? this._errorId : undefined)}\n @click=${this._handleDropzoneClick}\n @keydown=${this._handleDropzoneKeyDown}\n @dragover=${this._handleDragOver}\n @dragleave=${this._handleDragLeave}\n @drop=${this._handleDrop}\n >\n <slot>${this.labelDropzone}</slot>\n </div>\n\n <input\n class=\"file-input\"\n type=\"file\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n accept=${ifDefined(this.accept || undefined)}\n ?multiple=${this.multiple}\n ?disabled=${this.disabled}\n @change=${this._handleFileInputChange}\n />\n\n <slot name=\"file-list\" @slotchange=${this._handleFileListSlotChange}></slot>\n\n ${this._renderFileList()}\n ${hasError\n ? html`\n <div part=\"error\" class=\"field__error\" id=${this._errorId} role=\"alert\">\n ${this.error}\n </div>\n `\n : nothing}\n\n <div id=${this._liveId} class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n ${this._dragOver ? this.labelDragDetected : ''}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-file-upload': HelixFileUpload;\n }\n}\n"],"names":["helixFileUploadStyles","css","_nextFileUploadId","createIdCounter","HelixFileUpload","FormMixin","mixinDelegatesAria","HelixElement","name","progress","_a","_b","slot","changedProperties","errorEl","msg","disabled","_state","_mode","firstEntry","formData","entry","file","maxMb","tokens","token","baseType","rawFiles","candidateFiles","validFiles","invalidFiles","errorMessages","validationError","currentCount","capacity","allowedFiles","newEntries","overflow","index","percent","clamped","i","target","dropzone","dt","input","removedFile","_","removeButtons","targetIndex","targetButton","bytes","nothing","html","repeat","hasError","dropzoneClasses","dropzoneLabel","classMap","ifDefined","__decorateClass","property","state","query","customElement"],"mappings":";;;;;;;;;AAEO,MAAMA,IAAwBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-help-text-D7eytSim.js","sources":["../../src/components/hx-help-text/hx-help-text.styles.ts","../../src/components/hx-help-text/hx-help-text.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixHelpTextStyles = css`\n :host {\n display: block;\n }\n\n .help-text {\n display: inline-flex;\n align-items: baseline;\n gap: var(--hx-help-text-icon-gap, 0.375rem);\n font-family: var(--hx-help-text-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-help-text-font-size, var(--hx-font-size-sm, 0.875rem));\n font-weight: var(--hx-help-text-font-weight, var(--hx-font-weight-normal, 400));\n line-height: var(--hx-help-text-line-height, var(--hx-line-height-normal, 1.5));\n color: var(--hx-help-text-color, var(--hx-color-neutral-500, #64748b));\n margin: 0;\n }\n\n .help-text__icon {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n .help-text__text {\n min-width: 0;\n }\n\n /* ─── Variant: default ─── */\n\n .help-text--default {\n --hx-help-text-color: var(--hx-color-neutral-500, #64748b);\n }\n\n /* ─── Variant: error ─── */\n\n .help-text--error {\n --hx-help-text-color: var(--hx-color-error-600, #b91c1c);\n }\n\n /* ─── Variant: warning ─── */\n\n .help-text--warning {\n --hx-help-text-color: var(--hx-color-warning-700, #92400e);\n }\n\n /* ─── Variant: success ─── */\n\n .help-text--success {\n --hx-help-text-color: var(--hx-color-success-700, #166534);\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .help-text {\n color: GrayText;\n }\n\n .help-text--error {\n color: LinkText;\n }\n\n .help-text--warning {\n color: CanvasText;\n }\n\n .help-text--success {\n color: CanvasText;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixHelpTextStyles } from './hx-help-text.styles.js';\n\n/** Icon SVG for error variant (circle with exclamation mark). */\nconst errorIcon = html`<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" width=\"1em\" height=\"1em\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" />\n <line\n x1=\"8\"\n y1=\"4.5\"\n x2=\"8\"\n y2=\"8.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n <circle cx=\"8\" cy=\"11\" r=\"0.75\" fill=\"currentColor\" />\n</svg>`;\n\n/** Icon SVG for warning variant (triangle with exclamation mark). */\nconst warningIcon = html`<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" width=\"1em\" height=\"1em\">\n <path\n d=\"M7.134 2.5a1 1 0 011.732 0l5.196 9a1 1 0 01-.866 1.5H2.804a1 1 0 01-.866-1.5l5.196-9z\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n fill=\"none\"\n />\n <line\n x1=\"8\"\n y1=\"6\"\n x2=\"8\"\n y2=\"9\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n <circle cx=\"8\" cy=\"11\" r=\"0.625\" fill=\"currentColor\" />\n</svg>`;\n\n/** Icon SVG for success variant (circle with checkmark). */\nconst successIcon = html`<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" width=\"1em\" height=\"1em\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" />\n <path\n d=\"M5.25 8.25l1.75 1.75 3.75-3.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n</svg>`;\n\n/** Map of variant to icon template. Default has no icon. */\nconst variantIcons = {\n default: nothing,\n error: errorIcon,\n warning: warningIcon,\n success: successIcon,\n} as const;\n\n/**\n * Standardized help/hint text displayed below form fields.\n * Used by hx-field as a consistent sub-component for guidance and validation messages.\n *\n * Non-default variants render an inline icon alongside the text to satisfy\n * WCAG 1.4.1 (color is not the sole visual indicator). The `error` variant\n * uses `role=\"alert\"` for immediate screen-reader announcement; `warning`\n * and `success` use `aria-live=\"polite\"` for non-intrusive announcements.\n *\n * @summary Help text displayed below form controls for guidance or validation feedback.\n *\n * @tag hx-help-text\n *\n * @slot - The help text content.\n *\n * @csspart base - The root element of the help text.\n * @csspart icon - The icon wrapper (only rendered for non-default variants).\n * @csspart text - The text wrapper around the default slot.\n *\n * @cssprop [--hx-help-text-color=var(--hx-color-neutral-500)] - Text color.\n * @cssprop [--hx-help-text-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-help-text-font-size=var(--hx-font-size-sm)] - Font size.\n * @cssprop [--hx-help-text-font-weight=var(--hx-font-weight-normal)] - Font weight.\n * @cssprop [--hx-help-text-line-height=var(--hx-line-height-normal)] - Line height.\n * @cssprop [--hx-help-text-icon-gap=0.375rem] - Gap between icon and text.\n */\n@customElement('hx-help-text')\nexport class HelixHelpText extends HelixElement {\n static override styles = [helixHelpTextStyles];\n\n /**\n * Visual variant that determines the text color and icon.\n * Use `error` for validation errors, `warning` for cautions, `success` for confirmation.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'error' | 'warning' | 'success' = 'default';\n\n override render() {\n const classes = {\n 'help-text': true,\n [`help-text--${this.variant}`]: true,\n };\n\n const icon = variantIcons[this.variant];\n const role = this.variant === 'error' ? 'alert' : undefined;\n const ariaLive =\n this.variant === 'warning' || this.variant === 'success' ? 'polite' : undefined;\n\n return html`<span\n part=\"base\"\n class=${classMap(classes)}\n role=${ifDefined(role)}\n aria-live=${ifDefined(ariaLive)}\n >${icon !== nothing\n ? html`<span part=\"icon\" class=\"help-text__icon\">${icon}</span>`\n : nothing}<span part=\"text\" class=\"help-text__text\"><slot></slot></span>\n </span>`;\n }\n}\n\n/** Canonical type alias for the hx-help-text component. */\nexport type HxHelpText = HelixHelpText;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-help-text': HelixHelpText;\n }\n}\n"],"names":["helixHelpTextStyles","css","errorIcon","html","warningIcon","successIcon","variantIcons","nothing","HelixHelpText","HelixElement","classes","icon","role","ariaLive","classMap","ifDefined","__decorateClass","property","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAsBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACOnC,MAAMC,IAAYC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAeZC,IAAcD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAoBdE,IAAcF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAadG,IAAe;AAAA,EACnB,SAASC;AAAA,EACT,OAAOL;AAAA,EACP,SAASE;AAAA,EACT,SAASC;AACX;AA6BO,IAAMG,IAAN,cAA4BC,EAAa;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GASL,KAAA,UAAuD;AAAA,EAAA;AAAA,EAE9C,SAAS;AAChB,UAAMC,IAAU;AAAA,MACd,aAAa;AAAA,MACb,CAAC,cAAc,KAAK,OAAO,EAAE,GAAG;AAAA,IAAA,GAG5BC,IAAOL,EAAa,KAAK,OAAO,GAChCM,IAAO,KAAK,YAAY,UAAU,UAAU,QAC5CC,IACJ,KAAK,YAAY,aAAa,KAAK,YAAY,YAAY,WAAW;AAExE,WAAOV;AAAA;AAAA,cAEGW,EAASJ,CAAO,CAAC;AAAA,aAClBK,EAAUH,CAAI,CAAC;AAAA,kBACVG,EAAUF,CAAQ,CAAC;AAAA,SAC5BF,MAASJ,IACRJ,8CAAiDQ,CAAI,YACrDJ,CAAO;AAAA;AAAA,EAEf;AACF;AAhCaC,EACK,SAAS,CAACR,CAAmB;AAQ7CgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAR9BT,EASX,WAAA,WAAA,CAAA;AATWA,IAANQ,EAAA;AAAA,EADNE,EAAc,cAAc;AAAA,GAChBV,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-icon-button-BHneqPCU.js","sources":["../../src/components/hx-icon-button/hx-icon-button.styles.ts","../../src/components/hx-icon-button/hx-icon-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixIconButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled);\n }\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: var(--hx-border-width-thin) solid var(--hx-icon-button-border-color);\n border-radius: var(--hx-icon-button-border-radius, var(--hx-border-radius-md));\n background-color: var(--hx-icon-button-bg);\n color: var(--hx-icon-button-color, var(--hx-color-primary-500));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast),\n color var(--hx-transition-fast),\n border-color var(--hx-transition-fast),\n box-shadow var(--hx-transition-fast);\n text-decoration: none;\n user-select: none;\n -webkit-user-select: none;\n flex-shrink: 0;\n }\n\n .button:focus-visible {\n outline: var(--hx-focus-ring-width) solid\n var(--hx-icon-button-focus-ring-color, var(--hx-focus-ring-color));\n outline-offset: var(--hx-focus-ring-offset);\n }\n\n .button:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n /* ─── Size Variants ─── */\n\n /* WCAG 2.5.5 (healthcare mandate): minimum 44x44px touch target for all sizes.\n min-width/min-height override the explicit size tokens when they fall below\n the 2.75rem (44px) threshold, preserving the visual icon size via font-size. */\n\n .button--sm {\n padding: var(--hx-space-1);\n width: var(--hx-icon-button-size, var(--hx-size-8));\n height: var(--hx-icon-button-size, var(--hx-size-8));\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n font-size: var(--hx-font-size-sm);\n }\n\n .button--md {\n padding: var(--hx-space-2);\n width: var(--hx-icon-button-size, var(--hx-size-10));\n height: var(--hx-icon-button-size, var(--hx-size-10));\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n font-size: var(--hx-font-size-md);\n }\n\n .button--lg {\n padding: var(--hx-space-3);\n width: var(--hx-icon-button-size, var(--hx-size-12));\n height: var(--hx-icon-button-size, var(--hx-size-12));\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n font-size: var(--hx-font-size-lg);\n }\n\n /* ─── Style Variants ─── */\n\n .button--primary {\n --hx-icon-button-bg: var(--hx-color-primary-500);\n --hx-icon-button-color: var(--hx-color-neutral-0);\n --hx-icon-button-border-color: transparent;\n }\n\n .button--primary:hover {\n --hx-icon-button-bg: var(--hx-color-primary-600);\n }\n\n .button--secondary {\n --hx-icon-button-bg: transparent;\n --hx-icon-button-color: var(--hx-color-primary-500);\n --hx-icon-button-border-color: var(--hx-color-primary-500);\n }\n\n .button--secondary:hover {\n --hx-icon-button-bg: var(--hx-color-primary-50);\n }\n\n .button--tertiary {\n --hx-icon-button-bg: transparent;\n --hx-icon-button-color: var(--hx-color-neutral-700);\n --hx-icon-button-border-color: var(--hx-color-neutral-300);\n }\n\n .button--tertiary:hover {\n --hx-icon-button-bg: var(--hx-color-neutral-100);\n }\n\n .button--danger {\n --hx-icon-button-bg: var(--hx-color-error-500);\n --hx-icon-button-color: var(--hx-color-neutral-0);\n --hx-icon-button-border-color: transparent;\n }\n\n .button--danger:hover {\n --hx-icon-button-bg: var(--hx-color-error-600);\n }\n\n .button--ghost {\n --hx-icon-button-bg: transparent;\n --hx-icon-button-color: var(--hx-color-primary-500);\n --hx-icon-button-border-color: transparent;\n }\n\n .button--ghost:hover {\n --hx-icon-button-bg: var(--hx-color-neutral-100);\n }\n\n /* ─── Icon Container ─── */\n\n .icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1em;\n height: 1em;\n line-height: 1;\n pointer-events: none;\n }\n\n /* ─── Disabled ─── */\n\n .button[disabled] {\n cursor: not-allowed;\n /* P1-02 fix: opacity is set only on :host([disabled]) above to prevent\n multiplicative stacking (0.5 * 0.5 = 0.25). Do not add opacity here. */\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .button {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .button {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n .button:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .button[disabled] {\n background-color: ButtonFace;\n color: GrayText;\n border-color: GrayText;\n opacity: 1;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixIconButtonStyles } from './hx-icon-button.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * An icon-only button component for compact, accessible actions.\n * Renders a square button or anchor element containing a single icon.\n * The `label` property is required and provides the accessible name\n * via `aria-label` and a native tooltip via the `title` attribute.\n *\n * @summary Icon-only action button with full accessibility support.\n *\n * @tag hx-icon-button\n *\n * @slot - Icon element to display (hx-icon, svg, or img).\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when the button is clicked (not disabled).\n *\n * @csspart button - The native button or anchor element.\n * @csspart icon - The icon container span wrapping the default slot.\n *\n * @cssprop [--hx-icon-button-bg=transparent] - Button background color.\n * @cssprop [--hx-icon-button-color=var(--hx-color-primary-500)] - Icon color.\n * @cssprop [--hx-icon-button-border-color=transparent] - Button border color.\n * @cssprop [--hx-icon-button-border-radius=var(--hx-border-radius-md)] - Button border radius.\n * @cssprop [--hx-icon-button-size] - Explicit width and height override for the button.\n * @cssprop [--hx-icon-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n */\n@customElement('hx-icon-button')\nexport class HelixIconButton extends HelixElement {\n static override styles = [helixIconButtonStyles];\n\n /**\n * Accessible name for the button. Required. Rendered as `aria-label` and\n * `title` on the underlying element. The component renders nothing when absent,\n * and a console warning is emitted to alert developers during authoring.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Visual style variant of the button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' = 'ghost';\n\n /**\n * Size of the button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * The type attribute for the underlying button element.\n * Has no effect when `href` is set.\n * @attr type\n */\n @property({ type: String })\n type: 'button' | 'submit' | 'reset' = 'button';\n\n /**\n * Whether the button is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * When set, renders an `<a>` element instead of a `<button>`.\n * @attr href\n */\n @property({ type: String })\n href: string | undefined = undefined;\n\n /**\n * Name submitted with form data. Only applicable when rendering as a button.\n * @attr name\n */\n @property({ type: String })\n name: string | undefined = undefined;\n\n /**\n * Value submitted with form data. Only applicable when rendering as a button.\n * @attr value\n */\n @property({ type: String })\n value: string | undefined = undefined;\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n /**\n * Dispatched when the button is clicked.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n\n // Handle form submission/reset if form-associated and not in href/link mode\n if (!this.href) {\n if (this.type === 'submit' && this._internals.form) {\n this._internals.form.requestSubmit();\n } else if (this.type === 'reset' && this._internals.form) {\n this._internals.form.reset();\n }\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _normalizedLabel(): string {\n return this.label.trim();\n }\n\n /** @internal */\n private _classes() {\n return {\n button: true,\n [`button--${this.variant}`]: true,\n [`button--${this.size}`]: true,\n };\n }\n\n /** @internal */\n private _iconSlot() {\n return html`<span part=\"icon\" class=\"icon\"><slot></slot></span>`;\n }\n\n // ─── Render ───\n\n override render() {\n const normalizedLabel = this._normalizedLabel();\n if (!normalizedLabel) {\n devWarn(\n 'hx-icon-button',\n 'The `label` property is required for accessibility. Render suppressed.',\n );\n return nothing;\n }\n\n if (this.href !== undefined) {\n // P1-03 fix: disabled anchor must set tabindex=\"-1\" explicitly — an <a>\n // without href is non-focusable by default in most browsers, but this is\n // browser-dependent. Explicit tabindex=\"-1\" guarantees keyboard exclusion\n // across all conforming browsers.\n // P1-07 note: aria-disabled IS required on the anchor branch because\n // <a> elements have no native disabled attribute; aria-disabled is the\n // only AT signal available.\n return html`\n <a\n part=\"button\"\n class=${classMap(this._classes())}\n href=${ifDefined(this.disabled ? undefined : this.href)}\n aria-label=${normalizedLabel}\n title=${normalizedLabel}\n aria-disabled=${this.disabled ? 'true' : nothing}\n tabindex=${this.disabled ? '-1' : nothing}\n @click=${this._handleClick}\n >\n ${this._iconSlot()}\n </a>\n `;\n }\n\n // P1-07 fix: aria-disabled is redundant on a natively disabled <button>.\n // The native disabled attribute already exposes aria-disabled=\"true\"\n // implicitly in the accessibility tree. Duplicate explicit aria-disabled\n // creates ambiguity about design intent. Keep only native ?disabled.\n return html`\n <button\n part=\"button\"\n class=${classMap(this._classes())}\n ?disabled=${this.disabled}\n type=${this.type}\n aria-label=${normalizedLabel}\n title=${normalizedLabel}\n name=${ifDefined(this.name)}\n value=${ifDefined(this.value)}\n @click=${this._handleClick}\n >\n ${this._iconSlot()}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-icon-button': HelixIconButton;\n }\n interface HTMLElementEventMap {\n 'hx-click': CustomEvent<{ originalEvent: MouseEvent }>;\n }\n}\n"],"names":["helixIconButtonStyles","css","HelixIconButton","HelixElement","disabled","e","html","normalizedLabel","classMap","ifDefined","nothing","__decorateClass","property","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-link-BESrWK8M.js","sources":["../../src/components/hx-link/hx-link.styles.ts","../../src/components/hx-link/hx-link.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixLinkStyles = css`\n :host {\n display: inline;\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n /* --- Base Link --- */\n\n .link {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n color: var(--hx-link-color, var(--hx-color-primary-500, #2563eb));\n font-family: var(--hx-link-font-family, var(--hx-font-family-sans, inherit));\n font-size: inherit;\n line-height: inherit;\n text-decoration: var(--hx-link-text-decoration, underline);\n text-underline-offset: var(--hx-link-underline-offset, 2px);\n cursor: pointer;\n outline: 0;\n transition:\n color var(--hx-transition-fast, 150ms ease),\n text-decoration-color var(--hx-transition-fast, 150ms ease);\n }\n\n .link:hover {\n color: var(--hx-link-color-hover, var(--hx-color-primary-700, #1e40af));\n text-decoration: var(--hx-link-text-decoration-hover, underline);\n }\n\n .link:active {\n color: var(--hx-link-color-active, var(--hx-color-primary-800, #1e3a8a));\n }\n\n .link:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-link-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #60a5fa))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n }\n\n /* --- Variant: subtle --- */\n\n .link--subtle {\n color: var(--hx-link-color-subtle, var(--hx-color-neutral-600, #475569));\n text-decoration: none;\n }\n\n .link--subtle:hover {\n color: var(--hx-link-color-hover, var(--hx-color-primary-700, #1e40af));\n text-decoration: underline;\n }\n\n /* --- Variant: danger --- */\n\n .link--danger {\n color: var(--hx-link-color-danger, var(--hx-color-error-text, #b91c1c));\n }\n\n .link--danger:hover {\n color: var(--hx-link-color-danger-hover, var(--hx-color-error-700, #991b1b));\n }\n\n /* --- Disabled --- */\n\n .link--disabled {\n color: var(--hx-link-color-disabled, var(--hx-color-neutral-400, #94a3b8));\n text-decoration: none;\n cursor: not-allowed;\n }\n\n /* --- External link icon --- */\n\n .link__external-icon {\n display: inline-flex;\n width: 0.75em;\n height: 0.75em;\n flex-shrink: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .link {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .link {\n forced-color-adjust: none;\n color: LinkText;\n }\n\n .link:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .link--disabled {\n color: GrayText;\n }\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-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n`;\n","import { html, nothing, svg } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixLinkStyles } from './hx-link.styles.js';\n\n/**\n * Variant options for the link component.\n */\nexport type LinkVariant = 'default' | 'subtle' | 'danger';\n\n/**\n * A semantic hyperlink component with accessibility-first design.\n * Renders a native `<a>` element for enabled state and a `<span>` for\n * disabled state with full keyboard and screen reader support.\n *\n * @summary Accessible hyperlink with external-link detection, disabled state,\n * and download support.\n *\n * @tag hx-link\n *\n * @slot - Default slot for link label text or content.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the link is clicked and is not disabled.\n *\n * @csspart link - The inner anchor or span element.\n * @csspart external-icon - The external link icon SVG (when target=\"_blank\").\n *\n * @cssprop [--hx-link-color=var(--hx-color-primary-500)] - Default link color.\n * @cssprop [--hx-link-color-hover=var(--hx-color-primary-700)] - Hover color.\n * @cssprop [--hx-link-color-active=var(--hx-color-primary-800)] - Active color.\n * @cssprop [--hx-link-color-disabled=var(--hx-color-neutral-400)] - Disabled color.\n * @cssprop [--hx-link-color-subtle=var(--hx-color-neutral-600)] - Subtle variant color.\n * @cssprop [--hx-link-color-danger=var(--hx-color-error-text)] - Danger variant color.\n * @cssprop [--hx-link-color-danger-hover=var(--hx-color-error-700)] - Danger variant hover color.\n * @cssprop [--hx-link-font-family=var(--hx-font-family-sans)] - Link font family.\n * @cssprop [--hx-link-text-decoration=underline] - Link text decoration.\n * @cssprop [--hx-link-text-decoration-hover=underline] - Hover text decoration.\n * @cssprop [--hx-link-underline-offset=2px] - Text underline offset.\n * @cssprop [--hx-link-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n *\n * @note The `:visited` pseudo-class does not work inside Shadow DOM due to\n * browser privacy restrictions. This is a known platform limitation.\n */\n@customElement('hx-link')\nexport class HelixLink extends HelixElement {\n static override styles = [helixLinkStyles];\n\n /**\n * The URL the link points to.\n * @attr href\n */\n @property({ type: String })\n href: string | undefined = undefined;\n\n /**\n * Where to display the linked URL (_self, _blank, etc.).\n * When set to \"_blank\", automatically adds rel=\"noopener noreferrer\"\n * and shows an external-link indicator.\n * @attr target\n */\n @property({ type: String })\n target: string | undefined = undefined;\n\n /**\n * Visual style variant of the link.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'subtle' | 'danger' = 'default';\n\n /**\n * Whether the link is disabled. Renders a span instead of an anchor.\n * The disabled span is keyboard-focusable (tabindex=\"0\") and announces\n * as a disabled link to screen readers.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Prompts the user to download the linked URL. When set to a string,\n * the value is used as the suggested filename.\n * @attr download\n */\n @property({ type: String })\n download: string | undefined = undefined;\n\n /**\n * Relationship between the current document and the linked URL.\n * Automatically set to \"noopener noreferrer\" when target=\"_blank\".\n * @attr rel\n */\n @property({ type: String })\n rel: string | undefined = undefined;\n\n // --- Event Handling ---\n\n /** @internal Blocks Enter and Space activation on disabled span. */\n private _handleDisabledKeydown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n }\n }\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n }\n\n // --- Render Helpers ---\n\n /** @internal */\n private _computeRel(): string | undefined {\n if (this.rel) return this.rel;\n if (this.target === '_blank') return 'noopener noreferrer';\n return undefined;\n }\n\n /** @internal */\n private _renderExternalIcon() {\n if (this.target !== '_blank') return nothing;\n\n return html`\n <svg\n class=\"link__external-icon\"\n part=\"external-icon\"\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 ${svg`<path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" /><polyline points=\"15 3 21 3 21 9\" /><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />`}\n </svg>\n <span class=\"sr-only\">(opens in new tab)</span>\n `;\n }\n\n // --- Render ---\n\n override render() {\n const classes = {\n link: true,\n [`link--${this.variant}`]: this.variant !== 'default',\n 'link--disabled': this.disabled,\n };\n\n if (this.disabled) {\n return html`\n <span\n part=\"link\"\n class=${classMap(classes)}\n role=\"link\"\n aria-disabled=\"true\"\n tabindex=\"0\"\n @click=${this._handleClick}\n @keydown=${this._handleDisabledKeydown}\n >\n <slot></slot>\n </span>\n `;\n }\n\n return html`\n <a\n part=\"link\"\n class=${classMap(classes)}\n href=${ifDefined(this.href)}\n target=${ifDefined(this.target)}\n rel=${ifDefined(this._computeRel())}\n download=${ifDefined(this.download)}\n @click=${this._handleClick}\n >\n <slot></slot>\n ${this._renderExternalIcon()}\n </a>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-link': HelixLink;\n }\n}\n"],"names":["helixLinkStyles","css","HelixLink","HelixElement","nothing","html","svg","classes","classMap","ifDefined","__decorateClass","property","customElement"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-menu-divider-Ck-9Os1t.js","sources":["../../src/components/hx-menu/hx-menu.styles.ts","../../src/components/hx-menu/hx-menu.ts","../../src/components/hx-menu/hx-menu-item.styles.ts","../../src/components/hx-menu/hx-menu-item.ts","../../src/components/hx-menu/hx-menu-divider.styles.ts","../../src/components/hx-menu/hx-menu-divider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMenuStyles = css`\n :host {\n display: block;\n }\n\n .menu {\n display: flex;\n flex-direction: column;\n padding: var(--hx-space-1, 0.25rem);\n background: var(--hx-menu-bg, var(--hx-color-neutral-0, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-menu-border-color, var(--hx-color-neutral-200, #e2e8f0));\n border-radius: var(--hx-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-menu-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n min-width: var(--hx-menu-min-width, 10rem);\n max-height: var(--hx-menu-max-height, 20rem);\n overflow-y: auto;\n outline: none;\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu {\n background-color: Canvas;\n border: 2px solid CanvasText;\n }\n }\n`;\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixMenuStyles } from './hx-menu.styles.js';\nimport type { HelixMenuItem } from './hx-menu-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A menu container that manages keyboard navigation over a list of menu items.\n * Use with `hx-menu-item` and `hx-menu-divider`.\n *\n * @summary Context/action menu with keyboard-navigable items.\n *\n * @tag hx-menu\n *\n * @slot - Default slot for hx-menu-item and hx-menu-divider elements.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-select - Dispatched when an item is selected.\n * @fires {CustomEvent<void>} hx-close - Dispatched when Escape is pressed.\n *\n * @csspart base - The root menu element.\n *\n * @cssprop [--hx-menu-bg=var(--hx-color-neutral-0)] - Menu background color.\n * @cssprop [--hx-menu-border-color=var(--hx-color-neutral-200)] - Menu border color.\n * @cssprop [--hx-menu-border-radius=var(--hx-border-radius-md)] - Menu border radius.\n * @cssprop [--hx-menu-shadow] - Menu box shadow.\n * @cssprop [--hx-menu-min-width=10rem] - Minimum menu width.\n * @cssprop [--hx-menu-max-height=20rem] - Maximum menu height before vertical scroll is activated.\n */\n@customElement('hx-menu')\nexport class HelixMenu extends HelixElement {\n static override styles = [helixMenuStyles];\n\n /**\n * Accessible label for the menu. Rendered as `aria-label` on the inner\n * `role=\"menu\"` element when set.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Index of the currently focused menu item within the list of enabled items.\n * @internal\n */\n private _focusedIndex = -1;\n\n /**\n * Accumulated character buffer for typeahead search within menu items.\n * @internal\n */\n private _typeaheadBuffer = '';\n\n /**\n * Timer handle that clears the typeahead buffer after a period of inactivity.\n * @internal\n */\n private _typeaheadTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** @internal */\n private _getItems(): HelixMenuItem[] {\n return Array.from(this.querySelectorAll<HelixMenuItem>('hx-menu-item')).filter(\n (item) => !item.disabled && !item.loading,\n );\n }\n\n /**\n * Synchronize roving tabindex across all enabled items.\n * Only the active item (or first item if none active) gets tabindex=0.\n */\n /** @internal */\n private _syncRovingTabIndex(): void {\n const items = this._getItems();\n const activeIndex = this._focusedIndex >= 0 ? this._focusedIndex : 0;\n items.forEach((item, i) => {\n item.setRovingTabIndex(i === activeIndex ? 0 : -1);\n });\n }\n\n /** Focus the first menu item. */\n focusFirst(): void {\n const items = this._getItems();\n const first = items[0];\n if (first !== undefined) {\n this._focusedIndex = 0;\n this._syncRovingTabIndex();\n first.focus();\n }\n }\n\n /** Focus the last menu item. */\n focusLast(): void {\n const items = this._getItems();\n const last = items[items.length - 1];\n if (last !== undefined) {\n this._focusedIndex = items.length - 1;\n this._syncRovingTabIndex();\n last.focus();\n }\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getItems();\n if (items.length === 0) return;\n this._focusedIndex = Math.max(0, Math.min(index, items.length - 1));\n this._syncRovingTabIndex();\n const target = items[this._focusedIndex];\n if (target !== undefined) target.focus();\n }\n\n /** @internal */\n private _updateFocusedIndex(): void {\n const items = this._getItems();\n const active = this.shadowRoot?.activeElement ?? document.activeElement;\n // Find the active item by checking if any item's shadow root contains the active element\n const idx = items.findIndex((item) => item.matches(':focus-within') || item === active);\n if (idx !== -1) this._focusedIndex = idx;\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n this._updateFocusedIndex();\n const items = this._getItems();\n if (items.length === 0) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this._focusItem(this._focusedIndex + 1 < items.length ? this._focusedIndex + 1 : 0);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._focusItem(this._focusedIndex > 0 ? this._focusedIndex - 1 : items.length - 1);\n break;\n case 'Home':\n e.preventDefault();\n this._focusItem(0);\n break;\n case 'End':\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n case 'Escape':\n e.preventDefault();\n this.dispatchEvent(new CustomEvent<void>('hx-close', { bubbles: true, composed: true }));\n break;\n default:\n if (e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n this._handleTypeahead(e.key, items);\n }\n break;\n }\n }\n\n /** @internal */\n private _handleTypeahead(char: string, items: HelixMenuItem[]): void {\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n }\n this._typeaheadBuffer += char.toLowerCase();\n this._typeaheadTimer = setTimeout(() => {\n this._typeaheadBuffer = '';\n this._typeaheadTimer = null;\n }, 500);\n\n const match = items.findIndex((item) => {\n if (item.disabled || item.hasAttribute('disabled')) return false;\n const text = item.textContent?.trim().toLowerCase() ?? '';\n return text.startsWith(this._typeaheadBuffer);\n });\n\n if (match !== -1) {\n this._focusItem(match);\n }\n }\n\n /** @internal */\n private _handleSlotChange(e: Event): void {\n const slot = e.target;\n if (!(slot instanceof HTMLSlotElement)) return;\n const validTags = new Set(['hx-menu-item', 'hx-menu-divider']);\n const invalid = slot\n .assignedElements()\n .filter((el) => !validTags.has(el.tagName.toLowerCase()));\n if (invalid.length > 0) {\n devWarn(\n 'hx-menu',\n `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n // Initialize roving tabindex when items are slotted\n this._syncRovingTabIndex();\n }\n\n /** @internal */\n private _handleItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem; value: string }>).detail;\n const items = this._getItems();\n this._focusedIndex = items.indexOf(detail.item);\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item: detail.item, value: detail.value },\n }),\n );\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = null;\n }\n }\n\n override firstUpdated(): void {\n if (!this.label) {\n devWarn(\n 'hx-menu',\n 'No accessible label provided. Set the `label` attribute on hx-menu so screen readers can identify this menu (WCAG 4.1.2).',\n );\n }\n }\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=\"menu\"\n role=\"menu\"\n aria-label=${this.label || 'Menu'}\n @keydown=${this._handleKeyDown}\n @hx-item-select=${this._handleItemSelect}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu': HelixMenu;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuItemStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n .menu-item {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n min-height: var(--hx-touch-target-min, 44px);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n cursor: pointer;\n color: var(--hx-menu-item-color, var(--hx-color-neutral-900, #0f172a));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-family: var(--hx-menu-item-font-family, var(--hx-font-family-sans, sans-serif));\n line-height: var(--hx-line-height-tight, 1.25);\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n background: none;\n width: 100%;\n box-sizing: border-box;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: var(--hx-menu-item-hover-bg, var(--hx-color-neutral-100, #f1f5f9));\n }\n\n .menu-item:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, var(--hx-color-primary-500)));\n outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);\n }\n\n .menu-item__prefix,\n .menu-item__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .menu-item__label {\n flex: 1 1 auto;\n }\n\n .menu-item__checked-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n width: 1em;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item--checked .menu-item__checked-icon {\n opacity: 1;\n }\n\n .menu-item__submenu-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n }\n\n .menu-item__spinner {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n animation: hx-menu-spin var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n @keyframes hx-menu-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item {\n transition: none;\n }\n\n .menu-item__checked-icon {\n transition: none;\n }\n\n .menu-item__spinner {\n animation: none;\n opacity: var(--hx-opacity-muted, 0.6);\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-item {\n forced-color-adjust: none;\n color: CanvasText;\n background-color: Canvas;\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .menu-item:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: -2px;\n }\n\n :host([disabled]) .menu-item {\n color: GrayText;\n opacity: 1;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixMenuItemStyles } from './hx-menu-item.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A single interactive item for use inside `hx-menu`. Supports normal, checkbox,\n * and radio types, loading state, prefix/suffix slots, and submenu nesting.\n * Use `aria-label` on the parent `hx-menu` to provide an accessible name.\n *\n * @summary Interactive item within an hx-menu.\n *\n * @tag hx-menu-item\n *\n * @slot - Default slot for the item label.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Shortcut text or icon rendered after the label.\n * @slot submenu - A nested hx-menu for submenu content.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-item-select - Dispatched when the item is activated via click, Enter, or Space.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-open - Dispatched when ArrowRight is pressed on an item with a submenu.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-close - Dispatched when ArrowLeft is pressed on an item, signaling the parent to close the submenu and return focus.\n *\n * @csspart base - The root item element.\n * @csspart prefix - Prefix slot wrapper.\n * @csspart label - Label slot wrapper.\n * @csspart suffix - Suffix slot wrapper.\n * @csspart submenu-icon - The chevron icon indicating a submenu.\n * @csspart checked-icon - The checkmark icon for checkbox-type items.\n *\n * @cssprop [--hx-menu-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-menu-item-hover-bg=var(--hx-color-neutral-100)] - Item hover/focus background.\n */\n@customElement('hx-menu-item')\nexport class HelixMenuItem extends HelixElement {\n static override styles = [helixMenuItemStyles];\n\n /**\n * @internal Managed by parent hx-menu for roving tabindex.\n * Only the active item in the menu has tabindex=0; all others have -1.\n */\n @state()\n private _rovingTabIndex = -1;\n\n /** @internal Set the roving tabindex value. Called by parent hx-menu. */\n setRovingTabIndex(value: number): void {\n this._rovingTabIndex = value;\n }\n\n /** Set whether the nested submenu is open. Called by the component managing submenu visibility. */\n setSubmenuOpen(open: boolean): void {\n this._submenuOpen = open;\n }\n\n /**\n * The value associated with this item, emitted in the hx-select event.\n * @attr value\n */\n @property({ type: String })\n value = '';\n\n /**\n * Whether the item is disabled. Prevents interaction and event dispatch.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Whether the item is checked. Only meaningful when type=\"checkbox\".\n * @attr checked\n */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /**\n * The type of menu item. \"checkbox\" renders a checkmark and toggles checked state.\n * \"radio\" renders a checkmark and emits selection for radio-group behavior.\n * @attr type\n */\n @property({ type: String, reflect: true })\n type: 'normal' | 'checkbox' | 'radio' = 'normal';\n\n /**\n * Whether the item is in a loading state. Shows a spinner and prevents interaction.\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /** @internal */\n @state()\n private _hasSubmenu = false;\n\n /** @internal Tracks whether the nested submenu is currently open. */\n @state()\n private _submenuOpen = false;\n\n /** @internal */\n @query('.menu-item') private _menuItemEl!: HTMLElement | null;\n\n /** Focus the inner interactive element. */\n override focus(options?: FocusOptions): void {\n this._menuItemEl?.focus(options);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // WCAG 4.1.2: menuitem role is only valid inside a role=\"menu\" or role=\"menubar\" container.\n // Check the closest ancestor with a menu role.\n const menuHost = this.closest('hx-menu, hx-split-button, [role=\"menu\"], [role=\"menubar\"]');\n if (!menuHost) {\n devWarn(\n 'hx-menu-item',\n 'hx-menu-item must be used inside an hx-menu or an element with role=\"menu\". ' +\n 'An orphaned menuitem violates WCAG 1.3.1 (Info and Relationships).',\n );\n }\n }\n\n /** @internal */\n private _handleSubmenuSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _activate(): void {\n if (this.disabled || this.loading) return;\n\n if (this.type === 'checkbox') {\n this.checked = !this.checked;\n } else if (this.type === 'radio') {\n const menu = this.closest('hx-menu');\n if (menu) {\n menu\n .querySelectorAll<HelixMenuItem>(':scope > hx-menu-item[type=\"radio\"]')\n .forEach((sibling) => {\n sibling.checked = sibling === this;\n });\n } else {\n this.checked = true;\n }\n }\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this, value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n if (this.disabled || this.loading) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n this._activate();\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._activate();\n return;\n }\n\n if (e.key === 'ArrowRight' && this._hasSubmenu) {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-open', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n return;\n }\n\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-close', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n }\n\n /** @internal */\n private _renderCheckedIcon() {\n return html`\n <span part=\"checked-icon\" class=\"menu-item__checked-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSubmenuIcon() {\n return html`\n <span part=\"submenu-icon\" class=\"menu-item__submenu-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSpinner() {\n return html`\n <svg class=\"menu-item__spinner\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"3\" opacity=\"0.3\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n />\n </svg>\n `;\n }\n\n /** @internal */\n private _getRole(): string {\n switch (this.type) {\n case 'checkbox':\n return 'menuitemcheckbox';\n case 'radio':\n return 'menuitemradio';\n default:\n return 'menuitem';\n }\n }\n\n override render() {\n const role = this._getRole();\n const hasCheckableRole = this.type === 'checkbox' || this.type === 'radio';\n const classes = {\n 'menu-item': true,\n 'menu-item--checked': this.checked,\n };\n\n return html`\n <div\n part=\"base\"\n class=${classMap(classes)}\n role=${role}\n tabindex=${this.disabled ? '-1' : String(this._rovingTabIndex)}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-checked=${hasCheckableRole ? (this.checked ? 'true' : 'false') : nothing}\n aria-haspopup=${this._hasSubmenu ? 'menu' : nothing}\n aria-expanded=${this._hasSubmenu ? (this._submenuOpen ? 'true' : 'false') : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n @click=${this._handleClick}\n @keydown=${this._handleKeyDown}\n >\n ${this.loading ? this._renderSpinner() : nothing}\n ${hasCheckableRole ? this._renderCheckedIcon() : nothing}\n <span part=\"prefix\" class=\"menu-item__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"menu-item__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"menu-item__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n ${this._hasSubmenu ? this._renderSubmenuIcon() : nothing}\n <slot name=\"submenu\" @slotchange=${this._handleSubmenuSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-item': HelixMenuItem;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuDividerStyles = css`\n :host {\n display: block;\n }\n\n .menu-divider {\n height: var(--hx-border-width-thin, 1px);\n background-color: var(--hx-menu-divider-color, var(--hx-color-neutral-200, #e2e8f0));\n margin: var(--hx-space-1, 0.25rem) calc(-1 * var(--hx-space-1, 0.25rem));\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-divider {\n background-color: GrayText;\n }\n }\n`;\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixMenuDividerStyles } from './hx-menu-divider.styles.js';\n\n/**\n * A visual separator for grouping items within an `hx-menu`.\n *\n * @summary Horizontal divider between menu sections.\n *\n * @tag hx-menu-divider\n *\n * @csspart base - The root separator element.\n *\n * @cssprop [--hx-menu-divider-color=var(--hx-color-neutral-200)] - Divider line color.\n */\n@customElement('hx-menu-divider')\nexport class HelixMenuDivider extends HelixElement {\n static override styles = [helixMenuDividerStyles];\n\n override render() {\n return html`<div\n part=\"base\"\n class=\"menu-divider\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n ></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-divider': HelixMenuDivider;\n }\n}\n"],"names":["helixMenuStyles","css","HelixMenu","HelixElement","item","items","activeIndex","i","first","last","index","target","active","_a","idx","char","match","slot","validTags","invalid","el","devWarn","detail","html","__decorateClass","property","customElement","helixMenuItemStyles","HelixMenuItem","value","open","options","menu","sibling","role","hasCheckableRole","classes","classMap","nothing","state","query","helixMenuDividerStyles","HelixMenuDivider"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-nav-item-pqPasRUm.js","sources":["../../src/components/hx-side-nav/hx-side-nav.styles.ts","../../src/components/hx-side-nav/hx-side-nav.ts","../../src/components/hx-side-nav/hx-nav-item.styles.ts","../../src/components/hx-side-nav/hx-nav-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSideNavStyles = css`\n :host {\n display: block;\n height: 100%;\n /* Mirror the nav background and text on the host so slotted light-DOM\n content (header, footer slots) inherits the correct dark surface color.\n Without this, axe-core cannot resolve the background for slotted nodes\n and evaluates their text against the page white background, producing\n false-positive color-contrast violations (WCAG 2.1 AA). */\n background-color: var(--hx-side-nav-bg, var(--hx-color-neutral-900, #0f172a));\n color: var(--hx-side-nav-color, var(--hx-color-neutral-100, #f1f5f9));\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Nav Container ─── */\n\n .side-nav {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: var(--hx-side-nav-width, 16rem);\n background-color: var(--hx-side-nav-bg, var(--hx-color-neutral-900, #0f172a));\n color: var(--hx-side-nav-color, var(--hx-color-neutral-100, #f1f5f9));\n transition: width var(--hx-transition-normal, 300ms) ease;\n overflow: hidden;\n border-inline-end: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-neutral-700, #334155));\n }\n\n /* ─── Collapsed State ─── */\n\n :host([collapsed]) .side-nav {\n width: var(--hx-side-nav-collapsed-width, 3.5rem);\n }\n\n /* ─── Header ─── */\n\n .side-nav__header {\n display: flex;\n align-items: center;\n padding: var(--hx-side-nav-header-padding, var(--hx-space-4, 1rem));\n flex-shrink: 0;\n min-height: var(--hx-space-14, 3.5rem);\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-neutral-700, #334155));\n overflow: hidden;\n }\n\n :host([collapsed]) .side-nav__header {\n justify-content: center;\n padding: var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Body ─── */\n\n .side-nav__body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--hx-space-2, 0.5rem) 0;\n }\n\n /* ─── Footer ─── */\n\n .side-nav__footer {\n display: flex;\n align-items: center;\n padding: var(--hx-side-nav-footer-padding, var(--hx-space-4, 1rem));\n flex-shrink: 0;\n min-height: var(--hx-space-14, 3.5rem);\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-neutral-700, #334155));\n overflow: hidden;\n }\n\n :host([collapsed]) .side-nav__footer {\n justify-content: center;\n padding: var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Toggle Button ─── */\n\n .side-nav__toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--hx-space-8, 2rem);\n height: var(--hx-space-8, 2rem);\n margin-inline-start: auto;\n flex-shrink: 0;\n padding: 0;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n background: transparent;\n color: var(--hx-side-nav-toggle-color, var(--hx-color-neutral-400, #94a3b8));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms) ease,\n color var(--hx-transition-fast, 150ms) ease;\n }\n\n .side-nav__toggle:hover {\n background-color: var(\n --hx-overlay-white-10,\n rgba(255, 255, 255, 0.1)\n ); /* fallback for browsers without color-mix() */\n color: var(--hx-color-neutral-100, #f1f5f9);\n }\n\n @supports (color: color-mix(in srgb, red 50%, blue)) {\n .side-nav__toggle:hover {\n background-color: color-mix(in srgb, currentColor 15%, transparent);\n }\n }\n\n .side-nav__toggle:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #60a5fa));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .side-nav__toggle svg {\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n fill: currentColor;\n flex-shrink: 0;\n transition: transform var(--hx-transition-normal, 300ms) ease;\n }\n\n :host([collapsed]) .side-nav__toggle svg {\n transform: rotate(180deg);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .side-nav {\n transition: none;\n }\n\n .side-nav__toggle {\n transition: none;\n }\n\n .side-nav__toggle svg {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .side-nav {\n border-inline-end-color: CanvasText;\n }\n\n .side-nav__header {\n border-bottom-color: CanvasText;\n }\n\n .side-nav__footer {\n border-top-color: CanvasText;\n }\n\n .side-nav__toggle {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n\n .side-nav__toggle:focus-visible {\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 { helixSideNavStyles } from './hx-side-nav.styles.js';\n\n/**\n * A collapsible left-side navigation panel with nested menu item support.\n * Designed for clinical portals, admin dashboards, and department navigation.\n *\n * @summary Collapsible side navigation panel for enterprise healthcare applications.\n *\n * @tag hx-side-nav\n *\n * @slot - Default slot for hx-nav-item children.\n * @slot header - Logo or branding content.\n * @slot footer - User profile or settings content.\n *\n * @fires {CustomEvent<{ collapsed: boolean }>} hx-collapse - Dispatched when the nav collapses to icon-only mode.\n * @fires {CustomEvent<{ collapsed: boolean }>} hx-expand - Dispatched when the nav expands to full width.\n *\n * @csspart nav - The outer nav element.\n * @csspart header - The header section.\n * @csspart body - The scrollable body section.\n * @csspart footer - The footer section.\n * @csspart toggle - The collapse/expand toggle button.\n *\n * @cssprop [--hx-side-nav-width=16rem] - Full expanded width.\n * @cssprop [--hx-side-nav-collapsed-width=3.5rem] - Collapsed icon-only width.\n * @cssprop [--hx-side-nav-bg=var(--hx-color-neutral-900)] - Background color.\n * @cssprop [--hx-side-nav-color=var(--hx-color-neutral-100)] - Text color.\n * @cssprop [--hx-side-nav-border-color=var(--hx-color-neutral-700)] - Border color.\n * @cssprop [--hx-side-nav-header-padding=var(--hx-space-4)] - Header padding.\n * @cssprop [--hx-side-nav-footer-padding=var(--hx-space-4)] - Footer padding.\n * @cssprop [--hx-side-nav-toggle-color=var(--hx-color-neutral-400)] - Toggle button icon color.\n */\n@customElement('hx-side-nav')\nexport class HelixSideNav extends HelixElement {\n static override styles = [helixSideNavStyles];\n\n // ─── Properties ───\n\n /**\n * When true, the nav collapses to show icons only.\n * @attr collapsed\n */\n @property({ type: Boolean, reflect: true })\n collapsed = false;\n\n /**\n * The accessible label for the nav landmark.\n * @attr label\n */\n @property({ type: String })\n label = 'Main Navigation';\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('collapsed')) {\n this._propagateCollapsedToChildren();\n }\n }\n\n // ─── Collapsed State Propagation ───\n\n /**\n * Propagates the collapsed state to all slotted hx-nav-item children by\n * setting or removing the `data-collapsed` attribute. This allows child\n * items to respond to collapsed mode via their CSS selectors.\n */\n /** @internal */\n private _propagateCollapsedToChildren(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const navItems = slot\n .assignedElements({ flatten: true })\n .filter((el) => el.tagName.toLowerCase() === 'hx-nav-item');\n\n for (const item of navItems) {\n if (!(item instanceof HTMLElement)) continue;\n if (this.collapsed) {\n item.setAttribute('data-collapsed', '');\n } else {\n item.removeAttribute('data-collapsed');\n }\n }\n }\n\n /**\n * Handles the default slot's slotchange event so that if items are added\n * after initial render, they immediately receive the correct collapsed state.\n */\n /** @internal */\n private _onDefaultSlotChange(): void {\n this._propagateCollapsedToChildren();\n }\n\n // ─── Keyboard Navigation ───\n\n /**\n * Implements roving tabindex-style ArrowUp/ArrowDown keyboard navigation\n * among direct hx-nav-item children in the body slot. Disabled items are\n * skipped. Focus is applied to the interactive element inside the shadow DOM\n * of each item (anchor or button with part=\"link\").\n */\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n const validKeys = ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft', 'Home', 'End'];\n if (!validKeys.includes(e.key)) return;\n\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const topLevelItems = slot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n\n if (topLevelItems.length === 0) return;\n\n // Build a flattened list of navigable items: direct children plus visible\n // child items from expanded parent items (per ARIA APG tree pattern).\n const navItems: HTMLElement[] = [];\n for (const item of topLevelItems) {\n navItems.push(item);\n // If this item is expanded, include its non-disabled children\n if (item.hasAttribute('expanded')) {\n const childrenSlot =\n item.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"children\"]');\n if (childrenSlot) {\n const childItems = childrenSlot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n navItems.push(...childItems);\n }\n }\n }\n\n if (navItems.length === 0) return;\n\n // Find which item currently contains focus\n const activeEl = document.activeElement;\n let currentIndex = -1;\n for (let i = 0; i < navItems.length; i++) {\n const item = navItems[i];\n if (!item) continue;\n if (\n item === activeEl ||\n item.contains(activeEl) ||\n item.shadowRoot?.contains(activeEl) === true\n ) {\n currentIndex = i;\n break;\n }\n }\n\n // Handle ArrowRight/ArrowLeft for expand/collapse (ARIA APG tree pattern)\n if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {\n e.preventDefault();\n const currentItem = currentIndex >= 0 ? navItems[currentIndex] : null;\n if (!currentItem) return;\n\n if (e.key === 'ArrowRight') {\n // If the item has children and is collapsed, expand it\n if (\n currentItem.hasAttribute('expanded') === false &&\n currentItem.querySelector('[slot=\"children\"]')\n ) {\n currentItem.setAttribute('expanded', '');\n (currentItem as HTMLElement & { expanded?: boolean }).expanded = true;\n } else if (currentItem.hasAttribute('expanded')) {\n // Already expanded: move focus to first child item\n const childrenSlot =\n currentItem.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"children\"]');\n if (childrenSlot) {\n const firstChild = childrenSlot\n .assignedElements({ flatten: true })\n .find(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n if (firstChild) {\n firstChild.focus();\n return;\n }\n }\n }\n } else {\n // ArrowLeft: if expanded, collapse; if collapsed or non-expandable, find parent\n if (currentItem.hasAttribute('expanded')) {\n currentItem.removeAttribute('expanded');\n (currentItem as HTMLElement & { expanded?: boolean }).expanded = false;\n } else {\n // Move focus to parent item if this item is a child in another item's slot\n const parentNavItem =\n currentItem.closest<HTMLElement>('hx-nav-item:not(:scope)') ??\n currentItem.parentElement?.closest<HTMLElement>('hx-nav-item') ??\n null;\n if (parentNavItem && !parentNavItem.hasAttribute('disabled')) {\n parentNavItem.focus();\n }\n }\n }\n return;\n }\n\n e.preventDefault();\n\n let nextIndex: number;\n if (e.key === 'ArrowDown') {\n nextIndex = currentIndex < navItems.length - 1 ? currentIndex + 1 : 0;\n } else if (e.key === 'ArrowUp') {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : navItems.length - 1;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else {\n nextIndex = navItems.length - 1;\n }\n\n const targetItem = navItems[nextIndex];\n if (!targetItem) return;\n // WCAG 2.1.1: call the public focus() method on the nav item rather than\n // piercing its Shadow DOM directly. hx-nav-item.focus() delegates to the\n // internal [part=\"link\"] element, preserving shadow encapsulation.\n targetItem.focus();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleToggle(): void {\n this.collapsed = !this.collapsed;\n\n if (this.collapsed) {\n /**\n * Dispatched when the nav collapses to icon-only mode.\n * @event hx-collapse\n */\n this.dispatchEvent(\n new CustomEvent<{ collapsed: boolean }>('hx-collapse', {\n bubbles: true,\n composed: true,\n detail: { collapsed: true },\n }),\n );\n } else {\n /**\n * Dispatched when the nav expands to full width.\n * @event hx-expand\n */\n this.dispatchEvent(\n new CustomEvent<{ collapsed: boolean }>('hx-expand', {\n bubbles: true,\n composed: true,\n detail: { collapsed: false },\n }),\n );\n }\n }\n\n // ─── Render ───\n\n /** @internal */\n private _renderToggleIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n />\n </svg>`;\n }\n\n override render() {\n return html`\n <nav part=\"nav\" class=\"side-nav\" aria-label=${this.label}>\n <div part=\"header\" class=\"side-nav__header\">\n <slot name=\"header\"></slot>\n <button\n part=\"toggle\"\n class=\"side-nav__toggle\"\n aria-label=${this.collapsed ? 'Expand navigation' : 'Collapse navigation'}\n aria-expanded=${!this.collapsed}\n @click=${this._handleToggle}\n >\n ${this._renderToggleIcon()}\n </button>\n </div>\n\n <div part=\"body\" class=\"side-nav__body\" id=\"side-nav-body\" @keydown=${this._handleKeydown}>\n <slot @slotchange=${this._onDefaultSlotChange}></slot>\n </div>\n\n <div part=\"footer\" class=\"side-nav__footer\">\n <slot name=\"footer\"></slot>\n </div>\n </nav>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-side-nav': HelixSideNav;\n }\n}\n\nexport type { HelixSideNav as HxSideNav };\n","import { css } from 'lit';\n\nexport const helixNavItemStyles = css`\n :host {\n display: block;\n /* The host background must be a concrete color so that axe-core can\n resolve text contrast ratios for shadow-DOM content correctly.\n WCAG 2.1 AA: neutral-300 (#cbd5e1) on neutral-900 (#0f172a) = 12.02:1. */\n background-color: var(--hx-nav-item-host-bg, var(--hx-color-neutral-900, #0f172a));\n color: var(--hx-nav-item-color, var(--hx-color-neutral-300, #cbd5e1));\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Nav Item ─── */\n\n .nav-item {\n display: flex;\n flex-direction: column;\n }\n\n /* ─── Link / Button ─── */\n\n .nav-item__link {\n display: flex;\n align-items: center;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-nav-item-padding, var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem));\n min-height: var(--hx-space-10, 2.5rem);\n text-decoration: none;\n color: var(--hx-nav-item-color, var(--hx-color-neutral-300, #cbd5e1));\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n margin: 0 var(--hx-space-2, 0.5rem);\n transition:\n background-color var(--hx-transition-fast, 150ms) ease,\n color var(--hx-transition-fast, 150ms) ease;\n white-space: nowrap;\n overflow: hidden;\n cursor: pointer;\n font-family: var(--hx-nav-item-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-normal, 1.5);\n position: relative;\n border: none;\n background: transparent;\n width: calc(100% - var(--hx-space-4, 1rem));\n text-align: start;\n }\n\n /* Link variant */\n a.nav-item__link {\n display: flex;\n }\n\n .nav-item__link:hover {\n background-color: var(\n --hx-nav-item-hover-bg,\n var(--hx-overlay-white-8, rgba(255, 255, 255, 0.08))\n ); /* fallback for browsers without color-mix() */\n color: var(--hx-nav-item-hover-color, var(--hx-color-neutral-100, #f1f5f9));\n }\n\n @supports (color: color-mix(in srgb, red 50%, blue)) {\n .nav-item__link:hover {\n background-color: var(\n --hx-nav-item-hover-bg,\n color-mix(in srgb, currentColor 10%, transparent)\n );\n }\n }\n\n .nav-item__link:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #60a5fa));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Active State ─── */\n\n :host([active]) .nav-item__link {\n /* neutral-50 (#f8fafc) on primary-600 (#1d4ed8) = 6.41:1 — WCAG AA ✓ */\n background-color: var(--hx-nav-item-active-bg, var(--hx-color-primary-600, #1d4ed8));\n color: var(--hx-nav-item-active-color, var(--hx-color-neutral-50, #f8fafc));\n }\n\n :host([active]) .nav-item__link:hover {\n /* neutral-50 (#f8fafc) on primary-700 (#1e40af) = 8.34:1 — WCAG AA ✓ */\n background-color: var(--hx-nav-item-active-hover-bg, var(--hx-color-primary-700, #1e40af));\n }\n\n /* ─── Disabled State ─── */\n\n :host([disabled]) .nav-item__link {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n cursor: not-allowed;\n }\n\n /* ─── Icon ─── */\n\n .nav-item__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n }\n\n /* ─── Label ─── */\n\n .nav-item__label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n transition: opacity var(--hx-transition-fast, 150ms) ease;\n }\n\n /* ─── Badge ─── */\n\n .nav-item__badge {\n margin-inline-start: auto;\n flex-shrink: 0;\n }\n\n /* ─── Expand Arrow ─── */\n\n .nav-item__arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n transition: transform var(--hx-transition-normal, 300ms) ease;\n }\n\n .nav-item__arrow svg {\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n fill: currentColor;\n }\n\n :host([expanded]) .nav-item__arrow {\n transform: rotate(90deg);\n }\n\n /* ─── Children (sub-nav) ─── */\n\n .nav-item__children {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--hx-transition-normal, 300ms ease);\n overflow: hidden;\n }\n\n :host([expanded]) .nav-item__children {\n grid-template-rows: 1fr;\n }\n\n .nav-item__children-inner {\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding-inline-start: var(--hx-space-6, 1.5rem);\n }\n\n /* ─── Tooltip (collapsed mode) ─── */\n\n .nav-item__tooltip {\n position: absolute;\n left: calc(100% + var(--hx-space-2, 0.5rem));\n top: 50%;\n transform: translateY(-50%);\n /* neutral-100 (#f1f5f9) on neutral-800 (#1e293b) = 13.35:1 — WCAG AA ✓ */\n background-color: var(--hx-color-neutral-800, #1e293b);\n color: var(--hx-color-neutral-100, #f1f5f9);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n font-size: var(--hx-font-size-xs, 0.75rem);\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms) ease;\n z-index: var(--hx-z-index-tooltip, 1600);\n box-shadow: var(--hx-shadow-md, 0 2px 8px rgb(0 0 0 / 0.2));\n }\n\n :host([data-collapsed]) .nav-item__link:hover .nav-item__tooltip,\n :host([data-collapsed]) .nav-item__link:focus-visible .nav-item__tooltip {\n opacity: 1;\n }\n\n /* ─── Collapsed host state (propagated from parent) ─── */\n\n :host([data-collapsed]) .nav-item__label {\n width: 0;\n overflow: hidden;\n opacity: 0;\n }\n\n :host([data-collapsed]) .nav-item__badge {\n display: none;\n }\n\n :host([data-collapsed]) .nav-item__arrow {\n display: none;\n }\n\n :host([data-collapsed]) .nav-item__children {\n display: none !important;\n }\n\n :host([data-collapsed]) .nav-item__link {\n justify-content: center;\n margin: 0 var(--hx-space-1, 0.25rem);\n width: calc(100% - var(--hx-space-2, 0.5rem));\n padding: var(--hx-space-2, 0.5rem);\n position: relative;\n overflow: visible;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .nav-item__link,\n .nav-item__label,\n .nav-item__arrow,\n .nav-item__children,\n .nav-item__tooltip {\n transition: none;\n }\n\n :host([expanded]) .nav-item__children {\n grid-template-rows: 1fr;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n :host([active]) .nav-item__link {\n border: 1px solid Highlight;\n }\n\n .nav-item__link:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .nav-item__tooltip {\n border: 1px solid CanvasText;\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, createIdCounter } from '../../base/index.js';\nimport { helixNavItemStyles } from './hx-nav-item.styles.js';\n\nconst _nextNavItemId = createIdCounter('hx-nav-item');\n\n/**\n * A navigation item for use inside hx-side-nav.\n * Supports icons, badges, sub-navigation, and active/disabled states.\n *\n * @summary Navigation item for hx-side-nav with support for icons, badges, and nested children.\n *\n * @tag hx-nav-item\n *\n * @slot - Default slot for item label text.\n * @slot icon - Icon to display before the label.\n * @slot badge - Badge content (e.g., notification count).\n * @slot children - Nested hx-nav-item children for sub-navigation.\n *\n * @csspart link - The anchor or button element.\n * @csspart icon - The icon container.\n * @csspart label - The label container.\n * @csspart badge - The badge container.\n * @csspart children - The children container.\n *\n * @cssprop [--hx-nav-item-color=var(--hx-color-neutral-300)] - Item text color.\n * @cssprop [--hx-nav-item-hover-bg] - Item hover background.\n * @cssprop [--hx-nav-item-hover-color=var(--hx-color-neutral-100)] - Item hover text color.\n * @cssprop [--hx-nav-item-active-bg=var(--hx-color-primary-600)] - Active item background.\n * @cssprop [--hx-nav-item-active-color=var(--hx-color-neutral-50)] - Active item text color.\n * @cssprop [--hx-nav-item-padding] - Item padding.\n * @cssprop [--hx-nav-item-host-bg=var(--hx-color-neutral-900)] - Component host background color.\n */\n@customElement('hx-nav-item')\nexport class HelixNavItem extends HelixElement {\n static override styles = [helixNavItemStyles];\n\n /** @internal — per-instance tooltip ID */\n private _tooltipId = `${_nextNavItemId()}-tooltip`;\n\n // ─── Properties ───\n\n /**\n * The URL this nav item links to.\n * @attr href\n */\n @property({ type: String })\n href = '';\n\n /**\n * Whether this item is the current/active page.\n * @attr active\n */\n @property({ type: Boolean, reflect: true })\n active = false;\n\n /**\n * Whether the sub-navigation is expanded.\n * @attr expanded\n */\n @property({ type: Boolean, reflect: true })\n expanded = false;\n\n /**\n * Whether this nav item is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── State ───\n\n /** Whether the children slot has assigned nodes. Updated via slotchange. */\n /** @internal */\n @state() private _hasChildren = false;\n\n /** Whether this item is in collapsed mode. Set externally by hx-side-nav via data-collapsed attribute. */\n /** @internal */\n @state() private _isCollapsed = false;\n\n // ─── Attribute Observer ───\n\n static override get observedAttributes(): string[] {\n return [...super.observedAttributes, 'data-collapsed'];\n }\n\n override attributeChangedCallback(name: string, old: string | null, value: string | null): void {\n super.attributeChangedCallback(name, old, value);\n if (name === 'data-collapsed') {\n this._isCollapsed = value !== null;\n }\n }\n\n // ─── Public API ───\n\n /**\n * Delegates focus to the internal link or button element (part=\"link\").\n * Allows parent components to focus nav items without piercing the Shadow DOM.\n * WCAG 2.1.1: keyboard navigation must not cross shadow boundaries via\n * direct shadowRoot queries.\n */\n override focus(options?: FocusOptions): void {\n const inner = this.shadowRoot?.querySelector<HTMLElement>('[part=\"link\"]');\n if (inner) {\n inner.focus(options);\n } else {\n super.focus(options);\n }\n }\n\n // ─── Slot Change Handler ───\n\n /** @internal */\n private _onChildrenSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasChildren = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _getDirectText(): string {\n return Array.from(this.childNodes)\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent?.trim() ?? '')\n .filter(Boolean)\n .join(' ');\n }\n\n /** @internal */\n private _handleToggle(e: Event): void {\n if (this.disabled) return;\n e.preventDefault();\n this.expanded = !this.expanded;\n }\n\n /** @internal */\n private _renderExpandArrow() {\n return html`<span class=\"nav-item__arrow\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\">\n <path\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n />\n </svg>\n </span>`;\n }\n\n // ─── Render ───\n\n override render() {\n const label = this._getDirectText();\n\n const innerContent = html`\n <span part=\"icon\" class=\"nav-item__icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"nav-item__label\">\n <slot></slot>\n </span>\n <span part=\"badge\" class=\"nav-item__badge\">\n <slot name=\"badge\"></slot>\n </span>\n ${this._hasChildren ? this._renderExpandArrow() : nothing}\n ${this._isCollapsed\n ? html`<span id=${this._tooltipId} class=\"nav-item__tooltip\" role=\"tooltip\">${label}</span>`\n : nothing}\n `;\n\n // Render as anchor when href provided and no expandable children\n const linkEl =\n this.href && !this._hasChildren\n ? html`<a\n part=\"link\"\n class=\"nav-item__link\"\n href=${this.href}\n aria-current=${this.active ? 'page' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-describedby=${this._isCollapsed ? this._tooltipId : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n >\n ${innerContent}\n </a>`\n : html`<button\n part=\"link\"\n class=\"nav-item__link\"\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-expanded=${this._hasChildren ? String(this.expanded) : nothing}\n aria-describedby=${this._isCollapsed ? this._tooltipId : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n @click=${this._handleToggle}\n >\n ${innerContent}\n </button>`;\n\n return html`\n <div class=\"nav-item\">\n ${linkEl}\n <div part=\"children\" class=\"nav-item__children\" role=\"group\">\n <div class=\"nav-item__children-inner\">\n <slot name=\"children\" @slotchange=${this._onChildrenSlotChange}></slot>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-nav-item': HelixNavItem;\n }\n}\n\nexport type { HelixNavItem as HxNavItem };\n"],"names":["helixSideNavStyles","css","HelixSideNav","HelixElement","changedProperties","slot","_a","navItems","el","item","topLevelItems","childrenSlot","_b","childItems","activeEl","currentIndex","i","_c","currentItem","_d","firstChild","parentNavItem","_e","nextIndex","targetItem","html","__decorateClass","property","customElement","helixNavItemStyles","_nextNavItemId","createIdCounter","HelixNavItem","name","old","value","options","inner","n","label","innerContent","nothing","linkEl","state"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-number-input-mOIZ3-46.js","sources":["../../src/components/hx-number-input/hx-number-input.styles.ts","../../src/components/hx-number-input/hx-number-input.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixNumberInputStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled);\n pointer-events: none;\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);\n font-family: var(--hx-number-input-font-family, var(--hx-font-family-sans));\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);\n font-size: var(--hx-font-size-sm);\n font-weight: var(--hx-font-weight-medium);\n color: var(--hx-number-input-label-color, var(--hx-color-neutral-700));\n line-height: var(--hx-line-height-normal);\n }\n\n .field__required-marker {\n color: var(--hx-number-input-error-color, var(--hx-color-error-text, #b91c1c));\n font-weight: var(--hx-font-weight-bold);\n }\n\n /* ─── Input Wrapper ─── */\n\n .field__input-wrapper {\n display: flex;\n align-items: stretch;\n border: var(--hx-border-width-thin) solid\n var(--hx-number-input-border-color, var(--hx-color-neutral-300));\n border-radius: var(--hx-number-input-border-radius, var(--hx-border-radius-md));\n background-color: var(--hx-number-input-bg, var(--hx-color-neutral-0));\n transition:\n border-color var(--hx-transition-fast),\n box-shadow var(--hx-transition-fast);\n overflow: hidden;\n }\n\n .field__input-wrapper:focus-within {\n border-color: var(--hx-number-input-focus-ring-color, var(--hx-focus-ring-color));\n /* Fallback for Safari < 16.2 (no color-mix support) */\n box-shadow: 0 0 0 var(--hx-focus-ring-width)\n var(--hx-number-input-focus-ring-color, var(--hx-focus-ring-color));\n box-shadow: 0 0 0 var(--hx-focus-ring-width)\n color-mix(\n in srgb,\n var(--hx-number-input-focus-ring-color, var(--hx-focus-ring-color))\n calc(var(--hx-focus-ring-opacity) * 100%),\n transparent\n );\n }\n\n /* ─── Error State ─── */\n\n .field--error .field__input-wrapper {\n border-color: var(--hx-number-input-error-color, var(--hx-color-error-500, #dc2626));\n }\n\n .field--error .field__input-wrapper:focus-within {\n border-color: var(--hx-number-input-error-color, var(--hx-color-error-500, #dc2626));\n /* Fallback for Safari < 16.2 (no color-mix support) */\n box-shadow: 0 0 0 var(--hx-focus-ring-width)\n var(--hx-number-input-error-color, var(--hx-color-error-500, #dc2626));\n box-shadow: 0 0 0 var(--hx-focus-ring-width)\n color-mix(\n in srgb,\n var(--hx-number-input-error-color, var(--hx-color-error-500, #dc2626))\n calc(var(--hx-focus-ring-opacity) * 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 padding: 0 var(--hx-space-3);\n color: var(--hx-color-neutral-500);\n flex-shrink: 0;\n }\n\n /* ─── Native Input ─── */\n\n .field__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font-family: inherit;\n color: var(--hx-number-input-color, var(--hx-color-neutral-800));\n line-height: var(--hx-line-height-normal);\n width: 100%;\n /* Size: md (default) */\n padding: var(--hx-space-2) var(--hx-space-3);\n font-size: var(--hx-font-size-md);\n min-height: var(--hx-size-10);\n }\n\n .field__input::placeholder {\n color: var(--hx-color-neutral-400);\n }\n\n .field__input:disabled {\n cursor: not-allowed;\n }\n\n /* ─── Hide native browser spinners ─── */\n\n .field__input[type='number']::-webkit-inner-spin-button,\n .field__input[type='number']::-webkit-outer-spin-button {\n display: none;\n }\n\n .field__input[type='number'] {\n appearance: textfield;\n }\n\n /* ─── Size Variants ─── */\n\n .field--sm .field__input {\n padding: var(--hx-space-1) var(--hx-space-2);\n font-size: var(--hx-font-size-sm);\n min-height: var(--hx-size-8);\n }\n\n .field--lg .field__input {\n padding: var(--hx-space-3) var(--hx-space-4);\n font-size: var(--hx-font-size-lg);\n min-height: var(--hx-size-12);\n }\n\n /* ─── Stepper ─── */\n\n .field__stepper {\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n border-inline-start: var(--hx-border-width-thin) solid\n var(--hx-number-input-border-color, var(--hx-color-neutral-300));\n }\n\n .field__stepper-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n cursor: pointer;\n color: var(--hx-color-neutral-600);\n padding: 0;\n flex: 1;\n min-width: var(--hx-size-8);\n line-height: 1;\n transition: background-color var(--hx-transition-fast);\n user-select: none;\n -webkit-user-select: none;\n }\n\n .field__stepper-btn:not(:last-child) {\n border-bottom: var(--hx-border-width-thin) solid\n var(--hx-number-input-border-color, var(--hx-color-neutral-300));\n }\n\n .field__stepper-btn:hover:not(:disabled) {\n background-color: var(--hx-color-neutral-50);\n color: var(--hx-color-neutral-800);\n }\n\n /* Suppress focus ring for mouse/touch focus; keep for keyboard and programmatic focus */\n .field__stepper-btn:focus:not(:focus-visible) {\n outline: none;\n }\n\n .field__stepper-btn:focus-visible {\n outline: var(--hx-focus-ring-width) solid\n var(--hx-number-input-focus-ring-color, var(--hx-focus-ring-color));\n outline-offset: -2px;\n }\n\n .field__stepper-btn:disabled {\n opacity: var(--hx-opacity-disabled);\n cursor: not-allowed;\n }\n\n .field__stepper-btn svg {\n pointer-events: none;\n width: var(--hx-number-input-icon-size, var(--hx-space-3, 0.75rem));\n height: var(--hx-number-input-icon-size, var(--hx-space-3, 0.75rem));\n }\n\n /* Size sm adjustments for stepper */\n .field--sm .field__stepper-btn {\n min-width: var(--hx-size-6);\n }\n\n /* Size lg adjustments for stepper */\n .field--lg .field__stepper-btn {\n min-width: var(--hx-size-10);\n }\n\n /* ─── Help Text & Error Messages ─── */\n\n .field__help-text {\n font-size: var(--hx-font-size-xs);\n color: var(--hx-color-neutral-500);\n line-height: var(--hx-line-height-normal);\n }\n\n .field__error {\n font-size: var(--hx-font-size-xs);\n color: var(--hx-number-input-error-color, var(--hx-color-error-text, #b91c1c));\n line-height: var(--hx-line-height-normal);\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .field__input-wrapper {\n transition: none;\n }\n\n .field__stepper-btn {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\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__stepper {\n border-color: ButtonText;\n }\n\n .field__stepper-btn {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border-color: ButtonText;\n }\n\n .field__stepper-btn:hover:not(:disabled) {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__stepper-btn:focus-visible {\n outline-color: Highlight;\n }\n\n .field__stepper-btn:disabled {\n color: GrayText;\n opacity: 1;\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 { devWarn } from '../../utils/dev-warn.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 { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixNumberInputStyles } from './hx-number-input.styles.js';\n\nconst _nextNumberInputId = createIdCounter('hx-number-input');\n\n/** Detail for hx-input and hx-change events dispatched by hx-number-input. */\nexport interface HxNumberInputDetail {\n value: number | null;\n}\n\n/**\n * A numeric input component with stepper controls, label, validation, and\n * full form association. Designed for healthcare data-entry contexts where\n * precise numeric values (dosage, age, measurements) must be captured safely.\n *\n * @summary Form-associated numeric input with stepper buttons, bounds checking,\n * label, error, and help text.\n *\n * @tag hx-number-input\n *\n * @slot label - Custom label content (overrides the label property). Use for Drupal Form API rendered labels.\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 * @slot prefix - Content rendered before the input (e.g., a unit icon).\n * @slot suffix - Content rendered after the input and before the stepper buttons (e.g., a unit label).\n *\n * @fires {CustomEvent<{value: number | null}>} hx-input - Dispatched on every keystroke as the user types.\n * @fires {CustomEvent<{value: number | null}>} 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, suffix, and stepper.\n * @csspart input - The native input element.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n * @csspart stepper - The stepper button group container.\n * @csspart increment - The increment (+) button.\n * @csspart decrement - The decrement (-) button.\n *\n * @cssprop [--hx-number-input-bg=var(--hx-color-neutral-0)] - Input background color.\n * @cssprop [--hx-number-input-color=var(--hx-color-neutral-800)] - Input text color.\n * @cssprop [--hx-number-input-border-color=var(--hx-color-neutral-300)] - Input border color.\n * @cssprop [--hx-number-input-border-radius=var(--hx-border-radius-md)] - Input border radius.\n * @cssprop [--hx-number-input-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-number-input-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-number-input-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-number-input-font-family=var(--hx-font-family-sans)] - Font family.\n */\n@customElement('hx-number-input')\nexport class HelixNumberInput extends FormMixin(HelixElement) {\n static override styles = [helixNumberInputStyles];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n // ─── Properties ───\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 * The current numeric value of the input. Null when the field is empty.\n * @attr value\n */\n @property({\n type: Number,\n reflect: true,\n converter: {\n fromAttribute: (attr: string | null): number | null => {\n if (attr === null || attr === '') return null;\n const n = Number(attr);\n return isNaN(n) ? null : n;\n },\n toAttribute: (val: number | null): string | null => (val === null ? null : String(val)),\n },\n })\n value: number | null = null;\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 * Whether the input is read-only.\n * @attr readonly\n */\n @property({ type: Boolean, reflect: true })\n readonly = false;\n\n /**\n * Minimum allowed value. When reached, the decrement button is disabled.\n * @attr min\n */\n @property({ type: Number })\n min: number | undefined = undefined;\n\n /**\n * Maximum allowed value. When reached, the increment button is disabled.\n * @attr max\n */\n @property({ type: Number })\n max: number | undefined = undefined;\n\n /**\n * The amount to increment or decrement on each step action.\n * @attr step\n */\n @property({ type: Number })\n step = 1;\n\n /**\n * The visible label text for the input.\n * @attr label\n */\n @property({ type: String })\n label = '';\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 * Size variant controlling input padding and font size.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * When set, hides the +/- stepper buttons.\n * @attr no-stepper\n */\n @property({ type: Boolean, attribute: 'no-stepper' })\n noStepper = false;\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 * Accessible label for the increment (+) stepper button.\n * @attr increment-label\n */\n @property({ attribute: 'increment-label' })\n incrementLabel = 'Increment';\n\n /**\n * Accessible label for the decrement (-) stepper button.\n * @attr decrement-label\n */\n @property({ attribute: 'decrement-label' })\n decrementLabel = 'Decrement';\n\n // ─── Internal References ───\n\n /** @internal */\n @query('.field__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── Internal State ───\n\n /** @internal */\n @state() private _hasLabelSlot = false;\n /** @internal */\n @state() private _hasErrorSlot = false;\n /** @internal */\n @state() private _hasHelpSlot = false;\n\n /** The value captured at first render, used by formResetCallback. */\n /** @internal */\n private _defaultValue: number | null = null;\n\n /** Timer ID for the long-press initial delay. */\n /** @internal */\n private _longPressTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Interval ID for the long-press rapid-repeat phase. */\n /** @internal */\n private _repeatInterval: ReturnType<typeof setInterval> | null = null;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private readonly _inputId = _nextNumberInputId();\n /** @internal */\n private readonly _helpTextId = `${this._inputId}-help`;\n /** @internal */\n private readonly _errorId = `${this._inputId}-error`;\n\n // ─── Slot Tracking ───\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 const assigned = slot.assignedElements();\n this._hasErrorSlot = assigned.length > 0;\n if (this._hasErrorSlot && assigned[0]) {\n if (!assigned[0].id) assigned[0].id = this._errorId;\n }\n }\n\n /** @internal */\n private _handleHelpSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHelpSlot = slot.assignedElements().length > 0;\n }\n\n // ─── Lifecycle ───\n\n override firstUpdated(): void {\n this._defaultValue = this.value;\n if (!this.label && !this._hasLabelSlot) {\n devWarn(\n 'hx-number-input',\n 'No accessible label provided. Set the `label` attribute or use the `label` slot so screen readers can identify this input (WCAG 4.1.2).',\n );\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._clearLongPress();\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('value')) {\n if (this.value !== null && isNaN(this.value)) {\n devWarn(\n 'hx-number-input',\n 'Received NaN as value. Resetting to null to prevent \"NaN\" from rendering in the input.',\n );\n this.value = null;\n return;\n }\n }\n if (\n changedProperties.has('value') ||\n changedProperties.has('required') ||\n changedProperties.has('min') ||\n changedProperties.has('max') ||\n changedProperties.has('step')\n ) {\n this._syncFormValue();\n }\n // Force screen reader re-announcement when error text changes (a11y-v3-005)\n if (changedProperties.has('error') && this.error) {\n const errorEl = this.shadowRoot?.querySelector('[role=\"alert\"]');\n if (errorEl) {\n const msg = this.error;\n requestAnimationFrame(() => {\n errorEl.textContent = '';\n requestAnimationFrame(() => {\n errorEl.textContent = msg;\n });\n });\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n private _syncFormValue(): void {\n this._internals.setFormValue(this.value !== null ? String(this.value) : null);\n }\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && this.value === null) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.requiredMessage,\n this._input ?? undefined,\n );\n return;\n }\n\n if (this.value !== null && this.min !== undefined && this.value < this.min) {\n this._internals.setValidity(\n { rangeUnderflow: true },\n `Value must be at least ${this.min}.`,\n this._input ?? undefined,\n );\n return;\n }\n\n if (this.value !== null && this.max !== undefined && this.value > this.max) {\n this._internals.setValidity(\n { rangeOverflow: true },\n `Value must be at most ${this.max}.`,\n this._input ?? undefined,\n );\n return;\n }\n\n if (this.value !== null && this.step && this.step !== 0) {\n const step = this._finite(this.step) ?? 1;\n const base = this._finite(this.min) ?? 0;\n const remainder = Math.abs((this.value - base) % step);\n const epsilon = 1e-9;\n if (remainder > epsilon && Math.abs(remainder - step) > epsilon) {\n this._internals.setValidity(\n { stepMismatch: true },\n `Value must be a multiple of ${step}.`,\n this._input ?? undefined,\n );\n return;\n }\n }\n\n this._internals.setValidity({});\n }\n\n /** @internal */\n protected override _onFormReset(): void {\n this.value = this._defaultValue;\n this._internals.setFormValue(this.value !== null ? String(this.value) : null);\n this._resetInteractionState();\n }\n\n /** @internal */\n protected override _onFormStateRestore(\n state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n const parsed = Number(state);\n this.value = isNaN(parsed) ? null : parsed;\n }\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Value Parsing ───\n\n /** @internal */\n private _finite(value: number | undefined): number | undefined {\n return Number.isFinite(value) ? value : undefined;\n }\n\n /** @internal */\n private _parseInput(raw: string): number | null {\n if (raw === '' || raw === null) return null;\n const parsed = parseFloat(raw);\n return isNaN(parsed) ? null : parsed;\n }\n\n /** @internal */\n private _clamp(v: number): number {\n let result = v;\n const min = this._finite(this.min);\n const max = this._finite(this.max);\n if (min !== undefined) result = Math.max(min, result);\n if (max !== undefined) result = Math.min(max, result);\n return result;\n }\n\n // ─── Stepper Helpers ───\n\n /** @internal */\n private get _atMin(): boolean {\n return this.value !== null && this.min !== undefined && this.value <= this.min;\n }\n\n /** @internal */\n private get _atMax(): boolean {\n return this.value !== null && this.max !== undefined && this.value >= this.max;\n }\n\n /** @internal */\n private _applyStep(delta: number): void {\n if (this.disabled || this.readonly) return;\n\n const current = this.value ?? 0;\n const step = this._finite(this.step) ?? 1;\n const next = this._clamp(parseFloat((current + delta * step).toFixed(10)));\n\n if (next === this.value) return;\n this.value = next;\n this._handleInteractionInput();\n\n this.dispatchEvent(\n new CustomEvent<{ value: number | null }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Long-press ───\n\n /** @internal */\n private _clearLongPress(): void {\n if (this._longPressTimer !== null) {\n clearTimeout(this._longPressTimer);\n this._longPressTimer = null;\n }\n if (this._repeatInterval !== null) {\n clearInterval(this._repeatInterval);\n this._repeatInterval = null;\n }\n }\n\n /** @internal */\n private _startLongPress(delta: number): void {\n this._applyStep(delta);\n this._longPressTimer = setTimeout(() => {\n this._repeatInterval = setInterval(() => {\n this._applyStep(delta);\n }, 100);\n }, 400);\n }\n\n /** @internal */\n private _handleStepperPointerDown(e: PointerEvent, delta: number): void {\n if (this.disabled || this.readonly) return;\n e.preventDefault();\n this._startLongPress(delta);\n }\n\n /** @internal */\n private _handleStepperPointerUp(): void {\n this._clearLongPress();\n }\n\n // ─── Keyboard ───\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n if (this.disabled || this.readonly) return;\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n this._applyStep(1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._applyStep(-1);\n }\n }\n\n // ─── Input Events ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n const target = e.target as HTMLInputElement;\n this.value = this._parseInput(target.value);\n this._handleInteractionInput();\n this._syncFormValue();\n\n this.dispatchEvent(\n new CustomEvent<{ value: number | null }>('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 const parsed = this._parseInput(target.value);\n this.value = parsed !== null ? this._clamp(parsed) : null;\n this._handleInteractionBlur();\n this._syncFormValue();\n\n this.dispatchEvent(\n new CustomEvent<{ value: number | null }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Public Methods ───\n\n /** Moves focus to the input element. */\n override focus(options?: FocusOptions): void {\n this._input?.focus(options);\n }\n\n /** Selects all text in the input. */\n select(): void {\n this._input?.select();\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderIncrementIcon() {\n return html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 12 12\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path d=\"M6 1v10M1 6h10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>`;\n }\n\n /** @internal */\n private _renderDecrementIcon() {\n return html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 12 12\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path d=\"M1 6h10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>`;\n }\n\n // ─── Render ───\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--sm': this.size === 'sm',\n 'field--md': this.size === 'md',\n 'field--lg': this.size === 'lg',\n };\n\n const describedBy =\n [\n hasError ? this._errorId : null,\n !hasError && (this.helpText || this._hasHelpSlot) ? this._helpTextId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n const displayValue = this.value !== null ? String(this.value) : '';\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 class=\"field__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n\n <input\n part=\"input\"\n class=\"field__input\"\n id=${this._inputId}\n type=\"number\"\n .value=${live(displayValue)}\n min=${ifDefined(this.min)}\n max=${ifDefined(this.max)}\n step=${this.step}\n ?required=${this.required}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n name=${ifDefined(this.name || 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 @keydown=${this._handleKeyDown}\n />\n\n <span class=\"field__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n\n ${this.noStepper\n ? nothing\n : html`\n <div part=\"stepper\" class=\"field__stepper\">\n <button\n part=\"increment\"\n class=\"field__stepper-btn\"\n type=\"button\"\n aria-label=${this.incrementLabel}\n ?disabled=${this.disabled || this.readonly || this._atMax}\n tabindex=\"-1\"\n @pointerdown=${(e: PointerEvent) => this._handleStepperPointerDown(e, 1)}\n @pointerup=${this._handleStepperPointerUp}\n @pointerleave=${this._handleStepperPointerUp}\n @pointercancel=${this._handleStepperPointerUp}\n >\n ${this._renderIncrementIcon()}\n </button>\n <button\n part=\"decrement\"\n class=\"field__stepper-btn\"\n type=\"button\"\n aria-label=${this.decrementLabel}\n ?disabled=${this.disabled || this.readonly || this._atMin}\n tabindex=\"-1\"\n @pointerdown=${(e: PointerEvent) => this._handleStepperPointerDown(e, -1)}\n @pointerup=${this._handleStepperPointerUp}\n @pointerleave=${this._handleStepperPointerUp}\n @pointercancel=${this._handleStepperPointerUp}\n >\n ${this._renderDecrementIcon()}\n </button>\n </div>\n `}\n </div>\n\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}>\n ${this.error\n ? html`\n <div part=\"error\" class=\"field__error\" id=${this._errorId} role=\"alert\">\n ${this.error}\n </div>\n `\n : nothing}\n </slot>\n\n <div\n part=\"help-text\"\n class=\"field__help-text\"\n id=${this._helpTextId}\n ?hidden=${hasError || (!this.helpText && !this._hasHelpSlot)}\n >\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>${this.helpText}</slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-number-input': HelixNumberInput;\n }\n}\n"],"names":["helixNumberInputStyles","css","_nextNumberInputId","createIdCounter","HelixNumberInput","FormMixin","HelixElement","slot","slottedLabel","assigned","changedProperties","errorEl","_a","msg","step","base","remainder","epsilon","state","_mode","parsed","disabled","value","raw","v","result","min","max","delta","current","next","target","options","html","hasError","fieldClasses","describedBy","displayValue","classMap","nothing","live","ifDefined","e","__decorateClass","property","attr","n","val","query","customElement"],"mappings":";;;;;;;;AAEO,MAAMA,IAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-overflow-menu-Dprb9lnT.js","sources":["../../src/components/hx-overflow-menu/hx-overflow-menu.styles.ts","../../src/components/hx-overflow-menu/hx-overflow-menu.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixOverflowMenuStyles = css`\n :host {\n display: inline-block;\n position: relative;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Trigger Button ─── */\n\n .trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: var(--hx-border-width-thin, 1px) solid transparent;\n border-radius: var(--hx-border-radius-md, 0.375rem);\n background-color: transparent;\n color: var(--hx-overflow-menu-button-color, var(--hx-color-neutral-600, #475569));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease);\n flex-shrink: 0;\n padding: 0;\n line-height: 1;\n }\n\n .trigger:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-overflow-menu-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .trigger:hover:not([disabled]) {\n background-color: var(--hx-color-neutral-100, #f1f5f9);\n }\n\n .trigger--open {\n background-color: var(--hx-color-neutral-100, #f1f5f9);\n }\n\n /* ─── Size Variants ─── */\n\n .trigger--sm {\n width: var(--hx-size-8, 2rem);\n height: var(--hx-size-8, 2rem);\n min-width: var(--hx-size-touch-target, 2.75rem);\n min-height: var(--hx-size-touch-target, 2.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n .trigger--md {\n width: var(--hx-size-10, 2.5rem);\n height: var(--hx-size-10, 2.5rem);\n min-width: var(--hx-size-touch-target, 2.75rem);\n min-height: var(--hx-size-touch-target, 2.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n }\n\n .trigger--lg {\n width: var(--hx-size-12, 3rem);\n height: var(--hx-size-12, 3rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n }\n\n /* ─── Panel ─── */\n\n .panel {\n position: fixed;\n z-index: var(--hx-overflow-menu-panel-z-index, 1000);\n min-width: var(--hx-overflow-menu-panel-min-width, 160px);\n background: var(--hx-overflow-menu-panel-bg, var(--hx-color-neutral-0, #ffffff));\n border: var(--hx-overflow-menu-panel-border, 1px solid var(--hx-color-neutral-200, #e2e8f0));\n border-radius: var(\n --hx-overflow-menu-panel-border-radius,\n var(--hx-border-radius-md, 0.375rem)\n );\n box-shadow: var(\n --hx-overflow-menu-panel-shadow,\n 0 4px 16px var(--hx-overlay-black-12, rgba(0, 0, 0, 0.12))\n );\n padding: var(--hx-space-1, 0.25rem) 0;\n outline: none;\n }\n\n /* ─── Slot: menu items ─── */\n\n ::slotted([role='menuitem']),\n ::slotted([role='menuitemcheckbox']),\n ::slotted([role='menuitemradio']) {\n display: block;\n width: 100%;\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n background: none;\n border: none;\n text-align: start;\n font-size: var(--hx-font-size-sm, 0.875rem);\n color: var(--hx-color-neutral-900, #0f172a);\n cursor: pointer;\n white-space: nowrap;\n box-sizing: border-box;\n }\n\n ::slotted([role='menuitem']:hover),\n ::slotted([role='menuitemcheckbox']:hover),\n ::slotted([role='menuitemradio']:hover) {\n background-color: var(--hx-color-neutral-50, #f8fafc);\n }\n\n ::slotted([role='menuitem']:focus-visible),\n ::slotted([role='menuitemcheckbox']:focus-visible),\n ::slotted([role='menuitemradio']:focus-visible) {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-overflow-menu-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: 0;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .trigger {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .trigger {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 2px solid ButtonText;\n }\n\n .trigger:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .trigger[disabled] {\n color: GrayText;\n border-color: GrayText;\n opacity: 1;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n\n .panel {\n background-color: Canvas;\n border: 2px solid CanvasText;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixOverflowMenuStyles } from './hx-overflow-menu.styles.js';\n\nconst _nextOverflowMenuId = createIdCounter('hx-overflow-menu');\n\n/**\n * An overflow menu (kebab/meatball menu) that reveals hidden actions via a\n * floating panel. Composed from a trigger button and a slotted menu panel.\n *\n * @summary \"...\" or kebab icon button that reveals hidden actions.\n *\n * @tag hx-overflow-menu\n *\n * @slot - Menu items (e.g. `<button role=\"menuitem\">` or `<hx-menu-item>` elements).\n *\n * @fires {CustomEvent<{value: string}>} hx-select - Dispatched when a menu item is selected.\n * @fires {CustomEvent<void>} hx-show - Dispatched when the panel opens.\n * @fires {CustomEvent<void>} hx-hide - Dispatched when the panel closes.\n *\n * @csspart button - The trigger icon button element.\n * @csspart trigger - Alias for button — the trigger icon button element.\n * @csspart panel - The floating menu panel container.\n * @csspart menu - Alias for panel — the floating menu panel container.\n *\n * @cssprop [--hx-overflow-menu-panel-bg=var(--hx-color-neutral-0,#fff)] - Panel background color.\n * @cssprop [--hx-overflow-menu-panel-border=1px solid var(--hx-color-neutral-200,#e5e7eb)] - Panel border.\n * @cssprop [--hx-overflow-menu-panel-border-radius=var(--hx-border-radius-md)] - Panel border radius.\n * @cssprop [--hx-overflow-menu-panel-shadow=0 4px 16px rgba(0,0,0,0.12)] - Panel box shadow.\n * @cssprop [--hx-overflow-menu-panel-min-width=160px] - Minimum panel width.\n * @cssprop [--hx-overflow-menu-panel-z-index=1000] - Panel z-index.\n * @cssprop [--hx-overflow-menu-button-color=var(--hx-color-neutral-600)] - Trigger icon color.\n *\n * @example\n * ```html\n * <hx-overflow-menu>\n * <button role=\"menuitem\">Edit</button>\n * <button role=\"menuitem\">Delete</button>\n * </hx-overflow-menu>\n * ```\n */\n@customElement('hx-overflow-menu')\nexport class HelixOverflowMenu extends HelixElement {\n static override styles = [helixOverflowMenuStyles];\n\n /**\n * Preferred placement of the floating panel relative to the trigger.\n * @attr placement\n */\n @property({ type: String, reflect: true })\n placement:\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end' = 'bottom-end';\n\n /**\n * Size of the trigger button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the trigger button is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Icon orientation: vertical (kebab ⋮) or horizontal (meatball ···).\n * @attr icon\n */\n @property({ type: String, reflect: true })\n icon: 'vertical' | 'horizontal' = 'vertical';\n\n /**\n * Accessible label for the trigger button.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = 'More actions';\n\n /**\n * Accessible label for the menu panel. Reflected as `label-menu`.\n * @attr label-menu\n */\n @property({ type: String, reflect: true, attribute: 'label-menu' })\n labelMenu = 'Actions';\n\n /**\n * Tracks whether the overflow menu panel is currently open and visible.\n * @internal\n */\n @state() private _open = false;\n\n /**\n * Unique ID for the floating panel element, used to wire aria-controls on the trigger button.\n * @internal\n */\n private readonly _panelId = `${_nextOverflowMenuId()}-panel`;\n\n /** @internal */\n @query('[part~=\"button\"]') private _buttonEl!: HTMLButtonElement | null;\n\n /** @internal */\n @query('[part~=\"panel\"]') private _panelEl!: HTMLElement | null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('click', this._handleDocumentClick, true);\n this.addEventListener('keydown', this._handleKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this._handleDocumentClick, true);\n this.removeEventListener('keydown', this._handleKeydown);\n }\n\n // ─── Open / Close ───\n\n /** @internal */\n private async _show(): Promise<void> {\n if (this._open || this.disabled) return;\n this._open = true;\n await this.updateComplete;\n await this._updatePosition();\n this._focusFirstItem();\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _hide(): void {\n if (!this._open) return;\n this._open = false;\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _toggle(): void {\n if (this._open) {\n this._hide();\n } else {\n void this._show();\n }\n }\n\n // ─── Positioning (Floating UI) ───\n\n /** @internal */\n private async _updatePosition(): Promise<void> {\n const trigger = this._buttonEl as HTMLElement | null;\n const panel = this._panelEl;\n if (!trigger || !panel) return;\n\n const { computePosition, flip, shift, offset } = await import('@floating-ui/dom');\n const { x, y } = await computePosition(trigger, panel, {\n placement: this.placement,\n strategy: 'fixed',\n middleware: [offset(4), flip(), shift({ padding: 8 })],\n });\n\n Object.assign(panel.style, {\n left: `${x}px`,\n top: `${y}px`,\n });\n }\n\n // ─── Focus management ───\n\n /** @internal */\n private _focusFirstItem(): void {\n const items = this._getMenuItems();\n items[0]?.focus();\n }\n\n /** @internal */\n private _getMenuItems(): HTMLElement[] {\n const slot = this.shadowRoot?.querySelector('slot') as HTMLSlotElement | null;\n return (\n (slot\n ?.assignedElements({ flatten: true })\n .filter(\n (el) =>\n el instanceof HTMLElement &&\n !el.hasAttribute('disabled') &&\n !(el as HTMLButtonElement).disabled &&\n (el.getAttribute('role') === 'menuitem' ||\n el.getAttribute('role') === 'menuitemcheckbox' ||\n el.getAttribute('role') === 'menuitemradio' ||\n el.tagName.toLowerCase().startsWith('hx-')),\n ) as HTMLElement[]) ?? []\n );\n }\n\n // ─── Event Handlers (arrow function class fields — stable reference, no bind needed) ───\n\n /** @internal */\n private readonly _handleTriggerClick = (e: MouseEvent): void => {\n e.stopPropagation();\n this._toggle();\n };\n\n /** @internal */\n private readonly _handleDocumentClick = (e: MouseEvent): void => {\n if (!this._open) return;\n const path = e.composedPath();\n if (!path.includes(this)) {\n this._hide();\n }\n };\n\n /** @internal */\n private readonly _handleKeydown = (e: KeyboardEvent): void => {\n if (!this._open) return;\n if (e.key === 'Escape') {\n e.stopPropagation();\n this._hide();\n this._buttonEl?.focus();\n return;\n }\n if (e.key === 'Tab') {\n this._hide();\n return;\n }\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n e.stopPropagation();\n const items = this._getMenuItems();\n if (items.length === 0) return;\n const focused = items.indexOf(document.activeElement as HTMLElement);\n let next: number;\n if (e.key === 'ArrowDown') {\n next = focused < 0 || focused >= items.length - 1 ? 0 : focused + 1;\n } else if (e.key === 'ArrowUp') {\n next = focused <= 0 ? items.length - 1 : focused - 1;\n } else if (e.key === 'Home') {\n next = 0;\n } else {\n next = items.length - 1;\n }\n items[next]?.focus();\n }\n };\n\n /** @internal */\n private readonly _handleSlotClick = (e: Event): void => {\n const target = e.target as HTMLElement;\n const menuItem = target.closest(\n '[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]',\n ) as HTMLElement | null;\n if (!menuItem) return;\n if (menuItem.hasAttribute('disabled') || (menuItem as HTMLButtonElement).disabled) return;\n const value = menuItem.getAttribute('data-value') ?? menuItem.textContent?.trim() ?? '';\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { value },\n }),\n );\n this._hide();\n };\n\n // ─── SVG Icons ───\n\n /** @internal */\n private _renderIcon() {\n if (this.icon === 'horizontal') {\n return html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <circle cx=\"5\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"19\" cy=\"12\" r=\"2\" />\n </svg>\n `;\n }\n return html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"19\" r=\"2\" />\n </svg>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const btnClasses = {\n trigger: true,\n [`trigger--${this.size}`]: true,\n 'trigger--open': this._open,\n };\n\n return html`\n <button\n part=\"button trigger\"\n class=${classMap(btnClasses)}\n type=\"button\"\n aria-label=${this.label}\n aria-haspopup=\"menu\"\n aria-expanded=${String(this._open)}\n aria-controls=${this._open ? this._panelId : nothing}\n ?disabled=${this.disabled}\n @click=${this._handleTriggerClick}\n >\n ${this._renderIcon()}\n </button>\n ${this._open\n ? html`\n <div\n id=${this._panelId}\n part=\"panel menu\"\n role=\"menu\"\n aria-label=${this.labelMenu}\n class=\"panel\"\n @click=${this._handleSlotClick}\n >\n <slot></slot>\n </div>\n `\n : nothing}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-overflow-menu': HelixOverflowMenu;\n }\n}\n"],"names":["helixOverflowMenuStyles","css","_nextOverflowMenuId","createIdCounter","HelixOverflowMenu","HelixElement","_a","items","focused","next","_b","menuItem","value","trigger","panel","computePosition","flip","shift","offset","x","y","slot","el","html","btnClasses","classMap","nothing","__decorateClass","property","state","query","customElement"],"mappings":"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"}
|