@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,278 @@
|
|
|
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 { customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { HelixHeadlessToggle } from '../root/toggle-root.js';
|
|
11
|
+
/**
|
|
12
|
+
* @summary A row of options with the selection marked by a moving indicator.
|
|
13
|
+
*
|
|
14
|
+
* @description
|
|
15
|
+
* The indicator is one element that travels, not a background that appears on
|
|
16
|
+
* whichever item is current. That difference is the whole point: a fill that
|
|
17
|
+
* swaps is two things changing at once and reads as a flicker, while one that
|
|
18
|
+
* moves is a single object the eye follows, and it says where the selection
|
|
19
|
+
* came from as well as where it went.
|
|
20
|
+
*
|
|
21
|
+
* Its whole box is measured from the selected item and written onto
|
|
22
|
+
* the indicator as custom properties, because labels are different lengths and
|
|
23
|
+
* no proportion of the group is the right answer. Measurement is client-side by
|
|
24
|
+
* necessity, so the server renders the indicator hidden and it fades in once it
|
|
25
|
+
* has somewhere to be, which is the harmless direction: it appears rather than
|
|
26
|
+
* jumping from a wrong place.
|
|
27
|
+
*
|
|
28
|
+
* A radio group, and only that. Navigation is links marked with `aria-current`
|
|
29
|
+
* and styled by the `data-navigation-item` recipe: radio semantics would announce a
|
|
30
|
+
* set of destinations as a set of choices. A tab controls a panel.
|
|
31
|
+
*
|
|
32
|
+
* Being a radio group, it is a form control, and it says so through
|
|
33
|
+
* `HelixFormElement`: it reports its value under a `name`, comes back to the
|
|
34
|
+
* markup's choice on reset, and restores the one a reader made when the browser
|
|
35
|
+
* brings a form back.
|
|
36
|
+
*
|
|
37
|
+
* The semantics were already right: the host has carried `role="radiogroup"`
|
|
38
|
+
* and the items `role="radio"` from the start. What none of it did was reach a
|
|
39
|
+
* form. A button in a shadow root submits nothing whatever its role, so the
|
|
40
|
+
* value has to be reported by the host, which is the only thing a form can
|
|
41
|
+
* see.
|
|
42
|
+
*
|
|
43
|
+
* @since 0.1.0
|
|
44
|
+
* @status experimental
|
|
45
|
+
* @aliases SegmentedControl, Segmented, Navigation, Switcher
|
|
46
|
+
* @documentation https://helix.fusion.dev/components/toggle-group
|
|
47
|
+
*
|
|
48
|
+
* @slot - The group's items.
|
|
49
|
+
*
|
|
50
|
+
* @event {Event} change - Announced once the value has moved.
|
|
51
|
+
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before the answer moves, and cancelable. The only way to refuse one.
|
|
52
|
+
* @event {HelixSelectEvent} helix-select - Fired when an item is chosen. Dispatched by the item and listened for here. Cancelable: refusing it takes the decision and nothing moves.
|
|
53
|
+
* @event {Event} input - Announced once the value has moved.
|
|
54
|
+
*
|
|
55
|
+
* @csspart divider - The rule after an inline label, separating it from the items.
|
|
56
|
+
* @csspart feedback - What is wrong with it.
|
|
57
|
+
* @csspart hint - Help under the row, while nothing is wrong.
|
|
58
|
+
* @csspart indicator - The moving marker behind the selected item.
|
|
59
|
+
* @csspart label - The question, over the row.
|
|
60
|
+
* @csspart row - The line the track sits on, with whatever flanks it.
|
|
61
|
+
* @csspart track - The bar the items sit in.
|
|
62
|
+
*/
|
|
63
|
+
let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinControllerValue(MixinField(HelixFormElement)) {
|
|
64
|
+
constructor() {
|
|
65
|
+
super(...arguments);
|
|
66
|
+
/* The mark. The selection sync it used to share a method with is `sync()`. */
|
|
67
|
+
this.indicator = new IndicatorController(this, {
|
|
68
|
+
// The same exact match `sync` makes: nothing chosen means nothing marked,
|
|
69
|
+
// and the controller takes the mark away rather than parking it on item one.
|
|
70
|
+
active: () => this.items.find((item) => item.value === this.value),
|
|
71
|
+
indicator: () => this.renderRoot?.querySelector('[part="indicator"]'),
|
|
72
|
+
surface: () => this.renderRoot?.querySelector('[part="track"]'),
|
|
73
|
+
});
|
|
74
|
+
/* Moving and choosing are one act, which is the radio group pattern this
|
|
75
|
+
control also follows, and is what the controller exists to stop being
|
|
76
|
+
written per component. */
|
|
77
|
+
/* Registered rather than held. A controller adds itself to the host, so there
|
|
78
|
+
is no reference to keep: nothing here talks to it after construction, which
|
|
79
|
+
is why it is `protected` and not `private`. A private field nothing reads
|
|
80
|
+
is an unused one, and the honest reading is that the subclass tier is where
|
|
81
|
+
a consumer would reach for it. */
|
|
82
|
+
this.keys = new KeyboardNavigationController(this, { items: () => this.items });
|
|
83
|
+
/* Stated once, and the group never thinks about it again. See the
|
|
84
|
+
controller: the cascade was four hand calls from four different
|
|
85
|
+
methods, so which paths reached it differed by component and a fifth
|
|
86
|
+
group would have got none at all. */
|
|
87
|
+
this.cascade = new DisabledCascadeController(this, {
|
|
88
|
+
items: () => this.items,
|
|
89
|
+
});
|
|
90
|
+
this.handleSelection = (event) => {
|
|
91
|
+
this.requestValue(event.detail.value);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Marks the chosen item, which used to happen inside the placing method.
|
|
96
|
+
*
|
|
97
|
+
* They were one method because the geometry needed the active item anyway,
|
|
98
|
+
* and that made a selection change look like a layout concern. `resolveActiveItem`
|
|
99
|
+
* rather than the first item, because a group opening on a disabled segment
|
|
100
|
+
* marked it as chosen.
|
|
101
|
+
*/
|
|
102
|
+
sync() {
|
|
103
|
+
/* An exact match and nothing else.
|
|
104
|
+
*
|
|
105
|
+
* This went through `resolveActiveItem`, which falls back to the first
|
|
106
|
+
* enabled item, so a group with no value marked one anyway:
|
|
107
|
+
* `aria-checked="true"`, the thumb placed under it, full selected styling,
|
|
108
|
+
* while the group reported nothing. A `required` group showed an answer it
|
|
109
|
+
* did not have, and a reader who submitted without touching it was told a
|
|
110
|
+
* value was missing while looking at one.
|
|
111
|
+
*
|
|
112
|
+
* The fallback is right where it came from. A tab set always shows a panel,
|
|
113
|
+
* so something has to be current; a group that reports a form value has the
|
|
114
|
+
* honest option of reporting none. */
|
|
115
|
+
const active = this.items.find((item) => item.value === this.value);
|
|
116
|
+
/* With nothing chosen there is no selection to carry the tab stop, so the
|
|
117
|
+
first item holds one until there is. Otherwise an unanswered group is a
|
|
118
|
+
control the keyboard cannot enter, which is what the fallback was quietly
|
|
119
|
+
also doing for it. */
|
|
120
|
+
const entry = active ? undefined : this.items.find((item) => !item.disabled);
|
|
121
|
+
for (const item of this.items) {
|
|
122
|
+
item.selected = item === active;
|
|
123
|
+
item.focusable = item === entry;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
get items() {
|
|
127
|
+
return [...this.children].filter((child) => child instanceof HelixHeadlessToggle);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Watches the group and every item it currently holds.
|
|
131
|
+
*
|
|
132
|
+
* Called again on `slotchange`, because the set was read once at first paint:
|
|
133
|
+
* an item added later was measured by nothing, so a group whose options
|
|
134
|
+
* arrive with the data had a thumb that stopped following the moment one of
|
|
135
|
+
* them changed width. Observing the same element twice is a no-op, so there
|
|
136
|
+
* is nothing to unwind first.
|
|
137
|
+
*/
|
|
138
|
+
watch() {
|
|
139
|
+
this.observer?.observe(this);
|
|
140
|
+
for (const item of this.items) {
|
|
141
|
+
this.observer?.observe(item);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
connectedCallback() {
|
|
145
|
+
super.connectedCallback();
|
|
146
|
+
this.addEventListener('helix-select', this.handleSelection);
|
|
147
|
+
/* The observer is rebuilt here, because nothing else does it.
|
|
148
|
+
*
|
|
149
|
+
* `firstUpdated` runs once for the life of the element and
|
|
150
|
+
* `disconnectedCallback` runs every time it moves, so a framework
|
|
151
|
+
* reordering a list left this permanently dead: the observer gone, nothing
|
|
152
|
+
* to rebuild it, and the component still rendering as though it were
|
|
153
|
+
* watching. Guarded on `hasUpdated`, because the first connection happens
|
|
154
|
+
* before the first render and there is nothing to watch yet.
|
|
155
|
+
* `check:observers` holds it. */
|
|
156
|
+
if (this.hasUpdated) {
|
|
157
|
+
this.measure();
|
|
158
|
+
this.watch();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
disconnectedCallback() {
|
|
162
|
+
super.disconnectedCallback();
|
|
163
|
+
this.removeEventListener('helix-select', this.handleSelection);
|
|
164
|
+
this.observer?.disconnect();
|
|
165
|
+
}
|
|
166
|
+
firstUpdated(changed) {
|
|
167
|
+
super.firstUpdated(changed);
|
|
168
|
+
this.sync();
|
|
169
|
+
this.indicator.place();
|
|
170
|
+
/* Per item, not only the host, which is what the controller's own observer
|
|
171
|
+
covers. An item can change width inside a track that keeps its size, and
|
|
172
|
+
the host never fires for that. */
|
|
173
|
+
this.measure();
|
|
174
|
+
this.watch();
|
|
175
|
+
}
|
|
176
|
+
/** The observer the items are registered on, rebuilt with them. */
|
|
177
|
+
measure() {
|
|
178
|
+
this.observer?.disconnect();
|
|
179
|
+
this.observer = new ResizeObserver(() => this.indicator.place());
|
|
180
|
+
}
|
|
181
|
+
updated(changed) {
|
|
182
|
+
super.updated(changed);
|
|
183
|
+
// Every update, not only the ones that name `value`: see the note on
|
|
184
|
+
// `ColorInput.updated`. The placement stays gated, because the indicator
|
|
185
|
+
// controller already places on every update of its own host.
|
|
186
|
+
this.sync();
|
|
187
|
+
if (changed.has('value')) {
|
|
188
|
+
this.indicator.place();
|
|
189
|
+
}
|
|
190
|
+
this.validate();
|
|
191
|
+
/* Every update, because the label and the message come and go with the
|
|
192
|
+
properties behind them, and an element reference to a node that has been
|
|
193
|
+
re-rendered is a reference to nothing. */
|
|
194
|
+
this.linkHost();
|
|
195
|
+
}
|
|
196
|
+
willUpdate(changed) {
|
|
197
|
+
super.willUpdate(changed);
|
|
198
|
+
// Through internals, so nothing lands on the host as an attribute. A nav
|
|
199
|
+
// renders a real `<nav>` in the shadow root and takes its semantics from
|
|
200
|
+
// that, so the host stays neutral.
|
|
201
|
+
/* The label goes on as a string as well as the element reference
|
|
202
|
+
`linkHost` sets, because this is the half a server can write. The
|
|
203
|
+
reference wins on the client, which is what lets a consumer slot a label
|
|
204
|
+
richer than a string. */
|
|
205
|
+
hostAria(this.internals, { label: this.label, role: 'radiogroup' });
|
|
206
|
+
// `null` rather than an empty string when nothing is chosen, which is the
|
|
207
|
+
// difference between a control that submits nothing and one that submits a
|
|
208
|
+
// blank.
|
|
209
|
+
this.internals.setFormValue(this.value === '' ? null : this.value);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The verdict on the answer, which `required` had been asking for and not
|
|
213
|
+
* getting.
|
|
214
|
+
*
|
|
215
|
+
* `required` arrived with `MixinField` and nothing enforced it: the attribute
|
|
216
|
+
* reflected, the marker rendered beside the label, and a form with an
|
|
217
|
+
* unanswered group submitted anyway. An API that exists and does nothing is
|
|
218
|
+
* worse than one that is missing, because the marker is a promise to the
|
|
219
|
+
* reader that something will stop them.
|
|
220
|
+
*
|
|
221
|
+
* The anchor is the track rather than the host, so the browser's own bubble
|
|
222
|
+
* points at the control rather than at a box with nothing in it.
|
|
223
|
+
*/
|
|
224
|
+
validate() {
|
|
225
|
+
this.reportRequired(this.value === '', 'Choose one to continue.', 'track');
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The row the track sits in, so something can sit beside it.
|
|
229
|
+
*
|
|
230
|
+
* **Bare slots, and a wrapper only around the row itself.** An unassigned
|
|
231
|
+
* slot is `display: contents` in the UA stylesheet and generates no box at
|
|
232
|
+
* all, so a group with nothing slotted lays out exactly as it did before this
|
|
233
|
+
* existed: no grid track, no flex item, no gap. Wrapping each side in a div
|
|
234
|
+
* instead would paint an empty inset band on every group in the library that
|
|
235
|
+
* never asked for one, which is the measurement Card already paid for.
|
|
236
|
+
*
|
|
237
|
+
* The row does always generate a box, and is entitled to: the track is always
|
|
238
|
+
* in it.
|
|
239
|
+
*/
|
|
240
|
+
render() {
|
|
241
|
+
/* The track is an element now, where it used to be the host itself.
|
|
242
|
+
It has to be: the label, the hint and the message are the host's children
|
|
243
|
+
too, and with the track on the host they were flex items in the same row
|
|
244
|
+
as the segments. The track also owns the box the indicator is measured
|
|
245
|
+
against, which is why `place` reads it rather than `this`. */
|
|
246
|
+
/* **Inside the track when it is placed at the start, not beside it.** A
|
|
247
|
+
label sitting outside reads as a field's label that happens to be on one
|
|
248
|
+
line; inside, with a rule after it, the group reads as one control that
|
|
249
|
+
says what it is for. The divider is what makes that legible: without it
|
|
250
|
+
the word is a first segment that cannot be pressed. */
|
|
251
|
+
const inside = this.labelPlacement === 'start';
|
|
252
|
+
const label = this.renderGroupLabel();
|
|
253
|
+
return html `${inside ? nothing : label}
|
|
254
|
+
<div part="row">
|
|
255
|
+
<slot name="start"></slot>
|
|
256
|
+
<div part="track">
|
|
257
|
+
${inside ? html `${label}<div part="divider" aria-hidden="true"></div>` : nothing}
|
|
258
|
+
<div part="indicator" aria-hidden="true"></div>
|
|
259
|
+
<slot
|
|
260
|
+
@slotchange=${() => {
|
|
261
|
+
this.watch();
|
|
262
|
+
this.sync();
|
|
263
|
+
this.indicator.place();
|
|
264
|
+
}}
|
|
265
|
+
></slot>
|
|
266
|
+
</div>
|
|
267
|
+
<slot name="end"></slot>
|
|
268
|
+
</div>
|
|
269
|
+
${this.renderHint()}${this.renderFeedback()}`;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
__decorate([
|
|
273
|
+
property({ attribute: 'label-placement', reflect: true })
|
|
274
|
+
], HelixHeadlessToggleGroup.prototype, "labelPlacement", void 0);
|
|
275
|
+
HelixHeadlessToggleGroup = __decorate([
|
|
276
|
+
customElement('helix-headless-toggle-group')
|
|
277
|
+
], HelixHeadlessToggleGroup);
|
|
278
|
+
export { HelixHeadlessToggleGroup };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary One option in a toggle group.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* Renders a `<button role="radio">`. This is a form control and nothing else.
|
|
8
|
+
*
|
|
9
|
+
* Navigation is not this. It is links marked with `aria-current` and styled by
|
|
10
|
+
* the `data-navigation-item` recipe in the base layer, which carries the same look
|
|
11
|
+
* without radio semantics announcing destinations as choices.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.1.0
|
|
14
|
+
* @status experimental
|
|
15
|
+
* @category actions
|
|
16
|
+
* @aliases Segment, NavItem, Option
|
|
17
|
+
* @documentation https://helix.fusion.dev/components/toggle
|
|
18
|
+
*
|
|
19
|
+
* @slot - The item's label.
|
|
20
|
+
*
|
|
21
|
+
* @event {HelixSelectEvent} helix-select - Fired when the item is chosen. Cancelable: refusing it takes the decision and nothing moves.
|
|
22
|
+
*
|
|
23
|
+
* @csspart item - The radio button.
|
|
24
|
+
*/
|
|
25
|
+
export declare class HelixHeadlessToggle extends HelixElement {
|
|
26
|
+
/**
|
|
27
|
+
* Identifies the item to the group.
|
|
28
|
+
*/
|
|
29
|
+
value: string;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the markup declared this one chosen, which is what a reset returns to.
|
|
32
|
+
*
|
|
33
|
+
* `<option selected>` reflects to `defaultSelected` and `option.selected` is
|
|
34
|
+
* live state that does not reflect, and those are two different facts. This
|
|
35
|
+
* element has one `selected` doing both jobs, so what is captured here is what
|
|
36
|
+
* the markup said at upgrade, before anything could overwrite it: read the
|
|
37
|
+
* attribute later and the listbox's own writes answer instead.
|
|
38
|
+
*
|
|
39
|
+
* **The deeper half is 302 and is not this.** State reflecting under the
|
|
40
|
+
* declaration's name is the fault `TreeItem` already avoids by mirroring to
|
|
41
|
+
* `data-selected`, and four families here still write `selected` back into a
|
|
42
|
+
* consumer's markup. Splitting them means moving what every stylesheet selects
|
|
43
|
+
* on, which is a change of its own rather than a property being added.
|
|
44
|
+
*/
|
|
45
|
+
get defaultSelected(): boolean;
|
|
46
|
+
set defaultSelected(next: boolean);
|
|
47
|
+
/** What the markup said, read once at construction for the reason above. */
|
|
48
|
+
private seeded;
|
|
49
|
+
/**
|
|
50
|
+
* Whether this item is the current one.
|
|
51
|
+
*/
|
|
52
|
+
selected: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the item can be chosen.
|
|
55
|
+
*/
|
|
56
|
+
disabled: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Moves focus to this item's own control.
|
|
59
|
+
*
|
|
60
|
+
* The group drives arrow-key navigation and cannot reach the control itself,
|
|
61
|
+
* which is inside this shadow root. Exposing the intent as a method keeps the
|
|
62
|
+
* group out of the child's internals.
|
|
63
|
+
*/
|
|
64
|
+
focusItem(): void;
|
|
65
|
+
/** Chooses this item and announces it. */
|
|
66
|
+
select(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Whether this item holds the group's tab stop while nothing is chosen.
|
|
69
|
+
*
|
|
70
|
+
* The stop normally rides on the selection, and an unanswered group has no
|
|
71
|
+
* selection, so it had no stop and the keyboard could not reach it. Written
|
|
72
|
+
* by the group, with no attribute: it is coordination between elements, and
|
|
73
|
+
* `tabindex` on a host the consumer rendered is the change a React consumer's
|
|
74
|
+
* hydration reports and does not patch up.
|
|
75
|
+
*/
|
|
76
|
+
focusable: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Mirrors the chosen state where a stylesheet can select on it.
|
|
79
|
+
*
|
|
80
|
+
* **A custom state and not the `selected` attribute it used to reflect.** The
|
|
81
|
+
* parent writes this: a listbox choosing a row, a tab strip moving the tab, a
|
|
82
|
+
* radio group answering for its set. Reflected, that put the element's own
|
|
83
|
+
* bookkeeping onto markup a consumer wrote and a consumer's server never sent,
|
|
84
|
+
* which React reconciles and reports as a mismatch, and which a serialized
|
|
85
|
+
* element pasted back declares as a choice nobody made. `ElementInternals`
|
|
86
|
+
* holds it instead, where it is not in the DOM at all.
|
|
87
|
+
*
|
|
88
|
+
* Reading `selected` is unaffected and so is writing it: the attribute still
|
|
89
|
+
* seeds the property, which is what `<helix-toggle selected>` in a consumer's
|
|
90
|
+
* markup means. What stops is the write back. See 302 and 304.
|
|
91
|
+
*/
|
|
92
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
93
|
+
protected render(): TemplateResult;
|
|
94
|
+
}
|
|
95
|
+
declare global {
|
|
96
|
+
interface HTMLElementTagNameMap {
|
|
97
|
+
'helix-headless-toggle': HelixHeadlessToggle;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
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 { customElement, HelixElement, HelixSelectEvent } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
|
+
/**
|
|
11
|
+
* @summary One option in a toggle group.
|
|
12
|
+
*
|
|
13
|
+
* @description
|
|
14
|
+
* Renders a `<button role="radio">`. This is a form control and nothing else.
|
|
15
|
+
*
|
|
16
|
+
* Navigation is not this. It is links marked with `aria-current` and styled by
|
|
17
|
+
* the `data-navigation-item` recipe in the base layer, which carries the same look
|
|
18
|
+
* without radio semantics announcing destinations as choices.
|
|
19
|
+
*
|
|
20
|
+
* @since 0.1.0
|
|
21
|
+
* @status experimental
|
|
22
|
+
* @category actions
|
|
23
|
+
* @aliases Segment, NavItem, Option
|
|
24
|
+
* @documentation https://helix.fusion.dev/components/toggle
|
|
25
|
+
*
|
|
26
|
+
* @slot - The item's label.
|
|
27
|
+
*
|
|
28
|
+
* @event {HelixSelectEvent} helix-select - Fired when the item is chosen. Cancelable: refusing it takes the decision and nothing moves.
|
|
29
|
+
*
|
|
30
|
+
* @csspart item - The radio button.
|
|
31
|
+
*/
|
|
32
|
+
let HelixHeadlessToggle = class HelixHeadlessToggle extends HelixElement {
|
|
33
|
+
constructor() {
|
|
34
|
+
super(...arguments);
|
|
35
|
+
/**
|
|
36
|
+
* Identifies the item to the group.
|
|
37
|
+
*/
|
|
38
|
+
this.value = '';
|
|
39
|
+
/** What the markup said, read once at construction for the reason above. */
|
|
40
|
+
this.seeded = this.hasAttribute('selected');
|
|
41
|
+
/**
|
|
42
|
+
* Whether this item is the current one.
|
|
43
|
+
*/
|
|
44
|
+
this.selected = false;
|
|
45
|
+
/**
|
|
46
|
+
* Whether the item can be chosen.
|
|
47
|
+
*/
|
|
48
|
+
this.disabled = false;
|
|
49
|
+
/**
|
|
50
|
+
* Whether this item holds the group's tab stop while nothing is chosen.
|
|
51
|
+
*
|
|
52
|
+
* The stop normally rides on the selection, and an unanswered group has no
|
|
53
|
+
* selection, so it had no stop and the keyboard could not reach it. Written
|
|
54
|
+
* by the group, with no attribute: it is coordination between elements, and
|
|
55
|
+
* `tabindex` on a host the consumer rendered is the change a React consumer's
|
|
56
|
+
* hydration reports and does not patch up.
|
|
57
|
+
*/
|
|
58
|
+
this.focusable = false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Whether the markup declared this one chosen, which is what a reset returns to.
|
|
62
|
+
*
|
|
63
|
+
* `<option selected>` reflects to `defaultSelected` and `option.selected` is
|
|
64
|
+
* live state that does not reflect, and those are two different facts. This
|
|
65
|
+
* element has one `selected` doing both jobs, so what is captured here is what
|
|
66
|
+
* the markup said at upgrade, before anything could overwrite it: read the
|
|
67
|
+
* attribute later and the listbox's own writes answer instead.
|
|
68
|
+
*
|
|
69
|
+
* **The deeper half is 302 and is not this.** State reflecting under the
|
|
70
|
+
* declaration's name is the fault `TreeItem` already avoids by mirroring to
|
|
71
|
+
* `data-selected`, and four families here still write `selected` back into a
|
|
72
|
+
* consumer's markup. Splitting them means moving what every stylesheet selects
|
|
73
|
+
* on, which is a change of its own rather than a property being added.
|
|
74
|
+
*/
|
|
75
|
+
get defaultSelected() {
|
|
76
|
+
return this.seeded;
|
|
77
|
+
}
|
|
78
|
+
set defaultSelected(next) {
|
|
79
|
+
this.seeded = next;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Moves focus to this item's own control.
|
|
83
|
+
*
|
|
84
|
+
* The group drives arrow-key navigation and cannot reach the control itself,
|
|
85
|
+
* which is inside this shadow root. Exposing the intent as a method keeps the
|
|
86
|
+
* group out of the child's internals.
|
|
87
|
+
*/
|
|
88
|
+
focusItem() {
|
|
89
|
+
this.renderRoot.querySelector('[part="item"]')?.focus();
|
|
90
|
+
}
|
|
91
|
+
/** Chooses this item and announces it. */
|
|
92
|
+
select() {
|
|
93
|
+
if (this.disabled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Mirrors the chosen state where a stylesheet can select on it.
|
|
100
|
+
*
|
|
101
|
+
* **A custom state and not the `selected` attribute it used to reflect.** The
|
|
102
|
+
* parent writes this: a listbox choosing a row, a tab strip moving the tab, a
|
|
103
|
+
* radio group answering for its set. Reflected, that put the element's own
|
|
104
|
+
* bookkeeping onto markup a consumer wrote and a consumer's server never sent,
|
|
105
|
+
* which React reconciles and reports as a mismatch, and which a serialized
|
|
106
|
+
* element pasted back declares as a choice nobody made. `ElementInternals`
|
|
107
|
+
* holds it instead, where it is not in the DOM at all.
|
|
108
|
+
*
|
|
109
|
+
* Reading `selected` is unaffected and so is writing it: the attribute still
|
|
110
|
+
* seeds the property, which is what `<helix-toggle selected>` in a consumer's
|
|
111
|
+
* markup means. What stops is the write back. See 302 and 304.
|
|
112
|
+
*/
|
|
113
|
+
willUpdate(changed) {
|
|
114
|
+
super.willUpdate(changed);
|
|
115
|
+
this.toggleState('selected', this.selected);
|
|
116
|
+
}
|
|
117
|
+
render() {
|
|
118
|
+
return html `<button
|
|
119
|
+
part="item"
|
|
120
|
+
type="button"
|
|
121
|
+
role="radio"
|
|
122
|
+
aria-checked=${this.selected ? 'true' : 'false'}
|
|
123
|
+
?disabled=${this.disabled}
|
|
124
|
+
tabindex=${this.selected || this.focusable ? '0' : '-1'}
|
|
125
|
+
@click=${() => this.select()}
|
|
126
|
+
>
|
|
127
|
+
<slot></slot>
|
|
128
|
+
</button>`;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
__decorate([
|
|
132
|
+
property()
|
|
133
|
+
], HelixHeadlessToggle.prototype, "value", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
property({ type: Boolean })
|
|
136
|
+
], HelixHeadlessToggle.prototype, "selected", void 0);
|
|
137
|
+
__decorate([
|
|
138
|
+
property({ reflect: true, type: Boolean })
|
|
139
|
+
], HelixHeadlessToggle.prototype, "disabled", void 0);
|
|
140
|
+
__decorate([
|
|
141
|
+
property({ attribute: false })
|
|
142
|
+
], HelixHeadlessToggle.prototype, "focusable", void 0);
|
|
143
|
+
HelixHeadlessToggle = __decorate([
|
|
144
|
+
customElement('helix-headless-toggle')
|
|
145
|
+
], HelixHeadlessToggle);
|
|
146
|
+
export { HelixHeadlessToggle };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/toolbar-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/toolbar-root.js';
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary A group of controls that share one tab stop.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* Separate from a button group, and the difference is what it holds: a group is
|
|
8
|
+
* homogeneous, a toolbar is not. A toolbar mixes buttons, toggles, and menus,
|
|
9
|
+
* which is why it is its own component rather than a variant of something.
|
|
10
|
+
*
|
|
11
|
+
* The whole toolbar is one tab stop and the arrows move between controls, so a
|
|
12
|
+
* page with three toolbars costs three presses of Tab to get past rather than
|
|
13
|
+
* thirty. Controls are found by asking the browser what is focusable rather
|
|
14
|
+
* than by matching tag names, so a toolbar works with anything put in it,
|
|
15
|
+
* including a consumer's own elements.
|
|
16
|
+
*
|
|
17
|
+
* @since 0.1.0
|
|
18
|
+
* @status stable
|
|
19
|
+
* @category layout
|
|
20
|
+
* @aliases Actions, Action bar
|
|
21
|
+
* @documentation https://helix.fusion.dev/components/toolbar
|
|
22
|
+
*
|
|
23
|
+
* @slot - The toolbar's controls.
|
|
24
|
+
*
|
|
25
|
+
* @csspart toolbar - The toolbar container.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HelixHeadlessToolbar extends HelixElement {
|
|
28
|
+
/**
|
|
29
|
+
* Accessible name for the toolbar.
|
|
30
|
+
*/
|
|
31
|
+
label: string;
|
|
32
|
+
/**
|
|
33
|
+
* Which way the arrow keys move.
|
|
34
|
+
*/
|
|
35
|
+
orientation?: 'horizontal' | 'vertical';
|
|
36
|
+
private watcher;
|
|
37
|
+
/**
|
|
38
|
+
* Children that can take the tab stop, in document order.
|
|
39
|
+
*
|
|
40
|
+
* Every child that is not `disabled` and not `aria-hidden`, which is
|
|
41
|
+
* deliberately a test on the element rather than a list of tag names: a
|
|
42
|
+
* toolbar holds anything, including elements this package has never heard of.
|
|
43
|
+
* Client only, there being no tree to walk on the server.
|
|
44
|
+
*
|
|
45
|
+
* **It does not ask a child whether it is focusable, and the description said
|
|
46
|
+
* it did.** That would mean reading a `focusable` property off each one, which
|
|
47
|
+
* `focus` below does when moving the stop and this does not when choosing the
|
|
48
|
+
* set. The two are separable and only one of them was ever written: an element
|
|
49
|
+
* that is neither disabled nor hidden and still cannot take focus is counted
|
|
50
|
+
* here and skipped there.
|
|
51
|
+
*/
|
|
52
|
+
private get controls();
|
|
53
|
+
/**
|
|
54
|
+
* Moves the single tab stop to one control.
|
|
55
|
+
*
|
|
56
|
+
* Prefers the control's own `focusable` property to writing `tabindex` on it.
|
|
57
|
+
* The attribute is a change to markup the consumer rendered, which a React
|
|
58
|
+
* consumer's hydration reports and does not patch up; a control that offers
|
|
59
|
+
* the property moves the stop inside its own shadow root instead.
|
|
60
|
+
*
|
|
61
|
+
* `tabindex` stays as the fallback, because a toolbar has to hold controls
|
|
62
|
+
* this package has never heard of.
|
|
63
|
+
*/
|
|
64
|
+
private setTabStop;
|
|
65
|
+
/**
|
|
66
|
+
* Sets the first tab stop once every custom control has upgraded.
|
|
67
|
+
*
|
|
68
|
+
* A custom element has no properties at all before it upgrades, so a pass
|
|
69
|
+
* that ran first would find no `focusable`, take the `tabindex` fallback, and
|
|
70
|
+
* write the very attribute this exists to avoid.
|
|
71
|
+
*/
|
|
72
|
+
private claimTabStop;
|
|
73
|
+
private readonly handleFocusIn;
|
|
74
|
+
/**
|
|
75
|
+
* Gives the tab stop back to a control that still exists.
|
|
76
|
+
*
|
|
77
|
+
* `controls` excludes anything disabled or hidden, so disabling the control
|
|
78
|
+
* holding the stop dropped it out of the list while every other control was
|
|
79
|
+
* already at `-1`. The toolbar then had no tab stop at all and the keyboard
|
|
80
|
+
* could not reach it again, from a change as ordinary as a Save button
|
|
81
|
+
* disabling itself once the form is clean.
|
|
82
|
+
*
|
|
83
|
+
* `foreign` stays false, the same as the first claim: a control this package
|
|
84
|
+
* has never heard of that was never given `tabindex="-1"` is still in the
|
|
85
|
+
* document's own tab order, so it is never the one that gets stranded.
|
|
86
|
+
*/
|
|
87
|
+
private readonly restoreTabStop;
|
|
88
|
+
/**
|
|
89
|
+
* The orientation in force.
|
|
90
|
+
*
|
|
91
|
+
* Unset is horizontal, and stays unset: the default is the absent attribute,
|
|
92
|
+
* so a reflected default cannot appear on the host after hydration.
|
|
93
|
+
*/
|
|
94
|
+
private get axis();
|
|
95
|
+
private readonly handleKeydown;
|
|
96
|
+
connectedCallback(): void;
|
|
97
|
+
disconnectedCallback(): void;
|
|
98
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
99
|
+
protected render(): TemplateResult;
|
|
100
|
+
}
|
|
101
|
+
declare global {
|
|
102
|
+
interface HTMLElementTagNameMap {
|
|
103
|
+
'helix-headless-toolbar': HelixHeadlessToolbar;
|
|
104
|
+
}
|
|
105
|
+
}
|