@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,925 @@
|
|
|
1
|
+
import { css as x, html as f, nothing as u } from "lit";
|
|
2
|
+
import { property as m, state as c, customElement as g, query as E } from "lit/decorators.js";
|
|
3
|
+
import { a as I } from "./forced-colors-CTEDFRGa.js";
|
|
4
|
+
import { s as y, i as w, r as S } from "./aria-idref-CxvyzfQS.js";
|
|
5
|
+
import { f as C } from "./aria-flatten-DY6v2vah.js";
|
|
6
|
+
import { H as A } from "./helix-element-BNEYeiys.js";
|
|
7
|
+
import { classMap as k } from "lit/directives/class-map.js";
|
|
8
|
+
const L = x`
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
contain: layout style;
|
|
12
|
+
font-family: var(--hx-tree-font-family, var(--hx-font-family-sans, sans-serif));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
* {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.tree {
|
|
20
|
+
display: block;
|
|
21
|
+
outline: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.tree:focus-visible {
|
|
25
|
+
outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);
|
|
26
|
+
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
27
|
+
border-radius: var(--hx-border-radius-sm, 0.25rem);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ─── High Contrast Mode (forced-colors) ─── */
|
|
31
|
+
|
|
32
|
+
@media (forced-colors: active) {
|
|
33
|
+
.tree:focus-visible {
|
|
34
|
+
outline: 3px solid Highlight;
|
|
35
|
+
outline-offset: 2px;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
function v(e) {
|
|
40
|
+
let t = e;
|
|
41
|
+
for (; t; ) {
|
|
42
|
+
if (t instanceof Element && t.tagName.toLowerCase() === "hx-tree-view")
|
|
43
|
+
return t;
|
|
44
|
+
if (t instanceof Element && t.assignedSlot) {
|
|
45
|
+
t = t.assignedSlot;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const s = t.parentNode;
|
|
49
|
+
if (s) {
|
|
50
|
+
t = s;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (t instanceof ShadowRoot) {
|
|
54
|
+
t = t.host;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function R(e) {
|
|
62
|
+
let t = e;
|
|
63
|
+
for (; t; ) {
|
|
64
|
+
if (t instanceof Element && t.tagName.toLowerCase() === "hx-tree-item")
|
|
65
|
+
return t;
|
|
66
|
+
if (t instanceof Element && t.assignedSlot) {
|
|
67
|
+
t = t.assignedSlot;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const s = t.parentNode;
|
|
71
|
+
if (s) {
|
|
72
|
+
t = s;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (t instanceof ShadowRoot) {
|
|
76
|
+
t = t.host;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
var H = Object.defineProperty, T = Object.getOwnPropertyDescriptor, b = (e, t, s, i) => {
|
|
84
|
+
for (var r = i > 1 ? void 0 : i ? T(t, s) : t, n = e.length - 1, l; n >= 0; n--)
|
|
85
|
+
(l = e[n]) && (r = (i ? l(t, s, r) : l(r)) || r);
|
|
86
|
+
return i && r && H(t, s, r), r;
|
|
87
|
+
};
|
|
88
|
+
let d = class extends A {
|
|
89
|
+
constructor() {
|
|
90
|
+
super(...arguments), this.label = "", this.selection = "none", this._currentIndex = 0, this._hasVisibleItems = !1, this._supportsIdrefRefs = !0, this._ariaMirror = null, this._resolvedAccessibleName = "", this._cachedVisibleItems = null, this._handleItemSelectHost = (e) => {
|
|
91
|
+
if (!(e instanceof CustomEvent)) return;
|
|
92
|
+
const t = e.detail, s = t == null ? void 0 : t.item;
|
|
93
|
+
s && v(s) !== this || this._handleTreeItemSelect(e);
|
|
94
|
+
}, this._handleHostKeyDown = (e) => {
|
|
95
|
+
const t = e.target;
|
|
96
|
+
t instanceof Element && v(t) !== this || this._handleKeyDown(e);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Invalidate the visible-items cache. Call after any expand/collapse or structural change.
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
_invalidateVisibleItemsCache() {
|
|
104
|
+
this._cachedVisibleItems = null;
|
|
105
|
+
}
|
|
106
|
+
// ─── Internal Helpers ───
|
|
107
|
+
/**
|
|
108
|
+
* Returns a flat ordered list of all visible (not inside a collapsed item) hx-tree-items
|
|
109
|
+
* in depth-first order. Result is cached; invalidated on expand/collapse/slotchange.
|
|
110
|
+
*/
|
|
111
|
+
/** @internal */
|
|
112
|
+
_getVisibleItems() {
|
|
113
|
+
return this._cachedVisibleItems || (this._cachedVisibleItems = this._collectVisibleItems(this)), this._cachedVisibleItems;
|
|
114
|
+
}
|
|
115
|
+
/** @internal */
|
|
116
|
+
_collectVisibleItems(e) {
|
|
117
|
+
const t = [];
|
|
118
|
+
for (const s of Array.from(e.children))
|
|
119
|
+
if (s.tagName.toLowerCase() === "hx-tree-item") {
|
|
120
|
+
const i = s;
|
|
121
|
+
t.push(i), i.expanded && t.push(...this._collectVisibleItems(i));
|
|
122
|
+
} else
|
|
123
|
+
t.push(...this._collectVisibleItems(s));
|
|
124
|
+
return t;
|
|
125
|
+
}
|
|
126
|
+
/** @internal */
|
|
127
|
+
_getSelectedItems() {
|
|
128
|
+
return Array.from(this.querySelectorAll("hx-tree-item[selected]"));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Updates the roving tabindex across all visible items so that only the
|
|
132
|
+
* item at `activeIndex` has `tabindex="0"`. All others receive `tabindex="-1"`.
|
|
133
|
+
* This is called whenever the active item changes (navigation, initial render).
|
|
134
|
+
*/
|
|
135
|
+
/** @internal */
|
|
136
|
+
_updateRovingTabindex(e, t) {
|
|
137
|
+
e.forEach((s, i) => {
|
|
138
|
+
s.setRovingActive(i === t);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** @internal */
|
|
142
|
+
_focusItem(e) {
|
|
143
|
+
var i;
|
|
144
|
+
const t = this._getVisibleItems();
|
|
145
|
+
if (t.length === 0) return;
|
|
146
|
+
const s = Math.max(0, Math.min(e, t.length - 1));
|
|
147
|
+
this._currentIndex = s, this._updateRovingTabindex(t, s), (i = t[s]) == null || i.focus();
|
|
148
|
+
}
|
|
149
|
+
// ─── Event Handling ───
|
|
150
|
+
/** @internal */
|
|
151
|
+
_handleTreeItemSelect(e) {
|
|
152
|
+
if (!(e instanceof CustomEvent)) return;
|
|
153
|
+
const s = e.detail.item;
|
|
154
|
+
if (this.selection !== "none") {
|
|
155
|
+
if (this.selection === "single") {
|
|
156
|
+
const i = s.selected;
|
|
157
|
+
this._getSelectedItems().forEach((r) => {
|
|
158
|
+
r.selected = !1;
|
|
159
|
+
}), s.selected = !i;
|
|
160
|
+
} else this.selection === "multiple" && (s.selected = !s.selected);
|
|
161
|
+
this.dispatchEvent(
|
|
162
|
+
new CustomEvent("hx-select", {
|
|
163
|
+
bubbles: !0,
|
|
164
|
+
composed: !0,
|
|
165
|
+
detail: { item: s, selected: s.selected }
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** @internal */
|
|
171
|
+
_handleKeyDown(e) {
|
|
172
|
+
var r, n, l;
|
|
173
|
+
const t = this._getVisibleItems();
|
|
174
|
+
if (t.length === 0) return;
|
|
175
|
+
let s = this._currentIndex;
|
|
176
|
+
const i = document.activeElement;
|
|
177
|
+
for (let a = 0; a < t.length; a++)
|
|
178
|
+
if (t[a] === i || (n = (r = t[a]) == null ? void 0 : r.shadowRoot) != null && n.activeElement) {
|
|
179
|
+
s = a;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
switch (e.key) {
|
|
183
|
+
case "ArrowDown": {
|
|
184
|
+
e.preventDefault();
|
|
185
|
+
const a = s < t.length - 1 ? s + 1 : 0;
|
|
186
|
+
this._focusItem(a);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
case "ArrowUp": {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
const a = s > 0 ? s - 1 : t.length - 1;
|
|
192
|
+
this._focusItem(a);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "ArrowLeft": {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
const a = t[s];
|
|
198
|
+
if (!a || a.disabled) break;
|
|
199
|
+
if (a.expanded && a.hasChildItems)
|
|
200
|
+
a.expanded = !1, this._invalidateVisibleItemsCache();
|
|
201
|
+
else {
|
|
202
|
+
const p = (l = a.parentElement) == null ? void 0 : l.closest("hx-tree-item");
|
|
203
|
+
if (p) {
|
|
204
|
+
const _ = t.indexOf(p);
|
|
205
|
+
_ >= 0 && this._focusItem(_);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
case "ArrowRight": {
|
|
211
|
+
e.preventDefault();
|
|
212
|
+
const a = t[s];
|
|
213
|
+
if (!a || a.disabled) break;
|
|
214
|
+
a.hasChildItems && (a.expanded ? this._focusItem(s + 1) : (a.expanded = !0, this._invalidateVisibleItemsCache()));
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case "Home": {
|
|
218
|
+
e.preventDefault(), this._focusItem(0);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
case "End": {
|
|
222
|
+
e.preventDefault(), this._focusItem(t.length - 1);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
default: {
|
|
226
|
+
if (e.key.length === 1) {
|
|
227
|
+
e.preventDefault();
|
|
228
|
+
const a = this._findTypeaheadMatch(e.key.toLowerCase(), s);
|
|
229
|
+
a !== -1 && this._focusItem(a);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Finds the next visible item (starting after `currentIndex`, wrapping around) whose
|
|
237
|
+
* label text begins with the given lowercase character. Returns -1 if no match.
|
|
238
|
+
* @internal
|
|
239
|
+
*/
|
|
240
|
+
_findTypeaheadMatch(e, t) {
|
|
241
|
+
const s = this._getVisibleItems();
|
|
242
|
+
if (s.length === 0) return -1;
|
|
243
|
+
for (let i = 1; i <= s.length; i++) {
|
|
244
|
+
const r = (t + i) % s.length, n = s[r];
|
|
245
|
+
if (n && n.labelText.toLowerCase().startsWith(e))
|
|
246
|
+
return r;
|
|
247
|
+
}
|
|
248
|
+
return -1;
|
|
249
|
+
}
|
|
250
|
+
/** @internal */
|
|
251
|
+
_handleFocusIn(e) {
|
|
252
|
+
e.target === e.currentTarget && this._getVisibleItems().length > 0 && this._focusItem(this._currentIndex);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Compute and push ARIA position metadata (level, posInSet, setSize, selectable) to all
|
|
256
|
+
* direct hx-tree-item children of a container in a single O(n) pass.
|
|
257
|
+
* Each item also recurses for its own children, building the full tree in O(total-items) total.
|
|
258
|
+
* @internal
|
|
259
|
+
*/
|
|
260
|
+
_updateAriaMetadataForContainer(e, t) {
|
|
261
|
+
const s = this.selection === "single" || this.selection === "multiple", i = Array.from(e.children).filter(
|
|
262
|
+
(n) => n.tagName.toLowerCase() === "hx-tree-item"
|
|
263
|
+
), r = i.length;
|
|
264
|
+
i.forEach((n, l) => {
|
|
265
|
+
n.setAriaMetadata(t, l + 1, r, s), this._updateAriaMetadataForContainer(n, t + 1);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Initializes the roving tabindex after items are first slotted in.
|
|
270
|
+
* Ensures the active item (index 0 by default) has tabindex="0" from the start,
|
|
271
|
+
* so a Tab into the tree lands directly on the first item without a redirect.
|
|
272
|
+
* Also updates `_hasVisibleItems` so the container tabindex re-renders correctly.
|
|
273
|
+
* Pushes O(n) ARIA metadata to all items to replace the O(n^2) per-item ancestor walk.
|
|
274
|
+
*/
|
|
275
|
+
/** @internal */
|
|
276
|
+
_handleSlotChange() {
|
|
277
|
+
this._invalidateVisibleItemsCache(), this._updateAriaMetadataForContainer(this, 1);
|
|
278
|
+
const e = this._getVisibleItems();
|
|
279
|
+
if (this._hasVisibleItems = e.length > 0, e.length === 0) return;
|
|
280
|
+
const t = Math.min(this._currentIndex, e.length - 1);
|
|
281
|
+
this._currentIndex = t, this._updateRovingTabindex(e, t);
|
|
282
|
+
}
|
|
283
|
+
// ─── Lifecycle ───
|
|
284
|
+
connectedCallback() {
|
|
285
|
+
super.connectedCallback();
|
|
286
|
+
const e = this.constructor;
|
|
287
|
+
this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : y(this._internals), this.addEventListener("keydown", this._handleHostKeyDown), this.addEventListener("hx-tree-item-select", this._handleItemSelectHost), this._syncHostAriaSemantics(), this._ariaMirror = w(this, () => {
|
|
288
|
+
this._syncHostAriaSemantics();
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
disconnectedCallback() {
|
|
292
|
+
var e;
|
|
293
|
+
super.disconnectedCallback(), this.removeEventListener("keydown", this._handleHostKeyDown), this.removeEventListener("hx-tree-item-select", this._handleItemSelectHost), (e = this._ariaMirror) == null || e.disconnect(), this._ariaMirror = null;
|
|
294
|
+
}
|
|
295
|
+
updated(e) {
|
|
296
|
+
super.updated(e), (e.has("label") || e.has("selection")) && this._syncHostAriaSemantics(), e.has("selection") && this._updateAriaMetadataForContainer(this, 1);
|
|
297
|
+
}
|
|
298
|
+
firstUpdated() {
|
|
299
|
+
this.hasAttribute("aria-label") || this.hasAttribute("aria-labelledby") || this.label;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Mirror tree semantics onto the host via ElementInternals so consumer-
|
|
303
|
+
* supplied `aria-label`, `aria-labelledby`, and the `label` property all
|
|
304
|
+
* reach the announced control. Falls back to a flattened-string label on
|
|
305
|
+
* engines that do not implement `ariaLabelledByElements`.
|
|
306
|
+
*
|
|
307
|
+
* Codex push-gate round-1 lift (mirrors hx-menu round-8 finding 1): on
|
|
308
|
+
* the legacy fallback path the inner `<div role="tree" aria-label="…">`
|
|
309
|
+
* is the announced surface. If we ALSO write `internals.role = 'tree'`
|
|
310
|
+
* onto the host, AT sees TWO trees for one logical surface — the
|
|
311
|
+
* duplicate-surface problem host-canonical migration is meant to
|
|
312
|
+
* eliminate. Suppress host role + label writes on the fallback path; the
|
|
313
|
+
* inner element is the canonical announced surface there. Modern path
|
|
314
|
+
* keeps the host as the canonical surface and clears the inner role.
|
|
315
|
+
* @internal
|
|
316
|
+
*/
|
|
317
|
+
_syncHostAriaSemantics() {
|
|
318
|
+
var l;
|
|
319
|
+
const e = this._internals;
|
|
320
|
+
this._supportsIdrefRefs ? (e.role = "tree", e.ariaMultiSelectable = this.selection === "none" ? null : this.selection === "multiple" ? "true" : "false") : (e.role = null, e.ariaLabel = null, e.ariaMultiSelectable = null);
|
|
321
|
+
const t = ((l = this.getAttribute("aria-label")) == null ? void 0 : l.trim()) || "", s = this.getAttribute("aria-labelledby"), i = S(this, s), r = i.length > 0;
|
|
322
|
+
if (this._supportsIdrefRefs) {
|
|
323
|
+
const a = e;
|
|
324
|
+
a.ariaLabelledByElements = r ? i : null;
|
|
325
|
+
}
|
|
326
|
+
let n = "";
|
|
327
|
+
r ? (n = i.map((p) => C(p)).filter(Boolean).join(" ") || t || this.label || "Tree", this._supportsIdrefRefs && (e.ariaLabel = null)) : t ? (n = t, this._supportsIdrefRefs && (e.ariaLabel = t)) : (n = this.label || "Tree", this._supportsIdrefRefs && (e.ariaLabel = n)), this._resolvedAccessibleName !== n && (this._resolvedAccessibleName = n, this._supportsIdrefRefs || this.requestUpdate());
|
|
328
|
+
}
|
|
329
|
+
// ─── Render ───
|
|
330
|
+
render() {
|
|
331
|
+
const e = this._hasVisibleItems ? "-1" : "0";
|
|
332
|
+
if (this._supportsIdrefRefs)
|
|
333
|
+
return f`
|
|
334
|
+
<div part="tree" class="tree" tabindex=${e} @focusin=${this._handleFocusIn}>
|
|
335
|
+
<slot @slotchange=${this._handleSlotChange}></slot>
|
|
336
|
+
</div>
|
|
337
|
+
`;
|
|
338
|
+
const t = this._resolvedAccessibleName || this.label || "Tree";
|
|
339
|
+
return f`
|
|
340
|
+
<div
|
|
341
|
+
part="tree"
|
|
342
|
+
class="tree"
|
|
343
|
+
role="tree"
|
|
344
|
+
tabindex=${e}
|
|
345
|
+
aria-label=${t}
|
|
346
|
+
aria-multiselectable=${this.selection === "none" ? u : this.selection === "multiple" ? "true" : "false"}
|
|
347
|
+
@focusin=${this._handleFocusIn}
|
|
348
|
+
>
|
|
349
|
+
<slot @slotchange=${this._handleSlotChange}></slot>
|
|
350
|
+
</div>
|
|
351
|
+
`;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
d.styles = [L, I];
|
|
355
|
+
d.__testSupportsIdrefRefsOverride = null;
|
|
356
|
+
b([
|
|
357
|
+
m({ type: String, reflect: !0 })
|
|
358
|
+
], d.prototype, "label", 2);
|
|
359
|
+
b([
|
|
360
|
+
m({ type: String, reflect: !0 })
|
|
361
|
+
], d.prototype, "selection", 2);
|
|
362
|
+
b([
|
|
363
|
+
c()
|
|
364
|
+
], d.prototype, "_currentIndex", 2);
|
|
365
|
+
b([
|
|
366
|
+
c()
|
|
367
|
+
], d.prototype, "_hasVisibleItems", 2);
|
|
368
|
+
d = b([
|
|
369
|
+
g("hx-tree-view")
|
|
370
|
+
], d);
|
|
371
|
+
const $ = x`
|
|
372
|
+
:host {
|
|
373
|
+
display: block;
|
|
374
|
+
contain: layout style;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
* {
|
|
378
|
+
box-sizing: border-box;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* ─── Item Container ─── */
|
|
382
|
+
|
|
383
|
+
.item {
|
|
384
|
+
display: block;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* ─── Item Row ─── */
|
|
388
|
+
|
|
389
|
+
.item-row {
|
|
390
|
+
display: flex;
|
|
391
|
+
align-items: center;
|
|
392
|
+
min-height: var(--hx-touch-target-min, 44px);
|
|
393
|
+
gap: var(--hx-tree-item-gap, var(--hx-space-2, 0.5rem));
|
|
394
|
+
padding: var(--hx-tree-item-padding-y, var(--hx-space-2, 0.5rem))
|
|
395
|
+
var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem));
|
|
396
|
+
padding-inline-start: calc(
|
|
397
|
+
var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem)) + var(--_indent-level, 0) *
|
|
398
|
+
var(--hx-tree-indent-size, 1.5rem)
|
|
399
|
+
);
|
|
400
|
+
border-radius: var(--hx-tree-item-border-radius, var(--hx-border-radius-sm, 0.25rem));
|
|
401
|
+
cursor: pointer;
|
|
402
|
+
outline: none;
|
|
403
|
+
color: var(--hx-tree-item-color, var(--hx-color-neutral-900, #0d1825));
|
|
404
|
+
font-family: var(--hx-tree-item-font-family, var(--hx-font-family-sans, sans-serif));
|
|
405
|
+
font-size: var(--hx-tree-item-font-size, var(--hx-font-size-sm, 0.875rem));
|
|
406
|
+
line-height: var(--hx-line-height-normal, 1.5);
|
|
407
|
+
transition: background-color var(--hx-transition-fast, 150ms ease);
|
|
408
|
+
user-select: none;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.item-row:hover {
|
|
412
|
+
background-color: var(--hx-tree-item-hover-bg, var(--hx-color-neutral-100, #ebeee9));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.item-row:focus-visible {
|
|
416
|
+
outline: var(--hx-focus-ring-width, 2px) solid
|
|
417
|
+
var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
|
|
418
|
+
outline-offset: var(--hx-focus-ring-offset, -2px);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* ─── Selected State ─── */
|
|
422
|
+
|
|
423
|
+
:host([selected]) .item-row {
|
|
424
|
+
background-color: var(--hx-tree-item-selected-bg, var(--hx-color-primary-100, #dbf0f0));
|
|
425
|
+
color: var(--hx-tree-item-selected-color, var(--hx-color-primary-800, #07494a));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
:host([selected]) .item-row:hover {
|
|
429
|
+
background-color: var(--hx-tree-item-selected-hover-bg, var(--hx-color-primary-200, #bce1e1));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* ─── Disabled State ─── */
|
|
433
|
+
|
|
434
|
+
:host([disabled]) .item-row {
|
|
435
|
+
opacity: var(--hx-opacity-disabled, 0.5);
|
|
436
|
+
cursor: not-allowed;
|
|
437
|
+
pointer-events: none;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* ─── Expand Icon ─── */
|
|
441
|
+
|
|
442
|
+
.expand-icon {
|
|
443
|
+
display: flex;
|
|
444
|
+
align-items: center;
|
|
445
|
+
justify-content: center;
|
|
446
|
+
flex-shrink: 0;
|
|
447
|
+
width: var(--hx-space-4, 1rem);
|
|
448
|
+
height: var(--hx-space-4, 1rem);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.expand-btn {
|
|
452
|
+
display: flex;
|
|
453
|
+
align-items: center;
|
|
454
|
+
justify-content: center;
|
|
455
|
+
width: var(--hx-space-4, 1rem);
|
|
456
|
+
height: var(--hx-space-4, 1rem);
|
|
457
|
+
padding: 0;
|
|
458
|
+
border: none;
|
|
459
|
+
background: transparent;
|
|
460
|
+
color: var(--hx-tree-item-expand-icon-color, var(--hx-color-neutral-500, #66787b));
|
|
461
|
+
cursor: pointer;
|
|
462
|
+
border-radius: var(--hx-border-radius-sm, 0.25rem);
|
|
463
|
+
transition: transform var(--hx-transition-fast, 150ms ease);
|
|
464
|
+
pointer-events: auto;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.expand-btn:hover {
|
|
468
|
+
background-color: var(
|
|
469
|
+
--hx-tree-item-expand-hover-bg,
|
|
470
|
+
var(--hx-overlay-black-6, rgba(0, 0, 0, 0.06))
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.expand-btn:focus-visible {
|
|
475
|
+
outline: var(--hx-focus-ring-width, 2px) solid
|
|
476
|
+
var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
|
|
477
|
+
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.expand-btn svg {
|
|
481
|
+
width: var(--hx-space-3, 0.75rem);
|
|
482
|
+
height: var(--hx-space-3, 0.75rem);
|
|
483
|
+
stroke: currentColor;
|
|
484
|
+
fill: none;
|
|
485
|
+
stroke-width: 2;
|
|
486
|
+
stroke-linecap: round;
|
|
487
|
+
stroke-linejoin: round;
|
|
488
|
+
transition: transform var(--hx-transition-fast, 150ms ease);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
:host([expanded]) .expand-btn svg {
|
|
492
|
+
transform: rotate(90deg);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.expand-placeholder {
|
|
496
|
+
display: block;
|
|
497
|
+
width: var(--hx-space-4, 1rem);
|
|
498
|
+
flex-shrink: 0;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/* ─── Icon Slot ─── */
|
|
502
|
+
|
|
503
|
+
.item-icon {
|
|
504
|
+
display: flex;
|
|
505
|
+
align-items: center;
|
|
506
|
+
flex-shrink: 0;
|
|
507
|
+
color: var(--hx-tree-item-icon-color, var(--hx-color-neutral-500, #66787b));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.item-icon:empty {
|
|
511
|
+
display: none;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/* ─── Label ─── */
|
|
515
|
+
|
|
516
|
+
.item-label {
|
|
517
|
+
flex: 1;
|
|
518
|
+
min-width: 0;
|
|
519
|
+
overflow: hidden;
|
|
520
|
+
text-overflow: ellipsis;
|
|
521
|
+
white-space: nowrap;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/* ─── Children (animated) ─── */
|
|
525
|
+
|
|
526
|
+
.children {
|
|
527
|
+
display: grid;
|
|
528
|
+
grid-template-rows: 0fr;
|
|
529
|
+
transition: grid-template-rows var(--hx-transition-base, 200ms ease);
|
|
530
|
+
--_indent-level: calc(var(--_indent-level, 0) + 1);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.children--expanded {
|
|
534
|
+
grid-template-rows: 1fr;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
@media (prefers-reduced-motion: reduce) {
|
|
538
|
+
.item-row,
|
|
539
|
+
.expand-btn,
|
|
540
|
+
.expand-btn svg,
|
|
541
|
+
.children {
|
|
542
|
+
transition: none;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/* ─── Forced Colors (Windows High Contrast) ─── */
|
|
547
|
+
|
|
548
|
+
@media (forced-colors: active) {
|
|
549
|
+
.item-row:focus-visible {
|
|
550
|
+
outline: 3px solid Highlight;
|
|
551
|
+
outline-offset: -2px;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.expand-btn:focus-visible {
|
|
555
|
+
outline: 3px solid Highlight;
|
|
556
|
+
outline-offset: 2px;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
:host([selected]) .item-row {
|
|
560
|
+
outline: 2px solid Highlight;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.children-inner {
|
|
565
|
+
overflow: hidden;
|
|
566
|
+
}
|
|
567
|
+
`;
|
|
568
|
+
var M = Object.defineProperty, D = Object.getOwnPropertyDescriptor, h = (e, t, s, i) => {
|
|
569
|
+
for (var r = i > 1 ? void 0 : i ? D(t, s) : t, n = e.length - 1, l; n >= 0; n--)
|
|
570
|
+
(l = e[n]) && (r = (i ? l(t, s, r) : l(r)) || r);
|
|
571
|
+
return i && r && M(t, s, r), r;
|
|
572
|
+
};
|
|
573
|
+
let o = class extends A {
|
|
574
|
+
constructor() {
|
|
575
|
+
super(...arguments), this.expanded = !1, this.selected = !1, this.disabled = !1, this._hasChildren = !1, this._rovingActive = !1, this._labelText = "", this._level = 1, this._posInSet = 1, this._setSize = 1, this._selectable = !1, this._supportsIdrefRefs = !0, this._ariaMirror = null, this._resolvedAccessibleName = "", this._handleClick = (e) => {
|
|
576
|
+
if (!this._isOwnEvent(e)) return;
|
|
577
|
+
const t = e.composedPath();
|
|
578
|
+
for (const s of t)
|
|
579
|
+
if (s instanceof Element) {
|
|
580
|
+
if (s === this) break;
|
|
581
|
+
if (s.getAttribute && s.getAttribute("part") === "children") return;
|
|
582
|
+
}
|
|
583
|
+
if (this.disabled) {
|
|
584
|
+
e.preventDefault(), e.stopPropagation();
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
this._activate();
|
|
588
|
+
}, this._handleKeyDown = (e) => {
|
|
589
|
+
if (this._isOwnEvent(e) && !this.disabled)
|
|
590
|
+
switch (e.key) {
|
|
591
|
+
case "ArrowRight":
|
|
592
|
+
e.preventDefault(), this._hasChildren && !this.expanded && (this.expanded = !0);
|
|
593
|
+
break;
|
|
594
|
+
case "ArrowLeft":
|
|
595
|
+
e.preventDefault(), this._hasChildren && this.expanded && (this.expanded = !1);
|
|
596
|
+
break;
|
|
597
|
+
case "Enter":
|
|
598
|
+
case " ":
|
|
599
|
+
e.preventDefault(), this._activate();
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
// ─── Computed ARIA ───
|
|
605
|
+
/**
|
|
606
|
+
* Whether this item has slotted children.
|
|
607
|
+
* @returns True if one or more elements are assigned to the children slot.
|
|
608
|
+
*/
|
|
609
|
+
get hasChildItems() {
|
|
610
|
+
return this._hasChildren;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* The text content of the item's label slot, used for typeahead keyboard navigation.
|
|
614
|
+
* Returns an empty string until the label slot has been assigned.
|
|
615
|
+
*/
|
|
616
|
+
get labelText() {
|
|
617
|
+
return this._labelText;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Recompute all cached ARIA metadata in a single DOM pass.
|
|
621
|
+
* Called on connect, slotchange, and whenever structural context may change.
|
|
622
|
+
* @internal
|
|
623
|
+
*/
|
|
624
|
+
_updateAriaMetadata() {
|
|
625
|
+
let e = 1, t = this.parentElement;
|
|
626
|
+
for (; t; )
|
|
627
|
+
t.tagName.toLowerCase() === "hx-tree-item" && e++, t = t.parentElement;
|
|
628
|
+
this._level = e;
|
|
629
|
+
const s = this.parentElement;
|
|
630
|
+
if (s) {
|
|
631
|
+
const r = Array.from(s.children).filter(
|
|
632
|
+
(n) => n.tagName.toLowerCase() === "hx-tree-item"
|
|
633
|
+
);
|
|
634
|
+
this._posInSet = r.indexOf(this) + 1, this._setSize = r.length;
|
|
635
|
+
} else
|
|
636
|
+
this._posInSet = 1, this._setSize = 1;
|
|
637
|
+
const i = this.closest("hx-tree-view");
|
|
638
|
+
if (i) {
|
|
639
|
+
const r = i.getAttribute("selection");
|
|
640
|
+
this._selectable = r === "single" || r === "multiple";
|
|
641
|
+
} else
|
|
642
|
+
this._selectable = !1;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Set ARIA position metadata from the parent hx-tree-view in a single O(n) pass.
|
|
646
|
+
* Calling this avoids the O(n^2) ancestor-walk + sibling-iteration in _updateAriaMetadata
|
|
647
|
+
* when the parent already knows the layout.
|
|
648
|
+
* @internal
|
|
649
|
+
*/
|
|
650
|
+
setAriaMetadata(e, t, s, i) {
|
|
651
|
+
this._level = e, this._posInSet = t, this._setSize = s, this._selectable = i;
|
|
652
|
+
}
|
|
653
|
+
// ─── Lifecycle ───
|
|
654
|
+
connectedCallback() {
|
|
655
|
+
super.connectedCallback();
|
|
656
|
+
const e = this.constructor;
|
|
657
|
+
this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : y(this._internals), this._updateAriaMetadata(), this.addEventListener("click", this._handleClick), this.addEventListener("keydown", this._handleKeyDown), this._syncHostAriaSemantics(), this._applyHostTabIndex(), this._ariaMirror = w(this, () => {
|
|
658
|
+
this._syncHostAriaSemantics();
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
disconnectedCallback() {
|
|
662
|
+
var e;
|
|
663
|
+
super.disconnectedCallback(), this.removeEventListener("click", this._handleClick), this.removeEventListener("keydown", this._handleKeyDown), (e = this._ariaMirror) == null || e.disconnect(), this._ariaMirror = null;
|
|
664
|
+
}
|
|
665
|
+
updated(e) {
|
|
666
|
+
super.updated(e), (e.has("disabled") || e.has("selected") || e.has("expanded") || e.has("_hasChildren") || e.has("_selectable") || e.has("_level") || e.has("_posInSet") || e.has("_setSize")) && this._syncHostAriaSemantics(), (e.has("_rovingActive") || e.has("disabled")) && this._applyHostTabIndex();
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Apply the roving tabindex through the right surface for the active
|
|
670
|
+
* path. On the modern host-canonical path the host carries the role +
|
|
671
|
+
* tabindex; on the legacy fallback path the inner `.item-row` carries
|
|
672
|
+
* both via the template, so the host MUST stay out of the tab order to
|
|
673
|
+
* avoid a double-focusable per item (mirrors hx-menu-item round-1
|
|
674
|
+
* finding 3).
|
|
675
|
+
* @internal
|
|
676
|
+
*/
|
|
677
|
+
_applyHostTabIndex() {
|
|
678
|
+
if (!this._supportsIdrefRefs) {
|
|
679
|
+
this.tabIndex = -1;
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
this.disabled ? this.tabIndex = -1 : this.tabIndex = this._rovingActive ? 0 : -1;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Mirror treeitem semantics onto the host via ElementInternals so
|
|
686
|
+
* consumer-supplied `aria-label`, `aria-labelledby`, expand/select state,
|
|
687
|
+
* and tree position all reach the announced control.
|
|
688
|
+
*
|
|
689
|
+
* Codex push-gate round-1 lift (mirrors hx-menu-item round-6 finding 2):
|
|
690
|
+
* on the legacy fallback path the inner `.item-row` already exposes
|
|
691
|
+
* role="treeitem" + aria-* via the template. If we ALSO write those onto
|
|
692
|
+
* the host's ElementInternals, AT sees TWO treeitems for one logical
|
|
693
|
+
* option — the duplicate-surface problem host-canonical migration is
|
|
694
|
+
* meant to eliminate. Suppress all of these state writes on the host
|
|
695
|
+
* when the fallback path is in effect; the inner element is the
|
|
696
|
+
* canonical announced surface.
|
|
697
|
+
* @internal
|
|
698
|
+
*/
|
|
699
|
+
_syncHostAriaSemantics() {
|
|
700
|
+
var l;
|
|
701
|
+
const e = this._internals;
|
|
702
|
+
this._supportsIdrefRefs ? (e.role = "treeitem", e.ariaDisabled = this.disabled ? "true" : null, e.ariaSelected = this._selectable ? this.selected ? "true" : "false" : null, e.ariaExpanded = this._hasChildren ? this.expanded ? "true" : "false" : null, e.ariaLevel = String(this._level), e.ariaPosInSet = String(this._posInSet), e.ariaSetSize = String(this._setSize)) : (e.role = null, e.ariaLabel = null, e.ariaDisabled = null, e.ariaSelected = null, e.ariaExpanded = null, e.ariaLevel = null, e.ariaPosInSet = null, e.ariaSetSize = null);
|
|
703
|
+
const t = ((l = this.getAttribute("aria-label")) == null ? void 0 : l.trim()) || "", s = this.getAttribute("aria-labelledby"), i = S(this, s), r = i.length > 0;
|
|
704
|
+
if (this._supportsIdrefRefs) {
|
|
705
|
+
const a = e;
|
|
706
|
+
a.ariaLabelledByElements = r ? i : null;
|
|
707
|
+
}
|
|
708
|
+
let n = "";
|
|
709
|
+
if (r) {
|
|
710
|
+
const a = i.map((p) => C(p)).filter(Boolean).join(" ") || t || "";
|
|
711
|
+
n = a, this._supportsIdrefRefs ? e.ariaLabel = null : e.ariaLabel = a || null;
|
|
712
|
+
} else t ? (n = t, e.ariaLabel = t) : e.ariaLabel = null;
|
|
713
|
+
this._resolvedAccessibleName !== n && (this._resolvedAccessibleName = n, this._supportsIdrefRefs || this.requestUpdate());
|
|
714
|
+
}
|
|
715
|
+
// ─── Children Detection ───
|
|
716
|
+
/**
|
|
717
|
+
* Updates _hasChildren and recomputes ARIA metadata when the children slot assignment changes.
|
|
718
|
+
* @internal
|
|
719
|
+
*/
|
|
720
|
+
_handleChildrenSlotChange(e) {
|
|
721
|
+
const t = e.target;
|
|
722
|
+
this._hasChildren = t.assignedElements().length > 0, this._updateAriaMetadata(), this._syncHostAriaSemantics();
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Captures the text content from the default (label) slot for use on the children group label.
|
|
726
|
+
* @internal
|
|
727
|
+
*/
|
|
728
|
+
_handleLabelSlotChange(e) {
|
|
729
|
+
const s = e.target.assignedNodes({ flatten: !0 });
|
|
730
|
+
this._labelText = s.map((i) => i.textContent ?? "").join("").trim();
|
|
731
|
+
}
|
|
732
|
+
// ─── Event Handlers ───
|
|
733
|
+
/**
|
|
734
|
+
* Origin guard for host-bound click/keydown handlers. Returns `true` only
|
|
735
|
+
* when the event originated on THIS host's surface (its shadow tree or
|
|
736
|
+
* itself) and not on a nested `hx-tree-item` projected into the
|
|
737
|
+
* `children` slot.
|
|
738
|
+
*
|
|
739
|
+
* Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):
|
|
740
|
+
* children are slotted descendants in the parent's light DOM. Click/
|
|
741
|
+
* keydown events from a Child item bubble through the parent host's
|
|
742
|
+
* listeners — without this guard, selecting Child also activates
|
|
743
|
+
* Parent (double `hx-tree-item-select`) and Enter/Space on Child
|
|
744
|
+
* re-trigger Parent's handlers.
|
|
745
|
+
*
|
|
746
|
+
* Uses the shared `findClosestTreeItem` walker (composed-tree, crosses
|
|
747
|
+
* shadow + slot boundaries) so the test bed is reused across the
|
|
748
|
+
* tree family. The event is "ours" iff the closest `hx-tree-item`
|
|
749
|
+
* ancestor of the original target is `this`.
|
|
750
|
+
* @internal
|
|
751
|
+
*/
|
|
752
|
+
_isOwnEvent(e) {
|
|
753
|
+
const t = e.composedPath();
|
|
754
|
+
for (const s of t) {
|
|
755
|
+
if (!(s instanceof Element)) continue;
|
|
756
|
+
const i = R(s);
|
|
757
|
+
if (i)
|
|
758
|
+
return i === this;
|
|
759
|
+
}
|
|
760
|
+
return !1;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Toggles the expanded state when the expand/collapse button is clicked, stopping event propagation.
|
|
764
|
+
* @internal
|
|
765
|
+
*/
|
|
766
|
+
_handleExpandClick(e) {
|
|
767
|
+
e.stopPropagation(), !this.disabled && (this.expanded = !this.expanded);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Dispatches the hx-tree-item-select event when the item is activated via
|
|
771
|
+
* click or keyboard. The host listens for click; this method is also
|
|
772
|
+
* invoked from the Enter/Space keydown branch.
|
|
773
|
+
* @internal
|
|
774
|
+
*/
|
|
775
|
+
_activate() {
|
|
776
|
+
this.disabled || this.dispatchEvent(
|
|
777
|
+
new CustomEvent("hx-tree-item-select", {
|
|
778
|
+
bubbles: !0,
|
|
779
|
+
composed: !0,
|
|
780
|
+
detail: { item: this }
|
|
781
|
+
})
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
// ─── Public API ───
|
|
785
|
+
/**
|
|
786
|
+
* Sets the roving tabindex state for this item.
|
|
787
|
+
* When `active` is true, the host (modern) or inner row (fallback) gets
|
|
788
|
+
* `tabindex="0"` making it the Tab-reachable surface in the tree. All
|
|
789
|
+
* other items should be set to false. Called by the parent hx-tree-view
|
|
790
|
+
* to manage the roving tabindex pattern.
|
|
791
|
+
*/
|
|
792
|
+
setRovingActive(e) {
|
|
793
|
+
this._rovingActive = e, this._applyHostTabIndex();
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Focus this item. On the modern host-canonical path, focus lands on the
|
|
797
|
+
* host (which carries the roving tabindex and announced role). On the
|
|
798
|
+
* legacy fallback path, focus delegates to the inner `.item-row` which
|
|
799
|
+
* still carries the role.
|
|
800
|
+
*/
|
|
801
|
+
focus(e) {
|
|
802
|
+
var t;
|
|
803
|
+
this._supportsIdrefRefs ? HTMLElement.prototype.focus.call(this, e) : (t = this._itemRowEl) == null || t.focus(e);
|
|
804
|
+
}
|
|
805
|
+
// ─── Render ───
|
|
806
|
+
/**
|
|
807
|
+
* Renders the expand/collapse chevron button, or a placeholder span when the item has no children.
|
|
808
|
+
* @internal
|
|
809
|
+
*/
|
|
810
|
+
_renderExpandIcon() {
|
|
811
|
+
return this._hasChildren ? f`
|
|
812
|
+
<button
|
|
813
|
+
part="expand-icon"
|
|
814
|
+
class="expand-btn"
|
|
815
|
+
tabindex="-1"
|
|
816
|
+
aria-label="${this.expanded ? "Collapse" : "Expand"}"
|
|
817
|
+
@click=${this._handleExpandClick}
|
|
818
|
+
>
|
|
819
|
+
<svg viewBox="0 0 16 16" aria-hidden="true">
|
|
820
|
+
<polyline points="6 4 10 8 6 12" />
|
|
821
|
+
</svg>
|
|
822
|
+
</button>
|
|
823
|
+
` : f`<span class="expand-placeholder" aria-hidden="true"></span>`;
|
|
824
|
+
}
|
|
825
|
+
render() {
|
|
826
|
+
const e = f`
|
|
827
|
+
<div
|
|
828
|
+
part="children"
|
|
829
|
+
class=${k({ children: !0, "children--expanded": this.expanded })}
|
|
830
|
+
role="group"
|
|
831
|
+
aria-label=${this._labelText ? `${this._labelText} children` : "children"}
|
|
832
|
+
aria-hidden=${!this.expanded || u}
|
|
833
|
+
>
|
|
834
|
+
<div class="children-inner">
|
|
835
|
+
<slot name="children" @slotchange=${this._handleChildrenSlotChange}></slot>
|
|
836
|
+
</div>
|
|
837
|
+
</div>
|
|
838
|
+
`;
|
|
839
|
+
if (this._supportsIdrefRefs)
|
|
840
|
+
return f`
|
|
841
|
+
<div part="item" class="item">
|
|
842
|
+
<div part="row" class="item-row">
|
|
843
|
+
${this._renderExpandIcon()}
|
|
844
|
+
<span class="item-icon">
|
|
845
|
+
<slot name="icon"></slot>
|
|
846
|
+
</span>
|
|
847
|
+
<span part="label" class="item-label">
|
|
848
|
+
<slot @slotchange=${this._handleLabelSlotChange}></slot>
|
|
849
|
+
</span>
|
|
850
|
+
</div>
|
|
851
|
+
${e}
|
|
852
|
+
</div>
|
|
853
|
+
`;
|
|
854
|
+
const t = this._resolvedAccessibleName || u, s = this._hasChildren ? String(this.expanded) : u, i = this._selectable ? String(this.selected) : u;
|
|
855
|
+
return f`
|
|
856
|
+
<div part="item" class="item">
|
|
857
|
+
<div
|
|
858
|
+
part="row"
|
|
859
|
+
class="item-row"
|
|
860
|
+
role="treeitem"
|
|
861
|
+
tabindex=${this._rovingActive ? "0" : "-1"}
|
|
862
|
+
aria-label=${t}
|
|
863
|
+
aria-expanded=${s}
|
|
864
|
+
aria-selected=${i}
|
|
865
|
+
aria-disabled=${this.disabled ? "true" : u}
|
|
866
|
+
aria-level=${this._level}
|
|
867
|
+
aria-posinset=${this._posInSet}
|
|
868
|
+
aria-setsize=${this._setSize}
|
|
869
|
+
>
|
|
870
|
+
${this._renderExpandIcon()}
|
|
871
|
+
<span class="item-icon">
|
|
872
|
+
<slot name="icon"></slot>
|
|
873
|
+
</span>
|
|
874
|
+
<span part="label" class="item-label">
|
|
875
|
+
<slot @slotchange=${this._handleLabelSlotChange}></slot>
|
|
876
|
+
</span>
|
|
877
|
+
</div>
|
|
878
|
+
${e}
|
|
879
|
+
</div>
|
|
880
|
+
`;
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
o.styles = [$, I];
|
|
884
|
+
o.__testSupportsIdrefRefsOverride = null;
|
|
885
|
+
h([
|
|
886
|
+
m({ type: Boolean, reflect: !0 })
|
|
887
|
+
], o.prototype, "expanded", 2);
|
|
888
|
+
h([
|
|
889
|
+
m({ type: Boolean, reflect: !0 })
|
|
890
|
+
], o.prototype, "selected", 2);
|
|
891
|
+
h([
|
|
892
|
+
m({ type: Boolean, reflect: !0 })
|
|
893
|
+
], o.prototype, "disabled", 2);
|
|
894
|
+
h([
|
|
895
|
+
c()
|
|
896
|
+
], o.prototype, "_hasChildren", 2);
|
|
897
|
+
h([
|
|
898
|
+
c()
|
|
899
|
+
], o.prototype, "_rovingActive", 2);
|
|
900
|
+
h([
|
|
901
|
+
c()
|
|
902
|
+
], o.prototype, "_labelText", 2);
|
|
903
|
+
h([
|
|
904
|
+
c()
|
|
905
|
+
], o.prototype, "_level", 2);
|
|
906
|
+
h([
|
|
907
|
+
c()
|
|
908
|
+
], o.prototype, "_posInSet", 2);
|
|
909
|
+
h([
|
|
910
|
+
c()
|
|
911
|
+
], o.prototype, "_setSize", 2);
|
|
912
|
+
h([
|
|
913
|
+
c()
|
|
914
|
+
], o.prototype, "_selectable", 2);
|
|
915
|
+
h([
|
|
916
|
+
E(".item-row")
|
|
917
|
+
], o.prototype, "_itemRowEl", 2);
|
|
918
|
+
o = h([
|
|
919
|
+
g("hx-tree-item")
|
|
920
|
+
], o);
|
|
921
|
+
export {
|
|
922
|
+
o as H,
|
|
923
|
+
d as a
|
|
924
|
+
};
|
|
925
|
+
//# sourceMappingURL=hx-tree-item-CHrUhuZL.js.map
|