@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 @@
|
|
|
1
|
+
export * from './root/icon-button-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/icon-button-root.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { HelixHeadlessButton } from '../../button/root/button-root.js';
|
|
2
|
+
/**
|
|
3
|
+
* @summary A button whose content is an icon, and which must be named.
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Everything a button does, with one thing added and it is the reason this is
|
|
7
|
+
* an element rather than a note on `Button`: **an icon-only control has no
|
|
8
|
+
* accessible name unless it is given one.** A button whose content is a glyph
|
|
9
|
+
* announces as "button" and nothing else, which is the single most common way a
|
|
10
|
+
* toolbar becomes unusable without sight. `label` is not optional in practice,
|
|
11
|
+
* and having a component that says so is what makes it reviewable.
|
|
12
|
+
*
|
|
13
|
+
* **Registered, so it can be rendered and not only subclassed.** The styled
|
|
14
|
+
* icon button extended `HelixHeadlessButton` directly, which left no
|
|
15
|
+
* `helix-headless-icon-button` for anything to use: a headless consumer wanting an
|
|
16
|
+
* icon button had a button and a naming convention. Anything in this tier that
|
|
17
|
+
* needs one, such as an announcement's dismiss control, can now render it
|
|
18
|
+
* without reaching into the styled tier for a tag that would never upgrade.
|
|
19
|
+
*
|
|
20
|
+
* Top-level rather than `Button.Icon`, because a namespace means composition
|
|
21
|
+
* and an icon-only button is not part of a button. It is a button with
|
|
22
|
+
* different content and a different shape, which makes it its own component.
|
|
23
|
+
*
|
|
24
|
+
* @since 0.1.0
|
|
25
|
+
* @status stable
|
|
26
|
+
* @category actions
|
|
27
|
+
* @aliases Icon button, Square button
|
|
28
|
+
* @documentation https://helix.fusion.dev/components/icon-button
|
|
29
|
+
*
|
|
30
|
+
* @slot - The icon.
|
|
31
|
+
*
|
|
32
|
+
* @csspart button - The inner button or anchor.
|
|
33
|
+
*/
|
|
34
|
+
export declare class HelixHeadlessIconButton extends HelixHeadlessButton {
|
|
35
|
+
}
|
|
36
|
+
declare global {
|
|
37
|
+
interface HTMLElementTagNameMap {
|
|
38
|
+
'helix-headless-icon-button': HelixHeadlessIconButton;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 } from '@fusion.dev/helix-core';
|
|
8
|
+
import { HelixHeadlessButton } from '../../button/root/button-root.js';
|
|
9
|
+
/**
|
|
10
|
+
* @summary A button whose content is an icon, and which must be named.
|
|
11
|
+
*
|
|
12
|
+
* @description
|
|
13
|
+
* Everything a button does, with one thing added and it is the reason this is
|
|
14
|
+
* an element rather than a note on `Button`: **an icon-only control has no
|
|
15
|
+
* accessible name unless it is given one.** A button whose content is a glyph
|
|
16
|
+
* announces as "button" and nothing else, which is the single most common way a
|
|
17
|
+
* toolbar becomes unusable without sight. `label` is not optional in practice,
|
|
18
|
+
* and having a component that says so is what makes it reviewable.
|
|
19
|
+
*
|
|
20
|
+
* **Registered, so it can be rendered and not only subclassed.** The styled
|
|
21
|
+
* icon button extended `HelixHeadlessButton` directly, which left no
|
|
22
|
+
* `helix-headless-icon-button` for anything to use: a headless consumer wanting an
|
|
23
|
+
* icon button had a button and a naming convention. Anything in this tier that
|
|
24
|
+
* needs one, such as an announcement's dismiss control, can now render it
|
|
25
|
+
* without reaching into the styled tier for a tag that would never upgrade.
|
|
26
|
+
*
|
|
27
|
+
* Top-level rather than `Button.Icon`, because a namespace means composition
|
|
28
|
+
* and an icon-only button is not part of a button. It is a button with
|
|
29
|
+
* different content and a different shape, which makes it its own component.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.1.0
|
|
32
|
+
* @status stable
|
|
33
|
+
* @category actions
|
|
34
|
+
* @aliases Icon button, Square button
|
|
35
|
+
* @documentation https://helix.fusion.dev/components/icon-button
|
|
36
|
+
*
|
|
37
|
+
* @slot - The icon.
|
|
38
|
+
*
|
|
39
|
+
* @csspart button - The inner button or anchor.
|
|
40
|
+
*/
|
|
41
|
+
let HelixHeadlessIconButton = class HelixHeadlessIconButton extends HelixHeadlessButton {
|
|
42
|
+
};
|
|
43
|
+
HelixHeadlessIconButton = __decorate([
|
|
44
|
+
customElement('helix-headless-icon-button')
|
|
45
|
+
], HelixHeadlessIconButton);
|
|
46
|
+
export { HelixHeadlessIconButton };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/image-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/image-root.js';
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary A picture that says whether it arrived.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* **An element rather than a recipe, because of the part CSS cannot do.**
|
|
8
|
+
* Reserving the box is `aspect-ratio` and needs nothing from anybody; `Link` and
|
|
9
|
+
* the megamenu row are recipes in `preview.css` for exactly that reason. What
|
|
10
|
+
* cannot be written as a rule is *when the picture arrived*: a stylesheet has no
|
|
11
|
+
* way to know, and no way to hear that it never will. So this owns three states
|
|
12
|
+
* and the two events that move between them, and leaves the box to the
|
|
13
|
+
* stylesheet.
|
|
14
|
+
*
|
|
15
|
+
* **The placeholder is a slot with nothing in it by default.** A default of
|
|
16
|
+
* `Skeleton` would be right and is not written here: this tier renders no other
|
|
17
|
+
* component, and reaching for one would make the headless package depend on the
|
|
18
|
+
* styled one. The styled tier draws the resting placeholder instead, and a
|
|
19
|
+
* consumer who wants a `Skeleton`, a blurred thumbnail or a solid color slots
|
|
20
|
+
* it.
|
|
21
|
+
*
|
|
22
|
+
* **No source is a loading state, not a fourth one.** A picture whose `src` has
|
|
23
|
+
* not arrived yet is the common case for anything drawn from data, and the
|
|
24
|
+
* useful answer there is the same as for one still on the wire: stand something
|
|
25
|
+
* in its place and keep the ground reserved. So an element with no `src` shows
|
|
26
|
+
* its placeholder and waits, rather than resolving to an empty box that has to
|
|
27
|
+
* be laid out twice.
|
|
28
|
+
*
|
|
29
|
+
* **`alt` is a property and not an afterthought.** An empty string is a real
|
|
30
|
+
* answer, meaning the picture is decoration and a screen reader should skip it,
|
|
31
|
+
* which is why the attribute is always written even when it is empty: omitting
|
|
32
|
+
* it entirely makes a reader announce the file name instead.
|
|
33
|
+
*
|
|
34
|
+
* @since 0.1.0
|
|
35
|
+
* @status experimental
|
|
36
|
+
* @category media
|
|
37
|
+
* @aliases Picture, Img, Figure
|
|
38
|
+
* @documentation https://helix.fusion.dev/components/image
|
|
39
|
+
*
|
|
40
|
+
* @slot fallback - Shown instead of it, if it never does.
|
|
41
|
+
* @slot placeholder - Shown until the picture arrives.
|
|
42
|
+
*
|
|
43
|
+
* @event {Event} error - Relayed for the same reason.
|
|
44
|
+
* @event {Event} load - Relayed, because the platform's own does not escape.
|
|
45
|
+
*
|
|
46
|
+
* @csspart fallback - What stands in when it fails.
|
|
47
|
+
* @csspart image - The picture itself.
|
|
48
|
+
* @csspart placeholder - What stands in until it arrives.
|
|
49
|
+
*/
|
|
50
|
+
export declare class HelixHeadlessImage extends HelixElement {
|
|
51
|
+
/**
|
|
52
|
+
* Where the picture is.
|
|
53
|
+
*/
|
|
54
|
+
src: string;
|
|
55
|
+
/**
|
|
56
|
+
* What it shows, for a reader who cannot see it.
|
|
57
|
+
*
|
|
58
|
+
* Empty is a real answer and means decoration. Omitting the attribute is not
|
|
59
|
+
* the same thing: a reader with nothing to read announces the file name.
|
|
60
|
+
*/
|
|
61
|
+
alt: string;
|
|
62
|
+
/**
|
|
63
|
+
* Whether to wait until it is nearly on screen.
|
|
64
|
+
*
|
|
65
|
+
* `lazy` by default, which is the opposite of the platform's, because a
|
|
66
|
+
* picture worth putting in a component is usually below the fold and the one
|
|
67
|
+
* that is not is the exception worth writing down.
|
|
68
|
+
*/
|
|
69
|
+
loading?: 'eager' | 'lazy';
|
|
70
|
+
/**
|
|
71
|
+
* The candidate widths, passed through to the picture.
|
|
72
|
+
*/
|
|
73
|
+
srcset: string;
|
|
74
|
+
/**
|
|
75
|
+
* How much of the line it will take, passed through to the picture.
|
|
76
|
+
*/
|
|
77
|
+
sizes: string;
|
|
78
|
+
/**
|
|
79
|
+
* How urgently to fetch it, for the one picture that is the page.
|
|
80
|
+
*
|
|
81
|
+
* The hero of a page is usually its largest contentful paint, and the fix is
|
|
82
|
+
* two attributes rather than one: `loading="eager"` stops it waiting for the
|
|
83
|
+
* viewport, and this stops it queueing behind everything else the parser
|
|
84
|
+
* found first. Left alone the browser decides, which is right for the other
|
|
85
|
+
* ninety-nine pictures.
|
|
86
|
+
*/
|
|
87
|
+
fetchPriority: 'auto' | 'high' | 'low';
|
|
88
|
+
/**
|
|
89
|
+
* Whether the browser may decode off the main thread.
|
|
90
|
+
*
|
|
91
|
+
* **The template hardcoded `async` and a consumer could not reach it**, which
|
|
92
|
+
* is worse than the property being absent: the decision was taken on their
|
|
93
|
+
* behalf and nothing said so. `async` is still the resting value and still
|
|
94
|
+
* right for a picture in a page, and `sync` is what a consumer reaches for
|
|
95
|
+
* when the picture is about to be composited with something else and a tear
|
|
96
|
+
* would show.
|
|
97
|
+
*/
|
|
98
|
+
decoding: 'async' | 'auto' | 'sync';
|
|
99
|
+
/**
|
|
100
|
+
* How the picture is fetched across origins, which decides whether a canvas
|
|
101
|
+
* can read it.
|
|
102
|
+
*/
|
|
103
|
+
crossOrigin: 'anonymous' | 'use-credentials' | null;
|
|
104
|
+
/**
|
|
105
|
+
* How much of the referring URL to send with the request.
|
|
106
|
+
*/
|
|
107
|
+
referrerPolicy: string;
|
|
108
|
+
/**
|
|
109
|
+
* Whether the picture is on its way, here, or never coming.
|
|
110
|
+
*
|
|
111
|
+
* Read-only to a consumer: it is a report rather than a setting.
|
|
112
|
+
*
|
|
113
|
+
* **Mirrored to `data-status`, and not reflected as `status`.** It is element
|
|
114
|
+
* state, so reflecting it puts the element's own bookkeeping into the markup
|
|
115
|
+
* a consumer rendered: React reads the attribute appearing at upgrade as a
|
|
116
|
+
* hydration mismatch, and a serialized `<helix-image status="loaded">` pasted
|
|
117
|
+
* back declares that a picture has arrived which this element has never
|
|
118
|
+
* fetched. The `data-` name is the library's answer to both, being a
|
|
119
|
+
* different name a re-parse cannot mistake for a declaration, and it is what
|
|
120
|
+
* `data-closed` on `Toast.Item` already does, and `AppHeader` did until its
|
|
121
|
+
* own moved to `:state(scrolled)` for the hydration reason recorded there.
|
|
122
|
+
* A picture arrives after somebody fetched it, which puts this on the safe
|
|
123
|
+
* side of hydration: a fact that can be true on the *first* update mirrors to
|
|
124
|
+
* a custom state instead, which is what `:state(open)` and `:state(checked)`
|
|
125
|
+
* became on 27 Aug 2026 for exactly that reason.
|
|
126
|
+
*
|
|
127
|
+
* `loading` writes nothing, because it is where every image starts and the
|
|
128
|
+
* resting state of a mirror is the attribute's absence.
|
|
129
|
+
*/
|
|
130
|
+
status: 'error' | 'loaded' | 'loading';
|
|
131
|
+
/**
|
|
132
|
+
* Which `src` the current status belongs to, so a new one starts over.
|
|
133
|
+
*/
|
|
134
|
+
private answered;
|
|
135
|
+
/**
|
|
136
|
+
* Says so under the platform's own name, because the platform's cannot escape.
|
|
137
|
+
*
|
|
138
|
+
* `load` and `error` on an `<img>` neither bubble nor compose, so the ones
|
|
139
|
+
* fired inside this shadow root reach nobody outside it. A consumer had a
|
|
140
|
+
* reflected attribute and a `MutationObserver` and nothing else. Re-emitting
|
|
141
|
+
* from the host is what `relayNativeEvent` is for, and it is what `Avatar`
|
|
142
|
+
* already did for the same pair on the same element.
|
|
143
|
+
*
|
|
144
|
+
* **These were `helix-load` and `helix-error`, and the rename is the fix.**
|
|
145
|
+
* The argument for a prefix is a collision with a native name, and there was
|
|
146
|
+
* none to collide with here: the native events cannot reach a consumer at
|
|
147
|
+
* all. So the prefix bought nothing and cost the two spellings this library
|
|
148
|
+
* had for one idea, `Avatar` relaying `load` while `Image` invented one. See
|
|
149
|
+
* 294 and 295.
|
|
150
|
+
*
|
|
151
|
+
* **Not bubbling, and that is not a small point.** The retired events were
|
|
152
|
+
* `bubbles: true, composed: true` deliberately, so a gallery could count its
|
|
153
|
+
* pictures with one listener. A bubbling relay of `load` reaches nothing in
|
|
154
|
+
* React: `load` is in react-dom's `nonDelegatedEvents`, so there is no root
|
|
155
|
+
* listener to catch it, and React attaches a direct one for `<img>` and never
|
|
156
|
+
* for a custom element. `bindReactHandler` binds exactly the non-bubbling
|
|
157
|
+
* ones, so matching the native propagation is what makes `onLoad` work at
|
|
158
|
+
* all. A gallery does here what it already does for `<img>`, which is listen
|
|
159
|
+
* in the capture phase or listen per picture.
|
|
160
|
+
*/
|
|
161
|
+
private announce;
|
|
162
|
+
private readonly handleLoad;
|
|
163
|
+
private readonly handleError;
|
|
164
|
+
/**
|
|
165
|
+
* Catches the picture that was already there.
|
|
166
|
+
*
|
|
167
|
+
* A cached image can finish loading before this element has a listener on it,
|
|
168
|
+
* and then `load` never fires and the placeholder stays up over a picture that
|
|
169
|
+
* is sitting right behind it. `complete` is the platform's own answer to that
|
|
170
|
+
* question, and `naturalWidth` separates a decoded picture from one that
|
|
171
|
+
* carries no pixels, which `complete` reports as finished either way.
|
|
172
|
+
*
|
|
173
|
+
* **It can only ever conclude success.** A picture that has not been attempted
|
|
174
|
+
* looks exactly like one that failed: `complete` is true and `naturalWidth` is
|
|
175
|
+
* zero for both, and a DOM that never fetches anything reports that for every
|
|
176
|
+
* image it has. Deciding `error` here called every picture broken the moment
|
|
177
|
+
* it rendered. Failure has an event of its own and that event is reliable, so
|
|
178
|
+
* this is only here to catch the success that happened too early to hear.
|
|
179
|
+
*/
|
|
180
|
+
private settle;
|
|
181
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
182
|
+
protected updated(changed: PropertyValues): void;
|
|
183
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
184
|
+
/**
|
|
185
|
+
* The picture's own state, under the platform's own names.
|
|
186
|
+
*
|
|
187
|
+
* The `<img>` is inside this shadow root, so a consumer asking how big the
|
|
188
|
+
* picture turned out to be, or whether it is already there, had nowhere to
|
|
189
|
+
* ask: `querySelector` does not cross a shadow boundary. `status` answers a
|
|
190
|
+
* narrower question and answers it in this library's words, which is the
|
|
191
|
+
* right report for the three states this element draws and is not a
|
|
192
|
+
* substitute for the numbers.
|
|
193
|
+
*
|
|
194
|
+
* `naturalWidth` and `naturalHeight` are the case worth having: they are how
|
|
195
|
+
* a consumer sizes a lightbox or works out an aspect ratio, and they exist
|
|
196
|
+
* nowhere else on the page.
|
|
197
|
+
*/
|
|
198
|
+
private get image();
|
|
199
|
+
/** Whether the picture has finished arriving, however it went. */
|
|
200
|
+
get complete(): boolean;
|
|
201
|
+
/** Which candidate the browser actually chose out of `srcset`. */
|
|
202
|
+
get currentSrc(): string;
|
|
203
|
+
/** The picture's own height in pixels, and zero until it has arrived. */
|
|
204
|
+
get naturalHeight(): number;
|
|
205
|
+
/** The picture's own width in pixels, and zero until it has arrived. */
|
|
206
|
+
get naturalWidth(): number;
|
|
207
|
+
protected render(): TemplateResult;
|
|
208
|
+
}
|
|
209
|
+
declare global {
|
|
210
|
+
interface HTMLElementTagNameMap {
|
|
211
|
+
'helix-headless-image': HelixHeadlessImage;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
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 } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
/**
|
|
11
|
+
* @summary A picture that says whether it arrived.
|
|
12
|
+
*
|
|
13
|
+
* @description
|
|
14
|
+
* **An element rather than a recipe, because of the part CSS cannot do.**
|
|
15
|
+
* Reserving the box is `aspect-ratio` and needs nothing from anybody; `Link` and
|
|
16
|
+
* the megamenu row are recipes in `preview.css` for exactly that reason. What
|
|
17
|
+
* cannot be written as a rule is *when the picture arrived*: a stylesheet has no
|
|
18
|
+
* way to know, and no way to hear that it never will. So this owns three states
|
|
19
|
+
* and the two events that move between them, and leaves the box to the
|
|
20
|
+
* stylesheet.
|
|
21
|
+
*
|
|
22
|
+
* **The placeholder is a slot with nothing in it by default.** A default of
|
|
23
|
+
* `Skeleton` would be right and is not written here: this tier renders no other
|
|
24
|
+
* component, and reaching for one would make the headless package depend on the
|
|
25
|
+
* styled one. The styled tier draws the resting placeholder instead, and a
|
|
26
|
+
* consumer who wants a `Skeleton`, a blurred thumbnail or a solid color slots
|
|
27
|
+
* it.
|
|
28
|
+
*
|
|
29
|
+
* **No source is a loading state, not a fourth one.** A picture whose `src` has
|
|
30
|
+
* not arrived yet is the common case for anything drawn from data, and the
|
|
31
|
+
* useful answer there is the same as for one still on the wire: stand something
|
|
32
|
+
* in its place and keep the ground reserved. So an element with no `src` shows
|
|
33
|
+
* its placeholder and waits, rather than resolving to an empty box that has to
|
|
34
|
+
* be laid out twice.
|
|
35
|
+
*
|
|
36
|
+
* **`alt` is a property and not an afterthought.** An empty string is a real
|
|
37
|
+
* answer, meaning the picture is decoration and a screen reader should skip it,
|
|
38
|
+
* which is why the attribute is always written even when it is empty: omitting
|
|
39
|
+
* it entirely makes a reader announce the file name instead.
|
|
40
|
+
*
|
|
41
|
+
* @since 0.1.0
|
|
42
|
+
* @status experimental
|
|
43
|
+
* @category media
|
|
44
|
+
* @aliases Picture, Img, Figure
|
|
45
|
+
* @documentation https://helix.fusion.dev/components/image
|
|
46
|
+
*
|
|
47
|
+
* @slot fallback - Shown instead of it, if it never does.
|
|
48
|
+
* @slot placeholder - Shown until the picture arrives.
|
|
49
|
+
*
|
|
50
|
+
* @event {Event} error - Relayed for the same reason.
|
|
51
|
+
* @event {Event} load - Relayed, because the platform's own does not escape.
|
|
52
|
+
*
|
|
53
|
+
* @csspart fallback - What stands in when it fails.
|
|
54
|
+
* @csspart image - The picture itself.
|
|
55
|
+
* @csspart placeholder - What stands in until it arrives.
|
|
56
|
+
*/
|
|
57
|
+
let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
58
|
+
constructor() {
|
|
59
|
+
super(...arguments);
|
|
60
|
+
/**
|
|
61
|
+
* Where the picture is.
|
|
62
|
+
*/
|
|
63
|
+
this.src = '';
|
|
64
|
+
/**
|
|
65
|
+
* What it shows, for a reader who cannot see it.
|
|
66
|
+
*
|
|
67
|
+
* Empty is a real answer and means decoration. Omitting the attribute is not
|
|
68
|
+
* the same thing: a reader with nothing to read announces the file name.
|
|
69
|
+
*/
|
|
70
|
+
this.alt = '';
|
|
71
|
+
/**
|
|
72
|
+
* The candidate widths, passed through to the picture.
|
|
73
|
+
*/
|
|
74
|
+
this.srcset = '';
|
|
75
|
+
/**
|
|
76
|
+
* How much of the line it will take, passed through to the picture.
|
|
77
|
+
*/
|
|
78
|
+
this.sizes = '';
|
|
79
|
+
/**
|
|
80
|
+
* How urgently to fetch it, for the one picture that is the page.
|
|
81
|
+
*
|
|
82
|
+
* The hero of a page is usually its largest contentful paint, and the fix is
|
|
83
|
+
* two attributes rather than one: `loading="eager"` stops it waiting for the
|
|
84
|
+
* viewport, and this stops it queueing behind everything else the parser
|
|
85
|
+
* found first. Left alone the browser decides, which is right for the other
|
|
86
|
+
* ninety-nine pictures.
|
|
87
|
+
*/
|
|
88
|
+
this.fetchPriority = 'auto';
|
|
89
|
+
/**
|
|
90
|
+
* Whether the browser may decode off the main thread.
|
|
91
|
+
*
|
|
92
|
+
* **The template hardcoded `async` and a consumer could not reach it**, which
|
|
93
|
+
* is worse than the property being absent: the decision was taken on their
|
|
94
|
+
* behalf and nothing said so. `async` is still the resting value and still
|
|
95
|
+
* right for a picture in a page, and `sync` is what a consumer reaches for
|
|
96
|
+
* when the picture is about to be composited with something else and a tear
|
|
97
|
+
* would show.
|
|
98
|
+
*/
|
|
99
|
+
this.decoding = 'async';
|
|
100
|
+
/**
|
|
101
|
+
* How the picture is fetched across origins, which decides whether a canvas
|
|
102
|
+
* can read it.
|
|
103
|
+
*/
|
|
104
|
+
this.crossOrigin = null;
|
|
105
|
+
/**
|
|
106
|
+
* How much of the referring URL to send with the request.
|
|
107
|
+
*/
|
|
108
|
+
this.referrerPolicy = '';
|
|
109
|
+
/**
|
|
110
|
+
* Whether the picture is on its way, here, or never coming.
|
|
111
|
+
*
|
|
112
|
+
* Read-only to a consumer: it is a report rather than a setting.
|
|
113
|
+
*
|
|
114
|
+
* **Mirrored to `data-status`, and not reflected as `status`.** It is element
|
|
115
|
+
* state, so reflecting it puts the element's own bookkeeping into the markup
|
|
116
|
+
* a consumer rendered: React reads the attribute appearing at upgrade as a
|
|
117
|
+
* hydration mismatch, and a serialized `<helix-image status="loaded">` pasted
|
|
118
|
+
* back declares that a picture has arrived which this element has never
|
|
119
|
+
* fetched. The `data-` name is the library's answer to both, being a
|
|
120
|
+
* different name a re-parse cannot mistake for a declaration, and it is what
|
|
121
|
+
* `data-closed` on `Toast.Item` already does, and `AppHeader` did until its
|
|
122
|
+
* own moved to `:state(scrolled)` for the hydration reason recorded there.
|
|
123
|
+
* A picture arrives after somebody fetched it, which puts this on the safe
|
|
124
|
+
* side of hydration: a fact that can be true on the *first* update mirrors to
|
|
125
|
+
* a custom state instead, which is what `:state(open)` and `:state(checked)`
|
|
126
|
+
* became on 27 Aug 2026 for exactly that reason.
|
|
127
|
+
*
|
|
128
|
+
* `loading` writes nothing, because it is where every image starts and the
|
|
129
|
+
* resting state of a mirror is the attribute's absence.
|
|
130
|
+
*/
|
|
131
|
+
this.status = 'loading';
|
|
132
|
+
/**
|
|
133
|
+
* Which `src` the current status belongs to, so a new one starts over.
|
|
134
|
+
*/
|
|
135
|
+
this.answered = '';
|
|
136
|
+
this.handleLoad = (event) => {
|
|
137
|
+
this.announce('loaded', event);
|
|
138
|
+
};
|
|
139
|
+
this.handleError = (event) => {
|
|
140
|
+
this.announce('error', event);
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Says so under the platform's own name, because the platform's cannot escape.
|
|
145
|
+
*
|
|
146
|
+
* `load` and `error` on an `<img>` neither bubble nor compose, so the ones
|
|
147
|
+
* fired inside this shadow root reach nobody outside it. A consumer had a
|
|
148
|
+
* reflected attribute and a `MutationObserver` and nothing else. Re-emitting
|
|
149
|
+
* from the host is what `relayNativeEvent` is for, and it is what `Avatar`
|
|
150
|
+
* already did for the same pair on the same element.
|
|
151
|
+
*
|
|
152
|
+
* **These were `helix-load` and `helix-error`, and the rename is the fix.**
|
|
153
|
+
* The argument for a prefix is a collision with a native name, and there was
|
|
154
|
+
* none to collide with here: the native events cannot reach a consumer at
|
|
155
|
+
* all. So the prefix bought nothing and cost the two spellings this library
|
|
156
|
+
* had for one idea, `Avatar` relaying `load` while `Image` invented one. See
|
|
157
|
+
* 294 and 295.
|
|
158
|
+
*
|
|
159
|
+
* **Not bubbling, and that is not a small point.** The retired events were
|
|
160
|
+
* `bubbles: true, composed: true` deliberately, so a gallery could count its
|
|
161
|
+
* pictures with one listener. A bubbling relay of `load` reaches nothing in
|
|
162
|
+
* React: `load` is in react-dom's `nonDelegatedEvents`, so there is no root
|
|
163
|
+
* listener to catch it, and React attaches a direct one for `<img>` and never
|
|
164
|
+
* for a custom element. `bindReactHandler` binds exactly the non-bubbling
|
|
165
|
+
* ones, so matching the native propagation is what makes `onLoad` work at
|
|
166
|
+
* all. A gallery does here what it already does for `<img>`, which is listen
|
|
167
|
+
* in the capture phase or listen per picture.
|
|
168
|
+
*/
|
|
169
|
+
announce(status, event) {
|
|
170
|
+
this.status = status;
|
|
171
|
+
const name = status === 'loaded' ? 'load' : 'error';
|
|
172
|
+
if (event) {
|
|
173
|
+
this.relayNativeEvent(event);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
/* No original to relay: `settle` catches a picture that was already
|
|
177
|
+
complete when the listener attached, which is the cached case, and the
|
|
178
|
+
platform fired its `load` before anyone was listening. The synthesized
|
|
179
|
+
one carries the native propagation rather than defaults, so a consumer
|
|
180
|
+
cannot tell the two paths apart. */
|
|
181
|
+
this.dispatchEvent(new Event(name, { bubbles: false, cancelable: false, composed: false }));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Catches the picture that was already there.
|
|
185
|
+
*
|
|
186
|
+
* A cached image can finish loading before this element has a listener on it,
|
|
187
|
+
* and then `load` never fires and the placeholder stays up over a picture that
|
|
188
|
+
* is sitting right behind it. `complete` is the platform's own answer to that
|
|
189
|
+
* question, and `naturalWidth` separates a decoded picture from one that
|
|
190
|
+
* carries no pixels, which `complete` reports as finished either way.
|
|
191
|
+
*
|
|
192
|
+
* **It can only ever conclude success.** A picture that has not been attempted
|
|
193
|
+
* looks exactly like one that failed: `complete` is true and `naturalWidth` is
|
|
194
|
+
* zero for both, and a DOM that never fetches anything reports that for every
|
|
195
|
+
* image it has. Deciding `error` here called every picture broken the moment
|
|
196
|
+
* it rendered. Failure has an event of its own and that event is reliable, so
|
|
197
|
+
* this is only here to catch the success that happened too early to hear.
|
|
198
|
+
*/
|
|
199
|
+
settle() {
|
|
200
|
+
const image = this.renderRoot?.querySelector('img');
|
|
201
|
+
if (this.src === '' || !image?.complete || image.naturalWidth === 0) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this.announce('loaded');
|
|
205
|
+
}
|
|
206
|
+
willUpdate(changed) {
|
|
207
|
+
super.willUpdate(changed);
|
|
208
|
+
/* A new picture is a new question, so the old answer goes. Without this a
|
|
209
|
+
second `src` inherits the first one's `loaded` and never shows its own
|
|
210
|
+
placeholder. */
|
|
211
|
+
if (changed.has('src') && this.answered !== this.src) {
|
|
212
|
+
this.answered = this.src;
|
|
213
|
+
this.status = 'loading';
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
updated(changed) {
|
|
217
|
+
super.updated?.(changed);
|
|
218
|
+
if (changed.has('src')) {
|
|
219
|
+
this.settle();
|
|
220
|
+
}
|
|
221
|
+
/* The mirror, written here rather than reflected. `loading` is the resting
|
|
222
|
+
state and writes nothing, so a picture on its way carries no attribute
|
|
223
|
+
and one that has arrived or failed says which. */
|
|
224
|
+
if (changed.has('status')) {
|
|
225
|
+
if (this.status === 'loading') {
|
|
226
|
+
this.removeAttribute('data-status');
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.setAttribute('data-status', this.status);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
firstUpdated(changed) {
|
|
234
|
+
super.firstUpdated?.(changed);
|
|
235
|
+
this.settle();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* The picture's own state, under the platform's own names.
|
|
239
|
+
*
|
|
240
|
+
* The `<img>` is inside this shadow root, so a consumer asking how big the
|
|
241
|
+
* picture turned out to be, or whether it is already there, had nowhere to
|
|
242
|
+
* ask: `querySelector` does not cross a shadow boundary. `status` answers a
|
|
243
|
+
* narrower question and answers it in this library's words, which is the
|
|
244
|
+
* right report for the three states this element draws and is not a
|
|
245
|
+
* substitute for the numbers.
|
|
246
|
+
*
|
|
247
|
+
* `naturalWidth` and `naturalHeight` are the case worth having: they are how
|
|
248
|
+
* a consumer sizes a lightbox or works out an aspect ratio, and they exist
|
|
249
|
+
* nowhere else on the page.
|
|
250
|
+
*/
|
|
251
|
+
get image() {
|
|
252
|
+
return this.renderRoot?.querySelector('img') ?? null;
|
|
253
|
+
}
|
|
254
|
+
/** Whether the picture has finished arriving, however it went. */
|
|
255
|
+
get complete() {
|
|
256
|
+
return this.image?.complete ?? false;
|
|
257
|
+
}
|
|
258
|
+
/** Which candidate the browser actually chose out of `srcset`. */
|
|
259
|
+
get currentSrc() {
|
|
260
|
+
return this.image?.currentSrc ?? '';
|
|
261
|
+
}
|
|
262
|
+
/** The picture's own height in pixels, and zero until it has arrived. */
|
|
263
|
+
get naturalHeight() {
|
|
264
|
+
return this.image?.naturalHeight ?? 0;
|
|
265
|
+
}
|
|
266
|
+
/** The picture's own width in pixels, and zero until it has arrived. */
|
|
267
|
+
get naturalWidth() {
|
|
268
|
+
return this.image?.naturalWidth ?? 0;
|
|
269
|
+
}
|
|
270
|
+
render() {
|
|
271
|
+
return html `<img
|
|
272
|
+
part="image"
|
|
273
|
+
alt=${this.alt}
|
|
274
|
+
loading=${this.loading ?? 'lazy'}
|
|
275
|
+
decoding=${this.decoding}
|
|
276
|
+
crossorigin=${this.crossOrigin ?? nothing}
|
|
277
|
+
referrerpolicy=${this.referrerPolicy || nothing}
|
|
278
|
+
fetchpriority=${this.fetchPriority}
|
|
279
|
+
src=${this.src || nothing}
|
|
280
|
+
srcset=${this.srcset || nothing}
|
|
281
|
+
sizes=${this.sizes || nothing}
|
|
282
|
+
@load=${this.handleLoad}
|
|
283
|
+
@error=${this.handleError}
|
|
284
|
+
/>
|
|
285
|
+
<span
|
|
286
|
+
part="placeholder"
|
|
287
|
+
aria-hidden="true"
|
|
288
|
+
?hidden=${this.status !== 'loading'}
|
|
289
|
+
><slot name="placeholder"></slot
|
|
290
|
+
></span>
|
|
291
|
+
<span
|
|
292
|
+
part="fallback"
|
|
293
|
+
aria-hidden="true"
|
|
294
|
+
?hidden=${this.status !== 'error'}
|
|
295
|
+
><slot name="fallback"></slot
|
|
296
|
+
></span>`;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
__decorate([
|
|
300
|
+
property()
|
|
301
|
+
], HelixHeadlessImage.prototype, "src", void 0);
|
|
302
|
+
__decorate([
|
|
303
|
+
property()
|
|
304
|
+
], HelixHeadlessImage.prototype, "alt", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
property({ reflect: true })
|
|
307
|
+
], HelixHeadlessImage.prototype, "loading", void 0);
|
|
308
|
+
__decorate([
|
|
309
|
+
property()
|
|
310
|
+
], HelixHeadlessImage.prototype, "srcset", void 0);
|
|
311
|
+
__decorate([
|
|
312
|
+
property()
|
|
313
|
+
], HelixHeadlessImage.prototype, "sizes", void 0);
|
|
314
|
+
__decorate([
|
|
315
|
+
property({ attribute: 'fetchpriority' })
|
|
316
|
+
], HelixHeadlessImage.prototype, "fetchPriority", void 0);
|
|
317
|
+
__decorate([
|
|
318
|
+
property()
|
|
319
|
+
], HelixHeadlessImage.prototype, "decoding", void 0);
|
|
320
|
+
__decorate([
|
|
321
|
+
property({ attribute: 'crossorigin' })
|
|
322
|
+
], HelixHeadlessImage.prototype, "crossOrigin", void 0);
|
|
323
|
+
__decorate([
|
|
324
|
+
property({ attribute: 'referrerpolicy' })
|
|
325
|
+
], HelixHeadlessImage.prototype, "referrerPolicy", void 0);
|
|
326
|
+
__decorate([
|
|
327
|
+
property({ attribute: false })
|
|
328
|
+
], HelixHeadlessImage.prototype, "status", void 0);
|
|
329
|
+
__decorate([
|
|
330
|
+
state()
|
|
331
|
+
], HelixHeadlessImage.prototype, "answered", void 0);
|
|
332
|
+
HelixHeadlessImage = __decorate([
|
|
333
|
+
customElement('helix-headless-image')
|
|
334
|
+
], HelixHeadlessImage);
|
|
335
|
+
export { HelixHeadlessImage };
|