@fusion.dev/helix-headless 0.0.0-dev
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/LICENSE +21 -0
- package/custom-elements.json +75202 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +2 -0
- package/dist/accordion/item/accordion-item.d.ts +141 -0
- package/dist/accordion/item/accordion-item.js +214 -0
- package/dist/accordion/root/accordion-root.d.ts +57 -0
- package/dist/accordion/root/accordion-root.js +96 -0
- package/dist/announcement/index.d.ts +1 -0
- package/dist/announcement/index.js +1 -0
- package/dist/announcement/root/announcement-root.d.ts +106 -0
- package/dist/announcement/root/announcement-root.js +144 -0
- package/dist/app-header/index.d.ts +1 -0
- package/dist/app-header/index.js +1 -0
- package/dist/app-header/root/app-header-root.d.ts +113 -0
- package/dist/app-header/root/app-header-root.js +147 -0
- package/dist/avatar/group/avatar-group.d.ts +116 -0
- package/dist/avatar/group/avatar-group.js +136 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +2 -0
- package/dist/avatar/root/avatar-root.d.ts +71 -0
- package/dist/avatar/root/avatar-root.js +147 -0
- package/dist/badge/index.d.ts +1 -0
- package/dist/badge/index.js +1 -0
- package/dist/badge/root/badge-root.d.ts +61 -0
- package/dist/badge/root/badge-root.js +121 -0
- package/dist/bar-chart/index.d.ts +1 -0
- package/dist/bar-chart/index.js +1 -0
- package/dist/bar-chart/root/bar-chart-root.d.ts +266 -0
- package/dist/bar-chart/root/bar-chart-root.js +515 -0
- package/dist/blockquote/index.d.ts +1 -0
- package/dist/blockquote/index.js +1 -0
- package/dist/blockquote/root/blockquote-root.d.ts +51 -0
- package/dist/blockquote/root/blockquote-root.js +84 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +104 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +137 -0
- package/dist/breadcrumbs/index.d.ts +2 -0
- package/dist/breadcrumbs/index.js +2 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +77 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +94 -0
- package/dist/button/index.d.ts +1 -0
- package/dist/button/index.js +1 -0
- package/dist/button/root/button-root.d.ts +251 -0
- package/dist/button/root/button-root.js +401 -0
- package/dist/button-group/index.d.ts +1 -0
- package/dist/button-group/index.js +1 -0
- package/dist/button-group/root/button-group-root.d.ts +62 -0
- package/dist/button-group/root/button-group-root.js +62 -0
- package/dist/callout/index.d.ts +1 -0
- package/dist/callout/index.js +1 -0
- package/dist/callout/root/callout-root.d.ts +72 -0
- package/dist/callout/root/callout-root.js +90 -0
- package/dist/card/index.d.ts +1 -0
- package/dist/card/index.js +1 -0
- package/dist/card/root/card-root.d.ts +54 -0
- package/dist/card/root/card-root.js +71 -0
- package/dist/carousel/index.d.ts +1 -0
- package/dist/carousel/index.js +1 -0
- package/dist/carousel/root/carousel-root.d.ts +399 -0
- package/dist/carousel/root/carousel-root.js +723 -0
- package/dist/chat/composer/chat-composer.d.ts +160 -0
- package/dist/chat/composer/chat-composer.js +273 -0
- package/dist/chat/index.d.ts +3 -0
- package/dist/chat/index.js +3 -0
- package/dist/chat/message/chat-message.d.ts +170 -0
- package/dist/chat/message/chat-message.js +271 -0
- package/dist/chat/root/chat-root.d.ts +216 -0
- package/dist/chat/root/chat-root.js +389 -0
- package/dist/checkbox/index.d.ts +1 -0
- package/dist/checkbox/index.js +1 -0
- package/dist/checkbox/root/checkbox-root.d.ts +108 -0
- package/dist/checkbox/root/checkbox-root.js +207 -0
- package/dist/checkbox-group/index.d.ts +1 -0
- package/dist/checkbox-group/index.js +1 -0
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +155 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +293 -0
- package/dist/code/index.d.ts +1 -0
- package/dist/code/index.js +1 -0
- package/dist/code/root/code-root.d.ts +36 -0
- package/dist/code/root/code-root.js +43 -0
- package/dist/code-block/index.d.ts +1 -0
- package/dist/code-block/index.js +1 -0
- package/dist/code-block/root/code-block-root.d.ts +112 -0
- package/dist/code-block/root/code-block-root.js +155 -0
- package/dist/color-input/index.d.ts +1 -0
- package/dist/color-input/index.js +1 -0
- package/dist/color-input/root/color-input-root.d.ts +227 -0
- package/dist/color-input/root/color-input-root.js +456 -0
- package/dist/color-picker/color.d.ts +74 -0
- package/dist/color-picker/color.js +238 -0
- package/dist/color-picker/index.d.ts +2 -0
- package/dist/color-picker/index.js +2 -0
- package/dist/color-picker/root/color-picker-root.d.ts +303 -0
- package/dist/color-picker/root/color-picker-root.js +576 -0
- package/dist/combobox/index.d.ts +1 -0
- package/dist/combobox/index.js +1 -0
- package/dist/combobox/root/combobox-root.d.ts +396 -0
- package/dist/combobox/root/combobox-root.js +808 -0
- package/dist/command/index.d.ts +1 -0
- package/dist/command/index.js +1 -0
- package/dist/command/root/command-root.d.ts +166 -0
- package/dist/command/root/command-root.js +353 -0
- package/dist/copy-button/index.d.ts +1 -0
- package/dist/copy-button/index.js +1 -0
- package/dist/copy-button/root/copy-button-root.d.ts +154 -0
- package/dist/copy-button/root/copy-button-root.js +225 -0
- package/dist/data-table/index.d.ts +2 -0
- package/dist/data-table/index.js +2 -0
- package/dist/data-table/root/data-table-root.d.ts +392 -0
- package/dist/data-table/root/data-table-root.js +729 -0
- package/dist/data-table/root/order.d.ts +116 -0
- package/dist/data-table/root/order.js +175 -0
- package/dist/date-input/index.d.ts +1 -0
- package/dist/date-input/index.js +1 -0
- package/dist/date-input/root/date-input-root.d.ts +361 -0
- package/dist/date-input/root/date-input-root.js +791 -0
- package/dist/date-picker/index.d.ts +1 -0
- package/dist/date-picker/index.js +1 -0
- package/dist/date-picker/root/date-picker-root.d.ts +361 -0
- package/dist/date-picker/root/date-picker-root.js +837 -0
- package/dist/dialog/index.d.ts +1 -0
- package/dist/dialog/index.js +1 -0
- package/dist/dialog/root/dialog-root.d.ts +185 -0
- package/dist/dialog/root/dialog-root.js +319 -0
- package/dist/divider/index.d.ts +1 -0
- package/dist/divider/index.js +1 -0
- package/dist/divider/root/divider-root.d.ts +68 -0
- package/dist/divider/root/divider-root.js +116 -0
- package/dist/donut-chart/index.d.ts +1 -0
- package/dist/donut-chart/index.js +1 -0
- package/dist/donut-chart/root/donut-chart-root.d.ts +209 -0
- package/dist/donut-chart/root/donut-chart-root.js +395 -0
- package/dist/drawer/index.d.ts +1 -0
- package/dist/drawer/index.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +144 -0
- package/dist/drawer/root/drawer-root.js +222 -0
- package/dist/drilldown/index.d.ts +2 -0
- package/dist/drilldown/index.js +2 -0
- package/dist/drilldown/item/drilldown-item.d.ts +87 -0
- package/dist/drilldown/item/drilldown-item.js +152 -0
- package/dist/drilldown/root/drilldown-root.d.ts +115 -0
- package/dist/drilldown/root/drilldown-root.js +263 -0
- package/dist/element-events.generated.d.ts +1 -0
- package/dist/element-events.generated.js +125 -0
- package/dist/empty/index.d.ts +1 -0
- package/dist/empty/index.js +1 -0
- package/dist/empty/root/empty-root.d.ts +47 -0
- package/dist/empty/root/empty-root.js +68 -0
- package/dist/file-input/index.d.ts +1 -0
- package/dist/file-input/index.js +1 -0
- package/dist/file-input/root/file-input-root.d.ts +196 -0
- package/dist/file-input/root/file-input-root.js +488 -0
- package/dist/format-date/index.d.ts +1 -0
- package/dist/format-date/index.js +1 -0
- package/dist/format-date/root/format-date-root.d.ts +151 -0
- package/dist/format-date/root/format-date-root.js +266 -0
- package/dist/heatmap/index.d.ts +2 -0
- package/dist/heatmap/index.js +2 -0
- package/dist/heatmap/root/buckets.d.ts +62 -0
- package/dist/heatmap/root/buckets.js +85 -0
- package/dist/heatmap/root/heatmap-root.d.ts +330 -0
- package/dist/heatmap/root/heatmap-root.js +526 -0
- package/dist/icon/index.d.ts +1 -0
- package/dist/icon/index.js +1 -0
- package/dist/icon/root/icon-root.d.ts +53 -0
- package/dist/icon/root/icon-root.js +93 -0
- package/dist/icon-button/index.d.ts +1 -0
- package/dist/icon-button/index.js +1 -0
- package/dist/icon-button/root/icon-button-root.d.ts +40 -0
- package/dist/icon-button/root/icon-button-root.js +46 -0
- package/dist/image/index.d.ts +1 -0
- package/dist/image/index.js +1 -0
- package/dist/image/root/image-root.d.ts +213 -0
- package/dist/image/root/image-root.js +335 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +99 -0
- package/dist/input/index.d.ts +1 -0
- package/dist/input/index.js +1 -0
- package/dist/input/root/input-root.d.ts +281 -0
- package/dist/input/root/input-root.js +472 -0
- package/dist/kbd/index.d.ts +1 -0
- package/dist/kbd/index.js +1 -0
- package/dist/kbd/root/kbd-root.d.ts +98 -0
- package/dist/kbd/root/kbd-root.js +230 -0
- package/dist/legend/index.d.ts +1 -0
- package/dist/legend/index.js +1 -0
- package/dist/legend/root/legend-root.d.ts +83 -0
- package/dist/legend/root/legend-root.js +125 -0
- package/dist/line-chart/index.d.ts +1 -0
- package/dist/line-chart/index.js +1 -0
- package/dist/line-chart/root/line-chart-root.d.ts +238 -0
- package/dist/line-chart/root/line-chart-root.js +365 -0
- package/dist/list/index.d.ts +2 -0
- package/dist/list/index.js +2 -0
- package/dist/list/item/list-item.d.ts +95 -0
- package/dist/list/item/list-item.js +148 -0
- package/dist/list/root/list-root.d.ts +72 -0
- package/dist/list/root/list-root.js +61 -0
- package/dist/listbox/index.d.ts +1 -0
- package/dist/listbox/index.js +1 -0
- package/dist/listbox/root/listbox-root.d.ts +357 -0
- package/dist/listbox/root/listbox-root.js +890 -0
- package/dist/loader/index.d.ts +1 -0
- package/dist/loader/index.js +1 -0
- package/dist/loader/root/loader-root.d.ts +52 -0
- package/dist/loader/root/loader-root.js +74 -0
- package/dist/megamenu/index.d.ts +1 -0
- package/dist/megamenu/index.js +1 -0
- package/dist/megamenu/root/megamenu-root.d.ts +254 -0
- package/dist/megamenu/root/megamenu-root.js +526 -0
- package/dist/menu/index.d.ts +2 -0
- package/dist/menu/index.js +2 -0
- package/dist/menu/item/menu-item.d.ts +231 -0
- package/dist/menu/item/menu-item.js +405 -0
- package/dist/menu/root/menu-root.d.ts +158 -0
- package/dist/menu/root/menu-root.js +422 -0
- package/dist/meter/index.d.ts +1 -0
- package/dist/meter/index.js +1 -0
- package/dist/meter/root/meter-root.d.ts +234 -0
- package/dist/meter/root/meter-root.js +316 -0
- package/dist/navigation/index.d.ts +1 -0
- package/dist/navigation/index.js +1 -0
- package/dist/navigation/root/navigation-root.d.ts +55 -0
- package/dist/navigation/root/navigation-root.js +130 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/notifications/notification/notification.d.ts +181 -0
- package/dist/notifications/notification/notification.js +305 -0
- package/dist/notifications/root/notifications-root.d.ts +168 -0
- package/dist/notifications/root/notifications-root.js +291 -0
- package/dist/number-input/index.d.ts +1 -0
- package/dist/number-input/index.js +1 -0
- package/dist/number-input/root/number-input-root.d.ts +282 -0
- package/dist/number-input/root/number-input-root.js +592 -0
- package/dist/option/group/option-group.d.ts +38 -0
- package/dist/option/group/option-group.js +58 -0
- package/dist/option/index.d.ts +2 -0
- package/dist/option/index.js +2 -0
- package/dist/option/root/option-root.d.ts +194 -0
- package/dist/option/root/option-root.js +247 -0
- package/dist/outline/index.d.ts +1 -0
- package/dist/outline/index.js +1 -0
- package/dist/outline/root/outline-root.d.ts +237 -0
- package/dist/outline/root/outline-root.js +519 -0
- package/dist/pagination/index.d.ts +3 -0
- package/dist/pagination/index.js +3 -0
- package/dist/pagination/root/pagination-root.d.ts +390 -0
- package/dist/pagination/root/pagination-root.js +695 -0
- package/dist/pagination/size/pagination-size.d.ts +127 -0
- package/dist/pagination/size/pagination-size.js +232 -0
- package/dist/pagination/summary/pagination-summary.d.ts +90 -0
- package/dist/pagination/summary/pagination-summary.js +145 -0
- package/dist/pin-input/index.d.ts +1 -0
- package/dist/pin-input/index.js +1 -0
- package/dist/pin-input/root/pin-input-root.d.ts +292 -0
- package/dist/pin-input/root/pin-input-root.js +553 -0
- package/dist/popover/index.d.ts +1 -0
- package/dist/popover/index.js +1 -0
- package/dist/popover/root/popover-root.d.ts +108 -0
- package/dist/popover/root/popover-root.js +231 -0
- package/dist/progress/index.d.ts +1 -0
- package/dist/progress/index.js +1 -0
- package/dist/progress/root/progress-root.d.ts +125 -0
- package/dist/progress/root/progress-root.js +212 -0
- package/dist/qr-code/index.d.ts +1 -0
- package/dist/qr-code/index.js +1 -0
- package/dist/qr-code/root/qr-code-root.d.ts +93 -0
- package/dist/qr-code/root/qr-code-root.js +233 -0
- package/dist/quote/index.d.ts +1 -0
- package/dist/quote/index.js +1 -0
- package/dist/quote/root/quote-root.d.ts +36 -0
- package/dist/quote/root/quote-root.js +50 -0
- package/dist/radio/group/radio-group.d.ts +84 -0
- package/dist/radio/group/radio-group.js +170 -0
- package/dist/radio/index.d.ts +2 -0
- package/dist/radio/index.js +2 -0
- package/dist/radio/root/radio-root.d.ts +102 -0
- package/dist/radio/root/radio-root.js +151 -0
- package/dist/rating/index.d.ts +1 -0
- package/dist/rating/index.js +1 -0
- package/dist/rating/root/rating-root.d.ts +242 -0
- package/dist/rating/root/rating-root.js +484 -0
- package/dist/scroll-area/index.d.ts +1 -0
- package/dist/scroll-area/index.js +1 -0
- package/dist/scroll-area/root/scroll-area-root.d.ts +96 -0
- package/dist/scroll-area/root/scroll-area-root.js +215 -0
- package/dist/select/index.d.ts +1 -0
- package/dist/select/index.js +1 -0
- package/dist/select/root/select-root.d.ts +170 -0
- package/dist/select/root/select-root.js +419 -0
- package/dist/skeleton/index.d.ts +1 -0
- package/dist/skeleton/index.js +1 -0
- package/dist/skeleton/root/skeleton-root.d.ts +31 -0
- package/dist/skeleton/root/skeleton-root.js +42 -0
- package/dist/slider/index.d.ts +1 -0
- package/dist/slider/index.js +1 -0
- package/dist/slider/root/slider-root.d.ts +235 -0
- package/dist/slider/root/slider-root.js +488 -0
- package/dist/sparkline/index.d.ts +1 -0
- package/dist/sparkline/index.js +1 -0
- package/dist/sparkline/root/sparkline-root.d.ts +147 -0
- package/dist/sparkline/root/sparkline-root.js +278 -0
- package/dist/speed-dial/index.d.ts +2 -0
- package/dist/speed-dial/index.js +2 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +71 -0
- package/dist/speed-dial/item/speed-dial-item.js +113 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +122 -0
- package/dist/speed-dial/root/speed-dial-root.js +251 -0
- package/dist/splitter/index.d.ts +1 -0
- package/dist/splitter/index.js +1 -0
- package/dist/splitter/root/splitter-root.d.ts +491 -0
- package/dist/splitter/root/splitter-root.js +1030 -0
- package/dist/stat/group/stat-group.d.ts +30 -0
- package/dist/stat/group/stat-group.js +47 -0
- package/dist/stat/index.d.ts +2 -0
- package/dist/stat/index.js +2 -0
- package/dist/stat/root/stat-root.d.ts +62 -0
- package/dist/stat/root/stat-root.js +51 -0
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +2 -0
- package/dist/steps/root/steps-root.d.ts +110 -0
- package/dist/steps/root/steps-root.js +130 -0
- package/dist/steps/step/step.d.ts +139 -0
- package/dist/steps/step/step.js +215 -0
- package/dist/switch/index.d.ts +1 -0
- package/dist/switch/index.js +1 -0
- package/dist/switch/root/switch-root.d.ts +74 -0
- package/dist/switch/root/switch-root.js +153 -0
- package/dist/table/cell/table-cell.d.ts +34 -0
- package/dist/table/cell/table-cell.js +52 -0
- package/dist/table/column/table-column.d.ts +165 -0
- package/dist/table/column/table-column.js +222 -0
- package/dist/table/index.d.ts +4 -0
- package/dist/table/index.js +4 -0
- package/dist/table/root/table-root.d.ts +98 -0
- package/dist/table/root/table-root.js +161 -0
- package/dist/table/row/table-row.d.ts +27 -0
- package/dist/table/row/table-row.js +42 -0
- package/dist/tabs/index.d.ts +3 -0
- package/dist/tabs/index.js +3 -0
- package/dist/tabs/panel/tab-panel.d.ts +67 -0
- package/dist/tabs/panel/tab-panel.js +98 -0
- package/dist/tabs/root/tabs-root.d.ts +123 -0
- package/dist/tabs/root/tabs-root.js +217 -0
- package/dist/tabs/tab/tab.d.ts +64 -0
- package/dist/tabs/tab/tab.js +116 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +41 -0
- package/dist/tag/root/tag-root.js +67 -0
- package/dist/textarea/index.d.ts +1 -0
- package/dist/textarea/index.js +1 -0
- package/dist/textarea/root/textarea-root.d.ts +215 -0
- package/dist/textarea/root/textarea-root.js +380 -0
- package/dist/time-input/index.d.ts +1 -0
- package/dist/time-input/index.js +1 -0
- package/dist/time-input/root/time-input-root.d.ts +322 -0
- package/dist/time-input/root/time-input-root.js +661 -0
- package/dist/time-picker/index.d.ts +1 -0
- package/dist/time-picker/index.js +1 -0
- package/dist/time-picker/root/time-picker-root.d.ts +380 -0
- package/dist/time-picker/root/time-picker-root.js +669 -0
- package/dist/timeline/index.d.ts +2 -0
- package/dist/timeline/index.js +2 -0
- package/dist/timeline/item/timeline-item.d.ts +81 -0
- package/dist/timeline/item/timeline-item.js +128 -0
- package/dist/timeline/root/timeline-root.d.ts +52 -0
- package/dist/timeline/root/timeline-root.js +72 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +2 -0
- package/dist/toast/item/toast-item.d.ts +183 -0
- package/dist/toast/item/toast-item.js +345 -0
- package/dist/toast/root/toast-root.d.ts +72 -0
- package/dist/toast/root/toast-root.js +87 -0
- package/dist/toggle/group/toggle-group.d.ts +140 -0
- package/dist/toggle/group/toggle-group.js +278 -0
- package/dist/toggle/index.d.ts +2 -0
- package/dist/toggle/index.js +2 -0
- package/dist/toggle/root/toggle-root.d.ts +99 -0
- package/dist/toggle/root/toggle-root.js +146 -0
- package/dist/toolbar/index.d.ts +1 -0
- package/dist/toolbar/index.js +1 -0
- package/dist/toolbar/root/toolbar-root.d.ts +105 -0
- package/dist/toolbar/root/toolbar-root.js +260 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/root/tooltip-root.d.ts +388 -0
- package/dist/tooltip/root/tooltip-root.js +707 -0
- package/dist/tour/index.d.ts +2 -0
- package/dist/tour/index.js +2 -0
- package/dist/tour/root/tour-root.d.ts +161 -0
- package/dist/tour/root/tour-root.js +351 -0
- package/dist/tour/stop/tour-stop.d.ts +131 -0
- package/dist/tour/stop/tour-stop.js +249 -0
- package/dist/tree/index.d.ts +2 -0
- package/dist/tree/index.js +2 -0
- package/dist/tree/item/tree-item.d.ts +208 -0
- package/dist/tree/item/tree-item.js +381 -0
- package/dist/tree/root/tree-root.d.ts +88 -0
- package/dist/tree/root/tree-root.js +287 -0
- package/dist/trend/index.d.ts +1 -0
- package/dist/trend/index.js +1 -0
- package/dist/trend/root/trend-root.d.ts +67 -0
- package/dist/trend/root/trend-root.js +106 -0
- package/dist/video/index.d.ts +1 -0
- package/dist/video/index.js +1 -0
- package/dist/video/root/video-root.d.ts +711 -0
- package/dist/video/root/video-root.js +1821 -0
- package/dist/video-playlist/index.d.ts +3 -0
- package/dist/video-playlist/index.js +3 -0
- package/dist/video-playlist/item/video-playlist-item.d.ts +101 -0
- package/dist/video-playlist/item/video-playlist-item.js +162 -0
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +121 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +237 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +108 -0
- package/dist/video-playlist/root/video-playlist-root.js +218 -0
- package/dist/virtual-list/index.d.ts +1 -0
- package/dist/virtual-list/index.js +1 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +121 -0
- package/dist/virtual-list/root/virtual-list-root.js +221 -0
- package/jsx.d.ts +49767 -0
- package/package.json +77 -0
- package/svelte.d.ts +129 -0
- package/vue.d.ts +9242 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { HelixElement, KeyboardNavigationController, type Placement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
|
|
4
|
+
/**
|
|
5
|
+
* @summary A menu of commands, opened from a trigger.
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* The trigger is slotted and stays the consumer's own element, the same way the
|
|
9
|
+
* tooltip takes one. The surface is rendered here, in the top layer through the
|
|
10
|
+
* popover API, so it clears any ancestor with `overflow: hidden` without a
|
|
11
|
+
* `z-index` anywhere.
|
|
12
|
+
*
|
|
13
|
+
* **It drills down rather than flying out.** A submenu replaces what is on
|
|
14
|
+
* screen and a back row returns, instead of opening a second panel beside the
|
|
15
|
+
* first. Panels beside panels need a diagonal path a pointer has to travel
|
|
16
|
+
* without straying, they run off the edge of a narrow window, and on a touch
|
|
17
|
+
* screen there is no hover to open them with at all. One panel that changes
|
|
18
|
+
* what it holds has none of those problems and reads the same on a phone.
|
|
19
|
+
*
|
|
20
|
+
* The open page is held here rather than in each item, because only one page
|
|
21
|
+
* shows at a time and something has to know which. Items are told by property,
|
|
22
|
+
* not by attribute: an attribute written onto a consumer's element after it
|
|
23
|
+
* upgrades is a hydration mismatch waiting to happen.
|
|
24
|
+
*
|
|
25
|
+
* @since 0.1.0
|
|
26
|
+
* @status experimental
|
|
27
|
+
* @category overlays
|
|
28
|
+
* @aliases Dropdown, Action menu
|
|
29
|
+
* @documentation https://helix.fusion.dev/components/menu
|
|
30
|
+
*
|
|
31
|
+
* @slot - The items.
|
|
32
|
+
* @slot trigger - What opens it.
|
|
33
|
+
*
|
|
34
|
+
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before it closes, and cancelable.
|
|
35
|
+
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before it opens, and cancelable.
|
|
36
|
+
* @event {HelixSelectEvent} helix-select - Fired when an item is chosen. Cancelable: refusing it takes the decision and nothing moves.
|
|
37
|
+
* @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
|
|
38
|
+
*
|
|
39
|
+
* @csspart back - The control that returns from a submenu.
|
|
40
|
+
* @csspart back-mark - The glyph on the back control of a submenu.
|
|
41
|
+
* @csspart empty - Shown when there are no items to show.
|
|
42
|
+
* @csspart header - The bar above a submenu, holding the way back and its name.
|
|
43
|
+
* @csspart loading - Shown while the items are still on their way.
|
|
44
|
+
* @csspart surface - The floating panel the menu is drawn on.
|
|
45
|
+
* @csspart title - The name of the submenu that is showing.
|
|
46
|
+
*/
|
|
47
|
+
export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
48
|
+
/**
|
|
49
|
+
* Preferred side.
|
|
50
|
+
*
|
|
51
|
+
* It moves if that side does not fit.
|
|
52
|
+
*/
|
|
53
|
+
placement: Placement;
|
|
54
|
+
/**
|
|
55
|
+
* Space between the trigger and the surface, in pixels.
|
|
56
|
+
*/
|
|
57
|
+
offset: number;
|
|
58
|
+
/**
|
|
59
|
+
* Accessible name for the surface.
|
|
60
|
+
*/
|
|
61
|
+
label: string;
|
|
62
|
+
/**
|
|
63
|
+
* What the row returning from a submenu reads.
|
|
64
|
+
*/
|
|
65
|
+
backLabel: string;
|
|
66
|
+
/**
|
|
67
|
+
* Which page is showing, and what is on it.
|
|
68
|
+
*
|
|
69
|
+
* This was a `page` field, a title getter and an items getter written here.
|
|
70
|
+
* None of them were about menus: a settings panel or a navigation tree wants
|
|
71
|
+
* the same thing, and could not have it without being a menu. The controller
|
|
72
|
+
* holds the same shape, so the port is a rename rather than a rewrite, and it
|
|
73
|
+
* adds a real stack: `back()` returns one level instead of to the root, which
|
|
74
|
+
* this could not do because it only ever went two deep.
|
|
75
|
+
*/
|
|
76
|
+
private readonly drilldown;
|
|
77
|
+
/**
|
|
78
|
+
* Moving between rows, which is not this element's own business any more.
|
|
79
|
+
*
|
|
80
|
+
* `selects` false, because arriving at Delete must not delete: moving and
|
|
81
|
+
* choosing are one act in a radio group and two acts here, which is the
|
|
82
|
+
* distinction the controller was already drawing for `Tabs`.
|
|
83
|
+
*
|
|
84
|
+
* The origin is the selection, which took a wrong turn first and is worth
|
|
85
|
+
* recording. `focus` looks like the right reading, since a menu's current row
|
|
86
|
+
* is the focused one, but that origin also carries a rule a menu must not
|
|
87
|
+
* follow: a press that did not come from the set moves nothing. That rule is
|
|
88
|
+
* there for a tab panel, which is a tab stop beside the tabs; a menu's panel
|
|
89
|
+
* holds the rows and nothing else, and Down on a menu that has just opened is
|
|
90
|
+
* how a reader gets to the first row at all. It moved nothing, and the specs
|
|
91
|
+
* written alongside this are what said so.
|
|
92
|
+
*
|
|
93
|
+
* The horizontal pair is reserved rather than released. Right opens a
|
|
94
|
+
* submenu and left comes back, which are the platform's own bindings for a
|
|
95
|
+
* menu that drills, so those keys are spoken for here rather than unhandled.
|
|
96
|
+
*/
|
|
97
|
+
protected readonly keys: KeyboardNavigationController;
|
|
98
|
+
private readonly panel;
|
|
99
|
+
/**
|
|
100
|
+
* Tells a slotted trigger the disclosure state, by property.
|
|
101
|
+
*
|
|
102
|
+
* This menu wrote nothing onto its trigger, which was the right call and cost
|
|
103
|
+
* a reader the one thing they needed: a control that opens a menu and never
|
|
104
|
+
* says so. The class note above already gives the mechanism for the way out,
|
|
105
|
+
* that items are "told by property, not by attribute", and `tellDisclosure`
|
|
106
|
+
* is that argument applied one level up. See #322.
|
|
107
|
+
*/
|
|
108
|
+
private tellTrigger;
|
|
109
|
+
/** The element the surface opens against. */
|
|
110
|
+
private get trigger();
|
|
111
|
+
/** The items on the page that is showing, which is what the keys move over. */
|
|
112
|
+
private get items();
|
|
113
|
+
/** Opens the menu. */
|
|
114
|
+
show(): void;
|
|
115
|
+
/** Closes the menu, and forgets which page was showing. */
|
|
116
|
+
hide(): void;
|
|
117
|
+
/** Shows an item's submenu in place of the current page. */
|
|
118
|
+
private enter;
|
|
119
|
+
/** Returns to the page above, or closes when there is none. */
|
|
120
|
+
private leave;
|
|
121
|
+
private readonly handleSelect;
|
|
122
|
+
/**
|
|
123
|
+
* Keeps whatever has focus in sight, however it got there.
|
|
124
|
+
*
|
|
125
|
+
* This was done in the arrow branches, which meant it was true of the arrow
|
|
126
|
+
* keys and of nothing else: a row reached by Tab, or focused by the drilldown
|
|
127
|
+
* on the way into a page, could sit below the fold of a scrolled panel. On
|
|
128
|
+
* `focusin` it is one rule about focus rather than a line repeated in every
|
|
129
|
+
* branch that moves it, and it survived the arrow keys moving out to a shared
|
|
130
|
+
* controller that knows nothing about this panel.
|
|
131
|
+
*/
|
|
132
|
+
private readonly handleFocusIn;
|
|
133
|
+
private readonly handleKeydown;
|
|
134
|
+
private readonly handleTriggerClick;
|
|
135
|
+
connectedCallback(): void;
|
|
136
|
+
disconnectedCallback(): void;
|
|
137
|
+
protected updated(changed: PropertyValues): void;
|
|
138
|
+
/**
|
|
139
|
+
* Walks the tree marking which rows are on the page showing.
|
|
140
|
+
*
|
|
141
|
+
* Two levels were marked by hand and nothing wrote `showingSubmenu` on a
|
|
142
|
+
* nested row, so drilling into a third-level submenu rendered the header over
|
|
143
|
+
* an empty panel: the page existed, its rows were still marked as belonging
|
|
144
|
+
* to the level above, and none of them rendered. `Drilldown.mark()` is the
|
|
145
|
+
* same walk and was already recursive.
|
|
146
|
+
*
|
|
147
|
+
* `slot === 'submenu'` rather than every child, because a row's other
|
|
148
|
+
* children are its label and its icons.
|
|
149
|
+
*/
|
|
150
|
+
private mark;
|
|
151
|
+
protected render(): TemplateResult;
|
|
152
|
+
}
|
|
153
|
+
declare global {
|
|
154
|
+
interface HTMLElementTagNameMap {
|
|
155
|
+
'helix-headless-menu': HelixHeadlessMenu;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { anchorElement, customElement, DrilldownController, HelixElement, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { caretLeft } from '@fusion.dev/helix-icons';
|
|
9
|
+
import { html, nothing } from 'lit';
|
|
10
|
+
import { property } from 'lit/decorators.js';
|
|
11
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
/**
|
|
13
|
+
* @summary A menu of commands, opened from a trigger.
|
|
14
|
+
*
|
|
15
|
+
* @description
|
|
16
|
+
* The trigger is slotted and stays the consumer's own element, the same way the
|
|
17
|
+
* tooltip takes one. The surface is rendered here, in the top layer through the
|
|
18
|
+
* popover API, so it clears any ancestor with `overflow: hidden` without a
|
|
19
|
+
* `z-index` anywhere.
|
|
20
|
+
*
|
|
21
|
+
* **It drills down rather than flying out.** A submenu replaces what is on
|
|
22
|
+
* screen and a back row returns, instead of opening a second panel beside the
|
|
23
|
+
* first. Panels beside panels need a diagonal path a pointer has to travel
|
|
24
|
+
* without straying, they run off the edge of a narrow window, and on a touch
|
|
25
|
+
* screen there is no hover to open them with at all. One panel that changes
|
|
26
|
+
* what it holds has none of those problems and reads the same on a phone.
|
|
27
|
+
*
|
|
28
|
+
* The open page is held here rather than in each item, because only one page
|
|
29
|
+
* shows at a time and something has to know which. Items are told by property,
|
|
30
|
+
* not by attribute: an attribute written onto a consumer's element after it
|
|
31
|
+
* upgrades is a hydration mismatch waiting to happen.
|
|
32
|
+
*
|
|
33
|
+
* @since 0.1.0
|
|
34
|
+
* @status experimental
|
|
35
|
+
* @category overlays
|
|
36
|
+
* @aliases Dropdown, Action menu
|
|
37
|
+
* @documentation https://helix.fusion.dev/components/menu
|
|
38
|
+
*
|
|
39
|
+
* @slot - The items.
|
|
40
|
+
* @slot trigger - What opens it.
|
|
41
|
+
*
|
|
42
|
+
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before it closes, and cancelable.
|
|
43
|
+
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before it opens, and cancelable.
|
|
44
|
+
* @event {HelixSelectEvent} helix-select - Fired when an item is chosen. Cancelable: refusing it takes the decision and nothing moves.
|
|
45
|
+
* @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
|
|
46
|
+
*
|
|
47
|
+
* @csspart back - The control that returns from a submenu.
|
|
48
|
+
* @csspart back-mark - The glyph on the back control of a submenu.
|
|
49
|
+
* @csspart empty - Shown when there are no items to show.
|
|
50
|
+
* @csspart header - The bar above a submenu, holding the way back and its name.
|
|
51
|
+
* @csspart loading - Shown while the items are still on their way.
|
|
52
|
+
* @csspart surface - The floating panel the menu is drawn on.
|
|
53
|
+
* @csspart title - The name of the submenu that is showing.
|
|
54
|
+
*/
|
|
55
|
+
let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinControllerOpen(HelixElement)) {
|
|
56
|
+
constructor() {
|
|
57
|
+
super(...arguments);
|
|
58
|
+
/**
|
|
59
|
+
* Preferred side.
|
|
60
|
+
*
|
|
61
|
+
* It moves if that side does not fit.
|
|
62
|
+
*/
|
|
63
|
+
this.placement = 'bottom-start';
|
|
64
|
+
/**
|
|
65
|
+
* Space between the trigger and the surface, in pixels.
|
|
66
|
+
*/
|
|
67
|
+
this.offset = 4;
|
|
68
|
+
/**
|
|
69
|
+
* Accessible name for the surface.
|
|
70
|
+
*/
|
|
71
|
+
this.label = 'Menu';
|
|
72
|
+
/**
|
|
73
|
+
* What the row returning from a submenu reads.
|
|
74
|
+
*/
|
|
75
|
+
this.backLabel = 'Back';
|
|
76
|
+
/**
|
|
77
|
+
* Which page is showing, and what is on it.
|
|
78
|
+
*
|
|
79
|
+
* This was a `page` field, a title getter and an items getter written here.
|
|
80
|
+
* None of them were about menus: a settings panel or a navigation tree wants
|
|
81
|
+
* the same thing, and could not have it without being a menu. The controller
|
|
82
|
+
* holds the same shape, so the port is a rename rather than a rewrite, and it
|
|
83
|
+
* adds a real stack: `back()` returns one level instead of to the root, which
|
|
84
|
+
* this could not do because it only ever went two deep.
|
|
85
|
+
*/
|
|
86
|
+
this.drilldown = new DrilldownController(this, {
|
|
87
|
+
isRow: (element) => 'isMenuItem' in element && element.isMenuItem === true,
|
|
88
|
+
root: () => [...this.children].filter((child) => child.slot !== 'trigger'),
|
|
89
|
+
slot: 'submenu',
|
|
90
|
+
});
|
|
91
|
+
/* One controller where there were two and a hand-written sequence between
|
|
92
|
+
them. It is the same three things in the same order; what it is not is a
|
|
93
|
+
third copy of them, and the second copy is how `Select` ended up never
|
|
94
|
+
reaching the top layer at all. */
|
|
95
|
+
/**
|
|
96
|
+
* Moving between rows, which is not this element's own business any more.
|
|
97
|
+
*
|
|
98
|
+
* `selects` false, because arriving at Delete must not delete: moving and
|
|
99
|
+
* choosing are one act in a radio group and two acts here, which is the
|
|
100
|
+
* distinction the controller was already drawing for `Tabs`.
|
|
101
|
+
*
|
|
102
|
+
* The origin is the selection, which took a wrong turn first and is worth
|
|
103
|
+
* recording. `focus` looks like the right reading, since a menu's current row
|
|
104
|
+
* is the focused one, but that origin also carries a rule a menu must not
|
|
105
|
+
* follow: a press that did not come from the set moves nothing. That rule is
|
|
106
|
+
* there for a tab panel, which is a tab stop beside the tabs; a menu's panel
|
|
107
|
+
* holds the rows and nothing else, and Down on a menu that has just opened is
|
|
108
|
+
* how a reader gets to the first row at all. It moved nothing, and the specs
|
|
109
|
+
* written alongside this are what said so.
|
|
110
|
+
*
|
|
111
|
+
* The horizontal pair is reserved rather than released. Right opens a
|
|
112
|
+
* submenu and left comes back, which are the platform's own bindings for a
|
|
113
|
+
* menu that drills, so those keys are spoken for here rather than unhandled.
|
|
114
|
+
*/
|
|
115
|
+
this.keys = new KeyboardNavigationController(this, {
|
|
116
|
+
items: () => this.items,
|
|
117
|
+
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
118
|
+
selects: () => false,
|
|
119
|
+
});
|
|
120
|
+
this.panel = new PopoverController(this, {
|
|
121
|
+
anchor: () => this.trigger,
|
|
122
|
+
// The host is `display: contents`, so it has no box a press can land in.
|
|
123
|
+
// What counts as inside is the surface, plus the trigger, whose own click
|
|
124
|
+
// handler decides what a press there means.
|
|
125
|
+
boundary: () => this,
|
|
126
|
+
offset: () => this.offset,
|
|
127
|
+
onDismiss: () => this.hide(),
|
|
128
|
+
placement: () => this.placement,
|
|
129
|
+
surface: () => this.renderRoot?.querySelector('[part="surface"]'),
|
|
130
|
+
});
|
|
131
|
+
this.handleSelect = (event) => {
|
|
132
|
+
const item = event.target;
|
|
133
|
+
if (!this.items.includes(item)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const chosen = item;
|
|
137
|
+
if (chosen.hasSubmenu) {
|
|
138
|
+
// A row that opens a page has not chosen anything, so its select does not
|
|
139
|
+
// leave this element: a consumer listening for a choice would otherwise
|
|
140
|
+
// hear one every time a reader looked in a submenu.
|
|
141
|
+
event.stopPropagation();
|
|
142
|
+
this.enter(chosen);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.hide();
|
|
146
|
+
};
|
|
147
|
+
/*
|
|
148
|
+
* Moves over the page, in the direction the key points.
|
|
149
|
+
*
|
|
150
|
+
* The arrows wrap, because a menu is a ring rather than a list with ends:
|
|
151
|
+
* pressing down on the last item to reach the first is what every menu on
|
|
152
|
+
* every platform does.
|
|
153
|
+
*/
|
|
154
|
+
/*
|
|
155
|
+
* Focuses an item and brings it into the surface, which is not the same act.
|
|
156
|
+
*
|
|
157
|
+
* A menu long enough to scroll had the tree's problem: the arrow keys moved
|
|
158
|
+
* focus past the bottom of the panel and the panel stayed where it was.
|
|
159
|
+
* Scrolled here rather than by the browser, because `scrollIntoView` would
|
|
160
|
+
* take the page behind the menu with it.
|
|
161
|
+
*/
|
|
162
|
+
/**
|
|
163
|
+
* Keeps whatever has focus in sight, however it got there.
|
|
164
|
+
*
|
|
165
|
+
* This was done in the arrow branches, which meant it was true of the arrow
|
|
166
|
+
* keys and of nothing else: a row reached by Tab, or focused by the drilldown
|
|
167
|
+
* on the way into a page, could sit below the fold of a scrolled panel. On
|
|
168
|
+
* `focusin` it is one rule about focus rather than a line repeated in every
|
|
169
|
+
* branch that moves it, and it survived the arrow keys moving out to a shared
|
|
170
|
+
* controller that knows nothing about this panel.
|
|
171
|
+
*/
|
|
172
|
+
this.handleFocusIn = (event) => {
|
|
173
|
+
const item = this.items.find((row) => row.contains(event.target));
|
|
174
|
+
if (!item) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
/* `surface`, which is the part this template renders and the name the
|
|
178
|
+
whole library spells this box with.
|
|
179
|
+
|
|
180
|
+
*Rewritten 28 Aug 2026, because it had come to say the reverse.* The
|
|
181
|
+
fault it records is real and was the other way round: the lookup asked
|
|
182
|
+
for a name the template did not render, found null, and `scrollItemIntoView`
|
|
183
|
+
ran with no scroller and took the page behind the menu with it, which is
|
|
184
|
+
the one thing that method exists to prevent. What the comment could not
|
|
185
|
+
know is that `check:vocabulary` later renamed the part *to* `surface`, so
|
|
186
|
+
a note naming `menu` as the right answer now teaches the opposite of the
|
|
187
|
+
rule that settled it. The lookup and the part have agreed since. */
|
|
188
|
+
const surface = this.renderRoot.querySelector('[part="surface"]');
|
|
189
|
+
scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
|
|
190
|
+
};
|
|
191
|
+
this.handleKeydown = (event) => {
|
|
192
|
+
const items = this.items;
|
|
193
|
+
const at = items.indexOf(document.activeElement);
|
|
194
|
+
if (event.key === 'Escape') {
|
|
195
|
+
event.stopPropagation();
|
|
196
|
+
this.leave();
|
|
197
|
+
}
|
|
198
|
+
else if (event.key === 'ArrowRight' && items[at]?.hasSubmenu) {
|
|
199
|
+
this.enter(items[at]);
|
|
200
|
+
}
|
|
201
|
+
else if (event.key === 'ArrowLeft') {
|
|
202
|
+
this.leave();
|
|
203
|
+
}
|
|
204
|
+
else if (event.key === 'Tab') {
|
|
205
|
+
/* Out, and the panel goes with it.
|
|
206
|
+
*
|
|
207
|
+
* Nothing closed the menu when focus left it, so tabbing out of an open
|
|
208
|
+
* one left a shadowed panel in the top layer sitting over whatever the
|
|
209
|
+
* reader had tabbed to. Deliberately not prevented: focus should carry on
|
|
210
|
+
* outward, which is what the reader asked for. And deliberately not a
|
|
211
|
+
* focus trap, because a menu is not a modal and Tab is a way out of one. */
|
|
212
|
+
this.hide();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
};
|
|
220
|
+
this.handleTriggerClick = () => {
|
|
221
|
+
if (this.open) {
|
|
222
|
+
this.hide();
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
this.show();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Tells a slotted trigger the disclosure state, by property.
|
|
231
|
+
*
|
|
232
|
+
* This menu wrote nothing onto its trigger, which was the right call and cost
|
|
233
|
+
* a reader the one thing they needed: a control that opens a menu and never
|
|
234
|
+
* says so. The class note above already gives the mechanism for the way out,
|
|
235
|
+
* that items are "told by property, not by attribute", and `tellDisclosure`
|
|
236
|
+
* is that argument applied one level up. See #322.
|
|
237
|
+
*/
|
|
238
|
+
tellTrigger() {
|
|
239
|
+
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
240
|
+
tellDisclosure(slot?.assignedElements({ flatten: false })[0], this.open);
|
|
241
|
+
}
|
|
242
|
+
/** The element the surface opens against. */
|
|
243
|
+
get trigger() {
|
|
244
|
+
return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this);
|
|
245
|
+
}
|
|
246
|
+
/** The items on the page that is showing, which is what the keys move over. */
|
|
247
|
+
get items() {
|
|
248
|
+
/* Disabled rows are not there for the keyboard.
|
|
249
|
+
*
|
|
250
|
+
* A disabled row renders no `tabindex` and cannot take focus, so leaving it
|
|
251
|
+
* in the list meant the arrow keys computed a move onto it, called `focus()`
|
|
252
|
+
* on something unfocusable, and stopped: the keyboard was stuck one row
|
|
253
|
+
* above every disabled item in the menu. `Drilldown` filters for the same
|
|
254
|
+
* reason. */
|
|
255
|
+
return this.drilldown.rows.filter((row) => !row.disabled);
|
|
256
|
+
}
|
|
257
|
+
/** Opens the menu. */
|
|
258
|
+
show() {
|
|
259
|
+
if (this.open || !this.requestOpen(true)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
this.updateComplete.then(() => {
|
|
263
|
+
// Raised in `updated()`, which the state change has just scheduled.
|
|
264
|
+
this.items[0]?.focus();
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/** Closes the menu, and forgets which page was showing. */
|
|
268
|
+
hide() {
|
|
269
|
+
if (!this.open || !this.requestOpen(false)) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.panel.hide();
|
|
273
|
+
this.drilldown.reset();
|
|
274
|
+
/* Only where the menu still had it. A dismissal that did not take focus with
|
|
275
|
+
it, a press somewhere else on the page, should leave focus where the
|
|
276
|
+
reader put it rather than yanking it back to the trigger. `Popover`
|
|
277
|
+
guards the same way, and `document.activeElement` retargets to the item
|
|
278
|
+
host here, which is what makes the containment test work. */
|
|
279
|
+
if (this.contains(document.activeElement)) {
|
|
280
|
+
this.trigger.focus();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/** Shows an item's submenu in place of the current page. */
|
|
284
|
+
enter(item) {
|
|
285
|
+
if (!this.drilldown.enter(item)) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
this.updateComplete.then(() => this.items[0]?.focusItem());
|
|
289
|
+
}
|
|
290
|
+
/** Returns to the page above, or closes when there is none. */
|
|
291
|
+
leave() {
|
|
292
|
+
if (this.drilldown.atRoot) {
|
|
293
|
+
this.hide();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
/* Held before going back, because focus returns to the row that opened the
|
|
297
|
+
page being left: a reader who drills in and comes straight out should be
|
|
298
|
+
on the row they pressed, not at the top of a list they have already
|
|
299
|
+
read. */
|
|
300
|
+
const leaving = this.drilldown.page;
|
|
301
|
+
this.drilldown.back();
|
|
302
|
+
this.updateComplete.then(() => leaving?.focus());
|
|
303
|
+
}
|
|
304
|
+
connectedCallback() {
|
|
305
|
+
super.connectedCallback();
|
|
306
|
+
/* Capture, so a drill-in never reaches a consumer's own listener on this
|
|
307
|
+
same host. The guarantee the class documents is that choosing a row that
|
|
308
|
+
opens a submenu is navigation rather than a choice, and stopping it in the
|
|
309
|
+
bubble phase stops it for ancestors and not for the siblings registered
|
|
310
|
+
here. `Drilldown` learned this already. */
|
|
311
|
+
this.addEventListener('helix-select', this.handleSelect, true);
|
|
312
|
+
this.addEventListener('keydown', this.handleKeydown);
|
|
313
|
+
this.addEventListener('focusin', this.handleFocusIn);
|
|
314
|
+
}
|
|
315
|
+
disconnectedCallback() {
|
|
316
|
+
super.disconnectedCallback();
|
|
317
|
+
this.removeEventListener('helix-select', this.handleSelect, true);
|
|
318
|
+
this.removeEventListener('keydown', this.handleKeydown);
|
|
319
|
+
this.removeEventListener('focusin', this.handleFocusIn);
|
|
320
|
+
}
|
|
321
|
+
updated(changed) {
|
|
322
|
+
super.updated(changed);
|
|
323
|
+
// Every update, so a trigger slotted after the first render is told too.
|
|
324
|
+
this.tellTrigger();
|
|
325
|
+
/* Put the panel where `open` says, however it got there. `show()` and
|
|
326
|
+
`hide()` raised and lowered it and nothing else did, so a menu opened by
|
|
327
|
+
declaring `open` rendered visible, out of the top layer and unanchored:
|
|
328
|
+
every imperative path worked and every declarative one was half-open. */
|
|
329
|
+
if (changed.has('open')) {
|
|
330
|
+
/* Here rather than a microtask later: `updated()` runs after the render,
|
|
331
|
+
so the panel is no longer `display: none` and `showPopover` is safe. */
|
|
332
|
+
if (this.open) {
|
|
333
|
+
this.panel.show();
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
this.panel.hide();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Every item shows or hides itself: which page is open is this element's
|
|
340
|
+
// business, and where an item belongs is the item's. Set as a property, so
|
|
341
|
+
// nothing is written onto a consumer's element.
|
|
342
|
+
for (const child of this.children) {
|
|
343
|
+
const item = child;
|
|
344
|
+
if (item.isMenuItem !== true) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
this.mark(item, this.drilldown.atRoot);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Walks the tree marking which rows are on the page showing.
|
|
352
|
+
*
|
|
353
|
+
* Two levels were marked by hand and nothing wrote `showingSubmenu` on a
|
|
354
|
+
* nested row, so drilling into a third-level submenu rendered the header over
|
|
355
|
+
* an empty panel: the page existed, its rows were still marked as belonging
|
|
356
|
+
* to the level above, and none of them rendered. `Drilldown.mark()` is the
|
|
357
|
+
* same walk and was already recursive.
|
|
358
|
+
*
|
|
359
|
+
* `slot === 'submenu'` rather than every child, because a row's other
|
|
360
|
+
* children are its label and its icons.
|
|
361
|
+
*/
|
|
362
|
+
mark(item, onPage) {
|
|
363
|
+
item.onPage = onPage;
|
|
364
|
+
item.showingSubmenu = item === this.drilldown.page;
|
|
365
|
+
for (const child of item.children) {
|
|
366
|
+
const nested = child;
|
|
367
|
+
if (nested.isMenuItem === true && child.slot === 'submenu') {
|
|
368
|
+
this.mark(nested, item === this.drilldown.page);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
render() {
|
|
373
|
+
return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>
|
|
374
|
+
<div
|
|
375
|
+
part="surface"
|
|
376
|
+
popover="manual"
|
|
377
|
+
role="menu"
|
|
378
|
+
aria-busy=${this.loading ? 'true' : nothing}
|
|
379
|
+
aria-label=${this.label}
|
|
380
|
+
data-drilled=${this.drilldown.atRoot ? nothing : ''}
|
|
381
|
+
?hidden=${!this.open}
|
|
382
|
+
>
|
|
383
|
+
${
|
|
384
|
+
// A header rather than a row in the list. The way back is not one of
|
|
385
|
+
// the things on this page, and putting it in the list means an arrow
|
|
386
|
+
// press lands on it as though it were.
|
|
387
|
+
this.drilldown.atRoot
|
|
388
|
+
? nothing
|
|
389
|
+
: html `<div part="header">
|
|
390
|
+
<button
|
|
391
|
+
part="back"
|
|
392
|
+
type="button"
|
|
393
|
+
aria-label=${this.backLabel}
|
|
394
|
+
@click=${() => this.leave()}
|
|
395
|
+
>
|
|
396
|
+
<svg part="back-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
397
|
+
${unsafeSVG(caretLeft.content)}
|
|
398
|
+
</svg>
|
|
399
|
+
</button>
|
|
400
|
+
<span part="title">${this.drilldown.label}</span>
|
|
401
|
+
</div>`}
|
|
402
|
+
<slot @slotchange=${(event) => this.countRows(event)}></slot>
|
|
403
|
+
${this.renderStatus(this.hasRows)}
|
|
404
|
+
</div>`;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
__decorate([
|
|
408
|
+
property()
|
|
409
|
+
], HelixHeadlessMenu.prototype, "placement", void 0);
|
|
410
|
+
__decorate([
|
|
411
|
+
property({ type: Number })
|
|
412
|
+
], HelixHeadlessMenu.prototype, "offset", void 0);
|
|
413
|
+
__decorate([
|
|
414
|
+
property()
|
|
415
|
+
], HelixHeadlessMenu.prototype, "label", void 0);
|
|
416
|
+
__decorate([
|
|
417
|
+
property({ attribute: 'back-label' })
|
|
418
|
+
], HelixHeadlessMenu.prototype, "backLabel", void 0);
|
|
419
|
+
HelixHeadlessMenu = __decorate([
|
|
420
|
+
customElement('helix-headless-menu')
|
|
421
|
+
], HelixHeadlessMenu);
|
|
422
|
+
export { HelixHeadlessMenu };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/meter-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/meter-root.js';
|