@helixui/library 3.3.1 → 3.4.0-next.121
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 +340 -71
- package/dist/components/hx-accordion/hx-accordion-item.d.ts +35 -0
- package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
- package/dist/components/hx-alert/hx-alert.d.ts +11 -0
- package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
- package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
- package/dist/components/hx-alert/index.js +1 -1
- package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
- package/dist/components/hx-badge/index.js +1 -1
- package/dist/components/hx-banner/hx-banner.d.ts +9 -1
- package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
- package/dist/components/hx-banner/index.js +1 -1
- package/dist/components/hx-button/hx-button.d.ts +11 -1
- 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 +13 -0
- package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
- package/dist/components/hx-button-group/index.js +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.d.ts +153 -1
- package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +151 -2
- 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-color-picker/hx-color-picker.d.ts +163 -1
- package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-combobox/hx-combobox.d.ts +311 -2
- 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-data-table/hx-data-table.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 +182 -56
- package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
- package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/hx-dialog.d.ts +240 -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-drawer/hx-drawer.d.ts +201 -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 +168 -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 +109 -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-icon-button/hx-icon-button.d.ts +16 -3
- package/dist/components/hx-icon-button/hx-icon-button.d.ts.map +1 -1
- package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
- package/dist/components/hx-icon-button/index.js +1 -1
- package/dist/components/hx-link/hx-link.d.ts +10 -1
- 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-item.d.ts +27 -1
- package/dist/components/hx-list/hx-list-item.d.ts.map +1 -1
- package/dist/components/hx-list/hx-list.d.ts +28 -0
- package/dist/components/hx-list/hx-list.d.ts.map +1 -1
- package/dist/components/hx-list/index.js +1 -1
- package/dist/components/hx-menu/hx-menu-divider.d.ts +10 -0
- package/dist/components/hx-menu/hx-menu-divider.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu-item.d.ts +99 -2
- package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu.d.ts +117 -2
- 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 +39 -0
- package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
- package/dist/components/hx-meter/hx-meter.styles.d.ts.map +1 -1
- package/dist/components/hx-meter/index.js +1 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +132 -1
- 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-phi-field/hx-phi-field.d.ts +0 -1
- package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
- package/dist/components/hx-popover/hx-popover.d.ts +91 -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-progress-bar/hx-progress-bar.d.ts +33 -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-radio-group/hx-radio-group.d.ts +152 -1
- package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
- package/dist/components/hx-radio-group/hx-radio.d.ts +14 -0
- package/dist/components/hx-radio-group/hx-radio.d.ts.map +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-select/hx-select.d.ts +304 -2
- 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/index.js +1 -1
- package/dist/components/hx-spinner/hx-spinner.d.ts +14 -0
- package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
- package/dist/components/hx-spinner/index.js +1 -1
- package/dist/components/hx-split-button/hx-split-button.d.ts +94 -7
- 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-stat/hx-stat.d.ts +28 -0
- package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
- package/dist/components/hx-stat/index.js +1 -1
- package/dist/components/hx-switch/hx-switch.d.ts +78 -1
- package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
- package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
- package/dist/components/hx-switch/index.js +1 -1
- package/dist/components/hx-table/hx-td.d.ts +30 -3
- package/dist/components/hx-table/hx-td.d.ts.map +1 -1
- package/dist/components/hx-table/hx-th.d.ts +39 -3
- package/dist/components/hx-table/hx-th.d.ts.map +1 -1
- package/dist/components/hx-table/hx-tr.d.ts +26 -0
- package/dist/components/hx-table/hx-tr.d.ts.map +1 -1
- package/dist/components/hx-table/index.js +1 -1
- package/dist/components/hx-tabs/hx-tab-panel.d.ts +34 -0
- package/dist/components/hx-tabs/hx-tab-panel.d.ts.map +1 -1
- package/dist/components/hx-tabs/hx-tab.d.ts +45 -2
- package/dist/components/hx-tabs/hx-tab.d.ts.map +1 -1
- package/dist/components/hx-tabs/hx-tab.styles.d.ts.map +1 -1
- package/dist/components/hx-tabs/hx-tabs.d.ts +32 -2
- package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
- package/dist/components/hx-tabs/index.js +1 -1
- package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
- package/dist/components/hx-tag/index.js +1 -1
- package/dist/components/hx-theme/hx-theme.d.ts +10 -5
- package/dist/components/hx-theme/hx-theme.d.ts.map +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.d.ts +210 -2
- package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toast/hx-toast-stack.d.ts +14 -0
- package/dist/components/hx-toast/hx-toast-stack.d.ts.map +1 -1
- package/dist/components/hx-toast/hx-toast.d.ts +22 -3
- package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
- package/dist/components/hx-toast/index.js +1 -1
- package/dist/components/hx-toast/toast-factory.d.ts.map +1 -1
- package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +110 -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 +52 -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-tree-view/hx-tree-item.d.ts +117 -12
- package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-view.d.ts +87 -7
- package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/css/helix-all.css +221 -1
- package/dist/css/helix-core.css +81 -0
- package/dist/css/helix-feedback.css +14 -0
- package/dist/css/helix-forms.css +109 -1
- package/dist/css/helix-overlay.css +17 -0
- package/dist/css/hx-alert.css +9 -0
- package/dist/css/hx-badge.css +28 -0
- package/dist/css/hx-checkbox.css +18 -0
- package/dist/css/hx-color-picker.css +25 -0
- package/dist/css/hx-date-picker.css +2 -1
- package/dist/css/hx-drawer.css +17 -0
- package/dist/css/hx-icon-button.css +30 -0
- package/dist/css/hx-meter.css +5 -0
- package/dist/css/hx-select.css +19 -0
- package/dist/css/hx-switch.css +17 -0
- package/dist/css/hx-tag.css +23 -0
- package/dist/css/hx-time-picker.css +11 -0
- package/dist/css/hx-toggle-button.css +17 -0
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +4 -1
- package/dist/index.js +38 -38
- package/dist/shared/aria-flatten-DY6v2vah.js +22 -0
- package/dist/shared/aria-flatten-DY6v2vah.js.map +1 -0
- package/dist/shared/aria-idref-CxvyzfQS.js +126 -0
- package/dist/shared/aria-idref-CxvyzfQS.js.map +1 -0
- package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -1
- package/dist/shared/{hx-alert-CLn7CstP.js → hx-alert-Bto8-TIi.js} +55 -37
- package/dist/shared/hx-alert-Bto8-TIi.js.map +1 -0
- package/dist/shared/{hx-badge-CQXgOXJM.js → hx-badge-JlFtAdxS.js} +37 -9
- package/dist/shared/hx-badge-JlFtAdxS.js.map +1 -0
- package/dist/shared/{hx-banner-D3DzpfcP.js → hx-banner-fpRnciIO.js} +13 -5
- package/dist/shared/hx-banner-fpRnciIO.js.map +1 -0
- package/dist/shared/{hx-button-DPY6SPVT.js → hx-button-BOwAEcF1.js} +108 -85
- package/dist/shared/{hx-button-DPY6SPVT.js.map → hx-button-BOwAEcF1.js.map} +1 -1
- package/dist/shared/{hx-button-group-BI-QBqmO.js → hx-button-group-DcHP5MBv.js} +15 -16
- package/dist/shared/{hx-button-group-BI-QBqmO.js.map → hx-button-group-DcHP5MBv.js.map} +1 -1
- package/dist/shared/hx-checkbox-C48KYKFq.js +696 -0
- package/dist/shared/hx-checkbox-C48KYKFq.js.map +1 -0
- package/dist/shared/hx-checkbox-group-BJIAX3zU.js +496 -0
- package/dist/shared/hx-checkbox-group-BJIAX3zU.js.map +1 -0
- package/dist/shared/hx-color-picker-Dk4cBwYQ.js +1221 -0
- package/dist/shared/hx-color-picker-Dk4cBwYQ.js.map +1 -0
- package/dist/shared/hx-combobox-BTLO9qiK.js +1359 -0
- package/dist/shared/hx-combobox-BTLO9qiK.js.map +1 -0
- package/dist/shared/{hx-data-table-CLqVqdxr.js → hx-data-table-Ct3gQ6ya.js} +3 -2
- package/dist/shared/{hx-data-table-CLqVqdxr.js.map → hx-data-table-Ct3gQ6ya.js.map} +1 -1
- package/dist/shared/{hx-date-picker-2iRG1p74.js → hx-date-picker-CiR7FVnR.js} +542 -206
- package/dist/shared/hx-date-picker-CiR7FVnR.js.map +1 -0
- package/dist/shared/hx-dialog-AOZpHSuF.js +717 -0
- package/dist/shared/hx-dialog-AOZpHSuF.js.map +1 -0
- package/dist/shared/{hx-drawer-Y1Ui2IWJ.js → hx-drawer-DH6CdAN1.js} +300 -98
- package/dist/shared/hx-drawer-DH6CdAN1.js.map +1 -0
- package/dist/shared/hx-dropdown-DiLd40Lm.js +401 -0
- package/dist/shared/hx-dropdown-DiLd40Lm.js.map +1 -0
- package/dist/shared/{hx-field-B3Qo8OLS.js → hx-field-zw0U1KVi.js} +99 -38
- package/dist/shared/hx-field-zw0U1KVi.js.map +1 -0
- package/dist/shared/{hx-icon-button-CGNdQSFM.js → hx-icon-button-a6OpeQz5.js} +149 -68
- package/dist/shared/hx-icon-button-a6OpeQz5.js.map +1 -0
- package/dist/shared/{hx-link-C-O6vq0Q.js → hx-link-CMnZRUtQ.js} +55 -43
- package/dist/shared/hx-link-CMnZRUtQ.js.map +1 -0
- package/dist/shared/{hx-list-MyEhh8c7.js → hx-list-De66EtAP.js} +163 -107
- package/dist/shared/hx-list-De66EtAP.js.map +1 -0
- package/dist/shared/hx-menu-divider-BjiRIWKq.js +797 -0
- package/dist/shared/hx-menu-divider-BjiRIWKq.js.map +1 -0
- package/dist/shared/{hx-meter-BPscsw5t.js → hx-meter-BJdh6nrF.js} +105 -64
- package/dist/shared/hx-meter-BJdh6nrF.js.map +1 -0
- package/dist/shared/{hx-nav-item-xqRPOCWX.js → hx-nav-item-CODtUlew.js} +13 -9
- package/dist/shared/{hx-nav-item-xqRPOCWX.js.map → hx-nav-item-CODtUlew.js.map} +1 -1
- package/dist/shared/hx-overflow-menu-BQ4fiMYu.js +492 -0
- package/dist/shared/hx-overflow-menu-BQ4fiMYu.js.map +1 -0
- package/dist/shared/hx-phi-field-C19oxlrr.js.map +1 -1
- package/dist/shared/{hx-popover-B-FP3-wW.js → hx-popover-B9W8-tC0.js} +123 -66
- package/dist/shared/hx-popover-B9W8-tC0.js.map +1 -0
- package/dist/shared/hx-progress-bar-C8nDMdYa.js +290 -0
- package/dist/shared/hx-progress-bar-C8nDMdYa.js.map +1 -0
- package/dist/shared/hx-radio-Z1lV1zTO.js +822 -0
- package/dist/shared/hx-radio-Z1lV1zTO.js.map +1 -0
- package/dist/shared/hx-select-D18CnJ0e.js +1089 -0
- package/dist/shared/hx-select-D18CnJ0e.js.map +1 -0
- package/dist/shared/{hx-spinner-DL5AYr16.js → hx-spinner-BB0h2hKZ.js} +62 -34
- package/dist/shared/hx-spinner-BB0h2hKZ.js.map +1 -0
- package/dist/shared/{hx-split-button-Djnc5Aeg.js → hx-split-button-BoABoEm5.js} +153 -82
- package/dist/shared/hx-split-button-BoABoEm5.js.map +1 -0
- package/dist/shared/{hx-stat-WOcNV1Ry.js → hx-stat-Dtf9lz-O.js} +77 -47
- package/dist/shared/hx-stat-Dtf9lz-O.js.map +1 -0
- package/dist/shared/hx-switch-B6kr-EwE.js +540 -0
- package/dist/shared/hx-switch-B6kr-EwE.js.map +1 -0
- package/dist/shared/{hx-tab-panel-DspCrKqo.js → hx-tab-panel-BQtBXKLD.js} +255 -131
- package/dist/shared/hx-tab-panel-BQtBXKLD.js.map +1 -0
- package/dist/shared/{hx-tag-CNSmdyaK.js → hx-tag-C5aCUpVi.js} +63 -40
- package/dist/shared/hx-tag-C5aCUpVi.js.map +1 -0
- package/dist/shared/{hx-td-DnnEMIuA.js → hx-td-BGkFOJEK.js} +267 -123
- package/dist/shared/hx-td-BGkFOJEK.js.map +1 -0
- package/dist/shared/hx-theme-BsefFWTO.js.map +1 -1
- package/dist/shared/hx-time-picker-iwCD7rzW.js +1038 -0
- package/dist/shared/hx-time-picker-iwCD7rzW.js.map +1 -0
- package/dist/shared/{hx-toggle-button-iLiYrMbD.js → hx-toggle-button-BQ81EDkl.js} +226 -65
- package/dist/shared/hx-toggle-button-BQ81EDkl.js.map +1 -0
- package/dist/shared/{hx-tooltip-nYOv9OLu.js → hx-tooltip-DVqtKPCD.js} +68 -46
- package/dist/shared/hx-tooltip-DVqtKPCD.js.map +1 -0
- package/dist/shared/hx-tree-item-CHrUhuZL.js +925 -0
- package/dist/shared/hx-tree-item-CHrUhuZL.js.map +1 -0
- package/dist/shared/menu-roving-DmMnzJhn.js +14 -0
- package/dist/shared/menu-roving-DmMnzJhn.js.map +1 -0
- package/dist/shared/menu-tree-BNM0SYYq.js +42 -0
- package/dist/shared/menu-tree-BNM0SYYq.js.map +1 -0
- package/dist/shared/{toast-factory-YSznocIV.js → toast-factory-CL2BzdSB.js} +128 -77
- package/dist/shared/toast-factory-CL2BzdSB.js.map +1 -0
- package/dist/utils/aria-flatten.d.ts +56 -0
- package/dist/utils/aria-flatten.d.ts.map +1 -0
- package/dist/utils/aria-idref.d.ts +127 -0
- package/dist/utils/aria-idref.d.ts.map +1 -0
- package/dist/utils/menu-label.d.ts +18 -0
- package/dist/utils/menu-label.d.ts.map +1 -0
- package/dist/utils/menu-roving.d.ts +28 -0
- package/dist/utils/menu-roving.d.ts.map +1 -0
- package/dist/utils/menu-tree.d.ts +41 -0
- package/dist/utils/menu-tree.d.ts.map +1 -0
- package/dist/utils/tree-walk.d.ts +53 -0
- package/dist/utils/tree-walk.d.ts.map +1 -0
- package/figma-inventory.json +132 -20
- package/package.json +2 -2
- package/dist/shared/hx-alert-CLn7CstP.js.map +0 -1
- package/dist/shared/hx-badge-CQXgOXJM.js.map +0 -1
- package/dist/shared/hx-banner-D3DzpfcP.js.map +0 -1
- package/dist/shared/hx-checkbox-D7xma9YH.js +0 -524
- package/dist/shared/hx-checkbox-D7xma9YH.js.map +0 -1
- package/dist/shared/hx-checkbox-group-C9n315Ju.js +0 -323
- package/dist/shared/hx-checkbox-group-C9n315Ju.js.map +0 -1
- package/dist/shared/hx-color-picker-uRc865FJ.js +0 -882
- package/dist/shared/hx-color-picker-uRc865FJ.js.map +0 -1
- package/dist/shared/hx-combobox-DDzqNKEW.js +0 -924
- package/dist/shared/hx-combobox-DDzqNKEW.js.map +0 -1
- package/dist/shared/hx-date-picker-2iRG1p74.js.map +0 -1
- package/dist/shared/hx-dialog-DRN_1-Y-.js +0 -514
- package/dist/shared/hx-dialog-DRN_1-Y-.js.map +0 -1
- package/dist/shared/hx-drawer-Y1Ui2IWJ.js.map +0 -1
- package/dist/shared/hx-dropdown-LyaRc8Rf.js +0 -263
- package/dist/shared/hx-dropdown-LyaRc8Rf.js.map +0 -1
- package/dist/shared/hx-field-B3Qo8OLS.js.map +0 -1
- package/dist/shared/hx-icon-button-CGNdQSFM.js.map +0 -1
- package/dist/shared/hx-link-C-O6vq0Q.js.map +0 -1
- package/dist/shared/hx-list-MyEhh8c7.js.map +0 -1
- package/dist/shared/hx-menu-divider-C2omnPtj.js +0 -558
- package/dist/shared/hx-menu-divider-C2omnPtj.js.map +0 -1
- package/dist/shared/hx-meter-BPscsw5t.js.map +0 -1
- package/dist/shared/hx-overflow-menu-DCLsdIBy.js +0 -374
- package/dist/shared/hx-overflow-menu-DCLsdIBy.js.map +0 -1
- package/dist/shared/hx-popover-B-FP3-wW.js.map +0 -1
- package/dist/shared/hx-progress-bar-Bn3JEPUf.js +0 -258
- package/dist/shared/hx-progress-bar-Bn3JEPUf.js.map +0 -1
- package/dist/shared/hx-radio-CJvNU2yP.js +0 -621
- package/dist/shared/hx-radio-CJvNU2yP.js.map +0 -1
- package/dist/shared/hx-select-C8fEHQhC.js +0 -807
- package/dist/shared/hx-select-C8fEHQhC.js.map +0 -1
- package/dist/shared/hx-spinner-DL5AYr16.js.map +0 -1
- package/dist/shared/hx-split-button-Djnc5Aeg.js.map +0 -1
- package/dist/shared/hx-stat-WOcNV1Ry.js.map +0 -1
- package/dist/shared/hx-switch-BrZFaRue.js +0 -420
- package/dist/shared/hx-switch-BrZFaRue.js.map +0 -1
- package/dist/shared/hx-tab-panel-DspCrKqo.js.map +0 -1
- package/dist/shared/hx-tag-CNSmdyaK.js.map +0 -1
- package/dist/shared/hx-td-DnnEMIuA.js.map +0 -1
- package/dist/shared/hx-time-picker-BoEIZwzv.js +0 -688
- package/dist/shared/hx-time-picker-BoEIZwzv.js.map +0 -1
- package/dist/shared/hx-toggle-button-iLiYrMbD.js.map +0 -1
- package/dist/shared/hx-tooltip-nYOv9OLu.js.map +0 -1
- package/dist/shared/hx-tree-item-C2CiWuDE.js +0 -703
- package/dist/shared/hx-tree-item-C2CiWuDE.js.map +0 -1
- package/dist/shared/toast-factory-YSznocIV.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { property as
|
|
3
|
-
import { classMap as
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { css as w, html as i, nothing as m } from "lit";
|
|
2
|
+
import { property as u, query as S, state as I, customElement as y } from "lit/decorators.js";
|
|
3
|
+
import { classMap as C } from "lit/directives/class-map.js";
|
|
4
|
+
import { d as E } from "./dev-warn-YlwPHjtX.js";
|
|
5
|
+
import { H as A } from "./helix-element-BNEYeiys.js";
|
|
6
|
+
const L = w`
|
|
6
7
|
/* ─── hx-toast host ─── */
|
|
7
8
|
|
|
8
9
|
:host {
|
|
@@ -195,7 +196,7 @@ const w = m`
|
|
|
195
196
|
border: 1px solid ButtonText;
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
|
-
`,
|
|
199
|
+
`, M = w`
|
|
199
200
|
:host {
|
|
200
201
|
display: block;
|
|
201
202
|
position: fixed;
|
|
@@ -269,12 +270,19 @@ const w = m`
|
|
|
269
270
|
--hx-toast-enter-translate: calc(var(--hx-space-2, 0.5rem) * -1);
|
|
270
271
|
}
|
|
271
272
|
`;
|
|
272
|
-
var
|
|
273
|
-
for (var e =
|
|
274
|
-
(
|
|
275
|
-
return
|
|
273
|
+
var $ = Object.defineProperty, H = Object.getOwnPropertyDescriptor, c = (t, s, r, o) => {
|
|
274
|
+
for (var e = o > 1 ? void 0 : o ? H(s, r) : s, l = t.length - 1, n; l >= 0; l--)
|
|
275
|
+
(n = t[l]) && (e = (o ? n(s, r, e) : n(e)) || e);
|
|
276
|
+
return o && e && $(s, r, e), e;
|
|
276
277
|
};
|
|
277
|
-
|
|
278
|
+
const z = {
|
|
279
|
+
default: 3e3,
|
|
280
|
+
info: 3e3,
|
|
281
|
+
success: 3e3,
|
|
282
|
+
warning: 4e3,
|
|
283
|
+
danger: 6e3
|
|
284
|
+
};
|
|
285
|
+
let a = class extends A {
|
|
278
286
|
constructor() {
|
|
279
287
|
super(...arguments), this.variant = "default", this.duration = 5e3, this.closable = !1, this.open = !1, this.labelClose = "Dismiss notification", this._hasActionContent = !1, this._timer = null, this._timerStartedAt = null, this._timerRemaining = null;
|
|
280
288
|
}
|
|
@@ -284,12 +292,35 @@ let a = class extends g {
|
|
|
284
292
|
return typeof window > "u" ? !1 : window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
285
293
|
}
|
|
286
294
|
// ─── Lifecycle ───
|
|
295
|
+
connectedCallback() {
|
|
296
|
+
super.connectedCallback(), this._internals.role = this._role, this._internals.ariaAtomic = "true", this.setAttribute("role", this._role);
|
|
297
|
+
}
|
|
287
298
|
updated(t) {
|
|
288
|
-
super.updated(t), t.has("open") && (this.open ? (this.removeAttribute("aria-hidden"), this._emitShow(), this.duration > 0 && !this._reducedMotion && !this._hasActionContent && this._startTimer()) : (this.setAttribute("aria-hidden", "true"), this._clearTimer(), this._emitHide()));
|
|
299
|
+
super.updated(t), t.has("variant") && (this._internals.role = this._role, this.setAttribute("role", this._role)), (t.has("open") || t.has("duration")) && this._auditWcag223(), t.has("open") && (this.open ? (this.removeAttribute("aria-hidden"), this._emitShow(), this.duration > 0 && !this._reducedMotion && !this._hasActionContent && this._startTimer()) : (this.setAttribute("aria-hidden", "true"), this._clearTimer(), this._emitHide()));
|
|
289
300
|
}
|
|
290
301
|
disconnectedCallback() {
|
|
291
302
|
super.disconnectedCallback(), this._clearTimer();
|
|
292
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* (group-6 §5.3) WCAG 2.2.3 (Level AA — No Time Limits) audit. When
|
|
306
|
+
* `duration` is shorter than the role-implied minimum-display-time for the
|
|
307
|
+
* current variant, surface a developer warning recommending a longer
|
|
308
|
+
* duration or `duration=0` for persistent toasts. Danger toasts in
|
|
309
|
+
* particular are safety-critical and routinely need more than 5 seconds
|
|
310
|
+
* for screen readers to finish reading.
|
|
311
|
+
*
|
|
312
|
+
* Fires only in DEV builds (Vite tree-shakes the call in production).
|
|
313
|
+
*
|
|
314
|
+
* @internal
|
|
315
|
+
*/
|
|
316
|
+
_auditWcag223() {
|
|
317
|
+
if (this.duration <= 0) return;
|
|
318
|
+
const t = z[this.variant] ?? 0;
|
|
319
|
+
this.duration < t && E(
|
|
320
|
+
"hx-toast",
|
|
321
|
+
`duration=${this.duration}ms is shorter than the WCAG 2.2.3 minimum (${t}ms) for variant="${this.variant}". Increase duration or set duration=0 for persistent toasts (recommended for variant="danger").`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
293
324
|
// ─── Public API ───
|
|
294
325
|
/** Show the toast. */
|
|
295
326
|
show() {
|
|
@@ -303,10 +334,10 @@ let a = class extends g {
|
|
|
303
334
|
/** @internal */
|
|
304
335
|
_startTimer(t) {
|
|
305
336
|
this._clearTimerHandle();
|
|
306
|
-
const
|
|
307
|
-
this._timerStartedAt = Date.now(), this._timerRemaining =
|
|
337
|
+
const s = t ?? this.duration;
|
|
338
|
+
this._timerStartedAt = Date.now(), this._timerRemaining = s, this._timer = setTimeout(() => {
|
|
308
339
|
this.open = !1;
|
|
309
|
-
},
|
|
340
|
+
}, s);
|
|
310
341
|
}
|
|
311
342
|
/** @internal */
|
|
312
343
|
_pauseTimer() {
|
|
@@ -331,10 +362,10 @@ let a = class extends g {
|
|
|
331
362
|
_emitHide() {
|
|
332
363
|
this.dispatchEvent(new CustomEvent("hx-hide", { bubbles: !0, composed: !0 }));
|
|
333
364
|
let t = !1;
|
|
334
|
-
const
|
|
365
|
+
const s = () => {
|
|
335
366
|
t || (t = !0, this.dispatchEvent(new CustomEvent("hx-after-hide", { bubbles: !0, composed: !0 })));
|
|
336
367
|
}, r = this._toastEl;
|
|
337
|
-
r && r.addEventListener("transitionend",
|
|
368
|
+
r && r.addEventListener("transitionend", s, { once: !0 }), setTimeout(s, 300);
|
|
338
369
|
}
|
|
339
370
|
// ─── Event Handlers ───
|
|
340
371
|
/** @internal */
|
|
@@ -359,24 +390,27 @@ let a = class extends g {
|
|
|
359
390
|
}
|
|
360
391
|
/** @internal */
|
|
361
392
|
_handleActionSlotChange(t) {
|
|
362
|
-
const
|
|
363
|
-
this._hasActionContent =
|
|
393
|
+
const s = t.target;
|
|
394
|
+
this._hasActionContent = s.assignedNodes({ flatten: !0 }).length > 0, this._hasActionContent && this.open && this._pauseTimer();
|
|
364
395
|
}
|
|
365
396
|
// ─── ARIA Helpers ───
|
|
366
|
-
/**
|
|
397
|
+
/**
|
|
398
|
+
* @internal
|
|
399
|
+
* Variant→role mapping (harmonized with hx-alert/hx-banner per group-6):
|
|
400
|
+
* only `danger` is assertive (role=alert); all other variants are polite
|
|
401
|
+
* (role=status). role implies aria-live, so we do NOT also expose an
|
|
402
|
+
* `_ariaLive` getter — that path was removed when the inner div stopped
|
|
403
|
+
* carrying explicit aria-live (§5.1 double-announce mitigation).
|
|
404
|
+
*/
|
|
367
405
|
get _role() {
|
|
368
406
|
return this.variant === "danger" ? "alert" : "status";
|
|
369
407
|
}
|
|
370
|
-
/** @internal */
|
|
371
|
-
get _ariaLive() {
|
|
372
|
-
return this.variant === "danger" ? "assertive" : "polite";
|
|
373
|
-
}
|
|
374
408
|
// ─── WCAG 1.4.1: Default Icons ───
|
|
375
409
|
// Each semantic variant renders a default icon when no icon is slotted,
|
|
376
410
|
// ensuring the severity is not conveyed by color alone.
|
|
377
411
|
/** @internal */
|
|
378
412
|
_renderSuccessIcon() {
|
|
379
|
-
return
|
|
413
|
+
return i`<svg viewBox="0 0 20 20" aria-hidden="true" width="16" height="16">
|
|
380
414
|
<path
|
|
381
415
|
fill="currentColor"
|
|
382
416
|
d="M10 2a8 8 0 100 16 8 8 0 000-16zm3.03 6.28a.75.75 0 00-1.06-1.06L9 10.19 7.78 8.97a.75.75 0 00-1.06 1.06l1.75 1.75a.75.75 0 001.06 0l3.5-3.5z"
|
|
@@ -385,7 +419,7 @@ let a = class extends g {
|
|
|
385
419
|
}
|
|
386
420
|
/** @internal */
|
|
387
421
|
_renderWarningIcon() {
|
|
388
|
-
return
|
|
422
|
+
return i`<svg viewBox="0 0 20 20" aria-hidden="true" width="16" height="16">
|
|
389
423
|
<path
|
|
390
424
|
fill="currentColor"
|
|
391
425
|
d="M8.49 2.92a1.75 1.75 0 013.02 0l6.25 10.83A1.75 1.75 0 0116.25 16H3.75a1.75 1.75 0 01-1.51-2.25L8.49 2.92zM10 7a.75.75 0 01.75.75v3a.75.75 0 01-1.5 0v-3A.75.75 0 0110 7zm0 7.5a.75.75 0 100-1.5.75.75 0 000 1.5z"
|
|
@@ -394,7 +428,7 @@ let a = class extends g {
|
|
|
394
428
|
}
|
|
395
429
|
/** @internal */
|
|
396
430
|
_renderDangerIcon() {
|
|
397
|
-
return
|
|
431
|
+
return i`<svg viewBox="0 0 20 20" aria-hidden="true" width="16" height="16">
|
|
398
432
|
<path
|
|
399
433
|
fill="currentColor"
|
|
400
434
|
d="M10 2a8 8 0 100 16 8 8 0 000-16zm-1.72 5.22a.75.75 0 011.06 0L10 7.94l.66-.72a.75.75 0 111.06 1.06L11.06 9l.66.72a.75.75 0 11-1.06 1.06L10 10.06l-.66.72a.75.75 0 01-1.06-1.06L8.94 9l-.66-.72a.75.75 0 010-1.06z"
|
|
@@ -403,7 +437,7 @@ let a = class extends g {
|
|
|
403
437
|
}
|
|
404
438
|
/** @internal */
|
|
405
439
|
_renderInfoIcon() {
|
|
406
|
-
return
|
|
440
|
+
return i`<svg viewBox="0 0 20 20" aria-hidden="true" width="16" height="16">
|
|
407
441
|
<path
|
|
408
442
|
fill="currentColor"
|
|
409
443
|
d="M10 2a8 8 0 100 16 8 8 0 000-16zm.75 4.75a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM9.25 9a.75.75 0 011.5 0v4a.75.75 0 01-1.5 0V9z"
|
|
@@ -422,7 +456,7 @@ let a = class extends g {
|
|
|
422
456
|
case "info":
|
|
423
457
|
return this._renderInfoIcon();
|
|
424
458
|
default:
|
|
425
|
-
return
|
|
459
|
+
return m;
|
|
426
460
|
}
|
|
427
461
|
}
|
|
428
462
|
/** @internal */
|
|
@@ -430,25 +464,30 @@ let a = class extends g {
|
|
|
430
464
|
return a._SEVERITY_LABELS[this.variant] ?? "";
|
|
431
465
|
}
|
|
432
466
|
// ─── Render ───
|
|
467
|
+
//
|
|
468
|
+
// (group-6) Host-canonical live region: role + aria-atomic live on the
|
|
469
|
+
// host via ElementInternals (set in connectedCallback). The inner base
|
|
470
|
+
// div is a presentation-only wrapper — it does NOT carry role, aria-live,
|
|
471
|
+
// or aria-atomic. role implies aria-live per ARIA spec, so the host has
|
|
472
|
+
// NO explicit aria-live attribute either (avoids §5.1 double-announce on
|
|
473
|
+
// older NVDA/JAWS that read both role and aria-live as separate live
|
|
474
|
+
// regions).
|
|
433
475
|
render() {
|
|
434
476
|
const t = this._severityLabel;
|
|
435
|
-
return
|
|
477
|
+
return i`
|
|
436
478
|
<div
|
|
437
479
|
part="base"
|
|
438
|
-
class=${
|
|
480
|
+
class=${C({
|
|
439
481
|
toast: !0,
|
|
440
482
|
[`toast--${this.variant}`]: !0
|
|
441
483
|
})}
|
|
442
|
-
role=${this._role}
|
|
443
|
-
aria-live=${this._ariaLive}
|
|
444
|
-
aria-atomic="true"
|
|
445
484
|
@mouseenter=${this._handleMouseEnter}
|
|
446
485
|
@mouseleave=${this._handleMouseLeave}
|
|
447
486
|
@focusin=${this._handleFocusIn}
|
|
448
487
|
@focusout=${this._handleFocusOut}
|
|
449
488
|
>
|
|
450
|
-
${this.open ?
|
|
451
|
-
${t ?
|
|
489
|
+
${this.open ? i`
|
|
490
|
+
${t ? i`<span class="toast__severity-label">${t}: </span>` : m}
|
|
452
491
|
<span part="icon" class="toast__icon">
|
|
453
492
|
<slot name="icon">${this._defaultIcon}</slot>
|
|
454
493
|
</span>
|
|
@@ -458,7 +497,7 @@ let a = class extends g {
|
|
|
458
497
|
<span part="action" class="toast__action">
|
|
459
498
|
<slot name="action" @slotchange=${this._handleActionSlotChange}></slot>
|
|
460
499
|
</span>
|
|
461
|
-
${this.closable ?
|
|
500
|
+
${this.closable ? i`
|
|
462
501
|
<button
|
|
463
502
|
part="close-button"
|
|
464
503
|
class="toast__close"
|
|
@@ -479,13 +518,13 @@ let a = class extends g {
|
|
|
479
518
|
<path d="M18 6L6 18M6 6l12 12" />
|
|
480
519
|
</svg>
|
|
481
520
|
</button>
|
|
482
|
-
` :
|
|
483
|
-
` :
|
|
521
|
+
` : m}
|
|
522
|
+
` : m}
|
|
484
523
|
</div>
|
|
485
524
|
`;
|
|
486
525
|
}
|
|
487
526
|
};
|
|
488
|
-
a.styles = [
|
|
527
|
+
a.styles = [L];
|
|
489
528
|
a._SEVERITY_LABELS = {
|
|
490
529
|
success: "Success",
|
|
491
530
|
warning: "Warning",
|
|
@@ -493,43 +532,43 @@ a._SEVERITY_LABELS = {
|
|
|
493
532
|
info: "Info"
|
|
494
533
|
};
|
|
495
534
|
c([
|
|
496
|
-
|
|
535
|
+
u({ type: String, reflect: !0 })
|
|
497
536
|
], a.prototype, "variant", 2);
|
|
498
537
|
c([
|
|
499
|
-
|
|
538
|
+
u({ type: Number })
|
|
500
539
|
], a.prototype, "duration", 2);
|
|
501
540
|
c([
|
|
502
|
-
|
|
541
|
+
u({ type: Boolean, reflect: !0 })
|
|
503
542
|
], a.prototype, "closable", 2);
|
|
504
543
|
c([
|
|
505
|
-
|
|
544
|
+
u({ type: Boolean, reflect: !0 })
|
|
506
545
|
], a.prototype, "open", 2);
|
|
507
546
|
c([
|
|
508
|
-
|
|
547
|
+
u({ attribute: "label-close" })
|
|
509
548
|
], a.prototype, "labelClose", 2);
|
|
510
549
|
c([
|
|
511
|
-
|
|
550
|
+
S(".toast")
|
|
512
551
|
], a.prototype, "_toastEl", 2);
|
|
513
552
|
c([
|
|
514
|
-
|
|
553
|
+
I()
|
|
515
554
|
], a.prototype, "_hasActionContent", 2);
|
|
516
555
|
a = c([
|
|
517
|
-
|
|
556
|
+
y("hx-toast")
|
|
518
557
|
], a);
|
|
519
|
-
var
|
|
520
|
-
for (var e =
|
|
521
|
-
(
|
|
522
|
-
return
|
|
558
|
+
var D = Object.defineProperty, B = Object.getOwnPropertyDescriptor, g = (t, s, r, o) => {
|
|
559
|
+
for (var e = o > 1 ? void 0 : o ? B(s, r) : s, l = t.length - 1, n; l >= 0; l--)
|
|
560
|
+
(n = t[l]) && (e = (o ? n(s, r, e) : n(e)) || e);
|
|
561
|
+
return o && e && D(s, r, e), e;
|
|
523
562
|
};
|
|
524
|
-
let
|
|
563
|
+
let p = class extends A {
|
|
525
564
|
constructor() {
|
|
526
565
|
super(...arguments), this.placement = "bottom-end", this.stackLimit = 3;
|
|
527
566
|
}
|
|
528
567
|
render() {
|
|
529
|
-
return
|
|
568
|
+
return i`
|
|
530
569
|
<div
|
|
531
570
|
part="base"
|
|
532
|
-
class=${
|
|
571
|
+
class=${C({
|
|
533
572
|
"toast-stack": !0,
|
|
534
573
|
[`toast-stack--${this.placement}`]: !0
|
|
535
574
|
})}
|
|
@@ -539,33 +578,45 @@ let d = class extends g {
|
|
|
539
578
|
`;
|
|
540
579
|
}
|
|
541
580
|
};
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
],
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
],
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
],
|
|
552
|
-
|
|
553
|
-
|
|
581
|
+
p.styles = [M];
|
|
582
|
+
g([
|
|
583
|
+
u({ type: String, reflect: !0 })
|
|
584
|
+
], p.prototype, "placement", 2);
|
|
585
|
+
g([
|
|
586
|
+
u({ type: Number, attribute: "stack-limit" })
|
|
587
|
+
], p.prototype, "stackLimit", 2);
|
|
588
|
+
p = g([
|
|
589
|
+
y("hx-toast-stack")
|
|
590
|
+
], p);
|
|
591
|
+
const b = 1500, v = /* @__PURE__ */ new WeakMap(), f = /* @__PURE__ */ new WeakSet();
|
|
592
|
+
function Y(t) {
|
|
554
593
|
if (typeof document > "u") throw new Error("toast() requires a browser environment");
|
|
555
|
-
const
|
|
556
|
-
let
|
|
557
|
-
if (
|
|
558
|
-
const
|
|
559
|
-
|
|
594
|
+
const s = t.placement ?? "bottom-end", r = `hx-toast-stack[placement="${s}"]`;
|
|
595
|
+
let o = document.querySelector(r);
|
|
596
|
+
if (o || (o = document.createElement("hx-toast-stack"), o.placement = s, document.body.appendChild(o)), o.stackLimit > 0) {
|
|
597
|
+
const n = [...o.querySelectorAll("hx-toast")].filter((h) => h.open).filter((h) => !f.has(h)), T = n.length + 1 - o.stackLimit;
|
|
598
|
+
for (let h = 0; h < T; h++) {
|
|
599
|
+
const d = n[h];
|
|
600
|
+
if (!d) break;
|
|
601
|
+
const _ = v.get(d), x = _ === void 0 ? Number.POSITIVE_INFINITY : Date.now() - _;
|
|
602
|
+
if (x >= b)
|
|
603
|
+
d.hide();
|
|
604
|
+
else {
|
|
605
|
+
const k = b - x;
|
|
606
|
+
f.add(d), setTimeout(() => {
|
|
607
|
+
f.delete(d), d.open && d.hide();
|
|
608
|
+
}, k);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
560
611
|
}
|
|
561
612
|
const e = document.createElement("hx-toast");
|
|
562
613
|
return e.variant = t.variant ?? "default", e.duration = t.duration ?? 3e3, e.closable = !0, e.textContent = t.message, e.addEventListener("hx-after-hide", () => {
|
|
563
|
-
e.remove();
|
|
564
|
-
}),
|
|
614
|
+
v.delete(e), f.delete(e), e.remove();
|
|
615
|
+
}), o.appendChild(e), e.show(), v.set(e, Date.now()), e;
|
|
565
616
|
}
|
|
566
617
|
export {
|
|
567
618
|
a as H,
|
|
568
|
-
|
|
569
|
-
|
|
619
|
+
p as a,
|
|
620
|
+
Y as t
|
|
570
621
|
};
|
|
571
|
-
//# sourceMappingURL=toast-factory-
|
|
622
|
+
//# sourceMappingURL=toast-factory-CL2BzdSB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-factory-CL2BzdSB.js","sources":["../../src/components/hx-toast/hx-toast.styles.ts","../../src/components/hx-toast/hx-toast.ts","../../src/components/hx-toast/hx-toast-stack.ts","../../src/components/hx-toast/toast-factory.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-toast styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-toast-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * neutral-0 = #FFFFFF, neutral-900 = #0D1825 (surface-inverse anchor),\n * primary-600 = #0F7078, success-600 = #0E8A4A, warning-500 = #C2711C,\n * error-600 = #C92A2A.\n */\nexport const helixToastStyles = css`\n /* ─── hx-toast host ─── */\n\n :host {\n display: block;\n pointer-events: none;\n }\n\n :host([open]) {\n pointer-events: auto;\n }\n\n /* ─── Toast base ─── */\n\n .toast {\n display: flex;\n align-items: flex-start;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n border-radius: var(--hx-toast-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-toast-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-toast-color, var(--hx-color-text-inverse, #ffffff));\n font-family: var(--hx-toast-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n line-height: var(--hx-line-height-normal, 1.5);\n box-shadow: var(\n --hx-toast-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 opacity: 0;\n transform: translateY(var(--hx-toast-enter-translate, var(--hx-space-2, 0.5rem)));\n transition:\n opacity var(--hx-transition-normal, 250ms ease),\n transform var(--hx-transition-normal, 250ms ease);\n width: var(--hx-toast-width, 20rem);\n max-width: 100%;\n pointer-events: auto;\n }\n\n :host([open]) .toast {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ─── Variant overrides ─── */\n\n /*\n * Toast variants paint on darker brand fills (primary-600/success-700/\n * error-600) because the lighter -500 fills can't pass AA against white\n * text in the precision-cool palette. The neutral-900 on-{role} tokens\n * are tuned for the lighter -500 surfaces and would fail here (e.g.\n * neutral-900 on primary-600 = 3.07:1), so the on-{role}-strong tokens\n * (neutral-0, no dark-mode flip) keep fg legible on the darker fills.\n * - text.on-primary-strong on info.bg-strong (primary-600, #0F7078) = 5.82:1\n * - text.on-success-strong on success.bg-strong (success-700, #146831) = 6.88:1\n * (success-600 #0E8A4A on white = 4.42:1 — drifts under AA at 14px)\n * - text.on-error-strong on danger.bg-strong (error-600, #C92A2A) = 5.46:1\n * - text.on-warning on warning.bg-strong (warning-500, #C2711C) = 4.83:1\n * (warning stays on the lighter -500 surface so on-warning works)\n *\n * 3.2.1 token-cascade: bg variants now route through surface.{role}-strong\n * semantics; fg variants route through text.on-{role}-strong (or on-warning\n * for the warning variant). Component-tier tokens are NOT bypassed — the\n * --hx-toast-bg / --hx-toast-color slots remain the single override point.\n */\n .toast--success {\n --hx-toast-bg: var(--hx-color-surface-success-strong, #146831);\n --hx-toast-color: var(--hx-color-text-on-success-strong, #ffffff);\n }\n\n .toast--warning {\n --hx-toast-bg: var(--hx-color-surface-warning-strong, #c2711c);\n --hx-toast-color: var(--hx-color-text-on-warning, #0d1825);\n }\n\n .toast--danger {\n --hx-toast-bg: var(--hx-color-surface-danger-strong, #c92a2a);\n --hx-toast-color: var(--hx-color-text-on-error-strong, #ffffff);\n }\n\n .toast--info {\n --hx-toast-bg: var(--hx-color-surface-info-strong, #0f7078);\n --hx-toast-color: var(--hx-color-text-on-primary-strong, #ffffff);\n }\n\n /* ─── Severity Label (WCAG 1.4.1) ─── */\n /* Visually hidden — non-color cue for severity variants (success/warning/danger/info). */\n /* Ensures variant is not conveyed by color alone for color-blind users. */\n\n .toast__severity-label {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ─── Icon ─── */\n\n .toast__icon {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n }\n\n .toast__icon:empty {\n display: none;\n }\n\n /* ─── Message ─── */\n\n .toast__message {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n /* ─── Action slot ─── */\n\n .toast__action {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n }\n\n .toast__action:empty {\n display: none;\n }\n\n /* ─── Close button ─── */\n\n .toast__close {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* WCAG 2.5.5: minimum 44×44px touch target */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n padding: var(--hx-space-1, 0.25rem);\n background: transparent;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n color: inherit;\n cursor: pointer;\n opacity: var(--hx-opacity-75, 0.75);\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .toast__close:hover {\n opacity: 1;\n }\n\n .toast__close:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid currentColor;\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Reduced motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .toast {\n transition: none;\n }\n\n .toast__close {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n /* Sole owner: bespoke per-class HC overrides on .toast and .toast__close.\n The shared forcedColorsSurface mixin was dropped in 3.2.1 (XOR rule);\n this block now carries the surface contract the mixin used to provide\n (background:Canvas + color:CanvasText + border:1px solid CanvasText)\n plus the per-class affordances the mixin never touched. */\n\n @media (forced-colors: active) {\n .toast {\n background: Canvas;\n color: CanvasText;\n border: 1px solid CanvasText;\n }\n\n .toast__close {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n }\n`;\n\nexport const helixToastStackStyles = css`\n :host {\n display: block;\n position: fixed;\n z-index: var(--hx-z-index-toast, 1700);\n pointer-events: none;\n }\n\n .toast-stack {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-space-4, 1rem);\n pointer-events: none;\n }\n\n /* ─── Placements ─── */\n\n :host([placement='top-start']) {\n top: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-center']) {\n top: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n bottom: auto;\n }\n\n :host([placement='top-end']) {\n top: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n bottom: auto;\n }\n\n :host([placement='bottom-start']) {\n bottom: 0;\n inset-inline-start: 0;\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-center']) {\n bottom: 0;\n inset-inline-start: 50%;\n transform: translateX(-50%);\n inset-inline-end: auto;\n top: auto;\n }\n\n :host([placement='bottom-end']) {\n bottom: 0;\n inset-inline-end: 0;\n inset-inline-start: auto;\n top: auto;\n }\n\n /* ─── Bottom placements: reverse order so newest is on top ─── */\n\n :host([placement^='bottom']) .toast-stack {\n flex-direction: column-reverse;\n }\n\n /* ─── Slide direction by placement ─── */\n\n :host([placement^='top']) ::slotted(hx-toast) {\n --hx-toast-enter-translate: calc(var(--hx-space-2, 0.5rem) * -1);\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { helixToastStyles } from './hx-toast.styles.js';\n\nexport type ToastVariant = 'default' | 'success' | 'warning' | 'danger' | 'info';\n\n// (group-6) WCAG 2.2.3 minimum display times by variant. When `duration > 0`\n// and shorter than the role-implied minimum, a devWarn fires recommending the\n// caller either lengthen `duration` or set `duration=0` for persistent\n// toasts. AT cannot reliably finish reading a danger announcement in less\n// than ~6 seconds; success/info polite announcements need at least ~3s.\nconst MIN_DISPLAY_MS_BY_VARIANT: Record<ToastVariant, number> = {\n default: 3000,\n info: 3000,\n success: 3000,\n warning: 4000,\n danger: 6000,\n};\n\n/**\n * A transient notification message that auto-dismisses after a configurable duration.\n * Supports multiple visual variants, a closable button, icon/action slots, and full\n * ARIA live region semantics for screen readers.\n *\n * @summary Transient notification toast component.\n *\n * @tag hx-toast\n *\n * @slot - Default slot for the notification message.\n * @slot icon - Optional icon rendered before the message.\n * @slot action - Optional action button rendered after the message.\n *\n * @fires {CustomEvent} hx-show - Dispatched when the toast becomes visible.\n * @fires {CustomEvent} hx-hide - Dispatched when the toast begins hiding.\n * @fires {CustomEvent} hx-after-hide - Dispatched after the hide animation completes.\n *\n * @csspart base - The inner toast container div.\n * @csspart icon - The icon slot wrapper.\n * @csspart message - The message slot wrapper.\n * @csspart close-button - The dismiss button (only when closable).\n * @csspart action - The action slot wrapper.\n *\n * @cssprop [--hx-toast-bg=var(--hx-color-surface-inverse)] - Toast background color.\n * @cssprop [--hx-toast-color=var(--hx-color-text-inverse)] - Toast text color.\n * @cssprop [--hx-toast-border-radius=var(--hx-border-radius-md)] - Toast border radius.\n * @cssprop [--hx-toast-shadow] - Toast box shadow.\n * @cssprop [--hx-toast-width=20rem] - Toast width.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-surface-inverse] - Default-variant background semantic (neutral-900 anchor; flipped per mode).\n * @cssprop [--hx-color-text-inverse] - Default-variant foreground semantic (neutral-0 anchor; flipped per mode).\n * @cssprop [--hx-toast-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-toast-enter-translate=var(--hx-space-2)] - CSS custom property.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-transition-normal] - Transition timing.\n * @cssprop [--hx-color-surface-success-strong] - Success-variant background semantic (3.2.1 cascade).\n * @cssprop [--hx-color-surface-warning-strong] - Warning-variant background semantic (3.2.1 cascade).\n * @cssprop [--hx-color-surface-danger-strong] - Danger-variant background semantic (3.2.1 cascade).\n * @cssprop [--hx-color-surface-info-strong] - Info-variant background semantic (3.2.1 cascade).\n * @cssprop [--hx-color-text-on-success-strong] - Success-variant foreground semantic (neutral-0 across modes).\n * @cssprop [--hx-color-text-on-warning] - Warning-variant foreground semantic (neutral-900; warning sits on lighter -500 fill).\n * @cssprop [--hx-color-text-on-error-strong] - Danger-variant foreground semantic (neutral-0 across modes).\n * @cssprop [--hx-color-text-on-primary-strong] - Info-variant foreground semantic (neutral-0 across modes).\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-opacity-75] - Opacity.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n */\n@customElement('hx-toast')\nexport class HelixToast extends HelixElement {\n // 3.2.1: forced-colors deference is owned by the bespoke @media block in\n // hx-toast.styles.ts (per-class overrides on .toast and .toast__close —\n // strictly more than the shared mixin's :host/[part] surface contract).\n // XOR rule per styles/forced-colors.ts: do NOT also compose\n // forcedColorsSurface — overlapping selectors inside the same media query\n // create a fragile specificity war.\n static override styles = [helixToastStyles];\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'success' | 'warning' | 'danger' | 'info' = 'default';\n\n /**\n * Auto-dismiss duration in milliseconds. Set to 0 for persistent toasts.\n * @attr duration\n */\n @property({ type: Number })\n duration = 5000;\n\n /**\n * Whether to show a close button.\n * @attr closable\n */\n @property({ type: Boolean, reflect: true })\n closable = false;\n\n /**\n * Whether the toast is currently visible.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Accessible label for the close button. Override for localization.\n * @attr label-close\n */\n @property({ attribute: 'label-close' })\n labelClose = 'Dismiss notification';\n\n // ─── Private State ───\n\n /** @internal */\n @query('.toast') private _toastEl!: HTMLElement | null;\n\n /** @internal Tracks whether the action slot has slotted content. */\n @state() private _hasActionContent = false;\n\n /** @internal */\n private _timer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Reduced Motion ───\n\n /** @internal Returns true when the user has opted into reduced motion. */\n private get _reducedMotion(): boolean {\n // Guard for SSR — window.matchMedia is unavailable server-side\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /** @internal */\n private _timerStartedAt: number | null = null;\n\n /** @internal */\n private _timerRemaining: number | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // (group-6) Host-canonical role + aria-atomic via ElementInternals.\n // role implies aria-live per ARIA spec (alert→assertive, status→polite),\n // so we do NOT also set explicit aria-live (avoids §5.1 double-announce\n // on older NVDA/JAWS).\n //\n // (group-6 codex round-1) Dual-write: keep an attribute fallback for\n // `role` on the host, harmonized with hx-alert/hx-banner. Some AT +\n // browser combos still ignore internals-backed ARIA reflection on\n // custom elements (notably older JAWS + Chrome and certain\n // VoiceOver+Safari builds); without an attribute they would stop\n // announcing toasts entirely. role implies aria-live, so we do NOT\n // also write an explicit aria-live attribute (the implicit live region\n // is what `role` already provides — adding aria-live duplicates the\n // signal and re-introduces the §5.1 double-announce on those same\n // older AT+browser combos).\n this._internals.role = this._role;\n this._internals.ariaAtomic = 'true';\n this.setAttribute('role', this._role);\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('variant')) {\n // Keep host role in sync with variant (alert vs status).\n // Dual-write: internals (modern) + attribute (legacy fallback).\n this._internals.role = this._role;\n this.setAttribute('role', this._role);\n }\n if (changedProperties.has('open') || changedProperties.has('duration')) {\n this._auditWcag223();\n }\n if (changedProperties.has('open')) {\n if (this.open) {\n this.removeAttribute('aria-hidden');\n this._emitShow();\n if (this.duration > 0 && !this._reducedMotion && !this._hasActionContent) {\n this._startTimer();\n }\n } else {\n this.setAttribute('aria-hidden', 'true');\n this._clearTimer();\n this._emitHide();\n }\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._clearTimer();\n }\n\n /**\n * (group-6 §5.3) WCAG 2.2.3 (Level AA — No Time Limits) audit. When\n * `duration` is shorter than the role-implied minimum-display-time for the\n * current variant, surface a developer warning recommending a longer\n * duration or `duration=0` for persistent toasts. Danger toasts in\n * particular are safety-critical and routinely need more than 5 seconds\n * for screen readers to finish reading.\n *\n * Fires only in DEV builds (Vite tree-shakes the call in production).\n *\n * @internal\n */\n private _auditWcag223(): void {\n if (this.duration <= 0) return;\n const min = MIN_DISPLAY_MS_BY_VARIANT[this.variant] ?? 0;\n if (this.duration < min) {\n devWarn(\n 'hx-toast',\n `duration=${this.duration}ms is shorter than the WCAG 2.2.3 minimum (${min}ms) for variant=\"${this.variant}\". Increase duration or set duration=0 for persistent toasts (recommended for variant=\"danger\").`,\n );\n }\n }\n\n // ─── Public API ───\n\n /** Show the toast. */\n show(): void {\n if (!this.open) {\n this.open = true;\n }\n }\n\n /** Hide the toast. */\n hide(): void {\n if (this.open) {\n this.open = false;\n }\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _startTimer(remaining?: number): void {\n this._clearTimerHandle();\n const delay = remaining ?? this.duration;\n this._timerStartedAt = Date.now();\n this._timerRemaining = delay;\n this._timer = setTimeout(() => {\n this.open = false;\n }, delay);\n }\n\n /** @internal */\n private _pauseTimer(): void {\n if (this._timer === null || this._timerStartedAt === null || this._timerRemaining === null) {\n return;\n }\n const elapsed = Date.now() - this._timerStartedAt;\n this._timerRemaining = Math.max(0, this._timerRemaining - elapsed);\n this._clearTimerHandle();\n }\n\n /** @internal */\n private _clearTimerHandle(): void {\n if (this._timer !== null) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n }\n\n /** @internal */\n private _clearTimer(): void {\n this._clearTimerHandle();\n this._timerStartedAt = null;\n this._timerRemaining = null;\n }\n\n /** @internal */\n private _emitShow(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _emitHide(): void {\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n\n let fired = false;\n const fireAfterHide = () => {\n if (fired) return;\n fired = true;\n this.dispatchEvent(new CustomEvent<void>('hx-after-hide', { bubbles: true, composed: true }));\n };\n\n // Fire on transitionend if available; fallback ensures it fires in test environments\n // and when transitions are disabled (prefers-reduced-motion, no CSS transitions).\n const base = this._toastEl;\n if (base) {\n base.addEventListener('transitionend', fireAfterHide, { once: true });\n }\n // Fallback fires after the CSS transition duration (250ms) plus a small buffer.\n setTimeout(fireAfterHide, 300);\n }\n\n // ─── Event Handlers ───\n\n /** @internal */\n private _handleMouseEnter(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleMouseLeave(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleFocusIn(): void {\n this._pauseTimer();\n }\n\n /** @internal */\n private _handleFocusOut(): void {\n if (this.open && this.duration > 0) {\n this._startTimer(this._timerRemaining ?? undefined);\n }\n }\n\n /** @internal */\n private _handleClose(): void {\n this.hide();\n }\n\n /** @internal */\n private _handleActionSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasActionContent = slot.assignedNodes({ flatten: true }).length > 0;\n if (this._hasActionContent && this.open) {\n this._pauseTimer();\n }\n }\n\n // ─── ARIA Helpers ───\n\n /**\n * @internal\n * Variant→role mapping (harmonized with hx-alert/hx-banner per group-6):\n * only `danger` is assertive (role=alert); all other variants are polite\n * (role=status). role implies aria-live, so we do NOT also expose an\n * `_ariaLive` getter — that path was removed when the inner div stopped\n * carrying explicit aria-live (§5.1 double-announce mitigation).\n */\n private get _role(): 'alert' | 'status' {\n return this.variant === 'danger' ? 'alert' : 'status';\n }\n\n // ─── WCAG 1.4.1: Default Icons ───\n // Each semantic variant renders a default icon when no icon is slotted,\n // ensuring the severity is not conveyed by color alone.\n\n /** @internal */\n private _renderSuccessIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm3.03 6.28a.75.75 0 00-1.06-1.06L9 10.19 7.78 8.97a.75.75 0 00-1.06 1.06l1.75 1.75a.75.75 0 001.06 0l3.5-3.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderWarningIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M8.49 2.92a1.75 1.75 0 013.02 0l6.25 10.83A1.75 1.75 0 0116.25 16H3.75a1.75 1.75 0 01-1.51-2.25L8.49 2.92zM10 7a.75.75 0 01.75.75v3a.75.75 0 01-1.5 0v-3A.75.75 0 0110 7zm0 7.5a.75.75 0 100-1.5.75.75 0 000 1.5z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderDangerIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm-1.72 5.22a.75.75 0 011.06 0L10 7.94l.66-.72a.75.75 0 111.06 1.06L11.06 9l.66.72a.75.75 0 11-1.06 1.06L10 10.06l-.66.72a.75.75 0 01-1.06-1.06L8.94 9l-.66-.72a.75.75 0 010-1.06z\"\n />\n </svg>`;\n }\n\n /** @internal */\n private _renderInfoIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\" width=\"16\" height=\"16\">\n <path\n fill=\"currentColor\"\n d=\"M10 2a8 8 0 100 16 8 8 0 000-16zm.75 4.75a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM9.25 9a.75.75 0 011.5 0v4a.75.75 0 01-1.5 0V9z\"\n />\n </svg>`;\n }\n\n /** @internal Returns the default icon for the current variant, or nothing for 'default'. */\n private get _defaultIcon() {\n switch (this.variant) {\n case 'success':\n return this._renderSuccessIcon();\n case 'warning':\n return this._renderWarningIcon();\n case 'danger':\n return this._renderDangerIcon();\n case 'info':\n return this._renderInfoIcon();\n default:\n return nothing;\n }\n }\n\n // ─── WCAG 1.4.1: Severity label map ───\n\n /** @internal */\n private static readonly _SEVERITY_LABELS: Partial<Record<ToastVariant, string>> = {\n success: 'Success',\n warning: 'Warning',\n danger: 'Error',\n info: 'Info',\n };\n\n /** @internal */\n private get _severityLabel(): string {\n return HelixToast._SEVERITY_LABELS[this.variant] ?? '';\n }\n\n // ─── Render ───\n //\n // (group-6) Host-canonical live region: role + aria-atomic live on the\n // host via ElementInternals (set in connectedCallback). The inner base\n // div is a presentation-only wrapper — it does NOT carry role, aria-live,\n // or aria-atomic. role implies aria-live per ARIA spec, so the host has\n // NO explicit aria-live attribute either (avoids §5.1 double-announce on\n // older NVDA/JAWS that read both role and aria-live as separate live\n // regions).\n\n override render() {\n const severityLabel = this._severityLabel;\n\n return html`\n <div\n part=\"base\"\n class=${classMap({\n toast: true,\n [`toast--${this.variant}`]: true,\n })}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n @focusin=${this._handleFocusIn}\n @focusout=${this._handleFocusOut}\n >\n ${this.open\n ? html`\n ${severityLabel\n ? html`<span class=\"toast__severity-label\">${severityLabel}: </span>`\n : nothing}\n <span part=\"icon\" class=\"toast__icon\">\n <slot name=\"icon\">${this._defaultIcon}</slot>\n </span>\n <span part=\"message\" class=\"toast__message\">\n <slot></slot>\n </span>\n <span part=\"action\" class=\"toast__action\">\n <slot name=\"action\" @slotchange=${this._handleActionSlotChange}></slot>\n </span>\n ${this.closable\n ? html`\n <button\n part=\"close-button\"\n class=\"toast__close\"\n aria-label=${this.labelClose}\n @click=${this._handleClose}\n >\n <svg\n aria-hidden=\"true\"\n width=\"16\"\n height=\"16\"\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 <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n `\n : nothing}\n `\n : nothing}\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast': HelixToast;\n }\n}\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixToastStackStyles } from './hx-toast.styles.js';\n\nexport type ToastStackPlacement =\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end';\n\n/**\n * A fixed-position container that stacks `hx-toast` elements at the specified\n * corner of the viewport. Enforces a maximum visible toast count via `stack-limit`.\n *\n * @summary Toast stack container managing position and count limits.\n *\n * @tag hx-toast-stack\n *\n * @slot - Accepts `hx-toast` elements.\n *\n * @csspart base - The inner stack container div.\n *\n * @cssprop [--hx-z-index-toast=9000] - Z-index for the fixed stack.\n *\n * ─── ARIA scope (group-6 §3.2 / §5.9) ─────────────────────────────────────\n *\n * `hx-toast-stack` deliberately has NO `role`, `aria-live`, `aria-atomic`,\n * or `aria-relevant` on its host or inner container. Each child `hx-toast`\n * is its own live region (role=alert/status via ElementInternals). Wrapping\n * those toasts in a second live region (e.g. `role=\"log\"` on the stack)\n * would create nested live regions, which causes older NVDA/JAWS to\n * announce every toast TWICE — once for the toast's own role, once for the\n * surrounding log region.\n *\n * The stack is purely a positional/z-index container; it is invisible to\n * the AT tree. Do NOT add a container role unless this entire architecture\n * is rewritten so individual toasts no longer carry their own roles.\n */\n@customElement('hx-toast-stack')\nexport class HelixToastStack extends HelixElement {\n static override styles = [helixToastStackStyles];\n\n /**\n * Corner of the viewport where toasts appear.\n * @attr placement\n */\n @property({ type: String, reflect: true })\n placement:\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end' = 'bottom-end';\n\n /**\n * Maximum number of simultaneously visible toasts. 0 = unlimited.\n * @attr stack-limit\n */\n @property({ type: Number, attribute: 'stack-limit' })\n stackLimit = 3;\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=${classMap({\n 'toast-stack': true,\n [`toast-stack--${this.placement}`]: true,\n })}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n\n// ─── Declarative Global Types ───\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-toast-stack': HelixToastStack;\n }\n}\n","import { HelixToast } from './hx-toast.js';\nimport { HelixToastStack } from './hx-toast-stack.js';\nimport type { ToastVariant } from './hx-toast.js';\nimport type { ToastStackPlacement } from './hx-toast-stack.js';\n\nexport interface ToastOptions {\n /** The notification message text. */\n message: string;\n /** Visual variant. Defaults to 'default'. */\n variant?: ToastVariant;\n /** Auto-dismiss duration in ms. 0 = persistent. Defaults to 3000. */\n duration?: number;\n /** Placement of the shared stack. Defaults to 'bottom-end'. */\n placement?: ToastStackPlacement;\n}\n\n/**\n * (group-6 §5.5) Minimum on-screen lifetime for any toast created via the\n * factory, regardless of `stackLimit`-driven displacement. Prevents\n * AT-clipping when rapid-fire `toast()` calls (e.g. during a Drupal\n * BigPipe re-attach burst) would otherwise hide a toast before NVDA/JAWS\n * finished reading it.\n */\nconst MIN_DISPLAY_MS = 1500;\n\n/** @internal Tracks `show()` timestamps so the factory can defer displacement. */\nconst _shownAt = new WeakMap<HelixToast, number>();\n\n/**\n * @internal\n * Tracks toasts that already have a deferred-hide scheduled so successive\n * `toast()` calls within the same MIN_DISPLAY_MS window do NOT pile multiple\n * timers on the same target while leaving newer overflow toasts untouched.\n *\n * (group-6 §5.5 burst-fix) Without this guard, a 5-call burst against a\n * limit-3 stack would schedule three hides on the SAME oldest toast (calls\n * 4, 5, and any subsequent within the window), and the stack would settle\n * at 4 visible toasts after the deferred hide fired — violating\n * `stackLimit`. The set + per-toast guard ensures each successive oldest\n * is hidden exactly once.\n */\nconst _pendingDisplacements = new WeakSet<HelixToast>();\n\n/**\n * Imperatively create and display a toast notification.\n *\n * Creates a shared `hx-toast-stack` on `document.body` if one does not exist,\n * then appends a new `hx-toast` with the given options. Respects the stack's\n * `stackLimit` by hiding the oldest visible toast when the limit is exceeded.\n *\n * @example\n * import { toast } from '@helixui/library/components/hx-toast/index.js';\n * toast({ message: 'Patient record saved.', variant: 'success' });\n */\nexport function toast(options: ToastOptions): HelixToast {\n if (typeof document === 'undefined') throw new Error('toast() requires a browser environment');\n const placement = options.placement ?? 'bottom-end';\n\n // Find or create a dedicated stack for this placement\n const stackSelector = `hx-toast-stack[placement=\"${placement}\"]`;\n let stack = document.querySelector<HelixToastStack>(stackSelector);\n if (!stack) {\n stack = document.createElement('hx-toast-stack');\n stack.placement = placement;\n // Intentional design decision: the toast stack is appended to document.body rather\n // than inserted near the caller. This is required so that the fixed-position overlay\n // is not clipped by an ancestor with `overflow: hidden`, `transform`, or `filter`\n // (all of which create a new stacking context and break fixed positioning).\n // Drupal compatibility note: Drupal's BigPipe / AJAX behaviors can re-attach the\n // document body without removing these stacks. The selector check above\n // (`document.querySelector`) ensures only one stack per placement is ever created,\n // preventing duplicates on re-attach cycles.\n document.body.appendChild(stack);\n }\n\n // Enforce stack limit: hide oldest open toasts if at capacity.\n // (group-6 §5.5) Minimum display time prevents AT-clipping under rapid-fire\n // bursts. If a toast has not yet been on screen for MIN_DISPLAY_MS, defer\n // its hide until the remainder elapses; otherwise hide immediately.\n //\n // Burst-fix: previously this branch only inspected the single oldest toast,\n // so calls 4..N within the same MIN_DISPLAY_MS window all scheduled hides\n // on the same target while the stack settled at limit+(N-1) visible. Now we\n // walk every overflow slot and use `_pendingDisplacements` to guarantee each\n // successive oldest is hidden exactly once.\n if (stack.stackLimit > 0) {\n const openToasts = [...stack.querySelectorAll<HelixToast>('hx-toast')].filter((t) => t.open);\n // Treat anything already queued for displacement as already-hiding so we\n // pick the next surviving oldest. Since the new toast is appended after\n // this block, we must overshoot by 1 to cover it.\n const survivors = openToasts.filter((t) => !_pendingDisplacements.has(t));\n const overflow = survivors.length + 1 - stack.stackLimit;\n for (let i = 0; i < overflow; i++) {\n const target = survivors[i];\n if (!target) break;\n const shownAt = _shownAt.get(target);\n const elapsed = shownAt === undefined ? Number.POSITIVE_INFINITY : Date.now() - shownAt;\n if (elapsed >= MIN_DISPLAY_MS) {\n target.hide();\n } else {\n const remaining = MIN_DISPLAY_MS - elapsed;\n _pendingDisplacements.add(target);\n setTimeout(() => {\n _pendingDisplacements.delete(target);\n // Guard: only hide if still open (consumer may have hidden it manually)\n if (target.open) target.hide();\n }, remaining);\n }\n }\n }\n\n // Create toast element\n const toastEl = document.createElement('hx-toast');\n toastEl.variant = options.variant ?? 'default';\n toastEl.duration = options.duration ?? 3000;\n toastEl.closable = true;\n toastEl.textContent = options.message;\n\n // Remove from DOM after hiding\n toastEl.addEventListener('hx-after-hide', () => {\n _shownAt.delete(toastEl);\n _pendingDisplacements.delete(toastEl);\n toastEl.remove();\n });\n\n stack.appendChild(toastEl);\n toastEl.show();\n _shownAt.set(toastEl, Date.now());\n\n return toastEl;\n}\n"],"names":["helixToastStyles","css","helixToastStackStyles","MIN_DISPLAY_MS_BY_VARIANT","HelixToast","HelixElement","changedProperties","min","devWarn","remaining","delay","elapsed","fired","fireAfterHide","base","e","slot","html","nothing","severityLabel","classMap","__decorateClass","property","query","state","customElement","HelixToastStack","MIN_DISPLAY_MS","_shownAt","_pendingDisplacements","toast","options","placement","stackSelector","stack","survivors","t","overflow","i","target","shownAt","toastEl"],"mappings":";;;;;AAYO,MAAMA,IAAmBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAmMnBC,IAAwBD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AccName-aware text flattener. Walks the subtree of `root` and concatenates
|
|
3
|
+
* text-node content, REJECTING any element subtree carrying `aria-hidden="true"`
|
|
4
|
+
* or the `hidden` attribute per W3C AccName 1.2 §4.3.10. Used by host-canonical
|
|
5
|
+
* components for both external IDREF flatten (host aria-labelledby/aria-describedby
|
|
6
|
+
* targets) and slotted-label aggregation, so nested decorative content like
|
|
7
|
+
* `<svg aria-hidden="true"><title>icon</title></svg>` does not leak into the
|
|
8
|
+
* announced name/description.
|
|
9
|
+
*
|
|
10
|
+
* The TreeWalker filter only inspects elements VISITED during the walk — it
|
|
11
|
+
* never tests the root itself, so a hidden ROOT (e.g. `<span slot="label" hidden>`)
|
|
12
|
+
* would still contribute its descendants' text. Per AccName 1.2 §4.3.10, a
|
|
13
|
+
* hidden root contributes the empty string. Gate the walk here so every caller
|
|
14
|
+
* honors the rule symmetrically.
|
|
15
|
+
*
|
|
16
|
+
* ## Intentional divergence from AccName 1.2 §4.3.7 (LabelledBy Recursion)
|
|
17
|
+
*
|
|
18
|
+
* The AccName 1.2 spec (§4.3.7 + "Hidden Not Referenced") states that when an
|
|
19
|
+
* element is DIRECTLY referenced by `aria-labelledby` / `aria-describedby`,
|
|
20
|
+
* that referenced element's subtree contributes to the computed name even when
|
|
21
|
+
* the element itself is hidden via `hidden` / `aria-hidden="true"`. The author's
|
|
22
|
+
* explicit IDREF is treated as intent to use that subtree as the name.
|
|
23
|
+
*
|
|
24
|
+
* This helper deliberately diverges from §4.3.7 by applying the §4.3.10 hidden
|
|
25
|
+
* gate uniformly to ALL callers, including the IDREF-target path. Rationale:
|
|
26
|
+
*
|
|
27
|
+
* 1. **Predictability across consumer mental models.** Consumers expect
|
|
28
|
+
* "visually hidden via `[hidden]` / `aria-hidden=true`" to mean
|
|
29
|
+
* "semantically removed", full stop. A label that disappears visually but
|
|
30
|
+
* keeps announcing creates a debugging trap, especially in CMS / Twig
|
|
31
|
+
* contexts where visibility toggles are often driven by template logic.
|
|
32
|
+
* 2. **Standard accessible-hide pattern is already supported.** Authors who
|
|
33
|
+
* want a label that is visually hidden but contributes its text via
|
|
34
|
+
* `aria-labelledby` should use the established `.sr-only` / `.visually-hidden`
|
|
35
|
+
* pattern (clip-path / position:absolute / width:1px), which neither
|
|
36
|
+
* attribute affects. That pattern correctly contributes here.
|
|
37
|
+
* 3. **Fail-safe for stale references.** A hidden referenced element is more
|
|
38
|
+
* often a stale or accidentally-toggled reference than an intentional
|
|
39
|
+
* hidden-name source. Returning the empty string lets the host fall back
|
|
40
|
+
* to its next AccName step (aria-label, slotted label, placeholder) rather
|
|
41
|
+
* than announcing surprising stale content.
|
|
42
|
+
*
|
|
43
|
+
* If a future component genuinely needs strict §4.3.7 behavior, add a second
|
|
44
|
+
* entry point (e.g. `flattenAccNameForIdRef`) that skips the root-level gate
|
|
45
|
+
* and reuses the TreeWalker logic; do not relax this gate globally.
|
|
46
|
+
*
|
|
47
|
+
* Single source of truth for accessible-name flattening across the library.
|
|
48
|
+
* Used by hx-time-picker, hx-date-picker, hx-toggle-button, and any future
|
|
49
|
+
* host-canonical component that aggregates slotted text into an accessible name.
|
|
50
|
+
*
|
|
51
|
+
* @param root - The element whose subtree text content should be flattened.
|
|
52
|
+
* @returns The concatenated, whitespace-collapsed text content with hidden
|
|
53
|
+
* subtrees excluded.
|
|
54
|
+
*/
|
|
55
|
+
export declare function flattenAccName(root: Element): string;
|
|
56
|
+
//# sourceMappingURL=aria-flatten.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aria-flatten.d.ts","sourceRoot":"","sources":["../../src/utils/aria-flatten.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CA6BpD"}
|