@fusion.dev/helix-headless 0.144.0 → 0.146.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 +15195 -4240
- package/dist/accordion/item/accordion-item.d.ts +62 -12
- package/dist/accordion/item/accordion-item.js +41 -10
- package/dist/accordion/root/accordion-root.d.ts +14 -5
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +24 -3
- package/dist/announcement/root/announcement-root.js +39 -2
- package/dist/app-header/root/app-header-root.d.ts +12 -0
- package/dist/app-header/root/app-header-root.js +13 -1
- package/dist/app-header/sectioning.d.ts +9 -0
- package/dist/app-header/sectioning.js +27 -0
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +57 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +73 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- 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.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +123 -42
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +133 -4
- package/dist/carousel/root/carousel-root.js +174 -24
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/composer/chat-composer.d.ts +38 -6
- package/dist/chat/composer/chat-composer.js +42 -9
- package/dist/chat/message/chat-message.d.ts +32 -1
- package/dist/chat/message/chat-message.js +27 -10
- package/dist/chat/naming.d.ts +26 -0
- package/dist/chat/naming.js +14 -0
- package/dist/chat/root/chat-root.d.ts +58 -0
- package/dist/chat/root/chat-root.js +43 -3
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -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 +57 -2
- package/dist/code-block/root/code-block-root.js +63 -8
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +26 -1
- package/dist/copy-button/root/copy-button-root.js +12 -5
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +170 -13
- package/dist/data-table/root/data-table-root.js +294 -52
- package/dist/data-table/tree.d.ts +55 -0
- package/dist/data-table/tree.js +54 -0
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/description-list/item/description-list-item.d.ts +17 -2
- package/dist/description-list/item/description-list-item.js +15 -2
- package/dist/description-list/root/description-list-root.d.ts +27 -1
- package/dist/description-list/root/description-list-root.js +26 -1
- 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 +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.d.ts +11 -6
- package/dist/drilldown/item/drilldown-item.js +8 -5
- package/dist/drilldown/root/drilldown-root.d.ts +29 -0
- package/dist/drilldown/root/drilldown-root.js +28 -5
- package/dist/element-events.generated.js +83 -12
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +5 -0
- package/dist/filter-input/menu/filter-menu.js +16 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- 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 +5 -1
- package/dist/image/root/image-root.js +10 -2
- package/dist/input/root/input-root.d.ts +13 -3
- package/dist/input/root/input-root.js +12 -3
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +70 -1
- package/dist/list/item/list-item.js +77 -6
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +155 -9
- package/dist/list/root/list-root.js +246 -4
- package/dist/list/selection.d.ts +49 -0
- package/dist/list/selection.js +30 -0
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -4
- 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/map/root/map-root.d.ts +6 -2
- package/dist/map/root/map-root.js +5 -2
- package/dist/megamenu/root/megamenu-root.d.ts +62 -0
- package/dist/megamenu/root/megamenu-root.js +90 -5
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +87 -11
- package/dist/menu/item/menu-item.js +78 -22
- package/dist/menu/root/menu-root.d.ts +39 -1
- package/dist/menu/root/menu-root.js +65 -8
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +18 -2
- package/dist/navigation/root/navigation-root.js +29 -3
- package/dist/notifications/root/notifications-root.d.ts +25 -0
- package/dist/notifications/root/notifications-root.js +33 -5
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +161 -32
- package/dist/object-inspector/root/object-inspector-root.js +264 -123
- package/dist/object-inspector/rows.d.ts +75 -0
- package/dist/object-inspector/rows.js +119 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +86 -3
- package/dist/outline/root/outline-root.js +95 -12
- package/dist/pagination/size/pagination-size.d.ts +12 -2
- package/dist/pagination/size/pagination-size.js +20 -5
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- 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 +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +10 -5
- package/dist/rating/root/rating-root.js +32 -8
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- 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 +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +84 -0
- package/dist/scroll-area/root/scroll-area-root.js +106 -7
- 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 +92 -0
- package/dist/scroll-area/scrollbar.js +33 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -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 +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +20 -12
- package/dist/splitter/root/splitter-root.js +226 -203
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- 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 +20 -0
- package/dist/steps/reach.js +15 -0
- package/dist/steps/root/steps-root.d.ts +76 -0
- package/dist/steps/root/steps-root.js +93 -1
- package/dist/steps/step/step.d.ts +45 -2
- package/dist/steps/step/step.js +33 -6
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +11 -10
- package/dist/table/column/table-column.js +8 -19
- package/dist/table/root/table-root.d.ts +126 -4
- package/dist/table/root/table-root.js +156 -6
- package/dist/table/row/table-row.d.ts +47 -1
- package/dist/table/row/table-row.js +39 -2
- package/dist/tabs/panel/tab-panel.d.ts +22 -5
- package/dist/tabs/panel/tab-panel.js +34 -6
- package/dist/tabs/root/tabs-root.d.ts +37 -1
- package/dist/tabs/root/tabs-root.js +22 -4
- package/dist/tabs/tab/tab.d.ts +41 -4
- package/dist/tabs/tab/tab.js +49 -3
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- 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.d.ts +46 -0
- package/dist/timeline/group/timeline-group.js +37 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/timeline/root/timeline-root.d.ts +10 -3
- package/dist/toast/item/toast-item.d.ts +24 -18
- package/dist/toast/item/toast-item.js +36 -40
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +61 -4
- package/dist/tree/item/tree-item.js +92 -20
- package/dist/tree/root/tree-root.d.ts +58 -0
- package/dist/tree/root/tree-root.js +80 -16
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +13 -0
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +44 -0
- package/dist/video/media-events.js +35 -0
- package/dist/video/root/video-root.d.ts +117 -18
- package/dist/video/root/video-root.js +93 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
- package/dist/video-playlist/order.d.ts +41 -0
- package/dist/video-playlist/order.js +34 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +77 -3
- package/dist/video-playlist/root/video-playlist-root.js +60 -16
- package/dist/virtual-list/controls.d.ts +4 -0
- package/dist/virtual-list/controls.js +30 -0
- package/dist/virtual-list/fill.d.ts +22 -0
- package/dist/virtual-list/fill.js +23 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +259 -26
- package/dist/virtual-list/root/virtual-list-root.js +333 -49
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +8113 -1394
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +1678 -353
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -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`,
|
|
@@ -364,7 +364,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
364
364
|
super.updated(changed);
|
|
365
365
|
this.releaseCaret?.();
|
|
366
366
|
this.releaseCaret = undefined;
|
|
367
|
-
this.internals.setFormValue(this.formValue());
|
|
367
|
+
this.internals.setFormValue(this.formValue(), this.value);
|
|
368
368
|
this.sayCount();
|
|
369
369
|
const control = this.control;
|
|
370
370
|
if (control) {
|
|
@@ -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
|
+
});
|
|
@@ -154,18 +154,21 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
154
154
|
*/
|
|
155
155
|
year?: 'numeric' | '2-digit';
|
|
156
156
|
/**
|
|
157
|
-
* The clock this element last drew against
|
|
157
|
+
* The clock this element last drew against, moved on when the reading goes
|
|
158
|
+
* stale.
|
|
158
159
|
*
|
|
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.
|
|
160
|
+
* A controller's time and not a read of `Date.now()` inside `render`, which
|
|
161
|
+
* would make the template a function of something Lit cannot see change: the
|
|
162
|
+
* element would draw the right text once and never notice it had gone stale.
|
|
163
|
+
* The formatter says when its own answer expires, so the clock wakes at
|
|
164
|
+
* exactly that moment rather than polling: an item minutes old once a minute,
|
|
165
|
+
* an item hours old once an hour, and an item showing a date never.
|
|
162
166
|
*/
|
|
163
|
-
private clock;
|
|
167
|
+
private readonly clock;
|
|
164
168
|
/**
|
|
165
169
|
* The date read out of the light DOM, where no attribute carried one.
|
|
166
170
|
*/
|
|
167
171
|
private written;
|
|
168
|
-
private stopTicking;
|
|
169
172
|
private watching;
|
|
170
173
|
/** Whether the timestamp is a day with no time, which is formatted in UTC. */
|
|
171
174
|
private get dateOnly();
|
|
@@ -184,16 +187,6 @@ export declare class HelixHeadlessFormatDate extends HelixElement {
|
|
|
184
187
|
/** The light DOM's own text, which is the other way to write the value. */
|
|
185
188
|
private read;
|
|
186
189
|
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
190
|
protected render(): TemplateResult | typeof nothing;
|
|
198
191
|
}
|
|
199
192
|
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, 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';
|
|
@@ -15,9 +15,13 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
15
15
|
this.date = '';
|
|
16
16
|
this.elapsed = false;
|
|
17
17
|
this.locale = '';
|
|
18
|
-
this.clock =
|
|
18
|
+
this.clock = new RelativeClockController(this, {
|
|
19
|
+
expires: (now) => {
|
|
20
|
+
const moment = this.moment;
|
|
21
|
+
return moment && this.reading ? this.readingAt(moment, now).next : undefined;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
19
24
|
this.written = '';
|
|
20
|
-
this.stopTicking = undefined;
|
|
21
25
|
this.watching = undefined;
|
|
22
26
|
}
|
|
23
27
|
get dateOnly() {
|
|
@@ -62,15 +66,12 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
62
66
|
}
|
|
63
67
|
connectedCallback() {
|
|
64
68
|
super.connectedCallback();
|
|
65
|
-
this.tick();
|
|
66
69
|
if (this.hasUpdated) {
|
|
67
70
|
this.watch();
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
disconnectedCallback() {
|
|
71
74
|
super.disconnectedCallback();
|
|
72
|
-
this.stopTicking?.();
|
|
73
|
-
this.stopTicking = undefined;
|
|
74
75
|
this.watching?.disconnect();
|
|
75
76
|
this.watching = undefined;
|
|
76
77
|
}
|
|
@@ -89,7 +90,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
89
90
|
changed.has('locale') ||
|
|
90
91
|
changed.has('numeric') ||
|
|
91
92
|
changed.has('relative')) {
|
|
92
|
-
this.tick();
|
|
93
|
+
this.clock.tick();
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
read() {
|
|
@@ -99,7 +100,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
99
100
|
const written = this.textContent?.trim() ?? '';
|
|
100
101
|
if (written !== this.written) {
|
|
101
102
|
this.written = written;
|
|
102
|
-
this.tick();
|
|
103
|
+
this.clock.tick();
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
watch() {
|
|
@@ -107,21 +108,6 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
107
108
|
this.watching = new MutationObserver(() => this.read());
|
|
108
109
|
this.watching.observe(this, { characterData: true, childList: true, subtree: true });
|
|
109
110
|
}
|
|
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
111
|
render() {
|
|
126
112
|
const moment = this.moment;
|
|
127
113
|
if (!moment) {
|
|
@@ -132,7 +118,7 @@ let HelixHeadlessFormatDate = class HelixHeadlessFormatDate extends HelixElement
|
|
|
132
118
|
const text = new Intl.DateTimeFormat(this.locale || undefined, this.options).format(moment);
|
|
133
119
|
return html `<time part="time" datetime=${datetime}>${text}</time>`;
|
|
134
120
|
}
|
|
135
|
-
const now = new Date(this.clock
|
|
121
|
+
const now = new Date(this.clock.now);
|
|
136
122
|
const zone = this.timeZone || (this.dateOnly ? 'UTC' : undefined);
|
|
137
123
|
const whole = new Intl.DateTimeFormat(this.locale || undefined, {
|
|
138
124
|
dateStyle: 'long',
|
|
@@ -203,9 +189,6 @@ __decorate([
|
|
|
203
189
|
__decorate([
|
|
204
190
|
property()
|
|
205
191
|
], HelixHeadlessFormatDate.prototype, "year", void 0);
|
|
206
|
-
__decorate([
|
|
207
|
-
state()
|
|
208
|
-
], HelixHeadlessFormatDate.prototype, "clock", void 0);
|
|
209
192
|
__decorate([
|
|
210
193
|
state()
|
|
211
194
|
], HelixHeadlessFormatDate.prototype, "written", void 0);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../tooltip/index.js';
|
|
4
|
+
import { type Reading } from './buckets.js';
|
|
4
5
|
declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface);
|
|
5
6
|
/**
|
|
6
7
|
* @summary A strip of cells, each colored by its reading, for uptime, contributions, or activity.
|
|
@@ -30,7 +31,13 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
30
31
|
* down arrows move a cell, the left and right arrows move a column, which is a
|
|
31
32
|
* week with `rows="7"`, and Home and End go to the first and the last. The
|
|
32
33
|
* tooltip follows, the `live` part says the cell's row in words, and Escape
|
|
33
|
-
* puts the tooltip away.
|
|
34
|
+
* puts the tooltip away. PageUp and PageDown move four columns, which is four
|
|
35
|
+
* weeks with `rows="7"`.
|
|
36
|
+
*
|
|
37
|
+
* **The strip describes itself.** The `overview` part says the busiest
|
|
38
|
+
* reading and the total of the readings drawn, "Busiest: 11 Jun 12; Total
|
|
39
|
+
* 84", and the strip is described by it, as every chart is by its summary.
|
|
40
|
+
* Hide it visually. The `summary` slot is still yours, for words of your own.
|
|
34
41
|
*
|
|
35
42
|
* @since 0.1.0
|
|
36
43
|
* @status stable
|
|
@@ -51,6 +58,7 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
51
58
|
* @csspart footer - The three-slot row under the strip.
|
|
52
59
|
* @csspart live - The readout: a polite live region that says the cell the keys moved to. Hide it visually.
|
|
53
60
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
61
|
+
* @csspart overview - The busiest reading and the total of the readings drawn, written as a sentence for screen readers, which describes the strip. Rendered once there are cells. Hide it visually.
|
|
54
62
|
* @csspart start - The leading slot's box.
|
|
55
63
|
* @csspart strip - The grid of cells, which takes focus to be read by key. It is named by the host's `aria-labelledby` or `aria-label`, then by `label`, then by the caption of the table.
|
|
56
64
|
* @csspart summary - The middle slot's box.
|
|
@@ -87,6 +95,10 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
87
95
|
* @cssproperty --heatmap-tone-warning - The color of the `warning` tone.
|
|
88
96
|
*/
|
|
89
97
|
export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
98
|
+
/**
|
|
99
|
+
* The word the `overview` puts before the busiest reading.
|
|
100
|
+
*/
|
|
101
|
+
busiestLabel: string;
|
|
90
102
|
/**
|
|
91
103
|
* Shown when the table has no readings in it.
|
|
92
104
|
*
|
|
@@ -151,6 +163,10 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
151
163
|
* no order in it.
|
|
152
164
|
*/
|
|
153
165
|
tones: string;
|
|
166
|
+
/**
|
|
167
|
+
* The word the `overview` puts before the total of the readings drawn.
|
|
168
|
+
*/
|
|
169
|
+
totalLabel: string;
|
|
154
170
|
/**
|
|
155
171
|
* How many cells are actually drawn.
|
|
156
172
|
*
|
|
@@ -197,18 +213,6 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
197
213
|
* image a reader lands on. The host is a generic around it.
|
|
198
214
|
*/
|
|
199
215
|
protected readonly aria: AriaForwardController;
|
|
200
|
-
/**
|
|
201
|
-
* Hears an `aria-label` written on the element, which no property mirrors.
|
|
202
|
-
*
|
|
203
|
-
* Lit observes the attributes of its own properties only, and `ariaLabel`
|
|
204
|
-
* belongs to the platform.
|
|
205
|
-
*/
|
|
206
|
-
static get observedAttributes(): string[];
|
|
207
|
-
/**
|
|
208
|
-
* Called by the browser when an observed attribute changes. A new
|
|
209
|
-
* `aria-label` asks for an update, because it names the strip.
|
|
210
|
-
*/
|
|
211
|
-
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
|
|
212
216
|
private observer;
|
|
213
217
|
private announced;
|
|
214
218
|
/**
|
|
@@ -314,6 +318,13 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
314
318
|
private markEmpty;
|
|
315
319
|
protected updated(changed: PropertyValues): void;
|
|
316
320
|
protected render(): TemplateResult;
|
|
321
|
+
/**
|
|
322
|
+
* What the strip shows, in a sentence: the busiest reading drawn, as the
|
|
323
|
+
* table writes it, and the total of them all, in `locale`. The strip is
|
|
324
|
+
* described by it, so a reader landing on the strip hears what it holds
|
|
325
|
+
* before walking it.
|
|
326
|
+
*/
|
|
327
|
+
protected renderOverview(cells: Reading[]): TemplateResult;
|
|
317
328
|
/**
|
|
318
329
|
* The bubble over the cell a pointer is resting on.
|
|
319
330
|
*
|
|
@@ -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 { AriaForwardController, byRow, CHART_PLOT, customElement, drawTooltip, HelixElement, HelixResizeEvent, MixinChartSource, markRegion, searchableById, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, byRow, CHART_PLOT, customElement, drawTooltip, formatNumbers, HelixElement, HelixResizeEvent, MixinChartSource, markRegion, searchableById, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import '../../tooltip/index.js';
|
|
@@ -12,12 +12,14 @@ import { fits, toneOf } from './buckets.js';
|
|
|
12
12
|
let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(HelixElement) {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
|
+
this.busiestLabel = 'Busiest';
|
|
15
16
|
this.emptyText = 'No readings';
|
|
16
17
|
this.gap = 2;
|
|
17
18
|
this.minCell = 8;
|
|
18
19
|
this.rows = 1;
|
|
19
20
|
this.thresholds = '';
|
|
20
21
|
this.tones = '';
|
|
22
|
+
this.totalLabel = 'Total';
|
|
21
23
|
this.width = undefined;
|
|
22
24
|
this.metrics = undefined;
|
|
23
25
|
this.aria = new AriaForwardController(this, {
|
|
@@ -42,15 +44,6 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
|
|
|
42
44
|
get visible() {
|
|
43
45
|
return Math.min(this.points.length, this.room);
|
|
44
46
|
}
|
|
45
|
-
static get observedAttributes() {
|
|
46
|
-
return [...super.observedAttributes, 'aria-label'];
|
|
47
|
-
}
|
|
48
|
-
attributeChangedCallback(name, old, value) {
|
|
49
|
-
super.attributeChangedCallback(name, old, value);
|
|
50
|
-
if (name === 'aria-label') {
|
|
51
|
-
this.requestUpdate();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
47
|
get points() {
|
|
55
48
|
const series = this.series[0];
|
|
56
49
|
if (!series) {
|
|
@@ -151,7 +144,8 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
|
|
|
151
144
|
const cells = this.drawn;
|
|
152
145
|
const readable = cells.length > 0;
|
|
153
146
|
return html `<div
|
|
154
|
-
aria-
|
|
147
|
+
aria-describedby=${readable ? 'helix-chart-summary' : nothing}
|
|
148
|
+
aria-label=${this.named || 'Heatmap'}
|
|
155
149
|
part="strip"
|
|
156
150
|
id=${CHART_PLOT}
|
|
157
151
|
role=${readable ? 'application' : 'img'}
|
|
@@ -184,7 +178,29 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
|
|
|
184
178
|
<span part="start"><slot name="start"></slot></span>
|
|
185
179
|
<span part="summary"><slot name="summary"></slot></span>
|
|
186
180
|
<span part="end"><slot name="end"></slot></span>
|
|
187
|
-
</div
|
|
181
|
+
</div>${readable ? this.renderOverview(cells) : nothing}`;
|
|
182
|
+
}
|
|
183
|
+
renderOverview(cells) {
|
|
184
|
+
const rows = this.sourceRows;
|
|
185
|
+
const offset = this.points.length - cells.length;
|
|
186
|
+
const column = this.plottedColumns[0] ?? -1;
|
|
187
|
+
let busiest = -1;
|
|
188
|
+
let total = 0;
|
|
189
|
+
cells.forEach((cell, index) => {
|
|
190
|
+
if (cell.value === undefined) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
total += cell.value;
|
|
194
|
+
if (busiest < 0 || cell.value > (cells[busiest]?.value ?? 0)) {
|
|
195
|
+
busiest = index;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
const row = rows[offset + busiest];
|
|
199
|
+
const most = row
|
|
200
|
+
? `${this.busiestLabel}: ${row.label} ${row.cells[column]?.text ?? ''}`.trim()
|
|
201
|
+
: '';
|
|
202
|
+
const sum = `${this.totalLabel} ${formatNumbers(this.locale)(total)}`;
|
|
203
|
+
return html `<p id="helix-chart-summary" part="overview">${most ? `${most}; ${sum}` : sum}.</p>`;
|
|
188
204
|
}
|
|
189
205
|
renderTooltip() {
|
|
190
206
|
const at = this.pointer.at;
|
|
@@ -203,6 +219,9 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
|
|
|
203
219
|
}, undefined, this.pointer);
|
|
204
220
|
}
|
|
205
221
|
};
|
|
222
|
+
__decorate([
|
|
223
|
+
property({ attribute: 'busiest-label' })
|
|
224
|
+
], HelixHeadlessHeatmap.prototype, "busiestLabel", void 0);
|
|
206
225
|
__decorate([
|
|
207
226
|
property({ attribute: 'empty-text' })
|
|
208
227
|
], HelixHeadlessHeatmap.prototype, "emptyText", void 0);
|
|
@@ -221,6 +240,9 @@ __decorate([
|
|
|
221
240
|
__decorate([
|
|
222
241
|
property()
|
|
223
242
|
], HelixHeadlessHeatmap.prototype, "tones", void 0);
|
|
243
|
+
__decorate([
|
|
244
|
+
property({ attribute: 'total-label' })
|
|
245
|
+
], HelixHeadlessHeatmap.prototype, "totalLabel", void 0);
|
|
224
246
|
__decorate([
|
|
225
247
|
state()
|
|
226
248
|
], HelixHeadlessHeatmap.prototype, "width", void 0);
|
|
@@ -28,7 +28,8 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
28
28
|
* rendered is drawn then.
|
|
29
29
|
*
|
|
30
30
|
* A name with no match renders nothing, and the element fires `error`, so a
|
|
31
|
-
* typo in a name can be heard.
|
|
31
|
+
* typo in a name can be heard. It waits until the page has loaded and painted
|
|
32
|
+
* first, so a library a later module registers is not taken for a typo.
|
|
32
33
|
*
|
|
33
34
|
* An icon is decorative by default and hidden from assistive technology. Set
|
|
34
35
|
* `label` only when the icon is the only carrier of meaning, such as in a
|
|
@@ -120,6 +121,16 @@ export declare class HelixHeadlessIcon extends HelixElement {
|
|
|
120
121
|
private lookup;
|
|
121
122
|
protected willUpdate(changed: PropertyValues): void;
|
|
122
123
|
protected updated(changed: PropertyValues): void;
|
|
124
|
+
/** The name a report is waiting on the page to settle for, so it is asked once. */
|
|
125
|
+
private pending;
|
|
126
|
+
/**
|
|
127
|
+
* Says a name drew nothing, once the page has had its chance to register
|
|
128
|
+
* it: a library registered by a module further down the page, or by the
|
|
129
|
+
* page's own script after this element, is not a missing glyph. Asked again
|
|
130
|
+
* then, and said only where the name still draws nothing and nothing is
|
|
131
|
+
* still on its way.
|
|
132
|
+
*/
|
|
133
|
+
private reportMissing;
|
|
123
134
|
protected render(): TemplateResult | typeof nothing;
|
|
124
135
|
}
|
|
125
136
|
declare global {
|
|
@@ -9,6 +9,7 @@ import { html, nothing } from 'lit';
|
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
11
11
|
import { resolveIcon, watchIcons } from '../registry.js';
|
|
12
|
+
import { afterPageSettles } from '../settle.js';
|
|
12
13
|
let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
@@ -18,6 +19,7 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
18
19
|
this.missed = '';
|
|
19
20
|
this.waiting = false;
|
|
20
21
|
this.arrived = '';
|
|
22
|
+
this.pending = '';
|
|
21
23
|
}
|
|
22
24
|
static get observedAttributes() {
|
|
23
25
|
return [...super.observedAttributes, 'aria-label'];
|
|
@@ -69,22 +71,31 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
69
71
|
}
|
|
70
72
|
this.arrived = '';
|
|
71
73
|
if (this.drawn === undefined && this.name !== '' && !this.waiting) {
|
|
72
|
-
if (this.missed !== this.name) {
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
reportRuntime({
|
|
76
|
-
kind: 'unknown-icon',
|
|
77
|
-
message: `<${this.localName} name="${this.name}"> names no registered icon, so it draws ` +
|
|
78
|
-
'nothing. Check the name, register the glyph with `registerIcons`, or import it ' +
|
|
79
|
-
'and pass it as `icon`.',
|
|
80
|
-
tag: this.localName,
|
|
81
|
-
});
|
|
74
|
+
if (this.missed !== this.name && this.pending !== this.name) {
|
|
75
|
+
this.pending = this.name;
|
|
76
|
+
afterPageSettles(() => this.reportMissing());
|
|
82
77
|
}
|
|
83
78
|
}
|
|
84
79
|
else {
|
|
85
80
|
this.missed = '';
|
|
86
81
|
}
|
|
87
82
|
}
|
|
83
|
+
reportMissing() {
|
|
84
|
+
const name = this.pending;
|
|
85
|
+
this.pending = '';
|
|
86
|
+
if (this.name !== name || this.drawn !== undefined || this.waiting || !this.isConnected) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.missed = name;
|
|
90
|
+
this.dispatchEvent(new Event('error', { bubbles: false, cancelable: false, composed: false }));
|
|
91
|
+
reportRuntime({
|
|
92
|
+
kind: 'unknown-icon',
|
|
93
|
+
message: `<${this.localName} name="${name}"> names no registered icon, so it draws ` +
|
|
94
|
+
'nothing. Check the name, register the glyph with `registerIcons`, or import it ' +
|
|
95
|
+
'and pass it as `icon`.',
|
|
96
|
+
tag: this.localName,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
88
99
|
render() {
|
|
89
100
|
const icon = this.drawn;
|
|
90
101
|
if (!icon) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls back once the page has loaded and painted a frame after it: every
|
|
3
|
+
* module a page lists has run by then, and with it every `registerIcons` and
|
|
4
|
+
* `registerIconLibrary` they hold. A page that has loaded already waits only
|
|
5
|
+
* the frame.
|
|
6
|
+
*/
|
|
7
|
+
export declare const afterPageSettles: (callback: () => void) => void;
|
|
@@ -17,6 +17,8 @@ import { HelixHeadlessButton } from '../../button/root/button-root.js';
|
|
|
17
17
|
* mean a part of a button, and an icon-only button is a complete button with
|
|
18
18
|
* different content and a different shape.
|
|
19
19
|
*
|
|
20
|
+
* **Keyboard.** Enter and Space press the button, as `Button`'s do.
|
|
21
|
+
*
|
|
20
22
|
* @since 0.1.0
|
|
21
23
|
* @status stable
|
|
22
24
|
* @category actions
|
|
@@ -12,13 +12,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* The `placeholder` slot is empty by default, so the headless tier does not
|
|
13
13
|
* depend on `Skeleton`, which it does not ship.
|
|
14
14
|
*
|
|
15
|
+
* The placeholder is hidden from screen readers, the picture having a name of
|
|
16
|
+
* its own. The fallback is read once the picture fails, after the picture's
|
|
17
|
+
* `alt`, so a reader hears that it did not load, as a sighted reader sees.
|
|
18
|
+
*
|
|
15
19
|
* @since 0.1.0
|
|
16
20
|
* @status stable
|
|
17
21
|
* @category media
|
|
18
22
|
* @aliases Picture, Img, Figure
|
|
19
23
|
* @documentation https://fusion.dev/helix/components/image
|
|
20
24
|
*
|
|
21
|
-
* @slot fallback - Shown in place of the image if it fails to load.
|
|
25
|
+
* @slot fallback - Shown in place of the image if it fails to load, and read by screen readers then, such as "Photo unavailable".
|
|
22
26
|
* @slot placeholder - Shown until the image loads.
|
|
23
27
|
*
|
|
24
28
|
* @event {Event} error - The image failed to load. Relayed from the inner image, whose own event stays inside the shadow root.
|
|
@@ -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, DelayController, HelixElement } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, DelayController, HelixElement, reportRuntime } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
@@ -100,6 +100,14 @@ let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
|
100
100
|
firstUpdated(changed) {
|
|
101
101
|
super.firstUpdated?.(changed);
|
|
102
102
|
this.settle();
|
|
103
|
+
if (this.alt === undefined && this.getAttribute('aria-hidden') !== 'true') {
|
|
104
|
+
reportRuntime({
|
|
105
|
+
kind: 'missing-alt',
|
|
106
|
+
message: `<${this.localName}> has no \`alt\`, so a screen reader announces its file name. ` +
|
|
107
|
+
'Describe the picture in `alt`, or write `alt=""` for one that is decoration.',
|
|
108
|
+
tag: this.localName,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
103
111
|
}
|
|
104
112
|
get image() {
|
|
105
113
|
return this.renderRoot?.querySelector('img') ?? null;
|
|
@@ -139,7 +147,7 @@ let HelixHeadlessImage = class HelixHeadlessImage extends HelixElement {
|
|
|
139
147
|
></span>
|
|
140
148
|
<span
|
|
141
149
|
part="fallback"
|
|
142
|
-
aria-hidden
|
|
150
|
+
aria-hidden=${this.status === 'error' ? nothing : 'true'}
|
|
143
151
|
?hidden=${this.status !== 'error'}
|
|
144
152
|
><slot name="fallback"></slot
|
|
145
153
|
></span>`;
|