@fusion.dev/helix-headless 0.142.1 → 0.144.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 +25381 -1202
- package/dist/accordion/item/accordion-item.d.ts +38 -2
- package/dist/accordion/item/accordion-item.js +38 -6
- package/dist/accordion/root/accordion-root.d.ts +23 -1
- package/dist/accordion/root/accordion-root.js +39 -3
- package/dist/announcement/root/announcement-root.d.ts +11 -7
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/app-header/root/app-header-root.d.ts +21 -0
- package/dist/app-header/root/app-header-root.js +31 -5
- package/dist/area-chart/root/area-chart-root.d.ts +12 -4
- package/dist/area-chart/root/area-chart-root.js +39 -11
- package/dist/avatar/group/avatar-group.d.ts +24 -3
- package/dist/avatar/group/avatar-group.js +34 -2
- package/dist/avatar/root/avatar-root.d.ts +17 -1
- package/dist/avatar/root/avatar-root.js +31 -10
- package/dist/badge/root/badge-root.d.ts +12 -0
- package/dist/badge/root/badge-root.js +1 -1
- package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
- package/dist/bar-chart/root/bar-chart-root.js +58 -21
- package/dist/blockquote/root/blockquote-root.d.ts +12 -7
- package/dist/blockquote/root/blockquote-root.js +6 -4
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
- package/dist/button/root/button-root.d.ts +84 -1
- package/dist/button/root/button-root.js +81 -3
- package/dist/callout/root/callout-root.d.ts +32 -6
- package/dist/callout/root/callout-root.js +26 -7
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- package/dist/card/root/card-root.d.ts +30 -1
- package/dist/card/root/card-root.js +38 -5
- package/dist/carousel/root/carousel-root.d.ts +47 -5
- package/dist/carousel/root/carousel-root.js +53 -21
- package/dist/chat/composer/chat-composer.d.ts +13 -11
- package/dist/chat/composer/chat-composer.js +6 -12
- package/dist/chat/message/chat-message.js +8 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +2 -1
- package/dist/checkbox/root/checkbox-root.d.ts +7 -0
- package/dist/checkbox/root/checkbox-root.js +9 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
- package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/lines.d.ts +13 -0
- package/dist/code-block/lines.js +2 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -0
- package/dist/code-block/root/code-block-root.js +44 -3
- package/dist/color-input/root/color-input-root.d.ts +60 -2
- package/dist/color-input/root/color-input-root.js +55 -7
- package/dist/color-picker/channels.d.ts +26 -0
- package/dist/color-picker/channels.js +84 -0
- package/dist/color-picker/root/color-picker-root.d.ts +118 -12
- package/dist/color-picker/root/color-picker-root.js +183 -13
- package/dist/combobox/root/combobox-root.d.ts +126 -3
- package/dist/combobox/root/combobox-root.js +224 -21
- package/dist/command/root/command-root.d.ts +47 -10
- package/dist/command/root/command-root.js +45 -4
- package/dist/copy-button/from.d.ts +22 -0
- package/dist/copy-button/from.js +28 -0
- package/dist/copy-button/root/copy-button-root.d.ts +48 -7
- package/dist/copy-button/root/copy-button-root.js +54 -8
- package/dist/data-table/root/data-table-root.d.ts +164 -10
- package/dist/data-table/root/data-table-root.js +488 -57
- package/dist/date-input/root/date-input-root.d.ts +123 -9
- package/dist/date-input/root/date-input-root.js +147 -45
- package/dist/date-picker/root/date-picker-root.d.ts +229 -18
- package/dist/date-picker/root/date-picker-root.js +342 -46
- package/dist/dialog/description.d.ts +9 -0
- package/dist/dialog/description.js +14 -0
- package/dist/dialog/root/dialog-root.d.ts +101 -10
- package/dist/dialog/root/dialog-root.js +83 -4
- package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
- package/dist/donut-chart/root/donut-chart-root.js +48 -13
- package/dist/drawer/root/drawer-root.d.ts +93 -7
- package/dist/drawer/root/drawer-root.js +126 -5
- package/dist/drawer/swipe-start.d.ts +9 -0
- package/dist/drawer/swipe-start.js +12 -0
- package/dist/drilldown/item/drilldown-item.d.ts +16 -13
- package/dist/drilldown/item/drilldown-item.js +6 -2
- package/dist/drilldown/root/drilldown-root.d.ts +21 -5
- package/dist/drilldown/root/drilldown-root.js +26 -10
- package/dist/element-events.generated.js +42 -13
- package/dist/empty/root/empty-root.d.ts +1 -1
- package/dist/file-input/root/file-input-root.d.ts +65 -1
- package/dist/file-input/root/file-input-root.js +76 -12
- package/dist/file-input/screen.d.ts +35 -0
- package/dist/file-input/screen.js +49 -0
- package/dist/filter-input/menu/filter-menu.d.ts +9 -0
- package/dist/filter-input/menu/filter-menu.js +8 -0
- package/dist/filter-input/root/filter-input-root.d.ts +43 -6
- package/dist/filter-input/root/filter-input-root.js +89 -10
- package/dist/filter-input/suggest.d.ts +17 -0
- package/dist/filter-input/suggest.js +23 -0
- package/dist/format-date/options.d.ts +33 -0
- package/dist/format-date/options.js +42 -0
- package/dist/format-date/root/format-date-root.d.ts +62 -3
- package/dist/format-date/root/format-date-root.js +78 -37
- package/dist/graph/root/graph-root.d.ts +24 -3
- package/dist/graph/root/graph-root.js +66 -12
- package/dist/heatmap/root/buckets.d.ts +2 -1
- package/dist/heatmap/root/buckets.js +5 -1
- package/dist/heatmap/root/heatmap-root.d.ts +47 -9
- package/dist/heatmap/root/heatmap-root.js +46 -18
- package/dist/icon/index.d.ts +2 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/registry.d.ts +37 -0
- package/dist/icon/registry.js +83 -0
- package/dist/icon/root/icon-root.d.ts +53 -6
- package/dist/icon/root/icon-root.js +72 -4
- package/dist/icon/root/index.d.ts +2 -0
- package/dist/icon/root/index.js +2 -0
- package/dist/icon/set.d.ts +1 -0
- package/dist/icon/set.js +3 -0
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +23 -2
- package/dist/image/root/image-root.js +23 -4
- package/dist/input/root/input-root.d.ts +62 -9
- package/dist/input/root/input-root.js +61 -5
- package/dist/kbd/root/kbd-root.d.ts +26 -11
- package/dist/kbd/root/kbd-root.js +35 -38
- package/dist/kbd/shortcut.d.ts +18 -0
- package/dist/kbd/shortcut.js +35 -0
- package/dist/legend/hidden-series.d.ts +8 -0
- package/dist/legend/hidden-series.js +13 -0
- package/dist/legend/root/legend-root.d.ts +63 -0
- package/dist/legend/root/legend-root.js +61 -7
- package/dist/lightbox/item/lightbox-item.d.ts +17 -1
- package/dist/lightbox/item/lightbox-item.js +10 -1
- package/dist/lightbox/root/lightbox-root.d.ts +77 -6
- package/dist/lightbox/root/lightbox-root.js +116 -5
- package/dist/line-chart/root/line-chart-root.d.ts +29 -4
- package/dist/line-chart/root/line-chart-root.js +58 -17
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/range.d.ts +17 -0
- package/dist/listbox/range.js +5 -0
- package/dist/listbox/root/listbox-root.d.ts +184 -4
- package/dist/listbox/root/listbox-root.js +229 -23
- package/dist/loader/busy.d.ts +17 -0
- package/dist/loader/busy.js +24 -0
- package/dist/loader/root/loader-root.d.ts +37 -0
- package/dist/loader/root/loader-root.js +52 -3
- package/dist/map/root/map-root.d.ts +19 -4
- package/dist/map/root/map-root.js +36 -7
- package/dist/megamenu/root/megamenu-root.d.ts +10 -1
- package/dist/megamenu/root/megamenu-root.js +10 -1
- package/dist/menu/item/menu-item.d.ts +41 -12
- package/dist/menu/item/menu-item.js +46 -3
- package/dist/menu/root/menu-root.d.ts +32 -2
- package/dist/menu/root/menu-root.js +48 -8
- package/dist/meter/root/meter-root.d.ts +13 -0
- package/dist/meter/root/meter-root.js +24 -5
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/feed-keys.d.ts +10 -0
- package/dist/notifications/feed-keys.js +14 -0
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +29 -0
- package/dist/notifications/notification/notification.js +51 -3
- package/dist/notifications/root/notifications-root.d.ts +49 -0
- package/dist/notifications/root/notifications-root.js +76 -2
- package/dist/number-input/root/number-input-root.d.ts +109 -7
- package/dist/number-input/root/number-input-root.js +109 -21
- package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
- package/dist/object-inspector/root/object-inspector-root.js +92 -12
- package/dist/option/root/option-root.d.ts +58 -6
- package/dist/option/root/option-root.js +35 -5
- package/dist/outline/root/outline-root.d.ts +13 -2
- package/dist/outline/root/outline-root.js +4 -2
- package/dist/pagination/root/pagination-root.d.ts +19 -1
- package/dist/pagination/root/pagination-root.js +49 -9
- package/dist/pagination/size/pagination-size.d.ts +13 -3
- package/dist/pagination/size/pagination-size.js +7 -0
- package/dist/pin-input/format.d.ts +7 -0
- package/dist/pin-input/format.js +16 -0
- package/dist/pin-input/root/pin-input-root.d.ts +37 -0
- package/dist/pin-input/root/pin-input-root.js +48 -7
- package/dist/popover/root/popover-root.d.ts +78 -3
- package/dist/popover/root/popover-root.js +74 -5
- package/dist/progress/root/progress-root.d.ts +23 -1
- package/dist/progress/root/progress-root.js +40 -10
- package/dist/qr-code/export.d.ts +31 -0
- package/dist/qr-code/export.js +10 -0
- package/dist/qr-code/root/qr-code-root.d.ts +45 -0
- package/dist/qr-code/root/qr-code-root.js +78 -3
- package/dist/radio/group/radio-group.d.ts +64 -0
- package/dist/radio/group/radio-group.js +66 -12
- package/dist/radio/root/radio-root.d.ts +8 -5
- package/dist/radio/root/radio-root.js +1 -2
- package/dist/rating/root/rating-root.d.ts +49 -1
- package/dist/rating/root/rating-root.js +69 -10
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
- package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
- package/dist/select/root/select-root.d.ts +93 -3
- package/dist/select/root/select-root.js +111 -13
- package/dist/skeleton/root/skeleton-root.d.ts +39 -3
- package/dist/skeleton/root/skeleton-root.js +33 -4
- package/dist/skip-link/root/skip-link-root.d.ts +10 -0
- package/dist/skip-link/root/skip-link-root.js +15 -1
- package/dist/slider/root/slider-root.d.ts +59 -2
- package/dist/slider/root/slider-root.js +82 -8
- package/dist/sparkline/root/sparkline-root.d.ts +9 -10
- package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
- package/dist/speed-dial/item/speed-dial-item.js +7 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
- package/dist/speed-dial/root/speed-dial-root.js +19 -5
- package/dist/splitter/root/splitter-root.d.ts +28 -6
- package/dist/splitter/root/splitter-root.js +35 -1
- package/dist/stat/root/stat-root.d.ts +9 -1
- package/dist/stat/root/stat-root.js +15 -2
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/switch/root/switch-root.d.ts +14 -2
- package/dist/switch/root/switch-root.js +7 -1
- package/dist/table/cell/table-cell.d.ts +24 -4
- package/dist/table/cell/table-cell.js +21 -1
- package/dist/table/column/table-column.d.ts +32 -6
- package/dist/table/column/table-column.js +36 -6
- package/dist/table/root/table-root.d.ts +94 -3
- package/dist/table/root/table-root.js +128 -5
- package/dist/table/row/table-row.d.ts +7 -0
- package/dist/table/row/table-row.js +9 -1
- package/dist/tabs/root/tabs-root.d.ts +6 -1
- package/dist/tabs/root/tabs-root.js +6 -2
- package/dist/tag/group/tag-group.d.ts +107 -0
- package/dist/tag/group/tag-group.js +157 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +83 -1
- package/dist/tag/root/tag-root.js +87 -17
- package/dist/tag/selection.d.ts +10 -0
- package/dist/tag/selection.js +12 -0
- package/dist/textarea/grow.d.ts +22 -0
- package/dist/textarea/grow.js +20 -0
- package/dist/textarea/root/textarea-root.d.ts +13 -0
- package/dist/textarea/root/textarea-root.js +10 -2
- package/dist/time-input/root/time-input-root.d.ts +71 -6
- package/dist/time-input/root/time-input-root.js +110 -44
- package/dist/time-picker/root/time-picker-root.d.ts +155 -26
- package/dist/time-picker/root/time-picker-root.js +192 -63
- package/dist/toast/hotkey.d.ts +22 -0
- package/dist/toast/hotkey.js +23 -0
- package/dist/toast/item/toast-item.d.ts +16 -1
- package/dist/toast/item/toast-item.js +41 -13
- package/dist/toast/root/toast-root.d.ts +105 -8
- package/dist/toast/root/toast-root.js +209 -4
- package/dist/toggle/group/toggle-group.d.ts +95 -16
- package/dist/toggle/group/toggle-group.js +99 -13
- package/dist/toggle/root/toggle-root.d.ts +26 -11
- package/dist/toggle/root/toggle-root.js +14 -6
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/focus-target.d.ts +6 -0
- package/dist/tooltip/focus-target.js +9 -0
- package/dist/tooltip/root/tooltip-root.d.ts +73 -15
- package/dist/tooltip/root/tooltip-root.js +96 -7
- package/dist/tour/naming.d.ts +30 -0
- package/dist/tour/naming.js +10 -0
- package/dist/tour/root/tour-root.d.ts +67 -3
- package/dist/tour/root/tour-root.js +105 -17
- package/dist/tour/stop/tour-stop.d.ts +65 -3
- package/dist/tour/stop/tour-stop.js +61 -11
- package/dist/tour/wait.d.ts +11 -0
- package/dist/tour/wait.js +19 -0
- package/dist/tree/item/tree-item.d.ts +21 -5
- package/dist/tree/item/tree-item.js +14 -4
- package/dist/tree/root/tree-root.d.ts +29 -5
- package/dist/tree/root/tree-root.js +64 -8
- package/dist/trend/root/trend-root.d.ts +36 -1
- package/dist/trend/root/trend-root.js +41 -15
- package/dist/video/root/keys.d.ts +5 -0
- package/dist/video/root/keys.js +13 -1
- package/dist/video/root/video-root.d.ts +19 -0
- package/dist/video/root/video-root.js +48 -4
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
- package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
- package/dist/video-playlist/root/video-playlist-root.js +6 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
- package/dist/virtual-list/root/virtual-list-root.js +103 -21
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +9140 -1149
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +2089 -267
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A set of destinations, with a marker on the current one.
|
|
@@ -15,7 +15,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
15
15
|
*
|
|
16
16
|
* The component moves a marker to the current item. It finds the current item
|
|
17
17
|
* by reading `aria-current`, so the attribute that screen readers announce also
|
|
18
|
-
* places the marker.
|
|
18
|
+
* places the marker. Any value but `false` counts, so a sidebar of sections on
|
|
19
|
+
* one page can mark the section in view with `aria-current="location"`. Where
|
|
20
|
+
* several are marked, `page` wins.
|
|
19
21
|
*
|
|
20
22
|
* Set `orientation="vertical"` to stack the destinations in a column, for a
|
|
21
23
|
* sidebar.
|
|
@@ -35,8 +37,14 @@ export declare class HelixHeadlessNavigation extends HelixElement {
|
|
|
35
37
|
private readonly indicator;
|
|
36
38
|
/**
|
|
37
39
|
* The landmark's name, read by screen readers.
|
|
40
|
+
*
|
|
41
|
+
* An `aria-label` or `aria-labelledby` on the host names the landmark too,
|
|
42
|
+
* and wins over this, so a footer navigation written the usual way is not a
|
|
43
|
+
* second "Main".
|
|
38
44
|
*/
|
|
39
45
|
label: string;
|
|
46
|
+
/** Carries a host `aria-label` and `aria-labelledby` to the `<nav>`. */
|
|
47
|
+
protected readonly aria: AriaForwardController;
|
|
40
48
|
/**
|
|
41
49
|
* Stacks the destinations in a column, for a sidebar, where unset is a row
|
|
42
50
|
* for a header or a footer. The marker follows the current destination down
|
|
@@ -4,19 +4,30 @@ 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, IndicatorController } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, HelixElement, IndicatorController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.indicator = new IndicatorController(this, {
|
|
14
|
-
active: () =>
|
|
14
|
+
active: () => {
|
|
15
|
+
const items = this.items;
|
|
16
|
+
const marked = (item) => {
|
|
17
|
+
const current = item.getAttribute('aria-current');
|
|
18
|
+
return current !== null && current !== 'false';
|
|
19
|
+
};
|
|
20
|
+
return (items.find((item) => item.getAttribute('aria-current') === 'page') ?? items.find(marked));
|
|
21
|
+
},
|
|
15
22
|
indicator: () => this.partNamed('indicator'),
|
|
16
23
|
observe: () => this.items,
|
|
17
24
|
surface: () => this.partNamed('nav'),
|
|
18
25
|
});
|
|
19
26
|
this.label = 'Main';
|
|
27
|
+
this.aria = new AriaForwardController(this, {
|
|
28
|
+
label: true,
|
|
29
|
+
target: () => this.partNamed('nav'),
|
|
30
|
+
});
|
|
20
31
|
}
|
|
21
32
|
get items() {
|
|
22
33
|
const slot = this.renderRoot.querySelector('slot');
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a key moves focus in a feed of `count` rows, from the row at `at`, or
|
|
3
|
+
* `undefined` for a key the feed does not take.
|
|
4
|
+
*
|
|
5
|
+
* `onRow` says whether focus is on the row's own box. The arrows and `Home` and
|
|
6
|
+
* `End` move only from there, so a control inside a row keeps its keys.
|
|
7
|
+
* `PageDown` and `PageUp` move from anywhere in a row, which is how the APG feed
|
|
8
|
+
* pattern moves on from inside an article. The answer stays inside the feed.
|
|
9
|
+
*/
|
|
10
|
+
export declare const feedStep: (key: string, at: number, count: number, onRow: boolean) => number | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const feedStep = (key, at, count, onRow) => {
|
|
2
|
+
if (count <= 0) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
const anywhere = { PageDown: at + 1, PageUp: at - 1 };
|
|
6
|
+
const fromRow = {
|
|
7
|
+
ArrowDown: at + 1,
|
|
8
|
+
ArrowUp: at - 1,
|
|
9
|
+
End: count - 1,
|
|
10
|
+
Home: 0,
|
|
11
|
+
};
|
|
12
|
+
const to = anywhere[key] ?? (onRow ? fromRow[key] : undefined);
|
|
13
|
+
return to === undefined ? undefined : Math.max(0, Math.min(to, count - 1));
|
|
14
|
+
};
|
|
@@ -33,6 +33,7 @@ declare const HelixHeadlessNotificationGroup_base: (new (...args: any[]) => impo
|
|
|
33
33
|
*
|
|
34
34
|
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before the group collapses. Cancelable.
|
|
35
35
|
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before the group expands. Cancelable: cancel it to keep the group collapsed.
|
|
36
|
+
* @event {ToggleEvent} toggle - The group expanded or collapsed. The event carries `newState` and `oldState`.
|
|
36
37
|
*
|
|
37
38
|
* @csspart actions - The trailing region of the header.
|
|
38
39
|
* @csspart count - The number of notifications in the group.
|
|
@@ -79,6 +79,12 @@ export declare class HelixHeadlessNotification extends HelixHeadlessNotification
|
|
|
79
79
|
* Empty is the runtime's own.
|
|
80
80
|
*/
|
|
81
81
|
locale: string;
|
|
82
|
+
/**
|
|
83
|
+
* @internal Set by the feed: this row's place in it, counting from one, read
|
|
84
|
+
* as `aria-posinset`. Zero leaves the place to the browser, which counts the
|
|
85
|
+
* rows it can see.
|
|
86
|
+
*/
|
|
87
|
+
position: number;
|
|
82
88
|
/**
|
|
83
89
|
* Whether the notification has been read.
|
|
84
90
|
*
|
|
@@ -96,6 +102,24 @@ export declare class HelixHeadlessNotification extends HelixHeadlessNotification
|
|
|
96
102
|
*/
|
|
97
103
|
get read(): boolean;
|
|
98
104
|
set read(next: boolean);
|
|
105
|
+
/**
|
|
106
|
+
* @internal Set by the feed: how many rows the feed holds in all, read as
|
|
107
|
+
* `aria-setsize`, and `-1` when nobody knows. Zero leaves it to the browser.
|
|
108
|
+
*/
|
|
109
|
+
setSize: number;
|
|
110
|
+
/**
|
|
111
|
+
* @internal Set by the feed: whether `Tab` stops on this row. Every row is a
|
|
112
|
+
* stop until the feed has chosen one, which is also what a server sends, so
|
|
113
|
+
* the first render on the client is the server's.
|
|
114
|
+
*/
|
|
115
|
+
stop: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* What a screen reader hears before an unread notification's text.
|
|
118
|
+
*
|
|
119
|
+
* The unread mark is drawn, so a reader who cannot see it hears this word in
|
|
120
|
+
* its place. Translate it with the rest of your interface.
|
|
121
|
+
*/
|
|
122
|
+
unreadLabel: string;
|
|
99
123
|
/**
|
|
100
124
|
* @internal Read by the list to identify its children across the light DOM,
|
|
101
125
|
* which is cheaper than `instanceof` and is why this is public rather than
|
|
@@ -192,6 +216,11 @@ export declare class HelixHeadlessNotification extends HelixHeadlessNotification
|
|
|
192
216
|
protected render(): TemplateResult;
|
|
193
217
|
private readonly handleActions;
|
|
194
218
|
private readonly handleDismiss;
|
|
219
|
+
/**
|
|
220
|
+
* Where focus goes when this row leaves: the next row's first control, the
|
|
221
|
+
* one before, then the first control left in the feed.
|
|
222
|
+
*/
|
|
223
|
+
private neighbor;
|
|
195
224
|
}
|
|
196
225
|
declare global {
|
|
197
226
|
interface HTMLElementTagNameMap {
|
|
@@ -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, HelixReadEvent, hostAria, MixinDismissible, requestChange, slotFilled, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepActiveElement, deepContains, focusableElements, HelixElement, HelixReadEvent, hostAria, MixinDismissible, requestChange, slotFilled, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -17,6 +17,10 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDis
|
|
|
17
17
|
this.at = '';
|
|
18
18
|
this.defaultRead = false;
|
|
19
19
|
this.locale = '';
|
|
20
|
+
this.position = 0;
|
|
21
|
+
this.setSize = 0;
|
|
22
|
+
this.stop = true;
|
|
23
|
+
this.unreadLabel = 'Unread';
|
|
20
24
|
this.isNotification = true;
|
|
21
25
|
this.readState = undefined;
|
|
22
26
|
this.handleActions = () => {
|
|
@@ -25,7 +29,9 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDis
|
|
|
25
29
|
this.handleDismiss = (event) => {
|
|
26
30
|
event.stopPropagation();
|
|
27
31
|
if (this.dismiss()) {
|
|
32
|
+
const next = deepContains(this, deepActiveElement()) ? this.neighbor() : null;
|
|
28
33
|
this.remove();
|
|
34
|
+
next?.focus();
|
|
29
35
|
}
|
|
30
36
|
};
|
|
31
37
|
}
|
|
@@ -55,6 +61,8 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDis
|
|
|
55
61
|
willUpdate(changed) {
|
|
56
62
|
super.willUpdate(changed);
|
|
57
63
|
hostAria(this.internals, { role: 'listitem' });
|
|
64
|
+
this.internals.ariaPosInSet = this.position > 0 ? String(this.position) : null;
|
|
65
|
+
this.internals.ariaSetSize = this.setSize === 0 ? null : String(this.setSize);
|
|
58
66
|
this.toggleState('read', this.read);
|
|
59
67
|
}
|
|
60
68
|
updated(changed) {
|
|
@@ -102,10 +110,15 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDis
|
|
|
102
110
|
></${stamp}>`;
|
|
103
111
|
}
|
|
104
112
|
render() {
|
|
105
|
-
return html `<div
|
|
113
|
+
return html `<div
|
|
114
|
+
part="item"
|
|
115
|
+
role="group"
|
|
116
|
+
aria-labelledby="label"
|
|
117
|
+
tabindex=${this.stop ? 0 : -1}
|
|
118
|
+
>
|
|
106
119
|
<span part="media"><slot name="media"></slot></span>
|
|
107
120
|
<div part="body">
|
|
108
|
-
<div part="label"
|
|
121
|
+
<div id="label" part="label">${this.read ? nothing : html `<span role="img" aria-label=${this.unreadLabel}></span>`}<slot></slot></div>
|
|
109
122
|
<slot name="description"></slot>
|
|
110
123
|
<slot name="detail"></slot>
|
|
111
124
|
<span part="actions"><slot name="actions" @slotchange=${this.handleActions}></slot></span>
|
|
@@ -116,6 +129,29 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends MixinDis
|
|
|
116
129
|
</div>
|
|
117
130
|
</div>`;
|
|
118
131
|
}
|
|
132
|
+
neighbor() {
|
|
133
|
+
let feed = this.parentElement;
|
|
134
|
+
while (feed && !('markEveryoneRead' in feed)) {
|
|
135
|
+
feed = feed.parentElement;
|
|
136
|
+
}
|
|
137
|
+
const rows = feed
|
|
138
|
+
? feed.items
|
|
139
|
+
: [...(this.parentElement?.children ?? [])].filter((one) => 'isNotification' in one);
|
|
140
|
+
const at = rows.indexOf(this);
|
|
141
|
+
const order = [...rows.slice(at + 1), ...rows.slice(0, Math.max(at, 0)).reverse()];
|
|
142
|
+
for (const row of order) {
|
|
143
|
+
const target = row.shadowRoot?.querySelector('[part="dismiss"]') ?? focusableElements(row)[0];
|
|
144
|
+
if (target) {
|
|
145
|
+
return target;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!feed) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
return (feed.shadowRoot?.querySelector('[part="mark-all"]') ??
|
|
152
|
+
focusableElements(feed).find((one) => !this.contains(one)) ??
|
|
153
|
+
null);
|
|
154
|
+
}
|
|
119
155
|
};
|
|
120
156
|
__decorate([
|
|
121
157
|
property()
|
|
@@ -126,9 +162,21 @@ __decorate([
|
|
|
126
162
|
__decorate([
|
|
127
163
|
property()
|
|
128
164
|
], HelixHeadlessNotification.prototype, "locale", void 0);
|
|
165
|
+
__decorate([
|
|
166
|
+
property({ attribute: false })
|
|
167
|
+
], HelixHeadlessNotification.prototype, "position", void 0);
|
|
129
168
|
__decorate([
|
|
130
169
|
property({ type: Boolean })
|
|
131
170
|
], HelixHeadlessNotification.prototype, "read", null);
|
|
171
|
+
__decorate([
|
|
172
|
+
property({ attribute: false })
|
|
173
|
+
], HelixHeadlessNotification.prototype, "setSize", void 0);
|
|
174
|
+
__decorate([
|
|
175
|
+
property({ attribute: false })
|
|
176
|
+
], HelixHeadlessNotification.prototype, "stop", void 0);
|
|
177
|
+
__decorate([
|
|
178
|
+
property({ attribute: 'unread-label' })
|
|
179
|
+
], HelixHeadlessNotification.prototype, "unreadLabel", void 0);
|
|
132
180
|
HelixHeadlessNotification = __decorate([
|
|
133
181
|
customElement('helix-headless-notification')
|
|
134
182
|
], HelixHeadlessNotification);
|
|
@@ -21,6 +21,14 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
|
|
|
21
21
|
* the items and written to an attribute, so a stylesheet and a badge can both
|
|
22
22
|
* use it without counting.
|
|
23
23
|
*
|
|
24
|
+
* **The feed is one `Tab` stop for its rows.** Each row takes focus itself and
|
|
25
|
+
* is read by its label. `ArrowDown` and `ArrowUp` move to the next and the
|
|
26
|
+
* previous row, `Home` and `End` to the first and the last, and `PageDown` and
|
|
27
|
+
* `PageUp` move a row on or back from anywhere inside one, as in the APG feed
|
|
28
|
+
* pattern. The controls inside a row stay in the `Tab` order. Set `total` when
|
|
29
|
+
* the feed holds one page of a longer list, and each row says its place in the
|
|
30
|
+
* whole of it.
|
|
31
|
+
*
|
|
24
32
|
* @since 0.1.0
|
|
25
33
|
* @status stable
|
|
26
34
|
* @category feedback
|
|
@@ -67,6 +75,14 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
67
75
|
* Label for the mark-all control.
|
|
68
76
|
*/
|
|
69
77
|
markAllLabel: string;
|
|
78
|
+
/**
|
|
79
|
+
* How many notifications there are in all, where the feed holds only some of
|
|
80
|
+
* them, read as each row's `aria-setsize`. `-1` says the count is unknown.
|
|
81
|
+
*
|
|
82
|
+
* Unset, the browser counts the rows it can see, which is right for a feed
|
|
83
|
+
* that holds everything.
|
|
84
|
+
*/
|
|
85
|
+
total?: number;
|
|
70
86
|
/**
|
|
71
87
|
* How many items are unread, counted from the items themselves.
|
|
72
88
|
*
|
|
@@ -158,6 +174,32 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
158
174
|
*/
|
|
159
175
|
private readonly handleRead;
|
|
160
176
|
private assign;
|
|
177
|
+
/** The row `Tab` stops on, once a reader has been to one. */
|
|
178
|
+
private stopRow;
|
|
179
|
+
/**
|
|
180
|
+
* The rows a reader can reach with the keys: every row in the feed, in order,
|
|
181
|
+
* less the ones a folded group renders nowhere.
|
|
182
|
+
*/
|
|
183
|
+
private get reachable();
|
|
184
|
+
/** The row whose own box is the element focus is on, if it is one. */
|
|
185
|
+
private rowFocused;
|
|
186
|
+
/** A row taking focus becomes the feed's stop, so `Tab` comes back to it. */
|
|
187
|
+
private readonly handleFocusIn;
|
|
188
|
+
/**
|
|
189
|
+
* Moves between rows.
|
|
190
|
+
*
|
|
191
|
+
* The arrows and `Home` and `End` only from a row's own box, so a control in
|
|
192
|
+
* a row keeps its keys. `PageDown` and `PageUp` from anywhere in a row, which
|
|
193
|
+
* is how the APG feed pattern moves on from inside an article.
|
|
194
|
+
*/
|
|
195
|
+
private readonly handleKeydown;
|
|
196
|
+
/**
|
|
197
|
+
* Tells each row whether it is the stop, and where it sits in the feed.
|
|
198
|
+
*
|
|
199
|
+
* Through each row's own properties, written once it has hydrated, so a
|
|
200
|
+
* server's markup stays the server's: every row is a stop until this runs.
|
|
201
|
+
*/
|
|
202
|
+
private rove;
|
|
161
203
|
connectedCallback(): void;
|
|
162
204
|
disconnectedCallback(): void;
|
|
163
205
|
protected willUpdate(changed: PropertyValues): void;
|
|
@@ -202,6 +244,13 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
202
244
|
private markEmpty;
|
|
203
245
|
protected updated(changed: PropertyValues): void;
|
|
204
246
|
protected render(): TemplateResult;
|
|
247
|
+
/**
|
|
248
|
+
* Marks everything read, and keeps focus in the feed.
|
|
249
|
+
*
|
|
250
|
+
* The button shows only while something is unread, so the press that
|
|
251
|
+
* succeeds removes the button it was made on. Focus moves to the first row's
|
|
252
|
+
* control, or the first control left in the feed.
|
|
253
|
+
*/
|
|
205
254
|
private readonly handleMarkAll;
|
|
206
255
|
}
|
|
207
256
|
declare global {
|
|
@@ -4,9 +4,10 @@ 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, HelixReadEvent, hostAria, MixinCollection, markRegion, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepContains, focusableElements, HelixElement, HelixReadEvent, hostAria, MixinCollection, markRegion, rovingStop, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { feedStep } from '../feed-keys.js';
|
|
10
11
|
let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinCollection(HelixElement) {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
@@ -20,8 +21,53 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
20
21
|
this.handleRead = () => {
|
|
21
22
|
queueMicrotask(() => this.requestUpdate());
|
|
22
23
|
};
|
|
23
|
-
this.
|
|
24
|
+
this.handleFocusIn = (event) => {
|
|
25
|
+
const row = this.rowFocused(event.composedPath()[0]);
|
|
26
|
+
if (row && row !== this.stopRow) {
|
|
27
|
+
this.stopRow = row;
|
|
28
|
+
this.rove();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
this.handleKeydown = (event) => {
|
|
32
|
+
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const rows = this.reachable;
|
|
36
|
+
const from = event.composedPath()[0];
|
|
37
|
+
const own = this.rowFocused(from);
|
|
38
|
+
const inside = own ?? rows.find((row) => from instanceof Node && deepContains(row, from));
|
|
39
|
+
if (!inside) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const to = feedStep(event.key, rows.indexOf(inside), rows.length, own !== undefined);
|
|
43
|
+
if (to === undefined) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
const next = rows[to];
|
|
48
|
+
if (next) {
|
|
49
|
+
this.stopRow = next;
|
|
50
|
+
this.rove();
|
|
51
|
+
rowBox(next)?.focus();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
this.handleMarkAll = (event) => {
|
|
55
|
+
const button = event.currentTarget;
|
|
56
|
+
const focused = this.shadowRoot?.activeElement === button;
|
|
24
57
|
this.markEveryoneRead();
|
|
58
|
+
if (!focused) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
void this.updateComplete.then(() => {
|
|
62
|
+
if (button.isConnected) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const target = this.items
|
|
66
|
+
.map((row) => row.shadowRoot?.querySelector('[part="dismiss"]') ??
|
|
67
|
+
focusableElements(row)[0])
|
|
68
|
+
.find((one) => one !== undefined) ?? focusableElements(this)[0];
|
|
69
|
+
target?.focus();
|
|
70
|
+
});
|
|
25
71
|
};
|
|
26
72
|
}
|
|
27
73
|
static { this.shadowRootOptions = {
|
|
@@ -91,13 +137,36 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
91
137
|
slot?.assign?.(...[...this.children].filter((child) => child.getAttribute('slot') === name));
|
|
92
138
|
}
|
|
93
139
|
}
|
|
140
|
+
get reachable() {
|
|
141
|
+
return this.items.filter((row) => !('assignedSlot' in row) || row.assignedSlot !== null);
|
|
142
|
+
}
|
|
143
|
+
rowFocused(target) {
|
|
144
|
+
return this.reachable.find((row) => rowBox(row) === target);
|
|
145
|
+
}
|
|
146
|
+
rove() {
|
|
147
|
+
const rows = this.reachable;
|
|
148
|
+
const stop = rovingStop(rows, this.stopRow);
|
|
149
|
+
const direct = this.rows;
|
|
150
|
+
for (const row of this.items) {
|
|
151
|
+
const position = direct.indexOf(row) + 1;
|
|
152
|
+
whenHydrated(row, () => {
|
|
153
|
+
row.stop = row === stop;
|
|
154
|
+
row.position = this.total === undefined ? 0 : position;
|
|
155
|
+
row.setSize = this.total ?? 0;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
94
159
|
connectedCallback() {
|
|
95
160
|
super.connectedCallback();
|
|
96
161
|
this.addEventListener('helix-read', this.handleRead);
|
|
162
|
+
this.addEventListener('focusin', this.handleFocusIn);
|
|
163
|
+
this.addEventListener('keydown', this.handleKeydown);
|
|
97
164
|
}
|
|
98
165
|
disconnectedCallback() {
|
|
99
166
|
super.disconnectedCallback();
|
|
100
167
|
this.removeEventListener('helix-read', this.handleRead);
|
|
168
|
+
this.removeEventListener('focusin', this.handleFocusIn);
|
|
169
|
+
this.removeEventListener('keydown', this.handleKeydown);
|
|
101
170
|
}
|
|
102
171
|
willUpdate(changed) {
|
|
103
172
|
super.willUpdate(changed);
|
|
@@ -115,6 +184,7 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
115
184
|
this.assign();
|
|
116
185
|
this.markEmpty();
|
|
117
186
|
this.markMedia();
|
|
187
|
+
this.rove();
|
|
118
188
|
const unread = this.unread > 0 ? String(this.unread) : null;
|
|
119
189
|
if (this.getAttribute('unread') !== unread) {
|
|
120
190
|
if (unread === null) {
|
|
@@ -152,7 +222,11 @@ __decorate([
|
|
|
152
222
|
__decorate([
|
|
153
223
|
property({ attribute: 'mark-all-label' })
|
|
154
224
|
], HelixHeadlessNotifications.prototype, "markAllLabel", void 0);
|
|
225
|
+
__decorate([
|
|
226
|
+
property({ type: Number })
|
|
227
|
+
], HelixHeadlessNotifications.prototype, "total", void 0);
|
|
155
228
|
HelixHeadlessNotifications = __decorate([
|
|
156
229
|
customElement('helix-headless-notifications')
|
|
157
230
|
], HelixHeadlessNotifications);
|
|
158
231
|
export { HelixHeadlessNotifications };
|
|
232
|
+
const rowBox = (row) => row.shadowRoot?.querySelector('[part="item"]') ?? null;
|
|
@@ -18,8 +18,20 @@ declare const HelixHeadlessNumberInput_base: (new (...args: any[]) => import("@f
|
|
|
18
18
|
*
|
|
19
19
|
* `inputmode="decimal"` keeps the numeric keypad on phones.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* `format-options` shows the number with `Intl.NumberFormat` in `locale`, as a
|
|
22
|
+
* currency, a percent or a unit, while the field is not being edited. Focus
|
|
23
|
+
* shows the number itself, and a typed `$1,200` or `25%` is read back with the
|
|
24
|
+
* same options. The value stays the plain number: `1200`, or `0.25` for 25%.
|
|
25
|
+
* The locale's group separators are read in every field, so `1,234` is a
|
|
26
|
+
* number in `en-US`.
|
|
27
|
+
*
|
|
28
|
+
* On iOS and iPadOS the field is a text field described as a number field,
|
|
29
|
+
* with no `role="spinbutton"`, which VoiceOver reads as a slider you cannot
|
|
30
|
+
* type in. React Aria's NumberField does the same.
|
|
31
|
+
*
|
|
32
|
+
* Validity follows the platform's rules: `min`, `max`, and `step` are checked
|
|
33
|
+
* and reported through the host's own `setValidity`, under the platform's flag
|
|
34
|
+
* names.
|
|
23
35
|
*
|
|
24
36
|
* Stepping is separate from typing, so a number is not corrected while you type
|
|
25
37
|
* it.
|
|
@@ -31,6 +43,9 @@ declare const HelixHeadlessNumberInput_base: (new (...args: any[]) => import("@f
|
|
|
31
43
|
* @documentation https://fusion.dev/helix/components/number-input
|
|
32
44
|
*
|
|
33
45
|
* @slot end - Content after the number, such as a unit.
|
|
46
|
+
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
47
|
+
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
48
|
+
* @slot label - The label, for content richer than the `label` text.
|
|
34
49
|
* @slot start - Content before the number, such as a unit or an icon.
|
|
35
50
|
*
|
|
36
51
|
* @event {Event} change - The user finished changing the value. Relayed from the native field.
|
|
@@ -76,6 +91,16 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
76
91
|
* The name of the step down button, read by screen readers.
|
|
77
92
|
*/
|
|
78
93
|
decrementLabel: string;
|
|
94
|
+
/**
|
|
95
|
+
* `Intl.NumberFormat` options the number is shown with while the field is
|
|
96
|
+
* not being edited: a currency, a percent, a unit, or a number of decimals.
|
|
97
|
+
* Written as JSON in the attribute.
|
|
98
|
+
*
|
|
99
|
+
* ```html
|
|
100
|
+
* <helix-number-input format-options='{"style":"currency","currency":"EUR"}'></helix-number-input>
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
formatOptions?: Intl.NumberFormatOptions;
|
|
79
104
|
/**
|
|
80
105
|
* The name of the step up button, read by screen readers.
|
|
81
106
|
*/
|
|
@@ -88,6 +113,15 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
88
113
|
* what a reader wants from a whole key.
|
|
89
114
|
*/
|
|
90
115
|
largeStep?: number;
|
|
116
|
+
/**
|
|
117
|
+
* The locale a typed number is read in, such as `de-DE`. Empty reads it in
|
|
118
|
+
* the browser's language.
|
|
119
|
+
*
|
|
120
|
+
* Where the locale writes a decimal comma, `1,5` is read as one and a half,
|
|
121
|
+
* which is what the decimal keypad on a phone in that locale types. A dot is
|
|
122
|
+
* read as a decimal point in every locale.
|
|
123
|
+
*/
|
|
124
|
+
locale: string;
|
|
91
125
|
/**
|
|
92
126
|
* The largest value allowed.
|
|
93
127
|
*
|
|
@@ -120,6 +154,11 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
120
154
|
* Prevents editing. The value is still submitted with the form.
|
|
121
155
|
*/
|
|
122
156
|
readOnly: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* What the field is described as on iOS and iPadOS, where it carries no
|
|
159
|
+
* spinbutton role. See the class description.
|
|
160
|
+
*/
|
|
161
|
+
roleDescription: string;
|
|
123
162
|
/**
|
|
124
163
|
* Makes the label a grip that changes the value when it is dragged.
|
|
125
164
|
*
|
|
@@ -132,14 +171,50 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
132
171
|
*/
|
|
133
172
|
scrub: boolean;
|
|
134
173
|
/**
|
|
135
|
-
* How far one step moves.
|
|
174
|
+
* How far one step moves. A value off the step grid, counted from `min`, is
|
|
175
|
+
* invalid, as it is in a native number field.
|
|
136
176
|
*/
|
|
137
177
|
step: number;
|
|
138
|
-
/**
|
|
139
|
-
|
|
178
|
+
/**
|
|
179
|
+
* The message the browser shows when the number is off the step grid, with
|
|
180
|
+
* `{below}` and `{above}` filled in with the nearest valid values.
|
|
181
|
+
*/
|
|
182
|
+
stepMismatchMessage?: string;
|
|
183
|
+
/**
|
|
184
|
+
* What a screen reader says for the value, with `{value}` filled in, such as
|
|
185
|
+
* `{value} kilograms`.
|
|
186
|
+
*
|
|
187
|
+
* A unit slotted into `end` is drawn beside the number and is not part of
|
|
188
|
+
* what the spinbutton announces, so it goes here too. Empty announces the
|
|
189
|
+
* number alone.
|
|
190
|
+
*/
|
|
191
|
+
valueText: string;
|
|
192
|
+
/**
|
|
193
|
+
* Whether the mouse wheel steps the number while the field has focus, as
|
|
194
|
+
* React Aria's NumberField does unless told not to. Off, the wheel scrolls
|
|
195
|
+
* the page, which is what a reader passing over a form expects.
|
|
196
|
+
*/
|
|
197
|
+
wheel: boolean;
|
|
198
|
+
/** Whether the field has focus, so it shows the number itself and not its format. */
|
|
199
|
+
private editing;
|
|
200
|
+
/**
|
|
201
|
+
* What the field shows: the value as written while it is edited, and with
|
|
202
|
+
* `format-options` once it is not.
|
|
203
|
+
*/
|
|
204
|
+
private get shown();
|
|
205
|
+
/** Steps on the wheel, where asked, while the field has focus. */
|
|
206
|
+
private readonly handleWheel;
|
|
207
|
+
private readonly handleFocus;
|
|
208
|
+
/**
|
|
209
|
+
* Whether this is an iPhone or an iPad, read once on the client. A server
|
|
210
|
+
* has no navigator and renders the spinbutton.
|
|
211
|
+
*/
|
|
212
|
+
private readonly touchApple;
|
|
140
213
|
private get control();
|
|
141
214
|
/** The value as a number, or `null` where the field holds nothing usable. */
|
|
142
215
|
private get numeric();
|
|
216
|
+
/** Whether `value` is on the step grid, counted from `min`. */
|
|
217
|
+
private onStep;
|
|
143
218
|
/**
|
|
144
219
|
* A value pulled into range and onto the step grid.
|
|
145
220
|
*
|
|
@@ -254,7 +329,19 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
254
329
|
* the same as preventing one.
|
|
255
330
|
*/
|
|
256
331
|
private readonly handleBlur;
|
|
257
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* Pulls a typed number into range and onto the step grid, and returns
|
|
334
|
+
* whether that moved the value.
|
|
335
|
+
*/
|
|
336
|
+
private settle;
|
|
337
|
+
/**
|
|
338
|
+
* Relayed, because `change` does not cross a shadow boundary on its own.
|
|
339
|
+
*
|
|
340
|
+
* **Settled first.** The field's `change` arrives before its `blur`, so
|
|
341
|
+
* relaying it as it came announced the number as typed, 150 in a field whose
|
|
342
|
+
* `max` is 100, and the clamp that followed sent `input` alone: a consumer
|
|
343
|
+
* saving on `change` kept 150 while the form submitted 100.
|
|
344
|
+
*/
|
|
258
345
|
private readonly handleChange;
|
|
259
346
|
/**
|
|
260
347
|
* The four keys a spinner answers, which `Input` does not bind.
|
|
@@ -274,7 +361,13 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
274
361
|
* message is what a native spinner would have said.
|
|
275
362
|
*/
|
|
276
363
|
private sync;
|
|
277
|
-
/**
|
|
364
|
+
/**
|
|
365
|
+
* Puts the cursor in the field.
|
|
366
|
+
*
|
|
367
|
+
* **No `delegatesFocus`**, because the platform's delegate is the first
|
|
368
|
+
* focusable element, which is the Decrease stepper: a label pressed for the
|
|
369
|
+
* field landed on it, and the arrows then did nothing.
|
|
370
|
+
*/
|
|
278
371
|
focus(options?: FocusOptions): void;
|
|
279
372
|
/** Selects the number, so typing replaces it. */
|
|
280
373
|
select(): void;
|
|
@@ -287,6 +380,15 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
|
|
|
287
380
|
private releaseCaret;
|
|
288
381
|
protected willUpdate(changed: PropertyValues): void;
|
|
289
382
|
protected updated(changed: PropertyValues): void;
|
|
383
|
+
/**
|
|
384
|
+
* Enter submits the form, as it does in a native text field.
|
|
385
|
+
*
|
|
386
|
+
* On `keypress`, where the platform runs its own implicit submission, so a
|
|
387
|
+
* consumer who prevents the `keydown` for Enter stops this too.
|
|
388
|
+
*/
|
|
389
|
+
private readonly handleKeypress;
|
|
390
|
+
/** @internal A single line of text counts against implicit submission. */
|
|
391
|
+
protected get blocksImplicitSubmission(): boolean;
|
|
290
392
|
protected render(): TemplateResult;
|
|
291
393
|
/**
|
|
292
394
|
* The value as a number, or `NaN` while the control is empty.
|