@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
|
@@ -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, HelixSelectEvent } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, followLink, HelixElement, HelixSelectEvent, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
export const optionsAmong = (elements) => {
|
|
@@ -18,8 +18,13 @@ let HelixHeadlessOption = class HelixHeadlessOption extends HelixElement {
|
|
|
18
18
|
this.alternate = '';
|
|
19
19
|
this.alternateLabel = '';
|
|
20
20
|
this.disabled = false;
|
|
21
|
+
this.download = false;
|
|
22
|
+
this.href = '';
|
|
21
23
|
this.label = '';
|
|
24
|
+
this.rel = '';
|
|
22
25
|
this.selected = false;
|
|
26
|
+
this.target = '';
|
|
27
|
+
this.textValue = '';
|
|
23
28
|
this.value = '';
|
|
24
29
|
}
|
|
25
30
|
get defaultSelected() {
|
|
@@ -29,31 +34,41 @@ let HelixHeadlessOption = class HelixHeadlessOption extends HelixElement {
|
|
|
29
34
|
this.toggleAttribute('selected', next);
|
|
30
35
|
}
|
|
31
36
|
get text() {
|
|
37
|
+
if (this.textValue !== '') {
|
|
38
|
+
return this.textValue;
|
|
39
|
+
}
|
|
32
40
|
return ([...this.childNodes]
|
|
33
41
|
.filter((node) => node.nodeType === Node.TEXT_NODE || (node instanceof Element && node.slot === ''))
|
|
34
42
|
.map((node) => node.textContent ?? '')
|
|
35
43
|
.join('')
|
|
36
44
|
.trim() || this.label);
|
|
37
45
|
}
|
|
38
|
-
select() {
|
|
46
|
+
select(modifiers) {
|
|
39
47
|
if (this.disabled) {
|
|
40
48
|
return;
|
|
41
49
|
}
|
|
42
|
-
|
|
50
|
+
if (this.href === '') {
|
|
51
|
+
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (this.dispatchEvent(new HelixSelectEvent({ href: this.href, value: this.value }))) {
|
|
55
|
+
followLink(this.ownerDocument, this, modifiers);
|
|
56
|
+
}
|
|
43
57
|
}
|
|
44
58
|
willUpdate(changed) {
|
|
45
59
|
super.willUpdate(changed);
|
|
46
60
|
this.toggleState('selected', this.selected);
|
|
61
|
+
this.toggleState('active', this.active);
|
|
47
62
|
}
|
|
48
63
|
render() {
|
|
49
64
|
this.internals.role = 'option';
|
|
50
|
-
this.internals.ariaSelected = String(this.selected);
|
|
65
|
+
this.internals.ariaSelected = this.href === '' ? String(this.selected) : null;
|
|
51
66
|
this.internals.ariaDisabled = this.disabled ? 'true' : null;
|
|
52
67
|
this.internals.ariaDescription =
|
|
53
68
|
this.alternate !== '' && this.alternateLabel !== '' ? this.alternateLabel : null;
|
|
54
69
|
return html `<div
|
|
55
70
|
part="item${this.selected ? ' item-selected' : ''}${this.active ? ' item-active' : ''}"
|
|
56
|
-
@click=${() => this.select()}
|
|
71
|
+
@click=${(event) => this.select(event)}
|
|
57
72
|
>
|
|
58
73
|
<slot name="start"></slot>
|
|
59
74
|
<span part="text">
|
|
@@ -79,12 +94,27 @@ __decorate([
|
|
|
79
94
|
__decorate([
|
|
80
95
|
property({ reflect: true, type: Boolean })
|
|
81
96
|
], HelixHeadlessOption.prototype, "disabled", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
property({ type: Boolean })
|
|
99
|
+
], HelixHeadlessOption.prototype, "download", void 0);
|
|
100
|
+
__decorate([
|
|
101
|
+
property()
|
|
102
|
+
], HelixHeadlessOption.prototype, "href", void 0);
|
|
82
103
|
__decorate([
|
|
83
104
|
property()
|
|
84
105
|
], HelixHeadlessOption.prototype, "label", void 0);
|
|
106
|
+
__decorate([
|
|
107
|
+
property()
|
|
108
|
+
], HelixHeadlessOption.prototype, "rel", void 0);
|
|
85
109
|
__decorate([
|
|
86
110
|
property({ type: Boolean })
|
|
87
111
|
], HelixHeadlessOption.prototype, "selected", void 0);
|
|
112
|
+
__decorate([
|
|
113
|
+
property()
|
|
114
|
+
], HelixHeadlessOption.prototype, "target", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
property({ attribute: 'text-value' })
|
|
117
|
+
], HelixHeadlessOption.prototype, "textValue", void 0);
|
|
88
118
|
__decorate([
|
|
89
119
|
property()
|
|
90
120
|
], HelixHeadlessOption.prototype, "value", void 0);
|
|
@@ -11,6 +11,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
11
11
|
* render one inside the outline's shadow root, and the hrefs are fragments on
|
|
12
12
|
* the same page.
|
|
13
13
|
*
|
|
14
|
+
* Write the anchors flat, with `data-level` for their depth, or nested in
|
|
15
|
+
* lists, `<ul><li><a>`. A screen reader hears a nested list's levels; it hears
|
|
16
|
+
* `data-level` as a flat run of links.
|
|
17
|
+
*
|
|
14
18
|
* The current section is decided by the headings' positions. An
|
|
15
19
|
* `IntersectionObserver` with a band near the top fails both ways: when
|
|
16
20
|
* headings are far apart, none is in the band and no section is marked, and
|
|
@@ -22,7 +26,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
22
26
|
* @aliases Table of contents, On this page, Outline
|
|
23
27
|
* @documentation https://fusion.dev/helix/components/outline
|
|
24
28
|
*
|
|
25
|
-
* @slot - The links, as anchors with fragment hrefs.
|
|
29
|
+
* @slot - The links, as anchors with fragment hrefs, or lists holding them.
|
|
26
30
|
*
|
|
27
31
|
* @event {HelixActivateEvent} helix-activate - Fired when the section in view changes, with its id as the value. It reports the scroll position and cannot be prevented.
|
|
28
32
|
*
|
|
@@ -88,7 +92,14 @@ export declare class HelixHeadlessOutline extends HelixElement {
|
|
|
88
92
|
*/
|
|
89
93
|
private reading;
|
|
90
94
|
private observer;
|
|
91
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* The links, in document order. Empty on the server, which has no tree.
|
|
97
|
+
*
|
|
98
|
+
* **Anchors inside what is slotted count too.** A contents list is written
|
|
99
|
+
* `<ul><li><a>` more often than as a run of anchors, and reading only the
|
|
100
|
+
* anchors assigned to the slot found no sections in it: nothing was marked,
|
|
101
|
+
* nothing was announced, and nothing said why.
|
|
102
|
+
*/
|
|
92
103
|
private get links();
|
|
93
104
|
/**
|
|
94
105
|
* What each link points at, paired with the link, skipping anything missing.
|
|
@@ -78,8 +78,10 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
|
|
|
78
78
|
}
|
|
79
79
|
get links() {
|
|
80
80
|
const slot = this.renderRoot?.querySelector('slot');
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
const fragment = (element) => element instanceof HTMLAnchorElement && element.getAttribute('href')?.startsWith('#') === true;
|
|
82
|
+
return (slot?.assignedElements({ flatten: true }) ?? []).flatMap((element) => fragment(element)
|
|
83
|
+
? [element]
|
|
84
|
+
: [...element.querySelectorAll('a[href^="#"]')].filter(fragment));
|
|
83
85
|
}
|
|
84
86
|
get sections() {
|
|
85
87
|
return this.links.flatMap((link) => {
|
|
@@ -39,7 +39,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
39
39
|
* @slot next-icon - The glyph on the forward-one-page control, usually a caret.
|
|
40
40
|
* @slot previous-icon - The glyph on the back-one-page control, usually a caret.
|
|
41
41
|
*
|
|
42
|
-
* @event {
|
|
42
|
+
* @event {HelixActivateEvent} helix-activate - Fired after the page changes, with the new page as a string in `detail.value`. In `href` mode it comes a task after the click, once the page has moved.
|
|
43
|
+
* @event {HelixNavigateEvent} helix-navigate - Fired before the page changes, and cancelable. Canceling it is the only way to stop a page change. `detail.page` is the page asked for, as a number, and `detail.value` is the same page as a string.
|
|
43
44
|
*
|
|
44
45
|
* @csspart first - The control that jumps to the first page, under `ends`.
|
|
45
46
|
* @csspart gap - The control in place of hidden pages, which jumps into them.
|
|
@@ -218,6 +219,11 @@ export declare class HelixHeadlessPagination extends HelixElement {
|
|
|
218
219
|
private announced;
|
|
219
220
|
/** The page on show, whoever set it, and `undefined` until somebody has. */
|
|
220
221
|
private pageState;
|
|
222
|
+
/**
|
|
223
|
+
* The control a reader just used, while it held focus, and whether it was a
|
|
224
|
+
* gap. Read once by the update that follows, which decides where focus goes.
|
|
225
|
+
*/
|
|
226
|
+
private used;
|
|
221
227
|
/** Held across every component asking for the same locale. */
|
|
222
228
|
private get numbers();
|
|
223
229
|
/**
|
|
@@ -263,6 +269,18 @@ export declare class HelixHeadlessPagination extends HelixElement {
|
|
|
263
269
|
* for both shapes rather than two that have to stay in step.
|
|
264
270
|
*/
|
|
265
271
|
private readonly go;
|
|
272
|
+
private applyPage;
|
|
273
|
+
/**
|
|
274
|
+
* Puts focus back in the row after the control a reader used has gone.
|
|
275
|
+
*
|
|
276
|
+
* A page keeps its own control across a move, because the run is keyed by
|
|
277
|
+
* page, so focus stays on the page that was chosen. A gap points somewhere
|
|
278
|
+
* new once the run moves, and a step control is disabled at the end it
|
|
279
|
+
* reached, so after either of those focus goes to the current page, or in
|
|
280
|
+
* `compact` to the first step control that can still be used. Left alone,
|
|
281
|
+
* focus fell to the top of the document.
|
|
282
|
+
*/
|
|
283
|
+
private restoreFocus;
|
|
266
284
|
protected willUpdate(changed: PropertyValues): void;
|
|
267
285
|
/**
|
|
268
286
|
* Says where the reader now is, once they have moved.
|
|
@@ -4,10 +4,11 @@ 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, fillTemplate, formatNumbers, HelixElement, HelixNavigateEvent, hostAria, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepActiveElement, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixNavigateEvent, hostAria, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretDoubleLeft, caretDoubleRight, caretLeft, caretRight, } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
11
12
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
13
|
const fill = (template, page, pages, format = String) => fillTemplate(template, { page: format(page), pages: format(pages) });
|
|
13
14
|
let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement {
|
|
@@ -34,9 +35,15 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
|
|
|
34
35
|
this.announcement = '';
|
|
35
36
|
this.announced = undefined;
|
|
36
37
|
this.pageState = undefined;
|
|
37
|
-
this.
|
|
38
|
+
this.used = undefined;
|
|
39
|
+
this.go = (next, event, gap = false) => {
|
|
40
|
+
const control = event.currentTarget;
|
|
38
41
|
if (!this.request(next)) {
|
|
39
42
|
event.preventDefault();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (control && deepActiveElement() === control) {
|
|
46
|
+
this.used = { control, gap };
|
|
40
47
|
}
|
|
41
48
|
};
|
|
42
49
|
}
|
|
@@ -104,15 +111,43 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
|
|
|
104
111
|
}
|
|
105
112
|
return requestChange({
|
|
106
113
|
apply: (page) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
if (this.href) {
|
|
115
|
+
setTimeout(() => this.applyPage(page));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.applyPage(page);
|
|
110
119
|
},
|
|
111
|
-
event: (page) => new HelixNavigateEvent({ value: String(page) }),
|
|
120
|
+
event: (page) => new HelixNavigateEvent({ page, value: String(page) }),
|
|
112
121
|
host: this,
|
|
113
122
|
next,
|
|
114
123
|
});
|
|
115
124
|
}
|
|
125
|
+
applyPage(page) {
|
|
126
|
+
const previous = this.page;
|
|
127
|
+
this.pageState = page;
|
|
128
|
+
this.requestUpdate('page', previous);
|
|
129
|
+
this.dispatchEvent(new HelixActivateEvent({ value: String(page) }));
|
|
130
|
+
}
|
|
131
|
+
restoreFocus() {
|
|
132
|
+
const used = this.used;
|
|
133
|
+
this.used = undefined;
|
|
134
|
+
if (!used) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const { control, gap } = used;
|
|
138
|
+
const usable = (element) => element instanceof HTMLElement &&
|
|
139
|
+
element.isConnected &&
|
|
140
|
+
!element.disabled &&
|
|
141
|
+
element.getAttribute('aria-disabled') !== 'true';
|
|
142
|
+
if (!gap && usable(control)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const target = [
|
|
146
|
+
this.renderRoot.querySelector('[part~="page-current"]'),
|
|
147
|
+
...['previous', 'next', 'first', 'last'].map((name) => this.renderRoot.querySelector(`[part="${name}"]`)),
|
|
148
|
+
].find(usable);
|
|
149
|
+
target?.focus();
|
|
150
|
+
}
|
|
116
151
|
willUpdate(changed) {
|
|
117
152
|
super.willUpdate(changed);
|
|
118
153
|
hostAria(this.internals, { label: this.label, role: 'navigation' });
|
|
@@ -120,6 +155,7 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
|
|
|
120
155
|
}
|
|
121
156
|
updated(changed) {
|
|
122
157
|
super.updated(changed);
|
|
158
|
+
this.restoreFocus();
|
|
123
159
|
if (this.announced === undefined) {
|
|
124
160
|
this.announced = this.page;
|
|
125
161
|
return;
|
|
@@ -163,14 +199,14 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
|
|
|
163
199
|
part="gap"
|
|
164
200
|
href=${fill(this.href, to, this.count)}
|
|
165
201
|
aria-label=${name}
|
|
166
|
-
@click=${(event) => this.go(to, event)}
|
|
202
|
+
@click=${(event) => this.go(to, event, true)}
|
|
167
203
|
>…</a
|
|
168
204
|
>`
|
|
169
205
|
: html `<button
|
|
170
206
|
part="gap"
|
|
171
207
|
type="button"
|
|
172
208
|
aria-label=${name}
|
|
173
|
-
@click=${(event) => this.go(to, event)}
|
|
209
|
+
@click=${(event) => this.go(to, event, true)}
|
|
174
210
|
>
|
|
175
211
|
…
|
|
176
212
|
</button>`}
|
|
@@ -253,7 +289,11 @@ let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement
|
|
|
253
289
|
}
|
|
254
290
|
return html `${this.ends ? this.renderFirst() : nothing}${this.renderPrevious()}
|
|
255
291
|
<ol part="list" role="list">
|
|
256
|
-
${this.slots
|
|
292
|
+
${repeat(this.slots, (slot) => typeof slot === 'number'
|
|
293
|
+
? slot
|
|
294
|
+
: slot.from < this.current
|
|
295
|
+
? 'gap-before'
|
|
296
|
+
: 'gap-after', (slot) => (typeof slot === 'number' ? this.renderPage(slot) : this.renderGap(slot)))}
|
|
257
297
|
</ol>
|
|
258
298
|
${this.renderNext()}${this.ends ? this.renderLast() : nothing}${this.renderLive()}`;
|
|
259
299
|
}
|
|
@@ -23,16 +23,19 @@ import '../../select/index.js';
|
|
|
23
23
|
* `ElementInternals.states`.
|
|
24
24
|
*
|
|
25
25
|
* `value` is the current size, and `default-value` is the size from the markup.
|
|
26
|
-
* Changing it dispatches `helix-before-change
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Changing it dispatches `helix-before-change`, and then `input` and `change`
|
|
27
|
+
* once the size has moved, as a native `<select>` sends them together.
|
|
28
|
+
* Re-querying and returning to page one is up to you, because only you know
|
|
29
|
+
* whether the current position should be kept.
|
|
29
30
|
*
|
|
30
31
|
* @since 0.1.0
|
|
31
32
|
* @status stable
|
|
32
33
|
* @aliases Page size, Rows per page
|
|
33
34
|
* @documentation https://fusion.dev/helix/components/pagination
|
|
34
35
|
*
|
|
36
|
+
* @event {Event} change - Fired after the size changes.
|
|
35
37
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before the size changes, and cancelable. Canceling it is the only way to stop a size change.
|
|
38
|
+
* @event {Event} input - Fired after the size changes, with `change`.
|
|
36
39
|
*
|
|
37
40
|
* @csspart control - The select.
|
|
38
41
|
* @csspart control-feedback - The message that says what is wrong with the value.
|
|
@@ -105,6 +108,13 @@ export declare class HelixHeadlessPaginationSize extends HelixElement {
|
|
|
105
108
|
/** The one in force, which is the first offered where nothing named one. */
|
|
106
109
|
private get current();
|
|
107
110
|
private readonly handleChange;
|
|
111
|
+
/**
|
|
112
|
+
* The select's own `input` and `change`, stopped so this element is the one
|
|
113
|
+
* voice for a size. `input` is composed, so left alone it crossed this
|
|
114
|
+
* shadow boundary and arrived looking like this element's, with no `change`
|
|
115
|
+
* after it, and a refused size still sent it.
|
|
116
|
+
*/
|
|
117
|
+
private readonly stopNative;
|
|
108
118
|
protected willUpdate(changed: PropertyValues): void;
|
|
109
119
|
/**
|
|
110
120
|
* The control itself, which is the whole of this part, behind a seam the styled tier can move.
|
|
@@ -29,6 +29,8 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
|
|
|
29
29
|
const previous = this.value;
|
|
30
30
|
this.valueState = size;
|
|
31
31
|
this.requestUpdate('value', previous);
|
|
32
|
+
this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
33
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
|
|
32
34
|
},
|
|
33
35
|
event: (size) => new HelixBeforeChangeEvent({ value: String(size) }),
|
|
34
36
|
host: this,
|
|
@@ -41,6 +43,9 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
|
|
|
41
43
|
}
|
|
42
44
|
});
|
|
43
45
|
};
|
|
46
|
+
this.stopNative = (event) => {
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
};
|
|
44
49
|
}
|
|
45
50
|
get value() {
|
|
46
51
|
return this.valueState ?? this.defaultValue;
|
|
@@ -83,6 +88,8 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
|
|
|
83
88
|
label=${this.label}
|
|
84
89
|
.value=${String(this.current)}
|
|
85
90
|
@helix-before-change=${this.handleChange}
|
|
91
|
+
@input=${this.stopNative}
|
|
92
|
+
@change=${this.stopNative}
|
|
86
93
|
>
|
|
87
94
|
${this.options.map((size) => html `<${option}
|
|
88
95
|
part="option"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a `format` puts separators in a row of boxes: for each box, the text
|
|
3
|
+
* drawn after it, or nothing. `#` and `*` stand for a box and anything else is
|
|
4
|
+
* drawn, so `###-###` puts a dash after the third box. Web Awesome's OTP input
|
|
5
|
+
* takes the same shape.
|
|
6
|
+
*/
|
|
7
|
+
export declare const separatorsAfter: (format: string, count: number) => string[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const separatorsAfter = (format, count) => {
|
|
2
|
+
const after = Array.from({ length: count }, () => '');
|
|
3
|
+
let box = -1;
|
|
4
|
+
for (const character of format) {
|
|
5
|
+
if (character === '#' || character === '*') {
|
|
6
|
+
box += 1;
|
|
7
|
+
if (box >= count) {
|
|
8
|
+
break;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
else if (box >= 0 && box < count - 1) {
|
|
12
|
+
after[box] += character;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return after;
|
|
16
|
+
};
|
|
@@ -22,6 +22,12 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
22
22
|
* Only the first cell has `autocomplete="one-time-code"`, because the hint
|
|
23
23
|
* applies to the whole field.
|
|
24
24
|
*
|
|
25
|
+
* `autosubmit` submits the form once the last box is filled, through the form's
|
|
26
|
+
* default button where there is one. `format` draws separators between the
|
|
27
|
+
* boxes, such as the dash in `###-###`, as text a screen reader skips. Delete
|
|
28
|
+
* removes the character in the focused box and pulls the rest of the code
|
|
29
|
+
* back, as Backspace removes the one before it.
|
|
30
|
+
*
|
|
25
31
|
* The row of cells always runs left to right, with `dir="ltr"`, including in
|
|
26
32
|
* Arabic and Hebrew. The first box is the leftmost, a paste fills to the right,
|
|
27
33
|
* and the right arrow moves to the next box. The label, hint, and feedback
|
|
@@ -33,6 +39,10 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
33
39
|
* @aliases PinField, OTP, One-time code, Verification code, InputPin
|
|
34
40
|
* @documentation https://fusion.dev/helix/components/pin-input
|
|
35
41
|
*
|
|
42
|
+
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
43
|
+
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
44
|
+
* @slot label - The label, for content richer than the `label` text.
|
|
45
|
+
*
|
|
36
46
|
* @event {Event} change - The code was filled, or an edited code lost focus.
|
|
37
47
|
* @event {HelixBeforeChangeEvent} helix-before-change - The code is about to change. Cancelable.
|
|
38
48
|
* @event {HelixCompleteEvent} helix-complete - The last box was filled.
|
|
@@ -43,11 +53,14 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
43
53
|
* @csspart field - The row of boxes, ordered left to right in every language.
|
|
44
54
|
* @csspart hint - The help under the boxes, shown while there is no feedback.
|
|
45
55
|
* @csspart label - The label above the boxes.
|
|
56
|
+
* @csspart separator - The text `format` draws between two boxes.
|
|
46
57
|
*
|
|
47
58
|
* @cssstate invalid - The control has an error to show, from the browser's validation or from your `feedback`.
|
|
48
59
|
*/
|
|
49
60
|
export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
50
61
|
protected readonly aria: AriaForwardController;
|
|
62
|
+
/** @internal The element a missing name is checked on: the row of cells, so the name of one cell does not count as the name of the field. */
|
|
63
|
+
protected get namedControl(): HTMLElement | null;
|
|
51
64
|
/** Typed or dragged, so every edit is announced. See `announcesInput`. */
|
|
52
65
|
protected readonly announcesInput = true;
|
|
53
66
|
/**
|
|
@@ -59,10 +72,22 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
59
72
|
* the same code is one offer made six times.
|
|
60
73
|
*/
|
|
61
74
|
autocomplete: string;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the form is submitted once the last box is filled, as Web
|
|
77
|
+
* Awesome's `autosubmit` and Radix's `autoSubmit`. Only for a code the field
|
|
78
|
+
* took: a refused last character submits nothing.
|
|
79
|
+
*/
|
|
80
|
+
autosubmit: boolean;
|
|
62
81
|
/**
|
|
63
82
|
* Accessible name for one box, with `{index}` and `{length}` filled in.
|
|
64
83
|
*/
|
|
65
84
|
cellLabel: string;
|
|
85
|
+
/**
|
|
86
|
+
* Separators drawn between the boxes: `#` or `*` for a box and anything
|
|
87
|
+
* else as it is written, so `###-###` draws a dash after the third. The
|
|
88
|
+
* separators are hidden from screen readers and are not part of the value.
|
|
89
|
+
*/
|
|
90
|
+
format: string;
|
|
66
91
|
/**
|
|
67
92
|
* How many characters the code has.
|
|
68
93
|
*/
|
|
@@ -150,6 +175,9 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
150
175
|
* Backspace in an empty box goes back and clears the one it lands in, which
|
|
151
176
|
* is what makes a code correctable without the reader hunting for the box
|
|
152
177
|
* they meant. In a full box it does what it always does and is left alone.
|
|
178
|
+
*
|
|
179
|
+
* Home goes to the first box and End to the end of the code, the box after
|
|
180
|
+
* its last character, which is where the caret goes in a single text field.
|
|
153
181
|
*/
|
|
154
182
|
private readonly handleKeydown;
|
|
155
183
|
/**
|
|
@@ -272,6 +300,15 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
272
300
|
clear(): void;
|
|
273
301
|
protected firstUpdated(changed: PropertyValues): void;
|
|
274
302
|
protected updated(changed: PropertyValues): void;
|
|
303
|
+
/**
|
|
304
|
+
* Enter submits the form, as it does in a native text field.
|
|
305
|
+
*
|
|
306
|
+
* On `keypress`, where the platform runs its own implicit submission, so a
|
|
307
|
+
* consumer who prevents the `keydown` for Enter stops this too.
|
|
308
|
+
*/
|
|
309
|
+
private readonly handleKeypress;
|
|
310
|
+
/** @internal A single line of text counts against implicit submission. */
|
|
311
|
+
protected get blocksImplicitSubmission(): boolean;
|
|
275
312
|
protected render(): TemplateResult;
|
|
276
313
|
}
|
|
277
314
|
declare global {
|
|
@@ -7,15 +7,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { AriaForwardController, customElement, fillTemplate, HelixCompleteEvent, HelixFormElement, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
import { separatorsAfter } from '../format.js';
|
|
10
11
|
let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerValue(MixinField(HelixFormElement)) {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
13
14
|
this.aria = new AriaForwardController(this, {
|
|
14
|
-
target: () => this.partNamed('
|
|
15
|
+
target: () => this.partNamed('field'),
|
|
15
16
|
});
|
|
16
17
|
this.announcesInput = true;
|
|
17
18
|
this.autocomplete = 'one-time-code';
|
|
19
|
+
this.autosubmit = false;
|
|
18
20
|
this.cellLabel = 'Character {index} of {length}';
|
|
21
|
+
this.format = '';
|
|
19
22
|
this.length = 6;
|
|
20
23
|
this.mask = false;
|
|
21
24
|
this.placeholder = '';
|
|
@@ -44,7 +47,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
44
47
|
this.handlePaste = (event) => {
|
|
45
48
|
const cell = event.target;
|
|
46
49
|
const at = this.cells.indexOf(cell);
|
|
47
|
-
if (at === -1) {
|
|
50
|
+
if (at === -1 || this.isDisabled || this.readOnly) {
|
|
48
51
|
return;
|
|
49
52
|
}
|
|
50
53
|
event.preventDefault();
|
|
@@ -56,8 +59,22 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
56
59
|
if (at === -1 || this.isDisabled || this.readOnly) {
|
|
57
60
|
return;
|
|
58
61
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
62
|
+
const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
|
|
63
|
+
const to = event.key === 'Home'
|
|
64
|
+
? 0
|
|
65
|
+
: event.key === 'End'
|
|
66
|
+
? Math.min(this.value.length, this.count - 1)
|
|
67
|
+
: at + step;
|
|
68
|
+
if (event.key === 'Delete' && at < this.value.length) {
|
|
69
|
+
const characters = this.characters;
|
|
70
|
+
characters.splice(at, 1);
|
|
71
|
+
this.requestValue(characters.join('').replace(/\s+$/, ''));
|
|
72
|
+
this.updateComplete.then(() => {
|
|
73
|
+
this.paint();
|
|
74
|
+
this.cells[at]?.focus();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if (event.key === 'Backspace' && cell.value === '' && at > 0) {
|
|
61
78
|
const characters = this.characters;
|
|
62
79
|
characters[at - 1] = '';
|
|
63
80
|
this.requestValue(characters.join('').replace(/\s+$/, ''));
|
|
@@ -95,6 +112,14 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
95
112
|
this.within = false;
|
|
96
113
|
this.commit();
|
|
97
114
|
};
|
|
115
|
+
this.handleKeypress = (event) => {
|
|
116
|
+
if (event.key === 'Enter' && !event.defaultPrevented) {
|
|
117
|
+
this.submitImplicitly();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
get namedControl() {
|
|
122
|
+
return this.partNamed('field');
|
|
98
123
|
}
|
|
99
124
|
static { this.shadowRootOptions = {
|
|
100
125
|
...HelixFormElement.shadowRootOptions,
|
|
@@ -131,14 +156,17 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
131
156
|
}
|
|
132
157
|
const next = characters.join('');
|
|
133
158
|
const filled = Math.min(this.count - 1, start + cleaned.length);
|
|
134
|
-
this.requestValue(next);
|
|
159
|
+
const applied = this.requestValue(next);
|
|
135
160
|
this.updateComplete.then(() => {
|
|
136
161
|
this.paint();
|
|
137
162
|
this.cells[filled]?.focus();
|
|
138
163
|
this.cells[filled]?.select();
|
|
139
|
-
if (next.length === this.count) {
|
|
164
|
+
if (applied && this.value === next && next.length === this.count) {
|
|
140
165
|
this.dispatchEvent(new HelixCompleteEvent({ value: next }));
|
|
141
166
|
this.commit();
|
|
167
|
+
if (this.autosubmit) {
|
|
168
|
+
this.submitImplicitly();
|
|
169
|
+
}
|
|
142
170
|
}
|
|
143
171
|
});
|
|
144
172
|
}
|
|
@@ -198,8 +226,12 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
198
226
|
this.paint();
|
|
199
227
|
this.sync();
|
|
200
228
|
}
|
|
229
|
+
get blocksImplicitSubmission() {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
201
232
|
render() {
|
|
202
233
|
const characters = this.characters;
|
|
234
|
+
const separators = separatorsAfter(this.format, this.count);
|
|
203
235
|
return html `${this.renderGroupLabel()}
|
|
204
236
|
<div
|
|
205
237
|
dir="ltr"
|
|
@@ -224,8 +256,11 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
224
256
|
@focus=${this.handleFocus}
|
|
225
257
|
@input=${this.handleInput}
|
|
226
258
|
@keydown=${this.handleKeydown}
|
|
259
|
+
@keypress=${this.handleKeypress}
|
|
227
260
|
@paste=${this.handlePaste}
|
|
228
|
-
|
|
261
|
+
/>${separators[at]
|
|
262
|
+
? html `<span part="separator" aria-hidden="true">${separators[at]}</span>`
|
|
263
|
+
: nothing}`)}
|
|
229
264
|
</div>
|
|
230
265
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
231
266
|
}
|
|
@@ -233,9 +268,15 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
233
268
|
__decorate([
|
|
234
269
|
property()
|
|
235
270
|
], HelixHeadlessPinInput.prototype, "autocomplete", void 0);
|
|
271
|
+
__decorate([
|
|
272
|
+
property({ type: Boolean })
|
|
273
|
+
], HelixHeadlessPinInput.prototype, "autosubmit", void 0);
|
|
236
274
|
__decorate([
|
|
237
275
|
property({ attribute: 'cell-label' })
|
|
238
276
|
], HelixHeadlessPinInput.prototype, "cellLabel", void 0);
|
|
277
|
+
__decorate([
|
|
278
|
+
property()
|
|
279
|
+
], HelixHeadlessPinInput.prototype, "format", void 0);
|
|
239
280
|
__decorate([
|
|
240
281
|
property({ type: Number })
|
|
241
282
|
], HelixHeadlessPinInput.prototype, "length", void 0);
|