@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,661 @@
|
|
|
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 { AriaForwardController, valueAsTime as asTime, customElement, timeAsValue as fromTime, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, PopoverController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { clock } from '@fusion.dev/helix-icons';
|
|
9
|
+
import { nothing } from 'lit';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
import { html } from 'lit/static-html.js';
|
|
13
|
+
/* Side-effect imports, because this renders these in its own shadow root and a
|
|
14
|
+
custom element registers on import. Base elements here and styled ones in the
|
|
15
|
+
styled file, the arrangement Date Input has with its calendar. */
|
|
16
|
+
import '../../icon/index.js';
|
|
17
|
+
import '../../tag/index.js';
|
|
18
|
+
import '../../time-picker/index.js';
|
|
19
|
+
import { isTime, toMinutes, writeTime } from '../../time-picker/root/time-picker-root.js';
|
|
20
|
+
/**
|
|
21
|
+
* @summary A time, typed or picked from a list.
|
|
22
|
+
*
|
|
23
|
+
* @description
|
|
24
|
+
* **The list is `helix-time-picker`, not a second one written here.** It is worth
|
|
25
|
+
* having on its own, flat in a settings pane with nothing to open, and this
|
|
26
|
+
* element is the field, the overlay and the form. Exactly the arrangement Input
|
|
27
|
+
* Date has with `helix-date-picker` and Color Input with `helix-color-picker`.
|
|
28
|
+
*
|
|
29
|
+
* **Typed as well as picked, and that is the division the list depends on.** A
|
|
30
|
+
* list at a step offers the times a product actually has, and the field is how a
|
|
31
|
+
* reader says `09:07`. Neither is a worse version of the other: without the
|
|
32
|
+
* field a step is a cage, and without the list every common time is typed out.
|
|
33
|
+
*
|
|
34
|
+
* **The value is `HH:mm` on a twenty-four hour clock, always**, because that is
|
|
35
|
+
* what a form submits, what `min` and `max` compare against, and what sorts as a
|
|
36
|
+
* string. What the field *shows* is the reader's own convention while it is
|
|
37
|
+
* idle, and the value itself once the caret is in it: the same separation Input
|
|
38
|
+
* Date draws, and for the same reason, which is that `2:30 PM` cannot be typed
|
|
39
|
+
* back and `Intl` has no parser to make it so.
|
|
40
|
+
*
|
|
41
|
+
* @since 0.1.0
|
|
42
|
+
* @status experimental
|
|
43
|
+
* @category forms
|
|
44
|
+
* @aliases TimeField, InputTime
|
|
45
|
+
* @documentation https://helix.fusion.dev/components/time-input
|
|
46
|
+
*
|
|
47
|
+
* @slot feedback - What is wrong with it.
|
|
48
|
+
* @slot hint - Help under the field.
|
|
49
|
+
* @slot trigger - The mark on the field saying a list opens.
|
|
50
|
+
*
|
|
51
|
+
* @event {Event} change - Announced once the value has moved.
|
|
52
|
+
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before the time changes. Cancelable: refusing it takes the decision and nothing moves.
|
|
53
|
+
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before it closes. Cancelable: refusing it takes the decision and nothing moves.
|
|
54
|
+
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before the list opens. Cancelable: refusing it takes the decision and nothing moves.
|
|
55
|
+
* @event {Event} input - Announced once the value has moved.
|
|
56
|
+
* @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
|
|
57
|
+
*
|
|
58
|
+
* @csspart control - The text input.
|
|
59
|
+
* @csspart feedback - What is wrong with it.
|
|
60
|
+
* @csspart field - The box holding the text and the trigger.
|
|
61
|
+
* @csspart hint - Help under the field, while nothing is wrong.
|
|
62
|
+
* @csspart label - The question, over the field.
|
|
63
|
+
* @csspart picker - The list inside it.
|
|
64
|
+
* @csspart picker-column - One of them.
|
|
65
|
+
* @csspart picker-column-empty - Shown when a filter has hidden everything.
|
|
66
|
+
* @csspart picker-column-feedback - What is wrong with it.
|
|
67
|
+
* @csspart picker-column-filter-icon - The mark beside that field.
|
|
68
|
+
* @csspart picker-column-filter-mark - The glyph beside the filter field, where none is slotted.
|
|
69
|
+
* @csspart picker-column-hint - Help under the list.
|
|
70
|
+
* @csspart picker-column-items - The list itself.
|
|
71
|
+
* @csspart picker-column-label - The question, over the list.
|
|
72
|
+
* @csspart picker-column-loading - Shown while the options are still on their way.
|
|
73
|
+
* @csspart picker-column-search - The region holding the field that narrows the list.
|
|
74
|
+
* @csspart picker-column-search-field - The field itself.
|
|
75
|
+
* @csspart picker-columns - The row of columns, in `wheels`.
|
|
76
|
+
* @csspart picker-list - The listbox holding the times, in `list`.
|
|
77
|
+
* @csspart picker-list-empty - Shown when a filter has hidden everything.
|
|
78
|
+
* @csspart picker-list-feedback - What is wrong with it.
|
|
79
|
+
* @csspart picker-list-filter-icon - The mark beside that field.
|
|
80
|
+
* @csspart picker-list-filter-mark - The glyph beside the filter field, where none is slotted.
|
|
81
|
+
* @csspart picker-list-hint - Help under the list.
|
|
82
|
+
* @csspart picker-list-items - The list itself.
|
|
83
|
+
* @csspart picker-list-label - The question, over the list.
|
|
84
|
+
* @csspart picker-list-loading - Shown while the options are still on their way.
|
|
85
|
+
* @csspart picker-list-search - The region holding the field that narrows the list.
|
|
86
|
+
* @csspart picker-list-search-field - The field itself.
|
|
87
|
+
* @csspart picker-option - One time in it. Carries `data-between` inside a range.
|
|
88
|
+
* @csspart picker-option-description - The caption under the words, when there is one.
|
|
89
|
+
* @csspart picker-option-item - The row.
|
|
90
|
+
* @csspart picker-option-label - The words.
|
|
91
|
+
* @csspart picker-option-text - The words and the caption, as one column.
|
|
92
|
+
* @csspart rest - How many times are held beyond the ones shown.
|
|
93
|
+
* @csspart surface - The floating panel.
|
|
94
|
+
* @csspart time - One held time, as a tag, in `multiple`.
|
|
95
|
+
* @csspart time-dismiss - The remove button, when `dismissible`.
|
|
96
|
+
* @csspart time-dismiss-mark - The glyph on the dismiss control, where none is slotted.
|
|
97
|
+
* @csspart time-prefix - The category before the label.
|
|
98
|
+
* @csspart trigger - The control that opens the list.
|
|
99
|
+
* @csspart trigger-icon - The mark on the button that opens the clock.
|
|
100
|
+
*/
|
|
101
|
+
let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinControllerOpen(MixinControllerValue(MixinField(HelixFormElement))) {
|
|
102
|
+
constructor() {
|
|
103
|
+
super(...arguments);
|
|
104
|
+
/* A consumer's `aria-describedby` names ids in their own tree and the control
|
|
105
|
+
is in this shadow root, so the reference has to be carried down as an
|
|
106
|
+
element rather than copied as an id. See `AriaForwardController`: measured
|
|
107
|
+
in Chrome's own tree, the host held the description and the control the
|
|
108
|
+
reader is actually on was exposed without it. */
|
|
109
|
+
this.aria = new AriaForwardController(this, {
|
|
110
|
+
target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
|
|
111
|
+
});
|
|
112
|
+
/**
|
|
113
|
+
* What the browser may autofill here, as one of the platform's own tokens.
|
|
114
|
+
*
|
|
115
|
+
* Empty leaves the attribute off, which is the browser's default and is what
|
|
116
|
+
* lets autofill work at all. This used to be hardcoded `off`, so a reader
|
|
117
|
+
* could never have a birthday or a postal code filled in for them and a
|
|
118
|
+
* consumer had no way to ask for it. See 295.
|
|
119
|
+
*/
|
|
120
|
+
this.autocomplete = '';
|
|
121
|
+
/**
|
|
122
|
+
* How many times are shown as tags before the rest are counted, in `multiple`.
|
|
123
|
+
*
|
|
124
|
+
* `0` is all of them, and is the default, for the reason Date Input gives: how
|
|
125
|
+
* many fit depends on the width of the field and the length of what is in it,
|
|
126
|
+
* and this element knows neither.
|
|
127
|
+
*/
|
|
128
|
+
this.maxTags = 0;
|
|
129
|
+
/**
|
|
130
|
+
* How far apart the offered times are, in minutes.
|
|
131
|
+
*/
|
|
132
|
+
this.step = 15;
|
|
133
|
+
/**
|
|
134
|
+
* Earliest time that can be chosen, as `HH:mm`.
|
|
135
|
+
*/
|
|
136
|
+
this.min = '00:00';
|
|
137
|
+
/**
|
|
138
|
+
* Latest time that can be chosen, as `HH:mm`.
|
|
139
|
+
*/
|
|
140
|
+
this.max = '23:59';
|
|
141
|
+
/**
|
|
142
|
+
* Whether the field writes the time out, or holds the value as it is.
|
|
143
|
+
*
|
|
144
|
+
* `local` is the reader's own convention from `Intl`, which is what a time is
|
|
145
|
+
* for reading; `iso` is `HH:mm`, which is what it is for typing. The field
|
|
146
|
+
* swaps to the value while the caret is in it either way, so the rendering is
|
|
147
|
+
* never something this element would refuse to read back.
|
|
148
|
+
*/
|
|
149
|
+
this.timeStyle = 'local';
|
|
150
|
+
/**
|
|
151
|
+
* Language tag the times are written in.
|
|
152
|
+
*
|
|
153
|
+
* Absent uses the runtime's own.
|
|
154
|
+
*/
|
|
155
|
+
this.locale = '';
|
|
156
|
+
/**
|
|
157
|
+
* What the field says before a time is in it.
|
|
158
|
+
*/
|
|
159
|
+
this.placeholder = 'HH:mm';
|
|
160
|
+
/**
|
|
161
|
+
* Accessible name for the control that opens the list.
|
|
162
|
+
*/
|
|
163
|
+
this.triggerLabel = 'Choose a time';
|
|
164
|
+
/**
|
|
165
|
+
* Whether the caret is in the field, which is when it holds the value.
|
|
166
|
+
*/
|
|
167
|
+
this.editing = false;
|
|
168
|
+
/** The overlay, placed against the field for the reason Date Input gives. */
|
|
169
|
+
this.panel = new PopoverController(this, {
|
|
170
|
+
anchor: () => this.renderRoot?.querySelector('[part="field"]'),
|
|
171
|
+
/* The surface *and* the trigger.
|
|
172
|
+
*
|
|
173
|
+
* A control is not always one element: the button that opens this panel is
|
|
174
|
+
* part of it, and a press on it is not a press outside. Scoped to the
|
|
175
|
+
* surface alone, `pointerdown` on the trigger closed the panel and the
|
|
176
|
+
* trigger's own `toggleOpen` reopened it on the `click` that followed, so
|
|
177
|
+
* the panel could never be closed by the button that opened it. Measured
|
|
178
|
+
* across all five popover-bearing components: Menu, Popover and Tooltip
|
|
179
|
+
* already named their invoker; this one and its three siblings did not, and
|
|
180
|
+
* all four stayed open on a second press where Menu closed.
|
|
181
|
+
*
|
|
182
|
+
* `DismissController` documents this exact failure and takes a list for it.
|
|
183
|
+
* The list was the fix; using it was the part that did not happen here. */
|
|
184
|
+
boundary: () => [
|
|
185
|
+
this.renderRoot?.querySelector('[part="surface"]'),
|
|
186
|
+
this.renderRoot?.querySelector('[part="trigger"]'),
|
|
187
|
+
],
|
|
188
|
+
offset: () => 8,
|
|
189
|
+
onDismiss: () => this.requestOpen(false),
|
|
190
|
+
placement: 'bottom-start',
|
|
191
|
+
surface: () => this.renderRoot?.querySelector('[part="surface"]'),
|
|
192
|
+
});
|
|
193
|
+
/**
|
|
194
|
+
* What is being typed but not yet held, for `multiple` only.
|
|
195
|
+
*
|
|
196
|
+
* The other modes type into the value directly, because one time and a range
|
|
197
|
+
* are both a whole answer the moment they are complete. A multiple is a set
|
|
198
|
+
* being added to, so the field needs somewhere to hold a time before it joins.
|
|
199
|
+
*/
|
|
200
|
+
this.draft = '';
|
|
201
|
+
/** Adds what was typed to the set, or takes the last one back out. */
|
|
202
|
+
this.handleDraftKey = (event) => {
|
|
203
|
+
if (this.mode !== 'multiple') {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const held = this.held;
|
|
207
|
+
if (event.key === 'Enter' && isTime(this.draft)) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
if (!held.includes(this.draft)) {
|
|
210
|
+
this.requestValue([...held, this.draft].sort().join(','));
|
|
211
|
+
}
|
|
212
|
+
this.draft = '';
|
|
213
|
+
}
|
|
214
|
+
else if (event.key === 'Backspace' && this.draft === '' && held.length > 0) {
|
|
215
|
+
this.requestValue(held.slice(0, -1).join(','));
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
/** Takes one time back out of the set. */
|
|
219
|
+
this.removeTime = (at) => {
|
|
220
|
+
this.requestValue(this.held.filter((one) => one !== at).join(','));
|
|
221
|
+
};
|
|
222
|
+
this.handleInput = (event) => {
|
|
223
|
+
event.stopPropagation();
|
|
224
|
+
// Typing is editing, whatever the focus did. The field has to hold the value
|
|
225
|
+
// while it is being changed, or a keystroke lands in a rendering.
|
|
226
|
+
this.editing = true;
|
|
227
|
+
const typed = event.target.value;
|
|
228
|
+
if (this.mode === 'multiple') {
|
|
229
|
+
this.draft = typed;
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
/* Stored as commas once every time in it is whole, and kept exactly as typed
|
|
233
|
+
until then, which is the same rule Date Input follows: a form should
|
|
234
|
+
submit `09:00,17:00` however the dash was written, and half-typed text
|
|
235
|
+
must survive so the caret does not move mid-entry. */
|
|
236
|
+
const held = typed
|
|
237
|
+
.replace(/\s+[–-]\s+/g, ',')
|
|
238
|
+
.split(',')
|
|
239
|
+
.map((one) => one.trim())
|
|
240
|
+
.filter(Boolean);
|
|
241
|
+
const whole = held.length > 0 && held.every(isTime);
|
|
242
|
+
this.requestValue(whole ? held.join(',') : typed);
|
|
243
|
+
this.restore();
|
|
244
|
+
};
|
|
245
|
+
this.handlePicked = (event) => {
|
|
246
|
+
event.stopPropagation();
|
|
247
|
+
this.requestValue(event.detail.value);
|
|
248
|
+
this.restore();
|
|
249
|
+
/* One time has nothing more to say, so the list gets out of the way. A range
|
|
250
|
+
or a multiple has: the reader is still choosing, and shutting the list
|
|
251
|
+
under them after the first pick is taking the control away mid-answer. */
|
|
252
|
+
if (this.mode === undefined) {
|
|
253
|
+
this.requestOpen(false);
|
|
254
|
+
this.updateComplete.then(() => this.returnFocus());
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Puts the caret back in the field without the field reopening the list.
|
|
259
|
+
*
|
|
260
|
+
* Focus opens the list, so handing focus back after a pick would reopen the
|
|
261
|
+
* thing that was just answered, and a reader could not get out of it. Input
|
|
262
|
+
* Date guards the same case by asking where focus came from, which is enough
|
|
263
|
+
* there and is not enough here: the option that had focus is gone by the time
|
|
264
|
+
* this runs, so `relatedTarget` is whatever the document fell back to, which
|
|
265
|
+
* is outside this element and reads as a genuine arrival.
|
|
266
|
+
*
|
|
267
|
+
* A flag rather than a better guess, because this element is the one moving
|
|
268
|
+
* the focus and it is the only thing that can know so. Cleared synchronously,
|
|
269
|
+
* since `focus()` dispatches before it returns.
|
|
270
|
+
*
|
|
271
|
+
* Reasoned rather than measured, and Date Input carries the long version of
|
|
272
|
+
* why: `focus()` dispatches no event in an unfocused document, which is what
|
|
273
|
+
* both the test runtime and the browser pane here are, so the path cannot be
|
|
274
|
+
* exercised from either.
|
|
275
|
+
*/
|
|
276
|
+
this.returning = false;
|
|
277
|
+
this.handleBlur = () => {
|
|
278
|
+
this.editing = false;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Focusing the field opens the list, and only from outside the element.
|
|
282
|
+
*
|
|
283
|
+
* The guard is the one Date Input needed: picking a time shuts the panel and
|
|
284
|
+
* puts the caret back in the field, and without it the list came straight
|
|
285
|
+
* back and a reader could not get out of it.
|
|
286
|
+
*/
|
|
287
|
+
this.handleFocus = (event) => {
|
|
288
|
+
/* Not while the caret is being handed back. Picking a time returns focus
|
|
289
|
+
to the field, and treating that as editing put the field into the shape it
|
|
290
|
+
takes for typing: a reader chose "10:00 PM" from a list and the field
|
|
291
|
+
answered "22:00". Focus is a good enough signal for editing everywhere
|
|
292
|
+
except the one moment this element moved the focus itself, and it already
|
|
293
|
+
knows when that is. */
|
|
294
|
+
this.editing = !this.returning;
|
|
295
|
+
const from = event.relatedTarget;
|
|
296
|
+
if (this.open || this.isDisabled || this.returning) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (from instanceof Node && this.renderRoot?.contains?.(from)) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
this.requestOpen(true);
|
|
303
|
+
};
|
|
304
|
+
/** Escape shuts the list without moving the time. */
|
|
305
|
+
this.handleKeydown = (event) => {
|
|
306
|
+
if (event.key === 'Escape' && this.open) {
|
|
307
|
+
event.stopPropagation();
|
|
308
|
+
this.requestOpen(false);
|
|
309
|
+
this.returnFocus();
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Whether the control refuses changes while still submitting its value.
|
|
314
|
+
*
|
|
315
|
+
* **Enforced by refusing every request in one place**, which is the seam this
|
|
316
|
+
* component already has: `requestValue` is what every path here comes through,
|
|
317
|
+
* and gating it once is what stops the next call site from being written
|
|
318
|
+
* without the check.
|
|
319
|
+
*
|
|
320
|
+
* Not `disabled`, which is the confusion worth naming: a disabled control
|
|
321
|
+
* submits nothing and leaves the tab order, and a read-only one submits its
|
|
322
|
+
* value and stays reachable, which is what a form showing a value somebody
|
|
323
|
+
* else set needs.
|
|
324
|
+
*/
|
|
325
|
+
this.readOnly = false;
|
|
326
|
+
}
|
|
327
|
+
get control() {
|
|
328
|
+
if (typeof this.renderRoot?.querySelector !== 'function') {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
return this.renderRoot.querySelector('[part="control"]');
|
|
332
|
+
}
|
|
333
|
+
/** Every time in the value, which may hold more than one. */
|
|
334
|
+
get held() {
|
|
335
|
+
/* The en dash and the spaced hyphen both mean "to", because a range is shown
|
|
336
|
+
that way and what is shown is what gets typed back. A time carries a colon
|
|
337
|
+
rather than a hyphen, so unlike a date there is no ambiguity to guard
|
|
338
|
+
against, and the guard is kept anyway for the sake of one reading. */
|
|
339
|
+
return this.value
|
|
340
|
+
.replace(/\s+[–-]\s+/g, ',')
|
|
341
|
+
.split(',')
|
|
342
|
+
.map((one) => one.trim())
|
|
343
|
+
.filter(Boolean);
|
|
344
|
+
}
|
|
345
|
+
/** One time, written the way `time-style` asks for. */
|
|
346
|
+
written(at) {
|
|
347
|
+
return this.timeStyle === 'iso' || !isTime(at) ? at : writeTime(at, this.locale);
|
|
348
|
+
}
|
|
349
|
+
/** What the field shows: the value while it is being edited, a reading when not. */
|
|
350
|
+
get display() {
|
|
351
|
+
if (this.mode === 'multiple') {
|
|
352
|
+
return this.draft;
|
|
353
|
+
}
|
|
354
|
+
const held = this.held;
|
|
355
|
+
if (this.editing || this.timeStyle === 'iso') {
|
|
356
|
+
return this.mode === 'range' && held.length === 2 ? held.join(' – ') : this.value;
|
|
357
|
+
}
|
|
358
|
+
const written = held.map((one) => this.written(one));
|
|
359
|
+
return this.mode === 'range' ? written.join(' – ') : written.join(', ');
|
|
360
|
+
}
|
|
361
|
+
/** The times that get a tag, which is all of them until `maxTags` says not. */
|
|
362
|
+
get shownTimes() {
|
|
363
|
+
const held = this.held;
|
|
364
|
+
return this.maxTags > 0 ? held.slice(0, this.maxTags) : held;
|
|
365
|
+
}
|
|
366
|
+
/** How many are held beyond the ones shown. */
|
|
367
|
+
get restCount() {
|
|
368
|
+
return Math.max(0, this.held.length - this.shownTimes.length);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* What the list should show, which is only ever a whole time.
|
|
372
|
+
*
|
|
373
|
+
* Half-typed input reaches here on every keystroke and `09:` is not a time.
|
|
374
|
+
* Handing it on would clear the list's selection mid-word, which is the same
|
|
375
|
+
* reason Date Input withholds a half-typed date from its calendar.
|
|
376
|
+
*/
|
|
377
|
+
get picked() {
|
|
378
|
+
const held = this.held;
|
|
379
|
+
return held.length > 0 && held.every(isTime) ? held.join(',') : '';
|
|
380
|
+
}
|
|
381
|
+
returnFocus() {
|
|
382
|
+
this.returning = true;
|
|
383
|
+
this.control?.focus();
|
|
384
|
+
this.returning = false;
|
|
385
|
+
}
|
|
386
|
+
/** Puts the field back where the answer differs from what was typed. */
|
|
387
|
+
restore() {
|
|
388
|
+
const control = this.control;
|
|
389
|
+
if (control && control.value !== this.display) {
|
|
390
|
+
control.value = this.display;
|
|
391
|
+
}
|
|
392
|
+
this.sync();
|
|
393
|
+
}
|
|
394
|
+
/** Reports the value and the validity the host stands behind. */
|
|
395
|
+
sync() {
|
|
396
|
+
this.internals.setFormValue(this.value);
|
|
397
|
+
const control = this.control;
|
|
398
|
+
if (!control) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
/* Checked here rather than left to the input, which is `text` and has no
|
|
402
|
+
idea what a time is. String comparison is enough because a 24 hour `HH:mm`
|
|
403
|
+
sorts lexically, which is the whole reason the value is that shape. */
|
|
404
|
+
const value = this.value;
|
|
405
|
+
let message = '';
|
|
406
|
+
if (value !== '' && !isTime(value)) {
|
|
407
|
+
message = 'Enter a time as HH:mm.';
|
|
408
|
+
// biome-ignore lint/style/noNonNullAssertion: guarded by the `value !== ''` beside it, and an optional chain here would compare `undefined` and take the branch.
|
|
409
|
+
}
|
|
410
|
+
else if (value !== '' && toMinutes(value) < (toMinutes(this.min) ?? 0)) {
|
|
411
|
+
message = `Choose a time at or after ${writeTime(this.min, this.locale)}.`;
|
|
412
|
+
// biome-ignore lint/style/noNonNullAssertion: guarded by the `value !== ''` beside it, and an optional chain here would compare `undefined` and take the branch.
|
|
413
|
+
}
|
|
414
|
+
else if (value !== '' && toMinutes(value) > (toMinutes(this.max) ?? 1439)) {
|
|
415
|
+
message = `Choose a time at or before ${writeTime(this.max, this.locale)}.`;
|
|
416
|
+
}
|
|
417
|
+
if (message === '') {
|
|
418
|
+
this.internals.setValidity(control.validity, control.validationMessage, control);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
this.internals.setValidity({ badInput: true }, message, control);
|
|
422
|
+
}
|
|
423
|
+
this.refreshFeedback();
|
|
424
|
+
}
|
|
425
|
+
/** Refuses every change while read-only. See `readOnly`. */
|
|
426
|
+
requestValue(next) {
|
|
427
|
+
if (this.readOnly) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
return super.requestValue(next);
|
|
431
|
+
}
|
|
432
|
+
firstUpdated(changed) {
|
|
433
|
+
super.firstUpdated(changed);
|
|
434
|
+
// Whatever the markup arrived with, so a form knows before anything is typed.
|
|
435
|
+
this.sync();
|
|
436
|
+
}
|
|
437
|
+
updated(changed) {
|
|
438
|
+
super.updated(changed);
|
|
439
|
+
// Every update, not only the ones that name `value`: see the note on
|
|
440
|
+
// `ColorInput.updated`, and the fifteen controls that already did this.
|
|
441
|
+
this.sync();
|
|
442
|
+
/* Driven from here rather than from the toggle, because `open` is a property
|
|
443
|
+
a consumer may set directly and the panel has to follow either way. The
|
|
444
|
+
controller is idempotent, so arriving twice for one open costs nothing.
|
|
445
|
+
Without this the surface stays `display: none`, a `popover` element being
|
|
446
|
+
hidden until something shows it, and the list inside measures zero, which
|
|
447
|
+
is what a scroll into view cannot work without. */
|
|
448
|
+
if (this.open) {
|
|
449
|
+
this.panel.show();
|
|
450
|
+
/* After the panel is shown, not before. A set of wheels centers each on
|
|
451
|
+
its own answer and cannot do it against a box of zero height, which is
|
|
452
|
+
what everything in a `popover` measures until something shows it. The
|
|
453
|
+
picker calls this on its own updates too; that one lands too early and
|
|
454
|
+
is harmless, and this one is the call that works. */
|
|
455
|
+
this.renderRoot
|
|
456
|
+
?.querySelector('[part="picker"]')
|
|
457
|
+
?.reveal?.();
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
this.panel.hide();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/** Puts the caret in the field, the way a label pointing at one would. */
|
|
464
|
+
focus(options) {
|
|
465
|
+
this.control?.focus(options);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* The clock the field opens, behind a seam the styled tier can move.
|
|
469
|
+
*
|
|
470
|
+
* A method rather than a fragment inline, so a tier above can render its own,
|
|
471
|
+
* wrap this one, pass it a property the base does not know about, or leave it
|
|
472
|
+
* out, without reimplementing the whole template to do any of them. The tag is
|
|
473
|
+
* interpolated rather than written, so `tier` resolves it: this renders the
|
|
474
|
+
* headless element, and a styled subclass that sets `tier` renders the styled one
|
|
475
|
+
* from the same template.
|
|
476
|
+
*/
|
|
477
|
+
renderPicker() {
|
|
478
|
+
return html `<${this.tag('time-picker')}
|
|
479
|
+
part="picker"
|
|
480
|
+
exportparts="column: picker-column, column-empty: picker-column-empty,
|
|
481
|
+
column-feedback: picker-column-feedback, column-filter-icon: picker-column-filter-icon,
|
|
482
|
+
column-filter-mark: picker-column-filter-mark, column-hint: picker-column-hint,
|
|
483
|
+
column-items: picker-column-items, column-label: picker-column-label,
|
|
484
|
+
column-loading: picker-column-loading, column-search: picker-column-search,
|
|
485
|
+
column-search-field: picker-column-search-field, columns: picker-columns, list: picker-list,
|
|
486
|
+
list-empty: picker-list-empty, list-feedback: picker-list-feedback,
|
|
487
|
+
list-filter-icon: picker-list-filter-icon, list-filter-mark: picker-list-filter-mark,
|
|
488
|
+
list-hint: picker-list-hint, list-items: picker-list-items, list-label: picker-list-label,
|
|
489
|
+
list-loading: picker-list-loading, list-search: picker-list-search,
|
|
490
|
+
list-search-field: picker-list-search-field, option: picker-option,
|
|
491
|
+
option-description: picker-option-description, option-item: picker-option-item,
|
|
492
|
+
option-label: picker-option-label, option-text: picker-option-text"
|
|
493
|
+
?invalid=${this.resolvedFeedback !== ''}
|
|
494
|
+
mode=${this.mode ?? nothing}
|
|
495
|
+
appearance=${this.variant ?? nothing}
|
|
496
|
+
label=${this.label || 'Time'}
|
|
497
|
+
locale=${this.locale || nothing}
|
|
498
|
+
max=${this.max}
|
|
499
|
+
min=${this.min}
|
|
500
|
+
step=${this.step}
|
|
501
|
+
.value=${this.picked}
|
|
502
|
+
@helix-before-change=${this.handlePicked}
|
|
503
|
+
@change=${this.stopInner}
|
|
504
|
+
@input=${this.stopInner}
|
|
505
|
+
></${this.tag('time-picker')}>`;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* One chosen time, as a tag, behind a seam the styled tier can move.
|
|
509
|
+
*
|
|
510
|
+
* A method rather than a fragment inline, so a tier above can render its own,
|
|
511
|
+
* wrap this one, pass it a property the base does not know about, or leave it
|
|
512
|
+
* out, without reimplementing the whole template to do any of them. The tag is
|
|
513
|
+
* interpolated rather than written, so `tier` resolves it: this renders the
|
|
514
|
+
* headless element, and a styled subclass that sets `tier` renders the styled one
|
|
515
|
+
* from the same template.
|
|
516
|
+
*/
|
|
517
|
+
renderTag(at) {
|
|
518
|
+
return html `<${this.tag('tag')}
|
|
519
|
+
part="time"
|
|
520
|
+
exportparts="dismiss: time-dismiss, dismiss-mark: time-dismiss-mark, prefix: time-prefix"
|
|
521
|
+
dismissible
|
|
522
|
+
dismiss-label=${`Remove ${this.written(at)}`}
|
|
523
|
+
?disabled=${this.isDisabled}
|
|
524
|
+
@helix-dismiss=${(event) => {
|
|
525
|
+
event.stopPropagation();
|
|
526
|
+
this.removeTime(at);
|
|
527
|
+
}}
|
|
528
|
+
>${this.written(at)}</${this.tag('tag')}
|
|
529
|
+
>`;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* The mark on the button that opens the clock, behind a seam.
|
|
533
|
+
*
|
|
534
|
+
* Slot fallback, so a consumer replaces it by slotting; and a method, so the
|
|
535
|
+
* tier above replaces it by overriding.
|
|
536
|
+
*
|
|
537
|
+
* **A named import rather than `<helix-icon>`, and that is a reversal.** The
|
|
538
|
+
* element looked like the tidier of the two and loses on three counts.
|
|
539
|
+
* `helix-icon` indexes the whole icon map at runtime, `icons[this.name]`, and
|
|
540
|
+
* no bundler can shake a runtime lookup, so every consumer of any component
|
|
541
|
+
* that renders one ships all 50kB of path data; a named import ships one
|
|
542
|
+
* path. The import is checked when the package compiles, where a `name`
|
|
543
|
+
* string is checked only when `check:icons` runs. And `helix-icon` is not
|
|
544
|
+
* registered on the headless tier at all, which registers `helix-headless-icon`,
|
|
545
|
+
* so a headless consumer got an inert unknown element and no mark whatsoever.
|
|
546
|
+
*/
|
|
547
|
+
renderTrigger() {
|
|
548
|
+
return html `<slot name="trigger"><svg aria-hidden="true" fill="currentColor" part="trigger-icon" viewBox=${clock.viewBox}>
|
|
549
|
+
${unsafeSVG(clock.content)}
|
|
550
|
+
</svg></slot>`;
|
|
551
|
+
}
|
|
552
|
+
render() {
|
|
553
|
+
return html `${this.renderLabel()}
|
|
554
|
+
<div part="field" @keydown=${this.handleKeydown}>
|
|
555
|
+
${this.mode === 'multiple' ? this.shownTimes.map((at) => this.renderTag(at)) : nothing}
|
|
556
|
+
${this.restCount > 0 ? html `<span part="rest">${`+${this.restCount}`}</span>` : nothing}
|
|
557
|
+
<input
|
|
558
|
+
part="control"
|
|
559
|
+
id="control"
|
|
560
|
+
type="text"
|
|
561
|
+
.value=${this.display}
|
|
562
|
+
name=${this.name || nothing}
|
|
563
|
+
placeholder=${this.mode === 'multiple' && this.held.length > 0 ? nothing : this.placeholder || nothing}
|
|
564
|
+
autocomplete=${this.autocomplete || nothing}
|
|
565
|
+
aria-describedby=${this.describedBy ?? nothing}
|
|
566
|
+
?disabled=${this.isDisabled}
|
|
567
|
+
?readonly=${this.readOnly}
|
|
568
|
+
?required=${this.required}
|
|
569
|
+
@blur=${this.handleBlur}
|
|
570
|
+
@focus=${this.handleFocus}
|
|
571
|
+
@input=${this.handleInput}
|
|
572
|
+
@keydown=${this.handleDraftKey}
|
|
573
|
+
/>
|
|
574
|
+
<button
|
|
575
|
+
part="trigger"
|
|
576
|
+
type="button"
|
|
577
|
+
aria-controls="surface"
|
|
578
|
+
aria-expanded=${this.open ? 'true' : 'false'}
|
|
579
|
+
aria-haspopup="listbox"
|
|
580
|
+
aria-label=${this.triggerLabel}
|
|
581
|
+
?disabled=${this.isDisabled}
|
|
582
|
+
@click=${() => this.toggleOpen()}
|
|
583
|
+
>
|
|
584
|
+
${this.renderTrigger()}
|
|
585
|
+
</button>
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
<div part="surface" id="surface" popover="manual" ?hidden=${!this.open}>
|
|
589
|
+
${this.renderPicker()}
|
|
590
|
+
</div>
|
|
591
|
+
${this.renderHint()}${this.renderFeedback()}`;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* The value as a `Date` on 1 January 1970 UTC, or `null` while there is no time.
|
|
595
|
+
*
|
|
596
|
+
* The platform's own pair on `<input type="time">`, epoch day included: a time
|
|
597
|
+
* is an offset into a day rather than an instant, and putting it on the epoch
|
|
598
|
+
* is what makes `valueAsNumber` come out as milliseconds since midnight rather
|
|
599
|
+
* than as a moment nobody meant. Assigning any date reads the clock off it, so
|
|
600
|
+
* a consumer handing over `new Date()` gets the time of day they expected.
|
|
601
|
+
*/
|
|
602
|
+
get valueAsDate() {
|
|
603
|
+
return asTime(this.value);
|
|
604
|
+
}
|
|
605
|
+
set valueAsDate(date) {
|
|
606
|
+
this.value = fromTime(date);
|
|
607
|
+
}
|
|
608
|
+
/** The value as milliseconds since midnight, or `NaN` while there is no time. */
|
|
609
|
+
get valueAsNumber() {
|
|
610
|
+
return asTime(this.value)?.getTime() ?? Number.NaN;
|
|
611
|
+
}
|
|
612
|
+
set valueAsNumber(ms) {
|
|
613
|
+
this.value = Number.isNaN(ms) ? '' : fromTime(new Date(ms));
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
__decorate([
|
|
617
|
+
property()
|
|
618
|
+
], HelixHeadlessTimeInput.prototype, "autocomplete", void 0);
|
|
619
|
+
__decorate([
|
|
620
|
+
property({ reflect: true })
|
|
621
|
+
], HelixHeadlessTimeInput.prototype, "variant", void 0);
|
|
622
|
+
__decorate([
|
|
623
|
+
property({ reflect: true })
|
|
624
|
+
], HelixHeadlessTimeInput.prototype, "mode", void 0);
|
|
625
|
+
__decorate([
|
|
626
|
+
property({ attribute: 'max-tags', type: Number })
|
|
627
|
+
], HelixHeadlessTimeInput.prototype, "maxTags", void 0);
|
|
628
|
+
__decorate([
|
|
629
|
+
property({ type: Number })
|
|
630
|
+
], HelixHeadlessTimeInput.prototype, "step", void 0);
|
|
631
|
+
__decorate([
|
|
632
|
+
property()
|
|
633
|
+
], HelixHeadlessTimeInput.prototype, "min", void 0);
|
|
634
|
+
__decorate([
|
|
635
|
+
property()
|
|
636
|
+
], HelixHeadlessTimeInput.prototype, "max", void 0);
|
|
637
|
+
__decorate([
|
|
638
|
+
property({ attribute: 'time-style' })
|
|
639
|
+
], HelixHeadlessTimeInput.prototype, "timeStyle", void 0);
|
|
640
|
+
__decorate([
|
|
641
|
+
property()
|
|
642
|
+
], HelixHeadlessTimeInput.prototype, "locale", void 0);
|
|
643
|
+
__decorate([
|
|
644
|
+
property()
|
|
645
|
+
], HelixHeadlessTimeInput.prototype, "placeholder", void 0);
|
|
646
|
+
__decorate([
|
|
647
|
+
property({ attribute: 'trigger-label' })
|
|
648
|
+
], HelixHeadlessTimeInput.prototype, "triggerLabel", void 0);
|
|
649
|
+
__decorate([
|
|
650
|
+
state()
|
|
651
|
+
], HelixHeadlessTimeInput.prototype, "editing", void 0);
|
|
652
|
+
__decorate([
|
|
653
|
+
state()
|
|
654
|
+
], HelixHeadlessTimeInput.prototype, "draft", void 0);
|
|
655
|
+
__decorate([
|
|
656
|
+
property({ attribute: 'readonly', reflect: true, type: Boolean })
|
|
657
|
+
], HelixHeadlessTimeInput.prototype, "readOnly", void 0);
|
|
658
|
+
HelixHeadlessTimeInput = __decorate([
|
|
659
|
+
customElement('helix-headless-time-input')
|
|
660
|
+
], HelixHeadlessTimeInput);
|
|
661
|
+
export { HelixHeadlessTimeInput };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/time-picker-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './root/time-picker-root.js';
|