@helixui/library 3.3.1-next.118 → 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 +422 -322
- 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.map +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-checkbox-group/index.js +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-data-table/hx-data-table.d.ts.map +1 -1
- package/dist/components/hx-data-table/index.js +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/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 +96 -8
- 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-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/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/index.js +1 -1
- package/dist/components/hx-select/hx-select.d.ts +1 -0
- package/dist/components/hx-select/hx-select.d.ts.map +1 -1
- package/dist/components/hx-select/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/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/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 +123 -0
- package/dist/css/helix-core.css +81 -0
- package/dist/css/helix-feedback.css +14 -0
- package/dist/css/helix-forms.css +11 -0
- 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-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-tag.css +23 -0
- package/dist/css/hx-time-picker.css +11 -0
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +3 -1
- package/dist/index.js +35 -35
- package/dist/shared/aria-idref-CxvyzfQS.js +126 -0
- package/dist/shared/aria-idref-CxvyzfQS.js.map +1 -0
- 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-BdgoUeWi.js → hx-checkbox-C48KYKFq.js} +87 -87
- package/dist/shared/hx-checkbox-C48KYKFq.js.map +1 -0
- package/dist/shared/{hx-checkbox-group-LWezHrvS.js → hx-checkbox-group-BJIAX3zU.js} +2 -2
- package/dist/shared/{hx-checkbox-group-LWezHrvS.js.map → hx-checkbox-group-BJIAX3zU.js.map} +1 -1
- package/dist/shared/{hx-color-picker-DVhZl88b.js → hx-color-picker-Dk4cBwYQ.js} +2 -2
- package/dist/shared/{hx-color-picker-DVhZl88b.js.map → hx-color-picker-Dk4cBwYQ.js.map} +1 -1
- package/dist/shared/{hx-combobox-DvlezcDV.js → hx-combobox-BTLO9qiK.js} +2 -2
- package/dist/shared/{hx-combobox-DvlezcDV.js.map → hx-combobox-BTLO9qiK.js.map} +1 -1
- 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-N-0aG5XL.js → hx-date-picker-CiR7FVnR.js} +2 -2
- package/dist/shared/{hx-date-picker-N-0aG5XL.js.map → hx-date-picker-CiR7FVnR.js.map} +1 -1
- package/dist/shared/{hx-dialog-DzB7VytW.js → hx-dialog-AOZpHSuF.js} +2 -2
- package/dist/shared/{hx-dialog-DzB7VytW.js.map → hx-dialog-AOZpHSuF.js.map} +1 -1
- 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-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-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-CHxWY_cd.js → hx-popover-B9W8-tC0.js} +2 -2
- package/dist/shared/{hx-popover-CHxWY_cd.js.map → hx-popover-B9W8-tC0.js.map} +1 -1
- 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-CeGzARNk.js → hx-radio-Z1lV1zTO.js} +2 -2
- package/dist/shared/{hx-radio-CeGzARNk.js.map → hx-radio-Z1lV1zTO.js.map} +1 -1
- package/dist/shared/{hx-select-DrcS-YRJ.js → hx-select-D18CnJ0e.js} +2 -2
- 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-BX_8uNUs.js → hx-switch-B6kr-EwE.js} +2 -2
- package/dist/shared/{hx-switch-BX_8uNUs.js.map → hx-switch-B6kr-EwE.js.map} +1 -1
- 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-Dcz9IlUm.js → hx-toggle-button-BQ81EDkl.js} +2 -2
- package/dist/shared/{hx-toggle-button-Dcz9IlUm.js.map → hx-toggle-button-BQ81EDkl.js.map} +1 -1
- 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-idref.d.ts.map +1 -1
- 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 +69 -20
- package/package.json +2 -2
- package/dist/shared/aria-idref-Q0yiSR3p.js +0 -104
- package/dist/shared/aria-idref-Q0yiSR3p.js.map +0 -1
- 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-BdgoUeWi.js.map +0 -1
- package/dist/shared/hx-drawer-Y1Ui2IWJ.js.map +0 -1
- package/dist/shared/hx-dropdown-DJWlF94E.js +0 -316
- package/dist/shared/hx-dropdown-DJWlF94E.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-progress-bar-Bn3JEPUf.js +0 -258
- package/dist/shared/hx-progress-bar-Bn3JEPUf.js.map +0 -1
- package/dist/shared/hx-select-DrcS-YRJ.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-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-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
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composed-tree walkers for the `hx-tree-view` family.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the `menu-tree.ts` utilities (codex push-gate round-9 extraction
|
|
5
|
+
* for the menu family), but specialized for `hx-tree-view` / `hx-tree-item`
|
|
6
|
+
* where nesting is structural rather than slot-based — child items live in a
|
|
7
|
+
* named `slot="children"` projected into the parent item's shadow root,
|
|
8
|
+
* and any number of nesting levels are legal.
|
|
9
|
+
*
|
|
10
|
+
* Group 5c (codex push-gate round-1 lift): `hx-tree-view`'s host-bound
|
|
11
|
+
* keydown / select handlers receive bubbled events from EVERY descendant
|
|
12
|
+
* tree-item, including ones that legitimately belong to an inner
|
|
13
|
+
* `hx-tree-view`. The same guard pattern that `hx-menu` uses (act only when
|
|
14
|
+
* THIS host is the closest enclosing surface of the dispatching item) is
|
|
15
|
+
* required for trees too. `hx-tree-item._handleClick` /
|
|
16
|
+
* `_handleKeyDown` need to ignore bubbled events from a CHILD `hx-tree-item`
|
|
17
|
+
* — otherwise selecting Child also activates Parent and Enter on Child
|
|
18
|
+
* re-fires Parent's handler.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Walks the composed tree from `start` outward and returns the closest
|
|
24
|
+
* enclosing `<hx-tree-view>` element, or `null` if none exists. Crosses
|
|
25
|
+
* shadow boundaries (`getRootNode().host`) and slot boundaries
|
|
26
|
+
* (`assignedSlot`) so that an item nested inside a child tree-item — which
|
|
27
|
+
* lives in the parent item's `slot="children"`, projected into the parent's
|
|
28
|
+
* shadow root — resolves to the correct enclosing tree.
|
|
29
|
+
*
|
|
30
|
+
* Returned as `Element` to avoid a circular import between `hx-tree-view`
|
|
31
|
+
* and this util; callers narrow with `instanceof HelixTreeView` if needed.
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export declare function findClosestTreeView(start: Element): Element | null;
|
|
36
|
+
/**
|
|
37
|
+
* Walks the composed tree from `start` outward and returns the closest
|
|
38
|
+
* enclosing `<hx-tree-item>` element, or `null` if none exists. Includes
|
|
39
|
+
* `start` itself when it is an `hx-tree-item`.
|
|
40
|
+
*
|
|
41
|
+
* Used by `hx-tree-item`'s `_isOwnEvent` origin guard: a click or keydown
|
|
42
|
+
* is "ours" iff the closest `hx-tree-item` ancestor of the original event
|
|
43
|
+
* target is THIS item (not a child item slotted into our `children` slot).
|
|
44
|
+
* The walk crosses shadow + slot boundaries so a deeply nested child item
|
|
45
|
+
* resolves correctly.
|
|
46
|
+
*
|
|
47
|
+
* Returned as `Element` to avoid a circular import; callers narrow with
|
|
48
|
+
* `instanceof HelixTreeItem` if needed.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export declare function findClosestTreeItem(start: Element): Element | null;
|
|
53
|
+
//# sourceMappingURL=tree-walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-walk.d.ts","sourceRoot":"","sources":["../../src/utils/tree-walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAsBlE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAsBlE"}
|
package/figma-inventory.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-05-
|
|
3
|
+
"generatedAt": "2026-05-06T11:01:35.731Z",
|
|
4
4
|
"sourceCem": "custom-elements.json",
|
|
5
|
-
"helixVersion": "3.
|
|
5
|
+
"helixVersion": "3.4.0",
|
|
6
6
|
"tokensVersion": "3.3.1",
|
|
7
7
|
"components": [
|
|
8
8
|
{
|
|
@@ -11459,6 +11459,17 @@
|
|
|
11459
11459
|
"true"
|
|
11460
11460
|
],
|
|
11461
11461
|
"default": "false"
|
|
11462
|
+
},
|
|
11463
|
+
{
|
|
11464
|
+
"figmaAxisName": "loading",
|
|
11465
|
+
"cemAttribute": "loading",
|
|
11466
|
+
"cemFieldName": "loading",
|
|
11467
|
+
"type": "boolean",
|
|
11468
|
+
"values": [
|
|
11469
|
+
"false",
|
|
11470
|
+
"true"
|
|
11471
|
+
],
|
|
11472
|
+
"default": "false"
|
|
11462
11473
|
}
|
|
11463
11474
|
],
|
|
11464
11475
|
"textProperties": [
|
|
@@ -11505,6 +11516,10 @@
|
|
|
11505
11516
|
{
|
|
11506
11517
|
"description": "The icon container span wrapping the default slot.",
|
|
11507
11518
|
"name": "icon"
|
|
11519
|
+
},
|
|
11520
|
+
{
|
|
11521
|
+
"description": "The loading spinner SVG element shown when `loading` is true.",
|
|
11522
|
+
"name": "spinner"
|
|
11508
11523
|
}
|
|
11509
11524
|
],
|
|
11510
11525
|
"events": [
|
|
@@ -11981,6 +11996,12 @@
|
|
|
11981
11996
|
"cemAttribute": "rel",
|
|
11982
11997
|
"type": "text",
|
|
11983
11998
|
"defaultValue": "undefined"
|
|
11999
|
+
},
|
|
12000
|
+
{
|
|
12001
|
+
"figmaPropertyName": "externalLabel",
|
|
12002
|
+
"cemAttribute": "external-label",
|
|
12003
|
+
"type": "text",
|
|
12004
|
+
"defaultValue": "(opens in new tab)"
|
|
11984
12005
|
}
|
|
11985
12006
|
],
|
|
11986
12007
|
"slots": [
|
|
@@ -12748,7 +12769,7 @@
|
|
|
12748
12769
|
"figmaEligible": true,
|
|
12749
12770
|
"figmaComponentName": "hx-menu-item",
|
|
12750
12771
|
"figmaPagePlacement": "4a",
|
|
12751
|
-
"description": "A single interactive item for use inside `hx-menu`. Supports normal, checkbox, and radio types, loading state, prefix/suffix slots, and submenu nesting.
|
|
12772
|
+
"description": "A single interactive item for use inside `hx-menu`. Supports normal, checkbox, and radio types, loading state, prefix/suffix slots, and submenu nesting.",
|
|
12752
12773
|
"tier": "atom",
|
|
12753
12774
|
"variantAxes": [
|
|
12754
12775
|
{
|
|
@@ -12870,18 +12891,18 @@
|
|
|
12870
12891
|
"description": "Dispatched when the item is activated via click, Enter, or Space."
|
|
12871
12892
|
},
|
|
12872
12893
|
{
|
|
12873
|
-
"name": "hx-item-submenu-open",
|
|
12874
12894
|
"type": {
|
|
12875
12895
|
"text": "CustomEvent<{item: HelixMenuItem}>"
|
|
12876
12896
|
},
|
|
12877
|
-
"description": "Dispatched when ArrowRight is pressed on an item with a submenu."
|
|
12897
|
+
"description": "Dispatched when ArrowRight is pressed on an item with a submenu.",
|
|
12898
|
+
"name": "hx-item-submenu-open"
|
|
12878
12899
|
},
|
|
12879
12900
|
{
|
|
12880
|
-
"name": "hx-item-submenu-close",
|
|
12881
12901
|
"type": {
|
|
12882
12902
|
"text": "CustomEvent<{item: HelixMenuItem}>"
|
|
12883
12903
|
},
|
|
12884
|
-
"description": "Dispatched when ArrowLeft is pressed on an item, signaling the parent to close the submenu and return focus."
|
|
12904
|
+
"description": "Dispatched when ArrowLeft is pressed on an item, signaling the parent to close the submenu and return focus.",
|
|
12905
|
+
"name": "hx-item-submenu-close"
|
|
12885
12906
|
}
|
|
12886
12907
|
],
|
|
12887
12908
|
"cssProperties": [
|
|
@@ -17134,6 +17155,13 @@
|
|
|
17134
17155
|
"text": "CustomEvent<{value: string}>"
|
|
17135
17156
|
},
|
|
17136
17157
|
"description": "Dispatched when the selected option changes."
|
|
17158
|
+
},
|
|
17159
|
+
{
|
|
17160
|
+
"type": {
|
|
17161
|
+
"text": "Event"
|
|
17162
|
+
},
|
|
17163
|
+
"description": "Platform constraint-validation event fired when checkValidity() / reportValidity() determine the value is invalid (form-associated component contract via ElementInternals.setValidity).",
|
|
17164
|
+
"name": "invalid"
|
|
17137
17165
|
}
|
|
17138
17166
|
],
|
|
17139
17167
|
"cssProperties": [
|
|
@@ -21704,7 +21732,7 @@
|
|
|
21704
21732
|
"figmaEligible": true,
|
|
21705
21733
|
"figmaComponentName": "hx-tab-panel",
|
|
21706
21734
|
"figmaPagePlacement": "4a",
|
|
21707
|
-
"description": "A content panel associated with an `<hx-tab>`, managed by a parent `<hx-tabs>`.",
|
|
21735
|
+
"description": "A content panel associated with an `<hx-tab>`, managed by a parent `<hx-tabs>`. Group 5a host-canonical: `role=\"tabpanel\"` lives on the host via `_internals.role`. The host carries the canonical AT…",
|
|
21708
21736
|
"tier": "atom",
|
|
21709
21737
|
"variantAxes": [],
|
|
21710
21738
|
"textProperties": [
|
|
@@ -22043,7 +22071,7 @@
|
|
|
22043
22071
|
"manual",
|
|
22044
22072
|
"automatic"
|
|
22045
22073
|
],
|
|
22046
|
-
"default": "
|
|
22074
|
+
"default": "manual"
|
|
22047
22075
|
}
|
|
22048
22076
|
],
|
|
22049
22077
|
"textProperties": [
|
|
@@ -24201,31 +24229,46 @@
|
|
|
24201
24229
|
],
|
|
24202
24230
|
"cssParts": [
|
|
24203
24231
|
{
|
|
24204
|
-
"description": "The inner slot wrapper element. `display: contents` — no layout effect.",
|
|
24232
|
+
"description": "The inner slot wrapper element. `display: contents` — no layout effect. Theme-injected CSS custom properties (semantic surface — full token catalog lives in `@helixui/tokens`; the wildcard `--hx-*` was previously documented here but the CEM cssProperties[] surface requires explicit names).",
|
|
24205
24233
|
"name": "base"
|
|
24206
24234
|
}
|
|
24207
24235
|
],
|
|
24208
24236
|
"events": [],
|
|
24209
24237
|
"cssProperties": [
|
|
24210
24238
|
{
|
|
24211
|
-
"description": "
|
|
24212
|
-
"name": "--hx
|
|
24239
|
+
"description": "Primary text color (theme-injected).",
|
|
24240
|
+
"name": "--hx-color-text-primary",
|
|
24213
24241
|
"figmaBinding": null
|
|
24214
24242
|
},
|
|
24215
24243
|
{
|
|
24216
|
-
"description": "
|
|
24217
|
-
"name": "--hx-color-
|
|
24244
|
+
"description": "Base surface background (theme-injected).",
|
|
24245
|
+
"name": "--hx-color-surface-base",
|
|
24218
24246
|
"figmaBinding": null
|
|
24219
24247
|
},
|
|
24220
24248
|
{
|
|
24221
|
-
"description": "
|
|
24249
|
+
"description": "Default border color (theme-injected).",
|
|
24250
|
+
"name": "--hx-color-border-default",
|
|
24251
|
+
"figmaBinding": null
|
|
24252
|
+
},
|
|
24253
|
+
{
|
|
24254
|
+
"description": "Spacing token (theme-injected).",
|
|
24222
24255
|
"name": "--hx-space-4",
|
|
24223
24256
|
"figmaBinding": null
|
|
24224
24257
|
},
|
|
24225
24258
|
{
|
|
24226
|
-
"description": "Animation duration.",
|
|
24259
|
+
"description": "Animation duration (theme-injected).",
|
|
24227
24260
|
"name": "--hx-duration-fast",
|
|
24228
24261
|
"figmaBinding": null
|
|
24262
|
+
},
|
|
24263
|
+
{
|
|
24264
|
+
"description": "Medium border-radius (theme-injected).",
|
|
24265
|
+
"name": "--hx-radius-md",
|
|
24266
|
+
"figmaBinding": null
|
|
24267
|
+
},
|
|
24268
|
+
{
|
|
24269
|
+
"description": "Body font family (theme-injected).",
|
|
24270
|
+
"name": "--hx-font-family-body",
|
|
24271
|
+
"figmaBinding": null
|
|
24229
24272
|
}
|
|
24230
24273
|
],
|
|
24231
24274
|
"dependsOn": [],
|
|
@@ -24318,6 +24361,12 @@
|
|
|
24318
24361
|
"cemAttribute": "error",
|
|
24319
24362
|
"type": "text",
|
|
24320
24363
|
"defaultValue": ""
|
|
24364
|
+
},
|
|
24365
|
+
{
|
|
24366
|
+
"figmaPropertyName": "accessibleLabel",
|
|
24367
|
+
"cemAttribute": "accessible-label",
|
|
24368
|
+
"type": "text",
|
|
24369
|
+
"defaultValue": "null"
|
|
24321
24370
|
}
|
|
24322
24371
|
],
|
|
24323
24372
|
"slots": [
|
|
@@ -25150,7 +25199,7 @@
|
|
|
25150
25199
|
"events": [],
|
|
25151
25200
|
"cssProperties": [
|
|
25152
25201
|
{
|
|
25153
|
-
"description": "Z-index for the fixed stack.",
|
|
25202
|
+
"description": "Z-index for the fixed stack. ─── ARIA scope (group-6 §3.2 / §5.9) ───────────────────────────────────── `hx-toast-stack` deliberately has NO `role`, `aria-live`, `aria-atomic`, or `aria-relevant` on its host or inner container. Each child `hx-toast` is its own live region (role=alert/status via ElementInternals). Wrapping those toasts in a second live region (e.g. `role=\"log\"` on the stack) would create nested live regions, which causes older NVDA/JAWS to announce every toast TWICE — once for the toast's own role, once for the surrounding log region. The stack is purely a positional/z-index container; it is invisible to the AT tree. Do NOT add a container role unless this entire architecture is rewritten so individual toasts no longer carry their own roles.",
|
|
25154
25203
|
"name": "--hx-z-index-toast",
|
|
25155
25204
|
"default": "9000",
|
|
25156
25205
|
"figmaBinding": {
|
|
@@ -26268,7 +26317,7 @@
|
|
|
26268
26317
|
"name": "item"
|
|
26269
26318
|
},
|
|
26270
26319
|
{
|
|
26271
|
-
"description": "The interactive item row (
|
|
26320
|
+
"description": "The interactive item row (presentational on the modern path; carries role=\"treeitem\" + aria-* on the legacy fallback).",
|
|
26272
26321
|
"name": "row"
|
|
26273
26322
|
},
|
|
26274
26323
|
{
|
|
@@ -26280,7 +26329,7 @@
|
|
|
26280
26329
|
"name": "label"
|
|
26281
26330
|
},
|
|
26282
26331
|
{
|
|
26283
|
-
"description": "The children container.",
|
|
26332
|
+
"description": "The children container (always carries role=\"group\").",
|
|
26284
26333
|
"name": "children"
|
|
26285
26334
|
}
|
|
26286
26335
|
],
|
|
@@ -26424,7 +26473,7 @@
|
|
|
26424
26473
|
],
|
|
26425
26474
|
"cssParts": [
|
|
26426
26475
|
{
|
|
26427
|
-
"description": "The tree container element with role=\"tree\".",
|
|
26476
|
+
"description": "The tree container element with role=\"tree\" (legacy fallback path) or the inner shadow surface (modern path; role lives on the host).",
|
|
26428
26477
|
"name": "tree"
|
|
26429
26478
|
}
|
|
26430
26479
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helixui/library",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-next.121",
|
|
4
4
|
"description": "Enterprise Web Component Library built with Lit 3.x",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"customElements": "custom-elements.json",
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"lit": "^3.3.2",
|
|
62
|
-
"@helixui/tokens": "3.3.1-next.
|
|
62
|
+
"@helixui/tokens": "3.3.1-next.121"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@floating-ui/dom": "^1.7.6"
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
function p(e, i) {
|
|
2
|
-
if (!i) return [];
|
|
3
|
-
const o = i.split(/\s+/).filter(Boolean);
|
|
4
|
-
if (o.length === 0) return [];
|
|
5
|
-
const t = [];
|
|
6
|
-
f(e, t);
|
|
7
|
-
const r = e.ownerDocument;
|
|
8
|
-
r && !t.includes(r) && t.push(r);
|
|
9
|
-
const a = [];
|
|
10
|
-
for (const n of o)
|
|
11
|
-
for (const l of t) {
|
|
12
|
-
const c = l.getElementById(n);
|
|
13
|
-
if (c) {
|
|
14
|
-
a.push(c);
|
|
15
|
-
break;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return a;
|
|
19
|
-
}
|
|
20
|
-
function f(e, i) {
|
|
21
|
-
const o = /* @__PURE__ */ new Set(), t = (n) => {
|
|
22
|
-
o.has(n) || (o.add(n), i.push(n));
|
|
23
|
-
}, r = [e], a = /* @__PURE__ */ new Set([e]);
|
|
24
|
-
for (; r.length > 0; ) {
|
|
25
|
-
let l = r.shift(), c = l.getRootNode();
|
|
26
|
-
const s = l.assignedSlot ?? null;
|
|
27
|
-
for (s && !a.has(s) && (a.add(s), r.push(s)); c instanceof ShadowRoot; ) {
|
|
28
|
-
t(c);
|
|
29
|
-
const d = c.host ?? null;
|
|
30
|
-
if (!d) break;
|
|
31
|
-
const u = d.assignedSlot ?? null;
|
|
32
|
-
u && !a.has(u) && (a.add(u), r.push(u)), l = d, c = d.getRootNode();
|
|
33
|
-
}
|
|
34
|
-
c instanceof Document && t(c);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function R(e) {
|
|
38
|
-
return "ariaLabelledByElements" in e && "ariaDescribedByElements" in e && typeof e.ariaLabelledByElements < "u";
|
|
39
|
-
}
|
|
40
|
-
const w = [
|
|
41
|
-
"aria-label",
|
|
42
|
-
"aria-labelledby",
|
|
43
|
-
"aria-describedby",
|
|
44
|
-
"data-aria-label",
|
|
45
|
-
"data-aria-labelledby",
|
|
46
|
-
"data-aria-describedby"
|
|
47
|
-
], b = /* @__PURE__ */ new WeakMap();
|
|
48
|
-
function v(e, i) {
|
|
49
|
-
let o = b.get(e);
|
|
50
|
-
if (!o) {
|
|
51
|
-
const t = /* @__PURE__ */ new Set(), r = new MutationObserver(() => {
|
|
52
|
-
Array.from(t).forEach((a) => {
|
|
53
|
-
a();
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
r.observe(e, {
|
|
57
|
-
childList: !0,
|
|
58
|
-
subtree: !0,
|
|
59
|
-
attributes: !0,
|
|
60
|
-
attributeFilter: ["id"]
|
|
61
|
-
}), o = { observer: r, subscribers: t }, b.set(e, o);
|
|
62
|
-
}
|
|
63
|
-
return o.subscribers.add(i), () => {
|
|
64
|
-
const t = b.get(e);
|
|
65
|
-
t && (t.subscribers.delete(i), t.subscribers.size === 0 && (t.observer.disconnect(), b.delete(e)));
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function S(e, i, o = {}) {
|
|
69
|
-
const t = o.observedAttributes ?? w, r = o.observeRoot ?? !0, a = new MutationObserver(() => i());
|
|
70
|
-
a.observe(e, {
|
|
71
|
-
attributes: !0,
|
|
72
|
-
attributeFilter: [...t]
|
|
73
|
-
});
|
|
74
|
-
const n = /* @__PURE__ */ new Map(), l = () => {
|
|
75
|
-
const s = [];
|
|
76
|
-
f(e, s);
|
|
77
|
-
const d = e.ownerDocument;
|
|
78
|
-
return d && !s.includes(d) && s.push(d), s;
|
|
79
|
-
}, c = () => {
|
|
80
|
-
if (!r) return;
|
|
81
|
-
const s = l(), d = new Set(s);
|
|
82
|
-
for (const [u, h] of n)
|
|
83
|
-
d.has(u) || (h(), n.delete(u));
|
|
84
|
-
for (const u of s)
|
|
85
|
-
n.has(u) || n.set(u, v(u, i));
|
|
86
|
-
};
|
|
87
|
-
return c(), i(), {
|
|
88
|
-
resync() {
|
|
89
|
-
c(), i();
|
|
90
|
-
},
|
|
91
|
-
disconnect() {
|
|
92
|
-
a.disconnect();
|
|
93
|
-
for (const s of n.values())
|
|
94
|
-
s();
|
|
95
|
-
n.clear();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
export {
|
|
100
|
-
S as i,
|
|
101
|
-
p as r,
|
|
102
|
-
R as s
|
|
103
|
-
};
|
|
104
|
-
//# sourceMappingURL=aria-idref-Q0yiSR3p.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aria-idref-Q0yiSR3p.js","sources":["../../src/utils/aria-idref.ts"],"sourcesContent":["/**\n * Shared utilities for resolving `aria-labelledby` and `aria-describedby`\n * IDREF token lists across the Shadow DOM boundary.\n *\n * Selection-control components (`hx-checkbox`, `hx-radio-group`, `hx-switch`,\n * etc.) elevate their semantic surface to the host via `ElementInternals` so\n * that consumer-supplied `aria-labelledby` / `aria-describedby` on the host\n * resolves to light-DOM elements rather than being trapped on inner shadow\n * nodes.\n *\n * Modern Chromium 134+ and Safari 17.4+ expose the IDL element-references API\n * (`internals.ariaLabelledByElements`, `internals.ariaDescribedByElements`).\n * For those engines we resolve token IDs against the host's root node (a\n * Document or ShadowRoot) and assign the resulting elements directly.\n *\n * Older engines fall back to the host-attribute path: the ARIA delegation\n * mixin keeps the original token list in `data-aria-labelledby`/\n * `data-aria-describedby`, which assistive technology cannot follow into the\n * shadow root, but that is the same surface area as the pre-fix code and is\n * not a regression.\n *\n * Component authors do NOT need to wire this directly — see\n * `installAriaIdrefMirror()` for an installable observer that keeps an inner\n * node's `aria-*` attributes in sync with the token list across mutations.\n */\n\n/**\n * Resolves a whitespace-separated IDREF token list to live element references.\n *\n * Searches the host's containing root first (Document or ShadowRoot), then\n * walks up through enclosing shadow hosts, and finally falls back to the\n * top-level Document. Codex round-15 P1: hx-* controls embedded inside an\n * outer component's shadow tree often legitimately reference labels/descriptions\n * declared in the outer document or in an ancestor shadow tree. Restricting\n * resolution to a single root left those controls anonymous on the\n * `ariaLabelledByElements` / `ariaDescribedByElements` path. The IDL\n * element-references API accepts any element regardless of root, so widening\n * the search closes that gap.\n *\n * Codex round-16 P1: when the host is **slotted into** another component\n * (light-DOM child of a shadow-root-bearing element), `host.getRootNode()`\n * is still the document, so IDREF targets declared in the slot owner's\n * shadow root are unreachable through the ancestor-shadow-host chain. We\n * additionally walk `host.assignedSlot.getRootNode()` — that resolves to\n * the slot owner's shadow root — and continue up that root's host chain so\n * cross-shadow IDREF resolution works for the composed-tree slotting\n * pattern. The walk is recursive: a slot owner that is itself slotted into\n * another shadow tree contributes its own ancestor chain too.\n *\n * Tokens that fail to resolve at every level are silently dropped — matching\n * native attribute-string platform behaviour where unresolved tokens are\n * ignored.\n */\nexport function resolveIdrefTokens(host: Element, tokens: string | null): Element[] {\n if (!tokens) return [];\n const ids = tokens.split(/\\s+/).filter(Boolean);\n if (ids.length === 0) return [];\n\n // Build the ordered list of roots to search: host's own root first\n // (closest scope), then walking outward through enclosing shadow hosts,\n // then the top-level Document. Each id resolves at the first root that\n // owns it, mirroring how shadow-encapsulation-aware AT walks the tree.\n const roots: Array<Document | ShadowRoot> = [];\n collectIdrefSearchRoots(host, roots);\n // If host is detached or in an unusual root, also try the top-level\n // ownerDocument as a defensive last resort.\n const ownerDoc = host.ownerDocument;\n if (ownerDoc && !roots.includes(ownerDoc)) {\n roots.push(ownerDoc);\n }\n\n const out: Element[] = [];\n for (const id of ids) {\n for (const root of roots) {\n const el = root.getElementById(id);\n if (el) {\n out.push(el);\n break;\n }\n }\n }\n return out;\n}\n\n/**\n * Walks the composed-tree ancestry of `start` and pushes every Document or\n * ShadowRoot that could legitimately own an IDREF target into `roots` in the\n * order they should be searched (closest scope first). The walk crosses two\n * kinds of boundary:\n *\n * 1. A node sitting inside a ShadowRoot escapes via `root.host`.\n * 2. A node assigned to a `<slot>` in another shadow tree escapes via\n * `node.assignedSlot` — the slot lives in the slot-owner's shadow root,\n * so we hop into that root and keep climbing from there.\n *\n * Both pathways are followed because either may apply at any level. A\n * light-DOM custom element slotted into a shadow component has\n * `getRootNode() === document` AND `assignedSlot !== null`, so the loop\n * picks up document first, then crosses into the slot owner's shadow root\n * via `assignedSlot`. From inside any shadow root we follow `root.host`\n * outward AND, on every hop, check whether that host is itself slotted into\n * yet another shadow tree. De-duplication is by reference identity.\n *\n * @internal\n */\nfunction collectIdrefSearchRoots(start: Element, roots: Array<Document | ShadowRoot>): void {\n const visited = new Set<Document | ShadowRoot>();\n\n const pushRoot = (root: Document | ShadowRoot): void => {\n if (visited.has(root)) return;\n visited.add(root);\n roots.push(root);\n };\n\n // Worklist of nodes whose composed-tree ancestry still needs to be walked.\n // Each entry represents an entry point into a tree we haven't fully\n // explored yet (the original host, plus any hosts we discover via the\n // assignedSlot branch from inside a shadow ancestor).\n const queue: Element[] = [start];\n const queued = new Set<Element>([start]);\n\n while (queue.length > 0) {\n const startNode = queue.shift() as Element;\n let currentNode: Element = startNode;\n let currentRoot: Node | null = currentNode.getRootNode();\n\n // First, if currentNode is in document scope but is slotted into a\n // shadow root somewhere, queue the slot for separate exploration\n // (its tree may contain IDREF targets we need to see).\n const slotFromStart = (currentNode as HTMLElement).assignedSlot ?? null;\n if (slotFromStart && !queued.has(slotFromStart)) {\n queued.add(slotFromStart);\n queue.push(slotFromStart);\n }\n\n while (currentRoot instanceof ShadowRoot) {\n pushRoot(currentRoot);\n const shadowHost: Element | null = currentRoot.host ?? null;\n if (!shadowHost) break;\n // The shadow host itself may be slotted into yet another component.\n // Queue that branch so its tree is searched too.\n const hostSlot = (shadowHost as HTMLElement).assignedSlot ?? null;\n if (hostSlot && !queued.has(hostSlot)) {\n queued.add(hostSlot);\n queue.push(hostSlot);\n }\n currentNode = shadowHost;\n currentRoot = shadowHost.getRootNode();\n }\n\n if (currentRoot instanceof Document) {\n pushRoot(currentRoot);\n }\n }\n}\n\n/**\n * True when the runtime exposes the IDL element-references API on\n * `ElementInternals`. Older Firefox / Safari builds return `undefined`\n * for these accessors.\n */\nexport function supportsIdrefElementReferences(internals: ElementInternals): boolean {\n return (\n 'ariaLabelledByElements' in internals &&\n 'ariaDescribedByElements' in internals &&\n typeof (internals as ElementInternals & { ariaLabelledByElements?: unknown })\n .ariaLabelledByElements !== 'undefined'\n );\n}\n\n/**\n * Mirror snapshot describing what should be applied to inner ARIA-bearing\n * shadow nodes. Components consume this to project the correct attributes\n * onto whichever inner element owns the announced semantic role.\n */\nexport interface AriaIdrefSnapshot {\n /** Computed `aria-labelledby` token list, or `null` to omit. */\n labelledBy: string | null;\n /** Computed `aria-describedby` token list, or `null` to omit. */\n describedBy: string | null;\n}\n\n/**\n * Merges two whitespace-separated token lists, preserving order and removing\n * duplicates. `null`/empty inputs are skipped. Returns `null` when the merged\n * list is empty.\n */\nexport function mergeTokenLists(...lists: Array<string | null | undefined>): string | null {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const list of lists) {\n if (!list) continue;\n for (const token of list.split(/\\s+/)) {\n if (token && !seen.has(token)) {\n seen.add(token);\n out.push(token);\n }\n }\n }\n return out.length > 0 ? out.join(' ') : null;\n}\n\n/**\n * Options accepted by `installAriaIdrefMirror()`.\n */\nexport interface AriaIdrefMirrorOptions {\n /**\n * Attribute names on the host whose mutations should trigger a resync.\n * Defaults to `['aria-labelledby', 'aria-describedby', 'aria-label']` plus\n * the `data-aria-*` mirrors used by `mixinDelegatesAria`.\n */\n observedAttributes?: string[];\n /**\n * Whether to observe the resolved root for `id` attribute and `childList`\n * mutations so that late-inserted IDREF targets and id renames trigger a\n * resync. Defaults to `true`.\n */\n observeRoot?: boolean;\n}\n\n/**\n * Handle returned by `installAriaIdrefMirror()`. Call `disconnect()` from\n * `disconnectedCallback()` to tear the observers down. `resync()` forces an\n * immediate sync — useful from `connectedCallback()` after the host has been\n * re-attached to a new root.\n */\nexport interface AriaIdrefMirrorHandle {\n /** Force an immediate sync. */\n resync(): void;\n /** Tear down all observers and listeners. */\n disconnect(): void;\n}\n\n/**\n * Default attribute set observed on the host for ARIA / data-aria mirroring.\n */\nconst DEFAULT_HOST_OBSERVED_ATTRS: readonly string[] = [\n 'aria-label',\n 'aria-labelledby',\n 'aria-describedby',\n 'data-aria-label',\n 'data-aria-labelledby',\n 'data-aria-describedby',\n];\n\n/**\n * Per-root shared observer registry. Codex round-7 finding #11 (perf).\n *\n * Round-1 created a `subtree: true` MutationObserver per host instance, so a\n * page with N IDREF-aware controls would receive N×M sync callbacks for any\n * unrelated childList/id mutation in the document. This registry collapses\n * the cost: a single observer per Document/ShadowRoot fans mutations out to\n * the registered subscribers (the per-host `sync` callbacks) only.\n *\n * The registry uses a `WeakMap` keyed by root so subscribers are garbage\n * collected with their roots. Subscribers are stored in a `Set` keyed by the\n * `sync` callback identity so re-installation is idempotent.\n *\n * @internal\n */\ninterface SharedRootObserverEntry {\n observer: MutationObserver;\n subscribers: Set<() => void>;\n}\n\nconst sharedRootObservers: WeakMap<Document | ShadowRoot, SharedRootObserverEntry> = new WeakMap();\n\nfunction subscribeToRoot(root: Document | ShadowRoot, sync: () => void): () => void {\n let entry = sharedRootObservers.get(root);\n if (!entry) {\n const subscribers = new Set<() => void>();\n const observer = new MutationObserver(() => {\n // Snapshot subscribers before invocation: a sync() callback may itself\n // resubscribe (e.g. component reattach), and Set iteration over a live\n // collection during mutation is undefined.\n Array.from(subscribers).forEach((fn) => {\n fn();\n });\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['id'],\n });\n entry = { observer, subscribers };\n sharedRootObservers.set(root, entry);\n }\n entry.subscribers.add(sync);\n\n return () => {\n const current = sharedRootObservers.get(root);\n if (!current) return;\n current.subscribers.delete(sync);\n if (current.subscribers.size === 0) {\n current.observer.disconnect();\n sharedRootObservers.delete(root);\n }\n };\n}\n\n/**\n * Installs a `MutationObserver` pair that keeps host ARIA semantics in sync\n * with mutations to consumer-supplied attributes AND late-target / id\n * mutations in the host's resolved root.\n *\n * The `sync` callback is invoked on:\n * 1. Initial install (synchronously)\n * 2. Any change to one of the observed host attributes\n * 3. Any `id` attribute mutation, child insertion, or child removal in the\n * resolved root (Document or ShadowRoot containing the host)\n *\n * Components should call this from `connectedCallback()` and call\n * `handle.disconnect()` from `disconnectedCallback()`. The handle's\n * `resync()` method is safe to call from any lifecycle hook.\n *\n * Costs are bounded: the host observer touches one element; the root\n * observer is shared per `Document`/`ShadowRoot` (codex round-7 #11) so every\n * subscribing host pays a single attach cost regardless of how many other\n * IDREF-aware controls share the root.\n */\nexport function installAriaIdrefMirror(\n host: Element,\n sync: () => void,\n options: AriaIdrefMirrorOptions = {},\n): AriaIdrefMirrorHandle {\n const observedAttributes = options.observedAttributes ?? DEFAULT_HOST_OBSERVED_ATTRS;\n const observeRoot = options.observeRoot ?? true;\n\n // Observe consumer mutations to the host's ARIA / data-aria attributes.\n // We do NOT use `observedAttributes`/`attributeChangedCallback` here because\n // that requires class-level wiring that conflicts with downstream mixins\n // (e.g. `mixinDelegatesAria` already commandeers `attributeChangedCallback`\n // for the same attributes). A scoped `MutationObserver` is reentry-safe.\n const hostObserver = new MutationObserver(() => sync());\n hostObserver.observe(host, {\n attributes: true,\n attributeFilter: [...observedAttributes],\n });\n\n // Subscribe to the shared per-root observer so late-inserted targets and id\n // renames re-resolve through the IDREF path. Round-7 #11 collapses N\n // per-instance subtree observers into one per root, so on pages with many\n // controls a single mutation produces a single subscriber fan-out instead\n // of `controls × mutations` observer callbacks.\n //\n // Codex round-16 P1: subscribe to every root the resolver can match — the\n // host's own root, every enclosing shadow root, and the owner document.\n // Without this, dynamic IDREF targets in ancestor scopes (legitimate per\n // the round-15 widened resolver) bind correctly on first render but never\n // resync when the outer document mutates. We track active subscriptions\n // by root and incrementally diff on `attachRootObservers()` so resync\n // calls don't churn observers when nothing has changed.\n const rootSubscriptions = new Map<Document | ShadowRoot, () => void>();\n\n const computeRootsToObserve = (): Array<Document | ShadowRoot> => {\n const roots: Array<Document | ShadowRoot> = [];\n // Use the same composed-tree walk as `resolveIdrefTokens` so the\n // observer subscribes to every root the resolver can match — including\n // slot-owner shadow roots when the host is light-DOM-slotted into\n // another component (codex round-17 P1). Without this, a late id\n // mutation inside the slot owner's shadow tree never fires resync.\n collectIdrefSearchRoots(host, roots);\n const ownerDoc = host.ownerDocument;\n if (ownerDoc && !roots.includes(ownerDoc)) {\n roots.push(ownerDoc);\n }\n return roots;\n };\n\n const attachRootObservers = (): void => {\n if (!observeRoot) return;\n const wanted = computeRootsToObserve();\n const wantedSet = new Set(wanted);\n // Remove subscriptions for roots no longer in scope (e.g. when the host\n // is moved between trees and the old ancestor chain no longer applies).\n for (const [root, unsub] of rootSubscriptions) {\n if (!wantedSet.has(root)) {\n unsub();\n rootSubscriptions.delete(root);\n }\n }\n // Add subscriptions for new roots (host's root + ancestor shadow roots\n // + owner document) that the resolver can now match against.\n for (const root of wanted) {\n if (!rootSubscriptions.has(root)) {\n rootSubscriptions.set(root, subscribeToRoot(root, sync));\n }\n }\n };\n\n attachRootObservers();\n // Initial sync — caller's `sync` reads the current attribute snapshot.\n sync();\n\n return {\n resync(): void {\n attachRootObservers();\n sync();\n },\n disconnect(): void {\n hostObserver.disconnect();\n for (const unsub of rootSubscriptions.values()) {\n unsub();\n }\n rootSubscriptions.clear();\n },\n };\n}\n"],"names":["resolveIdrefTokens","host","tokens","ids","roots","collectIdrefSearchRoots","ownerDoc","out","id","root","el","start","visited","pushRoot","queue","queued","currentNode","currentRoot","slotFromStart","shadowHost","hostSlot","supportsIdrefElementReferences","internals","DEFAULT_HOST_OBSERVED_ATTRS","sharedRootObservers","subscribeToRoot","sync","entry","subscribers","observer","fn","current","installAriaIdrefMirror","options","observedAttributes","observeRoot","hostObserver","rootSubscriptions","computeRootsToObserve","attachRootObservers","wanted","wantedSet","unsub"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-alert-CLn7CstP.js","sources":["../../src/components/hx-alert/hx-alert.styles.ts","../../src/components/hx-alert/hx-alert.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-alert styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-alert-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * info-50 = #EFF6FE, info-200 = #BEDCFC, info-500 = #0C8BEB, info-800 = #064172,\n * success-50 = #EAFAEC, success-200 = #BAE6C2, success-500 = #3B9E58, success-800 = #0B4D23,\n * warning-50 = #FFF3EA, warning-200 = #FACFAE, warning-500 = #C2711C, warning-800 = #603301,\n * error-50 = #FFF2F0, error-200 = #FCCBC4, error-500 = #E5493E, error-800 = #7A090A,\n * primary-400 = #6AB1B1.\n */\nexport const helixAlertStyles = css`\n :host {\n display: block;\n }\n\n :host(:not([open])) {\n display: none;\n }\n\n /* ─── Screen-reader-only announcement region ─── */\n /* Always present in DOM so AT registers it before content is injected. */\n /* Visually hidden via clip-path technique (superior to display:none which */\n /* removes the element from the AT tree entirely). */\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: 0;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Alert Container ─── */\n\n .alert {\n display: flex;\n align-items: flex-start;\n gap: var(--hx-alert-gap, var(--hx-space-3, 0.75rem));\n padding: var(--hx-alert-padding, var(--hx-space-4, 1rem));\n border: var(--hx-alert-border-width, var(--hx-border-width-thin, 1px)) solid\n var(--hx-alert-border-color, var(--hx-color-info-200, #bedcfc));\n border-radius: var(--hx-alert-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-alert-bg, var(--hx-color-info-50, #eff6fe));\n color: var(--hx-alert-color, var(--hx-color-info-800, #064172));\n font-family: var(--hx-alert-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 }\n\n /* ─── Accent Variant (left border stripe) ─── */\n /* Removes full border and replaces with a left-side accent stripe. */\n /* Common healthcare/enterprise dashboard pattern for dense information UIs. */\n\n .alert--accent {\n border-width: 0;\n border-inline-start: var(--hx-alert-accent-width, 4px) solid\n var(--hx-alert-border-color, var(--hx-color-info-200, #bedcfc));\n border-radius: 0;\n }\n\n /* ─── Severity Label (WCAG 1.4.1) ─── */\n /* Visually hidden — provides a non-color cue for screen readers and users */\n /* who cannot distinguish variants by color alone (e.g. color-blind users). */\n /* Always present regardless of showIcon so severity is never color-only. */\n\n .alert__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 .alert__icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--hx-alert-icon-color, var(--hx-color-info-500, #0c8beb));\n }\n\n .alert__icon svg {\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n fill: currentColor;\n }\n\n /* ─── Title ─── */\n\n .alert__title {\n display: none;\n font-weight: var(--hx-font-weight-semibold, 600);\n margin-bottom: var(--hx-space-1, 0.25rem);\n }\n\n .alert__title--visible {\n display: block;\n }\n\n /* ─── Message ─── */\n\n .alert__message {\n flex: 1;\n min-width: 0;\n }\n\n /* ─── Actions ─── */\n /* Hidden by default; shown via JS slotchange detection to avoid invisible */\n /* margin-top spacing when no actions are slotted. */\n\n .alert__actions {\n display: none;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n margin-top: var(--hx-space-2, 0.5rem);\n }\n\n .alert__actions--visible {\n display: flex;\n }\n\n /* ─── Close Button ─── */\n /* Minimum 44px touch target per WCAG 2.5.8 (Target Size Minimum, AA) and */\n /* Apple HIG / Google Material guidelines. Uses absolute px units to ensure */\n /* the target size is independent of the consumer's base font size. */\n\n .alert__close-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n min-width: var(--hx-touch-target-size, 44px);\n min-height: var(--hx-touch-target-size, 44px);\n margin-inline-start: auto;\n padding: 0;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n background: transparent;\n color: var(--hx-alert-color, var(--hx-color-info-800, #064172));\n cursor: pointer;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: 1;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n opacity var(--hx-transition-fast, 150ms ease);\n opacity: var(--hx-opacity-75, 0.75);\n }\n\n .alert__close-button:hover {\n opacity: var(--hx-opacity-100, 1);\n /* color-mix() is supported in Chrome 111+, Firefox 113+, Safari 16.2+. */\n /* Falls back to transparent (no hover background) in older environments. */\n background-color: color-mix(in srgb, currentColor 10%, transparent);\n }\n\n .alert__close-button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-alert-close-btn-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n opacity: 1;\n }\n\n .alert__close-button svg {\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n fill: currentColor;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .alert__close-button {\n transition: none;\n }\n }\n\n /* ─── Variant: info ─── */\n\n :host([variant='info']) .alert,\n :host(:not([variant])) .alert {\n --hx-alert-bg: var(--hx-color-info-50, #eff6fe);\n --hx-alert-border-color: var(--hx-color-info-200, #bedcfc);\n --hx-alert-color: var(--hx-color-info-800, #064172);\n --hx-alert-icon-color: var(--hx-color-info-500, #0c8beb);\n }\n\n /* ─── Variant: success ─── */\n\n :host([variant='success']) .alert {\n --hx-alert-bg: var(--hx-color-success-50, #eafaec);\n --hx-alert-border-color: var(--hx-color-success-200, #bae6c2);\n --hx-alert-color: var(--hx-color-success-800, #0b4d23);\n --hx-alert-icon-color: var(--hx-color-success-500, #3b9e58);\n }\n\n /* ─── Variant: warning ─── */\n\n :host([variant='warning']) .alert {\n --hx-alert-bg: var(--hx-color-warning-50, #fff3ea);\n --hx-alert-border-color: var(--hx-color-warning-200, #facfae);\n --hx-alert-color: var(--hx-color-warning-800, #603301);\n --hx-alert-icon-color: var(--hx-color-warning-500, #c2711c);\n }\n\n /* ─── Variant: error ─── */\n\n :host([variant='error']) .alert {\n --hx-alert-bg: var(--hx-color-error-50, #fff2f0);\n --hx-alert-border-color: var(--hx-color-error-200, #fccbc4);\n --hx-alert-color: var(--hx-color-error-800, #7a090a);\n --hx-alert-icon-color: var(--hx-color-error-500, #e5493e);\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n /* Belt-and-suspenders: rich per-class HC overrides PLUS the forcedColorsSurface mixin. */\n\n @media (forced-colors: active) {\n .alert {\n border-color: CanvasText;\n }\n\n .alert--accent {\n border-inline-start-color: CanvasText;\n }\n\n .alert__icon svg {\n fill: CanvasText;\n }\n\n .alert__close-button {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixAlertStyles } from './hx-alert.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\n\n/** Alert variant determines visual styling and ARIA semantics. */\nexport type AlertVariant = 'info' | 'success' | 'warning' | 'error';\n\n/** Detail for the hx-close event dispatched by hx-alert. */\nexport interface HxAlertCloseDetail {\n reason: string;\n}\n\n/**\n * A feedback component for communicating status messages, warnings, and errors.\n * Critical for healthcare patient safety alerts.\n *\n * @summary Feedback alert for status messages with variant-based styling and ARIA live regions.\n *\n * @tag hx-alert\n *\n * @slot - Default slot for alert message content.\n * @slot title - Optional title/headline for the alert.\n * @slot icon - Custom icon to override the default variant icon.\n * @slot actions - Action buttons rendered within the alert.\n *\n * @attr {string} heading - Text used to build the close button's contextual aria-label\n * (e.g., \"Close Low blood pressure alert\"). When absent the label falls back to \"Close alert\".\n *\n * @fires {CustomEvent<{reason: string}>} hx-close - Dispatched when the user dismisses the alert.\n * @fires {CustomEvent} hx-after-close - Dispatched after the alert is dismissed.\n *\n * @csspart alert - The outer alert container.\n * @csspart title - The title/headline container.\n * @csspart icon - The icon container.\n * @csspart message - The message content area.\n * @csspart close-button - The dismiss button (only rendered when dismissible).\n * @csspart actions - The actions container.\n *\n * @cssprop [--hx-alert-bg=var(--hx-color-info-50)] - Alert background color.\n * @cssprop [--hx-alert-color=var(--hx-color-info-800)] - Alert text color.\n * @cssprop [--hx-alert-border-color=var(--hx-color-info-200)] - Alert border color.\n * @cssprop [--hx-alert-border-radius=var(--hx-border-radius-md)] - Alert border radius.\n * @cssprop [--hx-alert-border-width=var(--hx-border-width-thin)] - Alert border width.\n * @cssprop [--hx-alert-padding=var(--hx-space-4)] - Alert padding.\n * @cssprop [--hx-alert-gap=var(--hx-space-3)] - Gap between alert elements.\n * @cssprop [--hx-alert-icon-color=var(--hx-color-info-500)] - Alert icon color.\n * @cssprop [--hx-alert-font-family=var(--hx-font-family-sans)] - Alert font family.\n * @cssprop [--hx-touch-target-size=44px] - Minimum touch target size for the close button.\n * @cssprop [--hx-alert-accent-width=4px] - Width of the left border accent stripe.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-error-200] - Color.\n * @cssprop [--hx-color-error-50] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-error-800] - Color.\n * @cssprop [--hx-color-info-200] - Color.\n * @cssprop [--hx-color-info-50] - Color.\n * @cssprop [--hx-color-info-500] - Color.\n * @cssprop [--hx-color-info-800] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-color-success-200] - Color.\n * @cssprop [--hx-color-success-50] - Color.\n * @cssprop [--hx-color-success-500] - Color.\n * @cssprop [--hx-color-success-800] - Color.\n * @cssprop [--hx-color-warning-200] - Color.\n * @cssprop [--hx-color-warning-50] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-warning-800] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-opacity-100] - Opacity.\n * @cssprop [--hx-opacity-75] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-5] - Spacing token.\n * @cssprop [--hx-transition-fast] - Transition timing.\n */\n@customElement('hx-alert')\nexport class HelixAlert extends HelixElement {\n static override styles = [helixAlertStyles, forcedColorsSurface];\n\n // ─── Properties ───\n\n /**\n * Visual variant of the alert that determines colors and ARIA semantics.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'info' | 'success' | 'warning' | 'error' = 'info';\n\n /**\n * Whether the alert can be dismissed by the user.\n * @attr dismissible\n */\n @property({ type: Boolean, reflect: true })\n dismissible = false;\n\n /**\n * Optional heading text that provides context for the close button's accessible label.\n * When provided, the close button is announced as \"Close [heading] alert\".\n * When absent, the close button falls back to \"Close alert\".\n * @attr heading\n */\n @property({ type: String })\n heading = '';\n\n /**\n * Accessible label for the close button. Override for i18n.\n * @attr label-close\n */\n @property({ attribute: 'label-close' }) labelClose = 'Close alert';\n\n /**\n * Whether the alert is visible. Add the `open` attribute to show the alert.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Whether to show the default variant icon. Add `show-icon` attribute to display the icon.\n * @attr show-icon\n */\n @property({ type: Boolean, reflect: true, attribute: 'show-icon' })\n showIcon = false;\n\n /**\n * When true, applies a left border accent stripe instead of a full border.\n * Common healthcare/enterprise dashboard pattern for visual distinction of alert types.\n * @attr accent\n */\n @property({ type: Boolean, reflect: true })\n accent = false;\n\n /**\n * Override for the severity prefix announced to screen readers (e.g., \"Info:\", \"Error:\").\n * When not set, defaults to the English label matching the current variant.\n * @attr severity-label\n */\n @property({ attribute: 'severity-label' })\n severityLabel: string | undefined;\n\n /**\n * CSS selector for the element to return focus to after the alert is dismissed.\n * When set, the component will find and focus the matching element after dismissal.\n * If not set, focus management is the caller's responsibility via the hx-after-close event.\n * @attr return-focus-to\n */\n @property({ type: String, attribute: 'return-focus-to' })\n returnFocusTo: string | null = null;\n\n // ─── State ───\n\n /** @internal */\n @state()\n private _hasActions = false;\n\n /** @internal */\n @state()\n private _hasTitle = false;\n\n // ─── Private Handler References ───\n\n /** @internal */\n private _actionsSlotChangeHandler: (() => void) | null = null;\n /** @internal */\n private _titleSlotChangeHandler: (() => void) | null = null;\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _defaultSeverityLabel(): string {\n const labels: Record<string, string> = {\n info: 'Info:',\n success: 'Success:',\n warning: 'Warning:',\n error: 'Error:',\n };\n return labels[this.variant] ?? '';\n }\n\n /** @internal */\n private get _effectiveSeverityLabel(): string {\n return this.severityLabel ?? this._defaultSeverityLabel();\n }\n\n /** Returns true when the variant requires assertive announcement. */\n /** @internal */\n private get _isAssertive(): boolean {\n return this.variant === 'error';\n }\n\n /**\n * Returns the appropriate ARIA role based on variant.\n * role=\"alert\" implies aria-live=\"assertive\"; role=\"status\" implies aria-live=\"polite\".\n * We do NOT set aria-live explicitly to avoid double-announcements in JAWS.\n */\n /** @internal */\n private get _role(): string {\n return this._isAssertive ? 'alert' : 'status';\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Apply ARIA role to the host element for reliable screen reader support across\n // Shadow DOM boundaries. Placing role on a shadow-internal element has inconsistent\n // AT support in JAWS+Chrome and VoiceOver+Safari combinations (particularly pre-2024).\n this.setAttribute('role', this._role);\n if (!this.open) {\n this.setAttribute('aria-hidden', 'true');\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n const actionsSlot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"actions\"]');\n if (actionsSlot && this._actionsSlotChangeHandler) {\n actionsSlot.removeEventListener('slotchange', this._actionsSlotChangeHandler);\n }\n const titleSlot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"title\"]');\n if (titleSlot && this._titleSlotChangeHandler) {\n titleSlot.removeEventListener('slotchange', this._titleSlotChangeHandler);\n }\n }\n\n override firstUpdated(): void {\n // Track actions slot content to avoid invisible spacing when no actions are slotted.\n const actionsSlot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"actions\"]');\n if (actionsSlot) {\n this._actionsSlotChangeHandler = () => {\n this._hasActions = actionsSlot.assignedNodes({ flatten: true }).length > 0;\n };\n actionsSlot.addEventListener('slotchange', this._actionsSlotChangeHandler);\n }\n\n // Track title slot content so the title container doesn't create dead space when empty.\n const titleSlot = this.renderRoot.querySelector<HTMLSlotElement>('slot[name=\"title\"]');\n if (titleSlot) {\n this._titleSlotChangeHandler = () => {\n this._hasTitle = titleSlot.assignedNodes({ flatten: true }).length > 0;\n };\n titleSlot.addEventListener('slotchange', this._titleSlotChangeHandler);\n }\n }\n\n protected override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('variant')) {\n // Keep host ARIA role in sync with variant (assertive vs. polite).\n this.setAttribute('role', this._role);\n }\n if (changedProperties.has('open')) {\n // Manage aria-hidden in addition to display:none for reliable AT exclusion.\n // When open transitions from false→true, removing aria-hidden signals to AT\n // that the live region content should be announced.\n if (this.open) {\n this.removeAttribute('aria-hidden');\n // Trigger announcement via the sr-only polite live region for ATs (JAWS+Chrome,\n // NVDA) that do not re-announce existing content when aria-hidden is merely removed.\n // We inject text after a microtask so the DOM has settled and the live region\n // is registered by the AT before content arrives.\n const previousOpen = changedProperties.get('open');\n if (previousOpen === false) {\n Promise.resolve().then(() => {\n const announcer = this.renderRoot.querySelector<HTMLElement>('.sr-only');\n if (announcer) {\n announcer.textContent = '';\n // Second microtask ensures the clear is processed before re-injection,\n // guaranteeing the AT sees a content change rather than no-op.\n Promise.resolve().then(() => {\n const prefix = this._effectiveSeverityLabel;\n const message = this.textContent?.trim() ?? '';\n announcer.textContent = prefix ? `${prefix} ${message}` : message;\n });\n }\n });\n }\n } else {\n this.setAttribute('aria-hidden', 'true');\n // Clear the announcer when hidden so stale text is not re-read on next open.\n const announcer = this.renderRoot.querySelector<HTMLElement>('.sr-only');\n if (announcer) {\n announcer.textContent = '';\n }\n }\n }\n }\n\n // ─── Default Icons ───\n\n /** @internal */\n private _renderInfoIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\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 */\n private _renderSuccessIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\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\">\n <path\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 _renderErrorIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\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 _renderDefaultIcon() {\n switch (this.variant) {\n case 'success':\n return this._renderSuccessIcon();\n case 'warning':\n return this._renderWarningIcon();\n case 'error':\n return this._renderErrorIcon();\n case 'info':\n default:\n return this._renderInfoIcon();\n }\n }\n\n /** @internal */\n private _renderCloseIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>`;\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleDismiss(): void {\n this.open = false;\n\n /**\n * Dispatched when the user dismisses the alert.\n * @event hx-close\n */\n this.dispatchEvent(\n new CustomEvent<{ reason: string }>('hx-close', {\n bubbles: true,\n composed: true,\n detail: { reason: 'user' },\n }),\n );\n\n /**\n * Dispatched after the alert is dismissed.\n * @event hx-after-close\n */\n this.dispatchEvent(\n new CustomEvent<void>('hx-after-close', {\n bubbles: true,\n composed: true,\n }),\n );\n\n // Return focus to a designated element if specified via returnFocusTo.\n if (this.returnFocusTo) {\n const target = document.querySelector(this.returnFocusTo);\n if (target instanceof HTMLElement) {\n target.focus();\n }\n }\n }\n\n // ─── Render ───\n\n override render() {\n const classes = {\n alert: true,\n [`alert--${this.variant}`]: true,\n 'alert--accent': this.accent,\n };\n\n // WCAG 1.4.1: Always render a visually-hidden severity label so the variant\n // is never conveyed by color alone, regardless of whether showIcon is set.\n const severityLabel = this._effectiveSeverityLabel;\n\n return html`\n <div\n class=\"sr-only\"\n aria-live=${this._isAssertive ? 'assertive' : 'polite'}\n aria-atomic=\"true\"\n ></div>\n <div part=\"alert\" class=${classMap(classes)}>\n <span class=\"alert__severity-label\">${severityLabel}</span>\n ${this.showIcon\n ? html`\n <div part=\"icon\" class=\"alert__icon\">\n <slot name=\"icon\">${this._renderDefaultIcon()}</slot>\n </div>\n `\n : nothing}\n\n <div part=\"message\" class=\"alert__message\">\n <div part=\"title\" class=\"alert__title ${this._hasTitle ? 'alert__title--visible' : ''}\">\n <slot name=\"title\"></slot>\n </div>\n <slot></slot>\n <div\n part=\"actions\"\n class=\"alert__actions ${this._hasActions ? 'alert__actions--visible' : ''}\"\n >\n <slot name=\"actions\"></slot>\n </div>\n </div>\n\n ${this.dismissible\n ? html`\n <button\n part=\"close-button\"\n class=\"alert__close-button\"\n aria-label=${this.labelClose}\n @click=${this._handleDismiss}\n >\n ${this._renderCloseIcon()}\n </button>\n `\n : nothing}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-alert': HelixAlert;\n }\n}\n\nexport type { HelixAlert as HxAlert };\n"],"names":["helixAlertStyles","css","HelixAlert","HelixElement","actionsSlot","titleSlot","changedProperties","announcer","prefix","message","_a","html","target","classes","severityLabel","classMap","nothing","forcedColorsSurface","__decorateClass","property","state","customElement"],"mappings":";;;;;AAcO,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC6EzB,IAAMC,IAAN,cAAyBC,EAAa;AAAA,EAAtC,cAAA;AAAA,UAAA,GAAA,SAAA,GAUL,KAAA,UAAoD,QAOpD,KAAA,cAAc,IASd,KAAA,UAAU,IAM8B,KAAA,aAAa,eAOrD,KAAA,OAAO,IAOP,KAAA,WAAW,IAQX,KAAA,SAAS,IAiBT,KAAA,gBAA+B,MAM/B,KAAQ,cAAc,IAItB,KAAQ,YAAY,IAKpB,KAAQ,4BAAiD,MAEzD,KAAQ,0BAA+C;AAAA,EAAA;AAAA;AAAA;AAAA,EAK/C,wBAAgC;AAOtC,WANuC;AAAA,MACrC,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IAAA,EAEK,KAAK,OAAO,KAAK;AAAA,EACjC;AAAA;AAAA,EAGA,IAAY,0BAAkC;AAC5C,WAAO,KAAK,iBAAiB,KAAK,sBAAA;AAAA,EACpC;AAAA;AAAA;AAAA,EAIA,IAAY,eAAwB;AAClC,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAY,QAAgB;AAC1B,WAAO,KAAK,eAAe,UAAU;AAAA,EACvC;AAAA;AAAA,EAIS,oBAA0B;AACjC,UAAM,kBAAA,GAIN,KAAK,aAAa,QAAQ,KAAK,KAAK,GAC/B,KAAK,QACR,KAAK,aAAa,eAAe,MAAM;AAAA,EAE3C;AAAA,EAES,uBAA6B;AACpC,UAAM,qBAAA;AACN,UAAMC,IAAc,KAAK,WAAW,cAA+B,sBAAsB;AACzF,IAAIA,KAAe,KAAK,6BACtBA,EAAY,oBAAoB,cAAc,KAAK,yBAAyB;AAE9E,UAAMC,IAAY,KAAK,WAAW,cAA+B,oBAAoB;AACrF,IAAIA,KAAa,KAAK,2BACpBA,EAAU,oBAAoB,cAAc,KAAK,uBAAuB;AAAA,EAE5E;AAAA,EAES,eAAqB;AAE5B,UAAMD,IAAc,KAAK,WAAW,cAA+B,sBAAsB;AACzF,IAAIA,MACF,KAAK,4BAA4B,MAAM;AACrC,WAAK,cAAcA,EAAY,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS;AAAA,IAC3E,GACAA,EAAY,iBAAiB,cAAc,KAAK,yBAAyB;AAI3E,UAAMC,IAAY,KAAK,WAAW,cAA+B,oBAAoB;AACrF,IAAIA,MACF,KAAK,0BAA0B,MAAM;AACnC,WAAK,YAAYA,EAAU,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS;AAAA,IACvE,GACAA,EAAU,iBAAiB,cAAc,KAAK,uBAAuB;AAAA,EAEzE;AAAA,EAEmB,QAAQC,GAA+C;AAMxE,QALA,MAAM,QAAQA,CAAiB,GAC3BA,EAAkB,IAAI,SAAS,KAEjC,KAAK,aAAa,QAAQ,KAAK,KAAK,GAElCA,EAAkB,IAAI,MAAM;AAI9B,UAAI,KAAK;AACP,aAAK,gBAAgB,aAAa,GAKbA,EAAkB,IAAI,MAAM,MAC5B,MACnB,QAAQ,UAAU,KAAK,MAAM;AAC3B,gBAAMC,IAAY,KAAK,WAAW,cAA2B,UAAU;AACvE,UAAIA,MACFA,EAAU,cAAc,IAGxB,QAAQ,UAAU,KAAK,MAAM;;AAC3B,kBAAMC,IAAS,KAAK,yBACdC,MAAUC,IAAA,KAAK,gBAAL,gBAAAA,EAAkB,WAAU;AAC5C,YAAAH,EAAU,cAAcC,IAAS,GAAGA,CAAM,IAAIC,CAAO,KAAKA;AAAA,UAC5D,CAAC;AAAA,QAEL,CAAC;AAAA,WAEE;AACL,aAAK,aAAa,eAAe,MAAM;AAEvC,cAAMF,IAAY,KAAK,WAAW,cAA2B,UAAU;AACvE,QAAIA,MACFA,EAAU,cAAc;AAAA,MAE5B;AAAA,EAEJ;AAAA;AAAA;AAAA,EAKQ,kBAAkB;AACxB,WAAOI;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA,EAGQ,qBAAqB;AAC3B,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA,EAGQ,qBAAqB;AAC3B,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA,EAGQ,mBAAmB;AACzB,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA,EAGQ,qBAAqB;AAC3B,YAAQ,KAAK,SAAA;AAAA,MACX,KAAK;AACH,eAAO,KAAK,mBAAA;AAAA,MACd,KAAK;AACH,eAAO,KAAK,mBAAA;AAAA,MACd,KAAK;AACH,eAAO,KAAK,iBAAA;AAAA,MACd,KAAK;AAAA,MACL;AACE,eAAO,KAAK,gBAAA;AAAA,IAAgB;AAAA,EAElC;AAAA;AAAA,EAGQ,mBAAmB;AACzB,WAAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AA2B7B,QA1BA,KAAK,OAAO,IAMZ,KAAK;AAAA,MACH,IAAI,YAAgC,YAAY;AAAA,QAC9C,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,QAAQ,OAAA;AAAA,MAAO,CAC1B;AAAA,IAAA,GAOH,KAAK;AAAA,MACH,IAAI,YAAkB,kBAAkB;AAAA,QACtC,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA,GAIC,KAAK,eAAe;AACtB,YAAMC,IAAS,SAAS,cAAc,KAAK,aAAa;AACxD,MAAIA,aAAkB,eACpBA,EAAO,MAAA;AAAA,IAEX;AAAA,EACF;AAAA;AAAA,EAIS,SAAS;AAChB,UAAMC,IAAU;AAAA,MACd,OAAO;AAAA,MACP,CAAC,UAAU,KAAK,OAAO,EAAE,GAAG;AAAA,MAC5B,iBAAiB,KAAK;AAAA,IAAA,GAKlBC,IAAgB,KAAK;AAE3B,WAAOH;AAAA;AAAA;AAAA,oBAGS,KAAK,eAAe,cAAc,QAAQ;AAAA;AAAA;AAAA,gCAG9BI,EAASF,CAAO,CAAC;AAAA,8CACHC,CAAa;AAAA,UACjD,KAAK,WACHH;AAAA;AAAA,oCAEwB,KAAK,oBAAoB;AAAA;AAAA,gBAGjDK,CAAO;AAAA;AAAA;AAAA,kDAG+B,KAAK,YAAY,0BAA0B,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAM3D,KAAK,cAAc,4BAA4B,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAM3E,KAAK,cACHL;AAAA;AAAA;AAAA;AAAA,6BAIiB,KAAK,UAAU;AAAA,yBACnB,KAAK,cAAc;AAAA;AAAA,kBAE1B,KAAK,kBAAkB;AAAA;AAAA,gBAG7BK,CAAO;AAAA;AAAA;AAAA,EAGjB;AACF;AAjXad,EACK,SAAS,CAACF,GAAkBiB,CAAmB;AAS/DC,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAT9BjB,EAUX,WAAA,WAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAhB/BjB,EAiBX,WAAA,eAAA,CAAA;AASAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAzBfjB,EA0BX,WAAA,WAAA,CAAA;AAMwCgB,EAAA;AAAA,EAAvCC,EAAS,EAAE,WAAW,cAAA,CAAe;AAAA,GAhC3BjB,EAgC6B,WAAA,cAAA,CAAA;AAOxCgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAtC/BjB,EAuCX,WAAA,QAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM,WAAW,aAAa;AAAA,GA7CvDjB,EA8CX,WAAA,YAAA,CAAA;AAQAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GArD/BjB,EAsDX,WAAA,UAAA,CAAA;AAQAgB,EAAA;AAAA,EADCC,EAAS,EAAE,WAAW,iBAAA,CAAkB;AAAA,GA7D9BjB,EA8DX,WAAA,iBAAA,CAAA;AASAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,mBAAmB;AAAA,GAtE7CjB,EAuEX,WAAA,iBAAA,CAAA;AAMQgB,EAAA;AAAA,EADPE,EAAA;AAAM,GA5EIlB,EA6EH,WAAA,eAAA,CAAA;AAIAgB,EAAA;AAAA,EADPE,EAAA;AAAM,GAhFIlB,EAiFH,WAAA,aAAA,CAAA;AAjFGA,IAANgB,EAAA;AAAA,EADNG,EAAc,UAAU;AAAA,GACZnB,CAAA;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hx-badge-CQXgOXJM.js","sources":["../../src/components/hx-badge/hx-badge.styles.ts","../../src/components/hx-badge/hx-badge.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixBadgeStyles = css`\n :host {\n display: inline-block;\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-1, 0.25rem);\n border-radius: var(--hx-badge-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-badge-bg, var(--hx-color-primary-500, #429797));\n color: var(--hx-badge-color, var(--hx-color-text-on-primary, #0d1825));\n font-family: var(--hx-badge-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-badge-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n white-space: nowrap;\n vertical-align: middle;\n position: relative;\n }\n\n /* ─── Size Variants ─── */\n\n .badge--sm {\n font-size: var(--hx-badge-font-size, var(--hx-font-size-2xs, 0.625rem));\n padding: var(--hx-badge-padding-y, var(--hx-space-0-5, 0.125rem))\n var(--hx-badge-padding-x, var(--hx-space-1-5, 0.375rem));\n }\n\n .badge--md {\n font-size: var(--hx-badge-font-size, var(--hx-font-size-xs, 0.75rem));\n padding: var(--hx-badge-padding-y, var(--hx-space-1, 0.25rem))\n var(--hx-badge-padding-x, var(--hx-space-2, 0.5rem));\n }\n\n .badge--lg {\n font-size: var(--hx-badge-font-size, var(--hx-font-size-sm, 0.875rem));\n padding: var(--hx-badge-padding-y, var(--hx-space-1, 0.25rem))\n var(--hx-badge-padding-x, var(--hx-space-3, 0.75rem));\n }\n\n /* ─── Style Variants ─── */\n\n .badge--primary {\n --hx-badge-bg: var(--hx-badge-primary-bg, var(--hx-color-primary-500, #429797));\n --hx-badge-color: var(--hx-badge-primary-color, var(--hx-color-text-on-primary, #0d1825));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-primary-bg, var(--hx-color-primary-500, #429797))\n );\n }\n\n .badge--secondary {\n --hx-badge-bg: var(--hx-badge-secondary-bg, var(--hx-color-neutral-100, #ebeee9));\n --hx-badge-color: var(--hx-badge-secondary-color, var(--hx-color-neutral-700, #313e4b));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-secondary-bg, var(--hx-color-neutral-100, #ebeee9))\n );\n }\n\n .badge--success {\n --hx-badge-bg: var(--hx-badge-success-bg, var(--hx-color-success-700, #146831));\n --hx-badge-color: var(--hx-badge-success-color, var(--hx-color-neutral-0, #ffffff));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-success-bg, var(--hx-color-success-700, #146831))\n );\n }\n\n .badge--warning {\n --hx-badge-bg: var(--hx-badge-warning-bg, var(--hx-color-warning-500, #c2711c));\n --hx-badge-color: var(--hx-badge-warning-color, var(--hx-color-neutral-900, #0d1825));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-warning-bg, var(--hx-color-warning-500, #c2711c))\n );\n }\n\n .badge--error {\n --hx-badge-bg: var(--hx-badge-error-bg, var(--hx-color-error-500, #e5493e));\n --hx-badge-color: var(--hx-badge-error-color, var(--hx-color-text-on-error, #0d1825));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-error-bg, var(--hx-color-error-500, #e5493e))\n );\n }\n\n .badge--neutral {\n --hx-badge-bg: var(--hx-badge-neutral-bg, var(--hx-color-neutral-200, #d6dbd5));\n --hx-badge-color: var(--hx-badge-neutral-color, var(--hx-color-neutral-700, #313e4b));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-neutral-bg, var(--hx-color-neutral-200, #d6dbd5))\n );\n }\n\n .badge--info {\n --hx-badge-bg: var(--hx-badge-info-bg, var(--hx-color-info-700, #0e5997));\n --hx-badge-color: var(--hx-badge-info-color, var(--hx-color-neutral-0, #ffffff));\n --hx-badge-pulse-color-internal: var(\n --hx-badge-pulse-color,\n var(--hx-badge-info-bg, var(--hx-color-info-700, #0e5997))\n );\n }\n\n /* ─── Semantic Variant Label (WCAG 1.4.1) ─── */\n /* Visually hidden text prefix for semantic variants (success/warning/error/info). */\n /* Ensures the variant is not conveyed by color alone. */\n\n .badge__variant-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 /* ─── Pill Mode ─── */\n\n .badge--pill {\n border-radius: var(--hx-badge-border-radius, var(--hx-border-radius-full, 9999px));\n }\n\n /* ─── Dot Indicator (empty + pulse) ─── */\n\n .badge--dot {\n width: var(--hx-badge-dot-size, var(--hx-space-2, 0.5rem));\n height: var(--hx-badge-dot-size, var(--hx-space-2, 0.5rem));\n padding: 0;\n border-radius: var(--hx-border-radius-full, 9999px);\n }\n\n /* Guard: hide all inner content in dot mode — the dot is purely visual */\n .badge--dot ::slotted(*),\n .badge--dot slot,\n .badge--dot slot[name='prefix'] {\n display: none !important;\n }\n\n /* ─── Pulse Animation ─── */\n\n @keyframes hx-badge-pulse {\n 0%,\n 100% {\n opacity: 1;\n box-shadow: 0 0 0 2px var(--hx-badge-pulse-color-internal, currentColor);\n }\n 50% {\n opacity: var(--hx-opacity-75, 0.75);\n box-shadow: 0 0 0 6px transparent;\n }\n }\n\n .badge--pulse {\n animation: hx-badge-pulse var(--hx-badge-pulse-duration, var(--hx-duration-slow, 2s))\n var(--hx-badge-pulse-easing, var(--hx-easing-in-out, ease-in-out)) infinite;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .badge--pulse {\n animation: none;\n }\n }\n\n /* ─── Remove Button ─── */\n\n .badge__remove-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n margin-inline-start: var(--hx-space-1, 0.25rem);\n cursor: pointer;\n color: inherit;\n opacity: var(--hx-opacity-75, 0.75);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n line-height: 0;\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 }\n\n .badge__remove-button:hover {\n opacity: var(--hx-opacity-100, 1);\n }\n\n .badge__remove-button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, currentColor);\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .badge {\n border: 1px solid CanvasText;\n }\n\n .badge--pulse {\n animation: none;\n }\n\n .badge__remove-button {\n color: ButtonText;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixBadgeStyles } from './hx-badge.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A small status indicator for notifications, counts, and labels.\n *\n * @summary Presentational badge for status indicators, notification counts, and labels.\n *\n * @tag hx-badge\n *\n * @slot - Default slot for badge content (text, number). When empty with pulse enabled, renders as a dot indicator.\n * @slot prefix - Icon or content rendered before the badge text.\n *\n * @fires {CustomEvent<void>} hx-remove - Dispatched when the user clicks the remove button.\n *\n * @csspart badge - The badge element.\n * @csspart remove-button - The remove/dismiss button.\n *\n * @cssprop [--hx-badge-bg=var(--hx-color-primary-500)] - Badge background color. The primary override point.\n * @cssprop [--hx-badge-color=var(--hx-color-neutral-0)] - Badge text color. The primary override point.\n * @cssprop [--hx-badge-font-size] - Badge font size (set per size variant).\n * @cssprop [--hx-badge-font-weight=var(--hx-font-weight-semibold)] - Badge font weight.\n * @cssprop [--hx-badge-font-family=var(--hx-font-family-sans)] - Badge font family.\n * @cssprop [--hx-badge-border-radius=var(--hx-border-radius-md)] - Badge border radius.\n * @cssprop [--hx-badge-padding-x] - Badge horizontal padding (set per size variant).\n * @cssprop [--hx-badge-padding-y] - Badge vertical padding (set per size variant).\n * @cssprop [--hx-badge-pulse-color] - Pulse color matching variant background with reduced opacity.\n * @cssprop [--hx-badge-dot-size=var(--hx-size-2)] - Dot indicator size when rendered without content.\n * @cssprop [--hx-badge-secondary-bg=var(--hx-color-neutral-100)] - Background for the secondary variant.\n * @cssprop [--hx-badge-secondary-color=var(--hx-color-neutral-700)] - Text color for the secondary variant.\n * @cssprop [--hx-badge-info-bg=var(--hx-color-info-700)] - Background for the info variant.\n * @cssprop [--hx-badge-info-color=var(--hx-color-neutral-0)] - Text color for the info variant.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-font-size-2xs] - Font size.\n * @cssprop [--hx-space-0-5] - Spacing token.\n * @cssprop [--hx-space-1-5] - Spacing token.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-badge-pulse-color-internal] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-color-success-700] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-info-700] - Color.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-opacity-75] - Opacity.\n * @cssprop [--hx-badge-pulse-duration=var(--hx-duration-slow)] - CSS custom property.\n * @cssprop [--hx-duration-slow] - Animation duration.\n * @cssprop [--hx-badge-pulse-easing=var(--hx-easing-in-out)] - CSS custom property.\n * @cssprop [--hx-easing-in-out] - CSS custom property.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-opacity-100] - Opacity.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n */\n@customElement('hx-badge')\nexport class HelixBadge extends HelixElement {\n static override styles = [helixBadgeStyles, forcedColorsSurface];\n\n /**\n * Visual style variant of the badge.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'neutral' | 'info' =\n 'primary';\n\n /**\n * Size of the badge.\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 badge uses fully rounded (pill) styling.\n * @attr pill\n */\n @property({ type: Boolean, reflect: true })\n pill = false;\n\n /**\n * Whether the badge displays an animated pulse for attention.\n * @attr pulse\n */\n @property({ type: Boolean, reflect: true })\n pulse = false;\n\n /**\n * Whether the badge renders a dismiss button.\n * @attr removable\n */\n @property({ type: Boolean, reflect: true })\n removable = false;\n\n /**\n * Numeric count to display. When set, renders the count as badge content.\n * When count exceeds `max`, displays `${max}+` (e.g. `99+`).\n * @attr count\n */\n @property({ type: Number, reflect: true })\n count: number | undefined = undefined;\n\n /**\n * Maximum count value before truncation to `${max}+`. Defaults to 99.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 99;\n\n /**\n * Accessible label for the dot indicator mode (pulse + empty slot).\n * Required for WCAG 4.1.2 compliance when using the dot indicator pattern.\n * Example: `dot-label=\"3 new messages\"`.\n * @attr dot-label\n */\n @property({ type: String, attribute: 'dot-label' })\n dotLabel = '';\n\n /**\n * Accessible label for the remove button. Should describe what is being removed.\n * Defaults to \"Remove\". For better accessibility, include context: e.g. \"Remove Critical badge\".\n * @attr remove-label\n */\n @property({ type: String, attribute: 'remove-label' })\n removeLabel = 'Remove';\n\n /**\n * Tracks whether the default slot has assigned content.\n * @internal\n */\n @state()\n private _hasSlotContent = false;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-badge', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize as 'sm' | 'md' | 'lg';\n }\n }\n\n // ─── Slot Change Handling ───\n\n /** @internal */\n private _handleSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const nodes = slot.assignedNodes({ flatten: true });\n // Check if any assigned node has non-whitespace content\n this._hasSlotContent = nodes.some((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) return true;\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent ?? '').trim().length > 0;\n }\n return false;\n });\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleRemove(): void {\n this.dispatchEvent(\n new CustomEvent<void>('hx-remove', {\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // ─── Count Display ───\n\n /** @internal */\n private get _countDisplay(): string {\n if (this.count === undefined) return '';\n return this.count > this.max ? `${this.max}+` : String(this.count);\n }\n\n // ─── WCAG 1.4.1: Semantic variant label map ───\n // Variants that carry semantic meaning beyond decoration need a non-color cue.\n // Visually-hidden text is prepended so screen reader users and color-blind\n // users get the variant context even when no icon is slotted.\n\n /** @internal */\n private static readonly _SEMANTIC_VARIANT_LABELS: Partial<Record<HelixBadge['variant'], string>> =\n {\n success: 'Success',\n warning: 'Warning',\n error: 'Error',\n info: 'Info',\n };\n\n /** @internal */\n private get _semanticVariantLabel(): string {\n return HelixBadge._SEMANTIC_VARIANT_LABELS[this.variant] ?? '';\n }\n\n // ─── Render ───\n\n override render() {\n const hasCount = this.count !== undefined;\n const isDot = !this._hasSlotContent && !hasCount && this.pulse;\n\n if (isDot && !this.dotLabel) {\n devWarn(\n 'hx-badge',\n 'Dot badge is missing an accessible label. Set `dotLabel` so screen readers can announce the badge purpose (WCAG 4.1.2).',\n );\n }\n\n const classes = {\n badge: true,\n [`badge--${this.variant}`]: true,\n [`badge--${this.size}`]: true,\n 'badge--pill': this.pill,\n 'badge--pulse': this.pulse,\n 'badge--dot': isDot,\n };\n\n const variantLabel = this._semanticVariantLabel;\n\n return html`\n <span\n part=\"badge\"\n class=${classMap(classes)}\n role=${isDot && this.dotLabel ? 'img' : nothing}\n aria-label=${isDot && this.dotLabel ? this.dotLabel : nothing}\n aria-live=${hasCount ? 'polite' : nothing}\n >\n ${variantLabel\n ? html`<span class=\"badge__variant-label\">${variantLabel}: </span>`\n : nothing}\n ${isDot ? nothing : html`<slot name=\"prefix\"></slot>`}\n ${hasCount ? this._countDisplay : html`<slot @slotchange=${this._handleSlotChange}></slot>`}\n ${this.removable\n ? html`<button\n part=\"remove-button\"\n class=\"badge__remove-button\"\n aria-label=${this.removeLabel}\n @click=${this._handleRemove}\n >\n <svg viewBox=\"0 0 12 12\" aria-hidden=\"true\" width=\"10\" height=\"10\">\n <path\n d=\"M2.22 2.22a.75.75 0 011.06 0L6 4.94l2.72-2.72a.75.75 0 011.06 1.06L7.06 6l2.72 2.72a.75.75 0 01-1.06 1.06L6 7.06 3.28 9.78a.75.75 0 01-1.06-1.06L4.94 6 2.22 3.28a.75.75 0 010-1.06z\"\n fill=\"currentColor\"\n />\n </svg>\n </button>`\n : nothing}\n </span>\n `;\n }\n}\n\n/** Canonical type alias for the hx-badge component. */\nexport type HxBadge = HelixBadge;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-badge': HelixBadge;\n }\n}\n"],"names":["helixBadgeStyles","css","HelixBadge","HelixElement","legacySize","e","nodes","node","hasCount","isDot","classes","variantLabel","html","classMap","nothing","forcedColorsSurface","__decorateClass","property","state","customElement"],"mappings":"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"}
|