@fusion.dev/helix-headless 0.145.0 → 0.147.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +12286 -4281
- package/dist/accordion/item/accordion-item.d.ts +51 -18
- package/dist/accordion/item/accordion-item.js +45 -13
- package/dist/accordion/root/accordion-root.d.ts +16 -7
- package/dist/accordion/root/accordion-root.js +3 -3
- package/dist/announcement/root/announcement-root.d.ts +16 -6
- package/dist/announcement/root/announcement-root.js +37 -7
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +11 -3
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/root/badge-root.d.ts +60 -7
- package/dist/badge/root/badge-root.js +89 -6
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +48 -20
- package/dist/bar-chart/stack.d.ts +25 -0
- package/dist/bar-chart/stack.js +27 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
- package/dist/button/root/button-root.d.ts +50 -38
- package/dist/button/root/button-root.js +42 -53
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +36 -4
- package/dist/card/root/card-root.js +29 -10
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +40 -4
- package/dist/chat/root/chat-root.js +32 -6
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +18 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
- package/dist/checkbox-group/select-all.d.ts +21 -0
- package/dist/checkbox-group/select-all.js +7 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +79 -10
- package/dist/code-block/root/code-block-root.js +74 -5
- package/dist/color-input/root/color-input-root.d.ts +14 -0
- package/dist/color-input/root/color-input-root.js +17 -7
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +53 -16
- package/dist/color-picker/root/color-picker-root.js +155 -46
- package/dist/color-picker/wheel.d.ts +17 -0
- package/dist/color-picker/wheel.js +6 -0
- package/dist/combobox/root/combobox-root.d.ts +56 -0
- package/dist/combobox/root/combobox-root.js +92 -15
- package/dist/command/root/command-root.d.ts +19 -2
- package/dist/command/root/command-root.js +24 -23
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +16 -4
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +6 -0
- package/dist/data-table/keys.js +14 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +31 -57
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +11 -2
- package/dist/date-input/root/date-input-root.js +26 -12
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +33 -22
- package/dist/description-list/item/description-list-item.d.ts +18 -4
- package/dist/description-list/item/description-list-item.js +8 -4
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +55 -1
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +63 -2
- package/dist/drawer/root/drawer-root.js +75 -4
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +40 -5
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +22 -3
- package/dist/element-events.generated.js +35 -6
- package/dist/empty/root/empty-root.d.ts +34 -2
- package/dist/empty/root/empty-root.js +26 -4
- package/dist/file-input/root/file-input-root.d.ts +99 -8
- package/dist/file-input/root/file-input-root.js +120 -22
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +10 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +11 -2
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +38 -6
- package/dist/filter-input/root/filter-input-root.js +18 -28
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/options.d.ts +3 -4
- package/dist/format-date/options.js +2 -2
- package/dist/format-date/root/format-date-root.d.ts +27 -17
- package/dist/format-date/root/format-date-root.js +27 -48
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +83 -11
- package/dist/heatmap/root/heatmap-root.js +104 -12
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +25 -1
- package/dist/icon/root/icon-root.js +44 -12
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +14 -1
- package/dist/image/root/image-root.js +7 -2
- package/dist/input/root/input-root.d.ts +34 -3
- package/dist/input/root/input-root.js +17 -4
- package/dist/kbd/keys.d.ts +29 -0
- package/dist/kbd/keys.js +52 -0
- package/dist/kbd/root/kbd-root.d.ts +52 -1
- package/dist/kbd/root/kbd-root.js +40 -47
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +77 -12
- package/dist/legend/root/legend-root.js +71 -17
- package/dist/lightbox/root/lightbox-root.d.ts +98 -10
- package/dist/lightbox/root/lightbox-root.js +153 -18
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +24 -0
- package/dist/lightbox/zoom.js +18 -0
- package/dist/line-chart/root/line-chart-root.d.ts +38 -1
- package/dist/line-chart/root/line-chart-root.js +31 -3
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +70 -13
- package/dist/list/root/list-root.js +91 -13
- package/dist/list/selection.d.ts +54 -7
- package/dist/list/selection.js +32 -7
- package/dist/listbox/root/listbox-root.d.ts +44 -4
- package/dist/listbox/root/listbox-root.js +72 -34
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +80 -15
- package/dist/megamenu/root/megamenu-root.js +76 -19
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +50 -26
- package/dist/menu/root/menu-root.d.ts +17 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +62 -1
- package/dist/meter/root/meter-root.js +38 -16
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +20 -4
- package/dist/notifications/root/notifications-root.js +30 -8
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +34 -9
- package/dist/number-input/root/number-input-root.js +31 -25
- package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
- package/dist/object-inspector/root/object-inspector-root.js +134 -92
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +30 -0
- package/dist/outline/root/outline-root.js +17 -13
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +37 -0
- package/dist/pin-input/code.js +25 -0
- package/dist/pin-input/root/pin-input-root.d.ts +116 -115
- package/dist/pin-input/root/pin-input-root.js +163 -155
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +34 -0
- package/dist/popover/root/popover-root.d.ts +64 -8
- package/dist/popover/root/popover-root.js +67 -4
- package/dist/progress/root/progress-root.d.ts +47 -0
- package/dist/progress/root/progress-root.js +34 -16
- package/dist/qr-code/export.d.ts +45 -1
- package/dist/qr-code/export.js +28 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +36 -11
- package/dist/qr-code/root/qr-code-root.js +58 -11
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +7 -2
- package/dist/rating/root/rating-root.d.ts +30 -12
- package/dist/rating/root/rating-root.js +27 -27
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -8
- package/dist/scroll-area/scrollbar.js +10 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +71 -0
- package/dist/select/root/select-root.js +78 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +59 -5
- package/dist/slider/root/slider-root.js +45 -3
- package/dist/sparkline/readings.d.ts +36 -0
- package/dist/sparkline/readings.js +36 -0
- package/dist/sparkline/root/sparkline-root.d.ts +121 -7
- package/dist/sparkline/root/sparkline-root.js +160 -26
- package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
- package/dist/speed-dial/item/speed-dial-item.js +2 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
- package/dist/speed-dial/root/speed-dial-root.js +11 -3
- package/dist/splitter/root/splitter-root.d.ts +10 -12
- package/dist/splitter/root/splitter-root.js +211 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +56 -3
- package/dist/steps/root/steps-root.js +50 -6
- package/dist/steps/step/step.d.ts +8 -0
- package/dist/steps/step/step.js +8 -3
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +6 -10
- package/dist/table/column/table-column.js +8 -20
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +14 -18
- package/dist/table/row/table-row.d.ts +24 -0
- package/dist/table/row/table-row.js +37 -1
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +17 -3
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +44 -5
- package/dist/tag/group/tag-group.js +60 -9
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +41 -2
- package/dist/textarea/root/textarea-root.js +39 -1
- package/dist/time-input/root/time-input-root.d.ts +10 -2
- package/dist/time-input/root/time-input-root.js +24 -13
- package/dist/time-picker/root/time-picker-root.d.ts +28 -17
- package/dist/time-picker/root/time-picker-root.js +18 -29
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +16 -3
- package/dist/toast/item/toast-item.js +22 -6
- package/dist/toast/root/toast-root.d.ts +34 -4
- package/dist/toast/root/toast-root.js +74 -13
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +52 -7
- package/dist/toggle/group/toggle-group.js +58 -44
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +21 -5
- package/dist/toolbar/root/toolbar-root.js +52 -8
- package/dist/tooltip/root/tooltip-root.d.ts +20 -3
- package/dist/tooltip/root/tooltip-root.js +18 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +45 -2
- package/dist/tour/root/tour-root.js +53 -8
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +83 -19
- package/dist/trend/root/trend-root.js +59 -8
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +23 -6
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -8
- package/dist/virtual-list/fill.js +10 -17
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +65 -0
- package/dist/virtual-list/plan.js +27 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
- package/dist/virtual-list/root/virtual-list-root.js +218 -51
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +7441 -1458
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +1501 -326
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -27,6 +27,15 @@ declare const HelixHeadlessFilterChip_base: (new (...args: any[]) => import("@fu
|
|
|
27
27
|
* dismissal, which is also how you take control of the interaction for one
|
|
28
28
|
* press. `requestChange` documents the pattern.
|
|
29
29
|
*
|
|
30
|
+
* **Keyboard.** The remove button is a tab stop of its own, and Enter or Space
|
|
31
|
+
* on it asks to remove the filter. In a `FilterInput`, Backspace in the empty
|
|
32
|
+
* field asks to remove the last chip.
|
|
33
|
+
*
|
|
34
|
+
* The remove button is named `dismiss-label` followed by the chip's words,
|
|
35
|
+
* such as "Remove filter Status is not open", so a row of chips says which
|
|
36
|
+
* filter each button removes. Write `{label}` in `dismiss-label` to put the
|
|
37
|
+
* words elsewhere.
|
|
38
|
+
*
|
|
30
39
|
* To let the user change the operator, slot a menu trigger into `operator`.
|
|
31
40
|
* With the text fallback, the operator is a label. The chip does not interpret
|
|
32
41
|
* operators: their meaning belongs to your domain, as `FilterOperator`
|
|
@@ -100,6 +109,20 @@ export declare class HelixHeadlessFilterChip extends HelixHeadlessFilterChip_bas
|
|
|
100
109
|
* makes an unusual filter look unusual.
|
|
101
110
|
*/
|
|
102
111
|
operatorLabel: string;
|
|
112
|
+
/**
|
|
113
|
+
* The remove button's name: `dismissLabel` with the chip's words, its field,
|
|
114
|
+
* its comparison and its values, such as "Remove filter Status is not open".
|
|
115
|
+
*
|
|
116
|
+
* **Named for its chip**, as File Input names each remove button for its
|
|
117
|
+
* file: a row of buttons each called "Remove filter" says nothing about
|
|
118
|
+
* which filter each one takes away. `{label}` in `dismiss-label` says where
|
|
119
|
+
* the words go, and without it they follow the label.
|
|
120
|
+
*
|
|
121
|
+
* Each word is read from what is slotted and otherwise from `label` and
|
|
122
|
+
* `operator-label`, which is all a server and a hydrating render can read,
|
|
123
|
+
* so the values join the update after.
|
|
124
|
+
*/
|
|
125
|
+
private get removeName();
|
|
103
126
|
protected firstUpdated(changed: PropertyValues): void;
|
|
104
127
|
protected render(): TemplateResult;
|
|
105
128
|
}
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, MixinDismissible } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, MixinDismissible, slottedWords } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -16,8 +16,17 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
|
|
|
16
16
|
this.label = '';
|
|
17
17
|
this.operatorLabel = '';
|
|
18
18
|
}
|
|
19
|
+
get removeName() {
|
|
20
|
+
const read = (slot, fallback) => (this.childrenKnown && slottedWords(this, [slot])) || fallback;
|
|
21
|
+
const words = [read('field', this.label), read('operator', this.operatorLabel), read('', '')]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join(' ');
|
|
24
|
+
const label = this.dismissLabel;
|
|
25
|
+
return label.includes('{label}') ? label.replace('{label}', words) : `${label} ${words}`.trim();
|
|
26
|
+
}
|
|
19
27
|
firstUpdated(changed) {
|
|
20
28
|
super.firstUpdated(changed);
|
|
29
|
+
this.renderRoot.addEventListener('slotchange', () => this.requestUpdate());
|
|
21
30
|
this.finishHydration();
|
|
22
31
|
}
|
|
23
32
|
render() {
|
|
@@ -33,7 +42,7 @@ let HelixHeadlessFilterChip = class HelixHeadlessFilterChip extends MixinDismiss
|
|
|
33
42
|
? html `<button
|
|
34
43
|
part="dismiss"
|
|
35
44
|
type="button"
|
|
36
|
-
aria-label=${this.
|
|
45
|
+
aria-label=${this.removeName}
|
|
37
46
|
@click=${() => this.dismiss()}
|
|
38
47
|
>
|
|
39
48
|
<svg part="dismiss-mark" fill="currentColor" viewBox=${x.viewBox} aria-hidden="true">
|
|
@@ -71,6 +71,8 @@ import '../../menu/index.js';
|
|
|
71
71
|
* @csspart entry-mark - The mark at the end of a row: a check mark on a chosen value, and a caret on a field.
|
|
72
72
|
* @csspart entry-shortcut - The key drawn for a row's shortcut. The filter menu sets none, so it renders only where a subclass does.
|
|
73
73
|
* @csspart entry-shortcut-kbd - The key inside it.
|
|
74
|
+
* @csspart entry-shortcut-key - One key of the shortcut's chord.
|
|
75
|
+
* @csspart entry-shortcut-separator - The `+` between two keys of the shortcut, where the platform writes one.
|
|
74
76
|
* @csspart entry-start - The leading column.
|
|
75
77
|
* @csspart menu - The menu the fields are offered in.
|
|
76
78
|
* @csspart menu-back - The button that goes back from a field's page.
|
|
@@ -138,7 +138,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
|
|
|
138
138
|
return html `<${item}
|
|
139
139
|
part="entry"
|
|
140
140
|
exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
|
|
141
|
-
shortcut-kbd: entry-shortcut-kbd,
|
|
141
|
+
shortcut-kbd: entry-shortcut-kbd,
|
|
142
|
+
shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
|
|
143
|
+
start: entry-start"
|
|
142
144
|
data-facet="field"
|
|
143
145
|
data-field=${name}
|
|
144
146
|
>
|
|
@@ -147,7 +149,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
|
|
|
147
149
|
? html `<${item}
|
|
148
150
|
part="entry"
|
|
149
151
|
exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
|
|
150
|
-
shortcut-kbd: entry-shortcut-kbd,
|
|
152
|
+
shortcut-kbd: entry-shortcut-kbd,
|
|
153
|
+
shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
|
|
154
|
+
start: entry-start"
|
|
151
155
|
slot="submenu"
|
|
152
156
|
data-facet="comparison"
|
|
153
157
|
data-field=${name}
|
|
@@ -156,7 +160,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
|
|
|
156
160
|
${operators.map((operator) => html `<${item}
|
|
157
161
|
part="entry"
|
|
158
162
|
exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
|
|
159
|
-
shortcut-kbd: entry-shortcut-kbd,
|
|
163
|
+
shortcut-kbd: entry-shortcut-kbd,
|
|
164
|
+
shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
|
|
165
|
+
start: entry-start"
|
|
160
166
|
slot="submenu"
|
|
161
167
|
checkable
|
|
162
168
|
exclusive
|
|
@@ -179,7 +185,9 @@ let HelixHeadlessFilterMenu = class HelixHeadlessFilterMenu extends HelixElement
|
|
|
179
185
|
${offered.map((option) => html `<${item}
|
|
180
186
|
part="entry"
|
|
181
187
|
exportparts="end: entry-end, item: entry-item, mark: entry-mark, shortcut: entry-shortcut,
|
|
182
|
-
shortcut-kbd: entry-shortcut-kbd,
|
|
188
|
+
shortcut-kbd: entry-shortcut-kbd,
|
|
189
|
+
shortcut-key: entry-shortcut-key, shortcut-separator: entry-shortcut-separator,
|
|
190
|
+
start: entry-start"
|
|
183
191
|
slot="submenu"
|
|
184
192
|
checkable
|
|
185
193
|
?exclusive=${using?.arity === 'one'}
|
|
@@ -13,12 +13,36 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
|
|
|
13
13
|
* its tokens show a selection it owns, drawn from the options it was given.
|
|
14
14
|
*
|
|
15
15
|
* `value` is the typed text. Every keystroke fires `input` with the text on the
|
|
16
|
-
* element, so a table can narrow as the user types.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
* element, so a table can narrow as the user types. Backspace in an empty field
|
|
17
|
+
* fires `helix-dismiss` on the last token, the same event its remove control
|
|
18
|
+
* fires, so one handler covers the pointer and the keyboard.
|
|
19
|
+
*
|
|
20
|
+
* **What a form receives.** The text under `name`, and then one more entry
|
|
21
|
+
* under `name` for each token, in the order the tokens stand:
|
|
22
|
+
*
|
|
23
|
+
* | Token | Entry |
|
|
24
|
+
* |---|---|
|
|
25
|
+
* | Any element with a `value` attribute | The value as written: `saved:mine` |
|
|
26
|
+
* | `FilterChip` with `name` and values | `status:open,pending` |
|
|
27
|
+
* | The same, with `operator="none"` (what a typed `-status:` makes) | `-status:open,pending` |
|
|
28
|
+
* | The same, with any other `operator` except `any` | `created[after]:2024` |
|
|
29
|
+
* | A token with neither | Nothing |
|
|
30
|
+
*
|
|
31
|
+
* The values are the chip's text outside its `field` and `operator` slots,
|
|
32
|
+
* with the spaces around each comma removed. A server splits an entry at its
|
|
33
|
+
* first colon, reads a leading `-` as the negation, and reads a word in
|
|
34
|
+
* brackets before the colon as the comparison.
|
|
35
|
+
*
|
|
36
|
+
* **Keyboard.** Focus stays in the text. The text names the highlighted
|
|
37
|
+
* suggestion as its `aria-activedescendant`.
|
|
38
|
+
*
|
|
39
|
+
* | Key | What it does |
|
|
40
|
+
* |---|---|
|
|
41
|
+
* | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |
|
|
42
|
+
* | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |
|
|
43
|
+
* | Home, End | Highlights the first or the last suggestion while the panel is open. |
|
|
44
|
+
* | Escape | Closes the panel and stops there, so a dialog around the field stays open. |
|
|
45
|
+
* | Backspace | In an empty field, asks the last token to go. |
|
|
22
46
|
*
|
|
23
47
|
* **Typed filters.** The field parses only the fields you declare. Write
|
|
24
48
|
* `FilterField` elements, usually inside the `FilterMenu` slotted into `start`,
|
|
@@ -73,6 +97,7 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
|
|
|
73
97
|
* @aliases SearchField, FacetInput, TokenInput
|
|
74
98
|
* @documentation https://fusion.dev/helix/components/filter-input
|
|
75
99
|
*
|
|
100
|
+
* @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
|
|
76
101
|
* @slot end - Content after the text, such as a count or a control.
|
|
77
102
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
78
103
|
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
@@ -232,6 +257,11 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
|
|
|
232
257
|
* and one that pretends it was never there.
|
|
233
258
|
*/
|
|
234
259
|
private get suggestions();
|
|
260
|
+
/**
|
|
261
|
+
* Every option slotted into `suggestions`, and every option one level inside
|
|
262
|
+
* a group slotted there, hidden or not.
|
|
263
|
+
*/
|
|
264
|
+
private get options();
|
|
235
265
|
/**
|
|
236
266
|
* The direction of the selection, named as on `<input>`.
|
|
237
267
|
*
|
|
@@ -413,6 +443,8 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
|
|
|
413
443
|
private markActive;
|
|
414
444
|
/** Puts the caret in the text field. */
|
|
415
445
|
focus(options?: FocusOptions): void;
|
|
446
|
+
/** The cross on the clear button, behind a seam a tier can move. */
|
|
447
|
+
protected renderClearIcon(): TemplateResult;
|
|
416
448
|
protected render(): TemplateResult;
|
|
417
449
|
}
|
|
418
450
|
declare global {
|
|
@@ -162,22 +162,18 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
narrow() {
|
|
165
|
-
const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
|
|
166
165
|
const term = this.filterSuggestions
|
|
167
166
|
? currentTerm(this.value, this.control?.selectionStart ?? this.value.length)
|
|
168
167
|
: '';
|
|
169
|
-
for (const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
option.hidden = false;
|
|
179
|
-
this.narrowed.delete(option);
|
|
180
|
-
}
|
|
168
|
+
for (const option of this.options) {
|
|
169
|
+
const hide = !suggests(option.textContent ?? '', term);
|
|
170
|
+
if (hide && !option.hidden) {
|
|
171
|
+
option.hidden = true;
|
|
172
|
+
this.narrowed.add(option);
|
|
173
|
+
}
|
|
174
|
+
else if (!hide && this.narrowed.has(option)) {
|
|
175
|
+
option.hidden = false;
|
|
176
|
+
this.narrowed.delete(option);
|
|
181
177
|
}
|
|
182
178
|
}
|
|
183
179
|
}
|
|
@@ -220,20 +216,11 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
220
216
|
return this.clearable && this.value !== '' && !this.isDisabled;
|
|
221
217
|
}
|
|
222
218
|
get suggestions() {
|
|
219
|
+
return this.options.filter((option) => !option.disabled && !option.hidden);
|
|
220
|
+
}
|
|
221
|
+
get options() {
|
|
223
222
|
const slot = this.renderRoot?.querySelector('slot[name="suggestions"]');
|
|
224
|
-
|
|
225
|
-
for (const node of slot?.assignedElements({ flatten: true }) ?? []) {
|
|
226
|
-
if (isOption(node)) {
|
|
227
|
-
found.push(node);
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
for (const child of node.children) {
|
|
231
|
-
if (isOption(child)) {
|
|
232
|
-
found.push(child);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return found.filter((option) => !option.disabled && !option.hidden);
|
|
223
|
+
return (slot?.assignedElements({ flatten: true }) ?? []).flatMap((node) => isOption(node) ? [node] : [...node.children].filter(isOption));
|
|
237
224
|
}
|
|
238
225
|
get selectionDirection() {
|
|
239
226
|
return this.control?.selectionDirection ?? 'none';
|
|
@@ -364,7 +351,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
364
351
|
super.updated(changed);
|
|
365
352
|
this.releaseCaret?.();
|
|
366
353
|
this.releaseCaret = undefined;
|
|
367
|
-
this.internals.setFormValue(this.formValue());
|
|
354
|
+
this.internals.setFormValue(this.formValue(), this.value);
|
|
368
355
|
this.sayCount();
|
|
369
356
|
const control = this.control;
|
|
370
357
|
if (control) {
|
|
@@ -392,6 +379,9 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
392
379
|
focus(options) {
|
|
393
380
|
this.control?.focus(options);
|
|
394
381
|
}
|
|
382
|
+
renderClearIcon() {
|
|
383
|
+
return html `<slot name="clear-icon">${drawIcon(x)}</slot>`;
|
|
384
|
+
}
|
|
395
385
|
render() {
|
|
396
386
|
return html `${this.renderLabel()}
|
|
397
387
|
<div part="field" @focusin=${this.handleFocusIn} @focusout=${this.handleFocusOut}>
|
|
@@ -426,7 +416,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
426
416
|
aria-label=${this.clearLabel}
|
|
427
417
|
@click=${this.handleClear}
|
|
428
418
|
>
|
|
429
|
-
${
|
|
419
|
+
${this.renderClearIcon()}
|
|
430
420
|
</button>`
|
|
431
421
|
: nothing}
|
|
432
422
|
</div>
|
|
@@ -9,9 +9,34 @@
|
|
|
9
9
|
export declare const currentTerm: (text: string, caret?: number) => string;
|
|
10
10
|
/** Whether a suggestion's words hold the term, ignoring case and accents. */
|
|
11
11
|
export declare const suggests: (words: string, term: string) => boolean;
|
|
12
|
+
/** What a token says about the filter it shows, as `tokenEntry` reads it. */
|
|
13
|
+
export interface TokenWords {
|
|
14
|
+
/** The field it filters, from its `name` attribute. */
|
|
15
|
+
readonly field: string | null;
|
|
16
|
+
/** The comparison, from its `operator` attribute. */
|
|
17
|
+
readonly operator: string | null;
|
|
18
|
+
/** The values it shows, from its text. */
|
|
19
|
+
readonly text: string;
|
|
20
|
+
/** What it sends as written, from its `value` attribute. */
|
|
21
|
+
readonly value: string | null;
|
|
22
|
+
}
|
|
12
23
|
/**
|
|
13
|
-
*
|
|
14
|
-
* field
|
|
15
|
-
*
|
|
24
|
+
* The form entry for a token's words: its `value` where it has one, or else
|
|
25
|
+
* `field:values`, the way the field reads a filter typed.
|
|
26
|
+
*
|
|
27
|
+
* - The values are the token's text, with the spaces around each comma taken
|
|
28
|
+
* out: `status:open,pending`.
|
|
29
|
+
* - The comparison named `none`, which a typed `-field:` asks for, leads with a
|
|
30
|
+
* `-`: `-team:ops`.
|
|
31
|
+
* - Any comparison other than `any` and `none` is written in brackets after
|
|
32
|
+
* the field, so a chip that says `is after` keeps it: `created[after]:2024`.
|
|
33
|
+
* `any`, or no `operator`, writes none.
|
|
34
|
+
* - A token naming no field, or showing no values, sends nothing.
|
|
35
|
+
*/
|
|
36
|
+
export declare const entryFor: ({ field, operator, text, value }: TokenWords) => string | null;
|
|
37
|
+
/**
|
|
38
|
+
* The form entry for a slotted token. See `entryFor`. The values are the text
|
|
39
|
+
* of the token's unslotted content, so a name or a comparison slotted into a
|
|
40
|
+
* chip's `field` or `operator` is not read as a value.
|
|
16
41
|
*/
|
|
17
42
|
export declare const tokenEntry: (token: Element) => string | null;
|
|
@@ -8,16 +8,26 @@ export const suggests = (words, term) => {
|
|
|
8
8
|
const plain = (text) => text.normalize('NFD').replace(/\p{M}/gu, '').toLowerCase();
|
|
9
9
|
return term === '' || plain(words).includes(plain(term));
|
|
10
10
|
};
|
|
11
|
-
export const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return written;
|
|
11
|
+
export const entryFor = ({ field, operator, text, value }) => {
|
|
12
|
+
if (value !== null) {
|
|
13
|
+
return value;
|
|
15
14
|
}
|
|
16
|
-
const
|
|
17
|
-
const values = (token.textContent ?? '').replace(/\s+/gu, ' ').trim();
|
|
15
|
+
const values = text.replace(/\s+/gu, ' ').trim();
|
|
18
16
|
if (!field || values === '') {
|
|
19
17
|
return null;
|
|
20
18
|
}
|
|
21
|
-
const
|
|
22
|
-
|
|
19
|
+
const shown = values.replace(/\s*,\s*/gu, ',');
|
|
20
|
+
if (operator === 'none') {
|
|
21
|
+
return `-${field}:${shown}`;
|
|
22
|
+
}
|
|
23
|
+
return operator && operator !== 'any' ? `${field}[${operator}]:${shown}` : `${field}:${shown}`;
|
|
23
24
|
};
|
|
25
|
+
export const tokenEntry = (token) => entryFor({
|
|
26
|
+
field: token.getAttribute('name'),
|
|
27
|
+
operator: token.getAttribute('operator'),
|
|
28
|
+
text: [...token.childNodes]
|
|
29
|
+
.filter((node) => !(node.nodeType === 1 && node.hasAttribute('slot')))
|
|
30
|
+
.map((node) => node.textContent ?? '')
|
|
31
|
+
.join(''),
|
|
32
|
+
value: token.getAttribute('value'),
|
|
33
|
+
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What a Format Date was asked for, in its own spelling: the `Intl` options a
|
|
3
|
-
* consumer set
|
|
3
|
+
* consumer set. The element itself is one, so it passes itself.
|
|
4
4
|
*/
|
|
5
5
|
export interface Asked {
|
|
6
|
-
dateOnly: boolean;
|
|
7
6
|
dateStyle?: 'full' | 'long' | 'medium' | 'short' | undefined;
|
|
8
7
|
day?: 'numeric' | '2-digit' | undefined;
|
|
9
8
|
era?: 'long' | 'narrow' | 'short' | undefined;
|
|
@@ -26,8 +25,8 @@ export interface Asked {
|
|
|
26
25
|
* given beside `month` or `hour`, so the fields are left out wherever a style
|
|
27
26
|
* is set. `hourCycle` and `timeZone` go with either.
|
|
28
27
|
*
|
|
29
|
-
* **A day with no time is read in UTC** unless a zone is given. Parsed, it is
|
|
28
|
+
* **A day with no time, `dateOnly`, is read in UTC** unless a zone is given. Parsed, it is
|
|
30
29
|
* midnight UTC, and read in a zone west of it that is the day before: measured
|
|
31
30
|
* before this, `2026-08-04` read "August 3, 2026" in Los Angeles.
|
|
32
31
|
*/
|
|
33
|
-
export declare const formatOptions: (asked: Asked) => Intl.DateTimeFormatOptions;
|
|
32
|
+
export declare const formatOptions: (asked: Asked, dateOnly?: boolean) => Intl.DateTimeFormatOptions;
|
|
@@ -9,7 +9,7 @@ const FIELDS = [
|
|
|
9
9
|
'weekday',
|
|
10
10
|
'year',
|
|
11
11
|
];
|
|
12
|
-
export const formatOptions = (asked) => {
|
|
12
|
+
export const formatOptions = (asked, dateOnly = false) => {
|
|
13
13
|
const options = {};
|
|
14
14
|
const styled = asked.dateStyle !== undefined || asked.timeStyle !== undefined;
|
|
15
15
|
if (styled) {
|
|
@@ -35,7 +35,7 @@ export const formatOptions = (asked) => {
|
|
|
35
35
|
if (asked.timeZone) {
|
|
36
36
|
options.timeZone = asked.timeZone;
|
|
37
37
|
}
|
|
38
|
-
else if (
|
|
38
|
+
else if (dateOnly) {
|
|
39
39
|
options.timeZone = 'UTC';
|
|
40
40
|
}
|
|
41
41
|
return options;
|
|
@@ -25,6 +25,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
25
25
|
* **The text refreshes on one timer shared by the page.** Each element
|
|
26
26
|
* schedules an update for when its current reading expires, and an element
|
|
27
27
|
* showing a date schedules none, so a long feed left open costs almost nothing.
|
|
28
|
+
* `frozen` draws the reading once and leaves it.
|
|
28
29
|
*
|
|
29
30
|
* **The output is always `<time datetime>`**, so copy and paste and scripts
|
|
30
31
|
* parsing the page get the exact instant, whatever the visible text says. A
|
|
@@ -85,6 +86,19 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
85
86
|
* How the era is written, such as AD, where a date is shown.
|
|
86
87
|
*/
|
|
87
88
|
era?: 'long' | 'narrow' | 'short';
|
|
89
|
+
/**
|
|
90
|
+
* Draws an `elapsed` or `relative` reading once and leaves it, where it
|
|
91
|
+
* would otherwise move on as it goes stale.
|
|
92
|
+
*
|
|
93
|
+
* For a reading that describes a moment the page itself is about, such as
|
|
94
|
+
* "3 hours ago" in a report generated then, or a list a reader compares
|
|
95
|
+
* line by line while it should not change under them. The reading is taken
|
|
96
|
+
* when the element draws, and again whenever `date` or another option
|
|
97
|
+
* changes. Turned off, the reading catches up and moves on again.
|
|
98
|
+
* `sl-relative-time` and `wa-relative-time` keep still unless `sync` is
|
|
99
|
+
* set; this keeps moving unless `frozen` is.
|
|
100
|
+
*/
|
|
101
|
+
frozen: boolean;
|
|
88
102
|
/**
|
|
89
103
|
* How the hour is written, where a time of day is shown.
|
|
90
104
|
*/
|
|
@@ -100,9 +114,12 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
100
114
|
/**
|
|
101
115
|
* The locale to format the timestamp in.
|
|
102
116
|
*
|
|
103
|
-
*
|
|
117
|
+
* Absent is the page's: the `lang` of the nearest element with one, as
|
|
118
|
+
* Shoelace and Web Awesome read it, then the runtime's own.
|
|
104
119
|
*/
|
|
105
120
|
locale: string;
|
|
121
|
+
/** The locale the words are written in: `locale`, or the page's `lang`. */
|
|
122
|
+
private get language();
|
|
106
123
|
/**
|
|
107
124
|
* How the minute is written, where a time of day is shown.
|
|
108
125
|
*/
|
|
@@ -154,18 +171,21 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
154
171
|
*/
|
|
155
172
|
year?: 'numeric' | '2-digit';
|
|
156
173
|
/**
|
|
157
|
-
* The clock this element last drew against
|
|
174
|
+
* The clock this element last drew against, moved on when the reading goes
|
|
175
|
+
* stale.
|
|
158
176
|
*
|
|
159
|
-
* A
|
|
160
|
-
* make the template a function of something Lit cannot see change: the
|
|
161
|
-
* would draw the right text once and never notice it had gone stale.
|
|
177
|
+
* A controller's time and not a read of `Date.now()` inside `render`, which
|
|
178
|
+
* would make the template a function of something Lit cannot see change: the
|
|
179
|
+
* element would draw the right text once and never notice it had gone stale.
|
|
180
|
+
* The formatter says when its own answer expires, so the clock wakes at
|
|
181
|
+
* exactly that moment rather than polling: an item minutes old once a minute,
|
|
182
|
+
* an item hours old once an hour, and an item showing a date never.
|
|
162
183
|
*/
|
|
163
|
-
private clock;
|
|
184
|
+
private readonly clock;
|
|
164
185
|
/**
|
|
165
186
|
* The date read out of the light DOM, where no attribute carried one.
|
|
166
187
|
*/
|
|
167
188
|
private written;
|
|
168
|
-
private stopTicking;
|
|
169
189
|
private watching;
|
|
170
190
|
/** Whether the timestamp is a day with no time, which is formatted in UTC. */
|
|
171
191
|
private get dateOnly();
|
|
@@ -184,16 +204,6 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
184
204
|
/** The light DOM's own text, which is the other way to write the value. */
|
|
185
205
|
private read;
|
|
186
206
|
private watch;
|
|
187
|
-
/**
|
|
188
|
-
* Schedules the next reading, and only the next one.
|
|
189
|
-
*
|
|
190
|
-
* The formatter says when its own answer expires, so this asks for exactly
|
|
191
|
-
* that moment rather than polling: an item minutes old wakes once a minute, an
|
|
192
|
-
* item hours old once an hour, and an item showing a date never, which is the
|
|
193
|
-
* difference between a feed that costs nothing to leave open and one that
|
|
194
|
-
* does.
|
|
195
|
-
*/
|
|
196
|
-
private tick;
|
|
197
207
|
protected render(): TemplateResult | typeof nothing;
|
|
198
208
|
}
|
|
199
209
|
declare global {
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, elapsedTime, HelixElement,
|
|
7
|
+
import { customElement, elapsedTime, HelixElement, localeOf, RelativeClockController, relativeTime, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { formatOptions } from '../options.js';
|
|
@@ -14,12 +14,23 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.date = '';
|
|
16
16
|
this.elapsed = false;
|
|
17
|
+
this.frozen = false;
|
|
17
18
|
this.locale = '';
|
|
18
|
-
this.clock =
|
|
19
|
+
this.clock = new RelativeClockController(this, {
|
|
20
|
+
expires: (now) => {
|
|
21
|
+
const moment = this.moment;
|
|
22
|
+
if (!moment || !this.reading) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
return this.frozen ? Number.POSITIVE_INFINITY : this.readingAt(moment, now).next;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
19
28
|
this.written = '';
|
|
20
|
-
this.stopTicking = undefined;
|
|
21
29
|
this.watching = undefined;
|
|
22
30
|
}
|
|
31
|
+
get language() {
|
|
32
|
+
return localeOf(this, this.locale);
|
|
33
|
+
}
|
|
23
34
|
get dateOnly() {
|
|
24
35
|
return DATE_ONLY.test((this.date || this.written).trim());
|
|
25
36
|
}
|
|
@@ -32,45 +43,27 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
32
43
|
return Number.isNaN(parsed.getTime()) ? undefined : parsed;
|
|
33
44
|
}
|
|
34
45
|
get options() {
|
|
35
|
-
return formatOptions(
|
|
36
|
-
dateOnly: this.dateOnly,
|
|
37
|
-
dateStyle: this.dateStyle,
|
|
38
|
-
day: this.day,
|
|
39
|
-
era: this.era,
|
|
40
|
-
hour: this.hour,
|
|
41
|
-
hourCycle: this.hourCycle,
|
|
42
|
-
minute: this.minute,
|
|
43
|
-
month: this.month,
|
|
44
|
-
second: this.second,
|
|
45
|
-
timeStyle: this.timeStyle,
|
|
46
|
-
timeZone: this.timeZone,
|
|
47
|
-
timeZoneName: this.timeZoneName,
|
|
48
|
-
weekday: this.weekday,
|
|
49
|
-
year: this.year,
|
|
50
|
-
});
|
|
46
|
+
return formatOptions(this, this.dateOnly);
|
|
51
47
|
}
|
|
52
48
|
get reading() {
|
|
53
49
|
return this.elapsed || this.relative !== undefined;
|
|
54
50
|
}
|
|
55
51
|
readingAt(moment, now) {
|
|
56
52
|
return this.elapsed
|
|
57
|
-
? elapsedTime(this.
|
|
58
|
-
: relativeTime(this.
|
|
53
|
+
? elapsedTime(this.language)(moment, now)
|
|
54
|
+
: relativeTime(this.language, {
|
|
59
55
|
numeric: this.numeric ?? 'auto',
|
|
60
56
|
style: this.relative ?? 'long',
|
|
61
57
|
})(moment, now);
|
|
62
58
|
}
|
|
63
59
|
connectedCallback() {
|
|
64
60
|
super.connectedCallback();
|
|
65
|
-
this.tick();
|
|
66
61
|
if (this.hasUpdated) {
|
|
67
62
|
this.watch();
|
|
68
63
|
}
|
|
69
64
|
}
|
|
70
65
|
disconnectedCallback() {
|
|
71
66
|
super.disconnectedCallback();
|
|
72
|
-
this.stopTicking?.();
|
|
73
|
-
this.stopTicking = undefined;
|
|
74
67
|
this.watching?.disconnect();
|
|
75
68
|
this.watching = undefined;
|
|
76
69
|
}
|
|
@@ -86,10 +79,11 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
86
79
|
}
|
|
87
80
|
if (changed.has('date') ||
|
|
88
81
|
changed.has('elapsed') ||
|
|
82
|
+
changed.has('frozen') ||
|
|
89
83
|
changed.has('locale') ||
|
|
90
84
|
changed.has('numeric') ||
|
|
91
85
|
changed.has('relative')) {
|
|
92
|
-
this.tick();
|
|
86
|
+
this.clock.tick();
|
|
93
87
|
}
|
|
94
88
|
}
|
|
95
89
|
read() {
|
|
@@ -99,7 +93,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
99
93
|
const written = this.textContent?.trim() ?? '';
|
|
100
94
|
if (written !== this.written) {
|
|
101
95
|
this.written = written;
|
|
102
|
-
this.tick();
|
|
96
|
+
this.clock.tick();
|
|
103
97
|
}
|
|
104
98
|
}
|
|
105
99
|
watch() {
|
|
@@ -107,21 +101,6 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
107
101
|
this.watching = new MutationObserver(() => this.read());
|
|
108
102
|
this.watching.observe(this, { characterData: true, childList: true, subtree: true });
|
|
109
103
|
}
|
|
110
|
-
tick() {
|
|
111
|
-
this.stopTicking?.();
|
|
112
|
-
this.stopTicking = undefined;
|
|
113
|
-
const moment = this.moment;
|
|
114
|
-
if (!moment || !this.reading) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const now = new Date();
|
|
118
|
-
this.clock = now.getTime();
|
|
119
|
-
const { next } = this.readingAt(moment, now);
|
|
120
|
-
if (!Number.isFinite(next) || !this.isConnected) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
this.stopTicking = subscribe(next, () => this.tick());
|
|
124
|
-
}
|
|
125
104
|
render() {
|
|
126
105
|
const moment = this.moment;
|
|
127
106
|
if (!moment) {
|
|
@@ -129,18 +108,18 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
129
108
|
}
|
|
130
109
|
const datetime = this.dateOnly ? (this.date || this.written).trim() : moment.toISOString();
|
|
131
110
|
if (!this.reading) {
|
|
132
|
-
const text = new Intl.DateTimeFormat(this.
|
|
111
|
+
const text = new Intl.DateTimeFormat(this.language || undefined, this.options).format(moment);
|
|
133
112
|
return html `<time part="time" datetime=${datetime}>${text}</time>`;
|
|
134
113
|
}
|
|
135
|
-
const now = new Date(this.clock
|
|
114
|
+
const now = new Date(this.clock.now);
|
|
136
115
|
const zone = this.timeZone || (this.dateOnly ? 'UTC' : undefined);
|
|
137
|
-
const whole = new Intl.DateTimeFormat(this.
|
|
116
|
+
const whole = new Intl.DateTimeFormat(this.language || undefined, {
|
|
138
117
|
dateStyle: 'long',
|
|
139
118
|
...(this.dateOnly ? {} : { timeStyle: 'short' }),
|
|
140
119
|
...(this.hourCycle ? { hourCycle: this.hourCycle } : {}),
|
|
141
120
|
...(zone ? { timeZone: zone } : {}),
|
|
142
121
|
}).format(moment);
|
|
143
|
-
const spoken = relativeTime(this.
|
|
122
|
+
const spoken = relativeTime(this.language, { numeric: this.numeric ?? 'auto' })(moment, now).text;
|
|
144
123
|
return html `<time
|
|
145
124
|
part="time"
|
|
146
125
|
datetime=${datetime}
|
|
@@ -164,6 +143,9 @@ __decorate([
|
|
|
164
143
|
__decorate([
|
|
165
144
|
property()
|
|
166
145
|
], HelixHeadlessFormatDate.prototype, "era", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
property({ type: Boolean })
|
|
148
|
+
], HelixHeadlessFormatDate.prototype, "frozen", void 0);
|
|
167
149
|
__decorate([
|
|
168
150
|
property()
|
|
169
151
|
], HelixHeadlessFormatDate.prototype, "hour", void 0);
|
|
@@ -203,9 +185,6 @@ __decorate([
|
|
|
203
185
|
__decorate([
|
|
204
186
|
property()
|
|
205
187
|
], HelixHeadlessFormatDate.prototype, "year", void 0);
|
|
206
|
-
__decorate([
|
|
207
|
-
state()
|
|
208
|
-
], HelixHeadlessFormatDate.prototype, "clock", void 0);
|
|
209
188
|
__decorate([
|
|
210
189
|
state()
|
|
211
190
|
], HelixHeadlessFormatDate.prototype, "written", void 0);
|