@fusion.dev/helix-headless 0.142.0 → 0.143.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 +16710 -707
- 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.js +16 -5
- 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 +3 -1
- package/dist/avatar/root/avatar-root.js +8 -1
- package/dist/badge/root/badge-root.d.ts +8 -0
- package/dist/bar-chart/root/bar-chart-root.d.ts +19 -3
- package/dist/bar-chart/root/bar-chart-root.js +43 -13
- 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 +37 -0
- package/dist/button/root/button-root.js +44 -0
- package/dist/callout/root/callout-root.d.ts +14 -5
- package/dist/callout/root/callout-root.js +11 -3
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- 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 +7 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +65 -32
- package/dist/checkbox-group/root/checkbox-group-root.js +85 -37
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/root/code-block-root.d.ts +19 -0
- package/dist/code-block/root/code-block-root.js +21 -1
- package/dist/color-input/root/color-input-root.d.ts +26 -1
- package/dist/color-input/root/color-input-root.js +32 -3
- package/dist/color-picker/root/color-picker-root.d.ts +37 -7
- package/dist/color-picker/root/color-picker-root.js +83 -6
- package/dist/combobox/root/combobox-root.d.ts +90 -2
- package/dist/combobox/root/combobox-root.js +160 -19
- package/dist/command/root/command-root.d.ts +17 -6
- package/dist/command/root/command-root.js +12 -1
- package/dist/copy-button/root/copy-button-root.d.ts +21 -6
- package/dist/copy-button/root/copy-button-root.js +11 -1
- 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 +53 -8
- package/dist/date-input/root/date-input-root.js +70 -18
- package/dist/date-picker/root/date-picker-root.d.ts +84 -17
- package/dist/date-picker/root/date-picker-root.js +125 -20
- package/dist/dialog/root/dialog-root.d.ts +38 -10
- package/dist/dialog/root/dialog-root.js +55 -2
- package/dist/donut-chart/root/donut-chart-root.d.ts +39 -15
- package/dist/donut-chart/root/donut-chart-root.js +30 -10
- package/dist/drawer/root/drawer-root.d.ts +32 -7
- package/dist/drawer/root/drawer-root.js +50 -5
- 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 +35 -9
- package/dist/file-input/root/file-input-root.d.ts +18 -1
- package/dist/file-input/root/file-input-root.js +34 -8
- 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 +5 -2
- package/dist/filter-input/root/filter-input-root.js +22 -7
- package/dist/format-date/root/format-date-root.d.ts +11 -3
- package/dist/format-date/root/format-date-root.js +26 -5
- 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 +27 -6
- package/dist/heatmap/root/heatmap-root.js +23 -6
- package/dist/icon/root/icon-root.d.ts +24 -3
- package/dist/icon/root/icon-root.js +34 -1
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +9 -2
- package/dist/image/root/image-root.js +8 -2
- package/dist/input/root/input-root.d.ts +51 -9
- package/dist/input/root/input-root.js +46 -5
- package/dist/kbd/root/kbd-root.d.ts +12 -4
- package/dist/kbd/root/kbd-root.js +10 -11
- package/dist/legend/root/legend-root.d.ts +7 -0
- package/dist/legend/root/legend-root.js +7 -2
- package/dist/lightbox/item/lightbox-item.d.ts +2 -1
- package/dist/lightbox/root/lightbox-root.d.ts +16 -5
- package/dist/lightbox/root/lightbox-root.js +24 -3
- package/dist/line-chart/root/line-chart-root.d.ts +19 -2
- package/dist/line-chart/root/line-chart-root.js +40 -13
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/root/listbox-root.d.ts +111 -2
- package/dist/listbox/root/listbox-root.js +144 -16
- 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 +6 -0
- package/dist/meter/root/meter-root.js +18 -2
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +12 -0
- package/dist/notifications/notification/notification.js +31 -2
- package/dist/notifications/root/notifications-root.d.ts +7 -0
- package/dist/notifications/root/notifications-root.js +17 -2
- package/dist/number-input/root/number-input-root.d.ts +62 -7
- package/dist/number-input/root/number-input-root.js +68 -16
- package/dist/object-inspector/root/object-inspector-root.d.ts +48 -5
- package/dist/object-inspector/root/object-inspector-root.js +91 -11
- package/dist/option/root/option-root.d.ts +4 -1
- package/dist/option/root/option-root.js +1 -0
- 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/root/pin-input-root.d.ts +16 -0
- package/dist/pin-input/root/pin-input-root.js +19 -5
- package/dist/popover/root/popover-root.d.ts +19 -2
- package/dist/popover/root/popover-root.js +22 -1
- package/dist/progress/root/progress-root.d.ts +16 -1
- package/dist/progress/root/progress-root.js +31 -7
- package/dist/qr-code/root/qr-code-root.d.ts +19 -0
- package/dist/qr-code/root/qr-code-root.js +29 -1
- package/dist/radio/group/radio-group.d.ts +41 -0
- package/dist/radio/group/radio-group.js +50 -14
- 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 +24 -1
- package/dist/rating/root/rating-root.js +24 -7
- package/dist/scatter-chart/root/scatter-chart-root.js +15 -7
- package/dist/select/root/select-root.d.ts +69 -3
- package/dist/select/root/select-root.js +92 -8
- package/dist/skeleton/root/skeleton-root.d.ts +14 -3
- package/dist/skeleton/root/skeleton-root.js +17 -3
- 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 +20 -2
- package/dist/slider/root/slider-root.js +41 -3
- 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 +7 -1
- package/dist/stat/root/stat-root.js +14 -1
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/switch/root/switch-root.d.ts +2 -0
- package/dist/switch/root/switch-root.js +1 -0
- 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/root/tag-root.d.ts +23 -1
- package/dist/tag/root/tag-root.js +16 -2
- package/dist/textarea/root/textarea-root.d.ts +4 -0
- package/dist/textarea/root/textarea-root.js +1 -1
- package/dist/time-input/root/time-input-root.d.ts +28 -2
- package/dist/time-input/root/time-input-root.js +46 -10
- package/dist/time-picker/root/time-picker-root.d.ts +101 -18
- package/dist/time-picker/root/time-picker-root.js +115 -16
- package/dist/toast/root/toast-root.d.ts +64 -1
- package/dist/toast/root/toast-root.js +147 -2
- package/dist/toggle/group/toggle-group.d.ts +38 -1
- package/dist/toggle/group/toggle-group.js +34 -8
- package/dist/toggle/root/toggle-root.d.ts +14 -10
- package/dist/toggle/root/toggle-root.js +3 -3
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/root/tooltip-root.d.ts +37 -4
- package/dist/tooltip/root/tooltip-root.js +48 -0
- package/dist/tour/root/tour-root.d.ts +34 -5
- package/dist/tour/root/tour-root.js +51 -14
- package/dist/tour/stop/tour-stop.d.ts +18 -1
- package/dist/tour/stop/tour-stop.js +25 -5
- 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 +23 -1
- package/dist/trend/root/trend-root.js +28 -7
- 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 +4348 -965
- package/types/vue.d.ts +972 -232
|
@@ -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"
|
|
@@ -33,6 +33,10 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
33
33
|
* @aliases PinField, OTP, One-time code, Verification code, InputPin
|
|
34
34
|
* @documentation https://fusion.dev/helix/components/pin-input
|
|
35
35
|
*
|
|
36
|
+
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
37
|
+
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
38
|
+
* @slot label - The label, for content richer than the `label` text.
|
|
39
|
+
*
|
|
36
40
|
* @event {Event} change - The code was filled, or an edited code lost focus.
|
|
37
41
|
* @event {HelixBeforeChangeEvent} helix-before-change - The code is about to change. Cancelable.
|
|
38
42
|
* @event {HelixCompleteEvent} helix-complete - The last box was filled.
|
|
@@ -150,6 +154,9 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
150
154
|
* Backspace in an empty box goes back and clears the one it lands in, which
|
|
151
155
|
* is what makes a code correctable without the reader hunting for the box
|
|
152
156
|
* they meant. In a full box it does what it always does and is left alone.
|
|
157
|
+
*
|
|
158
|
+
* Home goes to the first box and End to the end of the code, the box after
|
|
159
|
+
* its last character, which is where the caret goes in a single text field.
|
|
153
160
|
*/
|
|
154
161
|
private readonly handleKeydown;
|
|
155
162
|
/**
|
|
@@ -272,6 +279,15 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
272
279
|
clear(): void;
|
|
273
280
|
protected firstUpdated(changed: PropertyValues): void;
|
|
274
281
|
protected updated(changed: PropertyValues): void;
|
|
282
|
+
/**
|
|
283
|
+
* Enter submits the form, as it does in a native text field.
|
|
284
|
+
*
|
|
285
|
+
* On `keypress`, where the platform runs its own implicit submission, so a
|
|
286
|
+
* consumer who prevents the `keydown` for Enter stops this too.
|
|
287
|
+
*/
|
|
288
|
+
private readonly handleKeypress;
|
|
289
|
+
/** @internal A single line of text counts against implicit submission. */
|
|
290
|
+
protected get blocksImplicitSubmission(): boolean;
|
|
275
291
|
protected render(): TemplateResult;
|
|
276
292
|
}
|
|
277
293
|
declare global {
|
|
@@ -11,7 +11,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.aria = new AriaForwardController(this, {
|
|
14
|
-
target: () => this.partNamed('
|
|
14
|
+
target: () => this.partNamed('field'),
|
|
15
15
|
});
|
|
16
16
|
this.announcesInput = true;
|
|
17
17
|
this.autocomplete = 'one-time-code';
|
|
@@ -44,7 +44,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
44
44
|
this.handlePaste = (event) => {
|
|
45
45
|
const cell = event.target;
|
|
46
46
|
const at = this.cells.indexOf(cell);
|
|
47
|
-
if (at === -1) {
|
|
47
|
+
if (at === -1 || this.isDisabled || this.readOnly) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
event.preventDefault();
|
|
@@ -56,7 +56,12 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
56
56
|
if (at === -1 || this.isDisabled || this.readOnly) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
|
-
const
|
|
59
|
+
const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
|
|
60
|
+
const to = event.key === 'Home'
|
|
61
|
+
? 0
|
|
62
|
+
: event.key === 'End'
|
|
63
|
+
? Math.min(this.value.length, this.count - 1)
|
|
64
|
+
: at + step;
|
|
60
65
|
if (event.key === 'Backspace' && cell.value === '' && at > 0) {
|
|
61
66
|
const characters = this.characters;
|
|
62
67
|
characters[at - 1] = '';
|
|
@@ -95,6 +100,11 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
95
100
|
this.within = false;
|
|
96
101
|
this.commit();
|
|
97
102
|
};
|
|
103
|
+
this.handleKeypress = (event) => {
|
|
104
|
+
if (event.key === 'Enter' && !event.defaultPrevented) {
|
|
105
|
+
this.submitImplicitly();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
98
108
|
}
|
|
99
109
|
static { this.shadowRootOptions = {
|
|
100
110
|
...HelixFormElement.shadowRootOptions,
|
|
@@ -131,12 +141,12 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
131
141
|
}
|
|
132
142
|
const next = characters.join('');
|
|
133
143
|
const filled = Math.min(this.count - 1, start + cleaned.length);
|
|
134
|
-
this.requestValue(next);
|
|
144
|
+
const applied = this.requestValue(next);
|
|
135
145
|
this.updateComplete.then(() => {
|
|
136
146
|
this.paint();
|
|
137
147
|
this.cells[filled]?.focus();
|
|
138
148
|
this.cells[filled]?.select();
|
|
139
|
-
if (next.length === this.count) {
|
|
149
|
+
if (applied && this.value === next && next.length === this.count) {
|
|
140
150
|
this.dispatchEvent(new HelixCompleteEvent({ value: next }));
|
|
141
151
|
this.commit();
|
|
142
152
|
}
|
|
@@ -198,6 +208,9 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
198
208
|
this.paint();
|
|
199
209
|
this.sync();
|
|
200
210
|
}
|
|
211
|
+
get blocksImplicitSubmission() {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
201
214
|
render() {
|
|
202
215
|
const characters = this.characters;
|
|
203
216
|
return html `${this.renderGroupLabel()}
|
|
@@ -224,6 +237,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
|
|
|
224
237
|
@focus=${this.handleFocus}
|
|
225
238
|
@input=${this.handleInput}
|
|
226
239
|
@keydown=${this.handleKeydown}
|
|
240
|
+
@keypress=${this.handleKeypress}
|
|
227
241
|
@paste=${this.handlePaste}
|
|
228
242
|
/>`)}
|
|
229
243
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CommandController, HelixElement, type Placement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, CommandController, HelixElement, type Placement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
|
|
4
4
|
/**
|
|
@@ -21,6 +21,10 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
|
|
|
21
21
|
* commands work as they do on `Dialog` and `Drawer`, so a button anywhere on
|
|
22
22
|
* the page can open the popover with no script.
|
|
23
23
|
*
|
|
24
|
+
* It closes on Escape, on a press outside it, and when focus moves out of the
|
|
25
|
+
* trigger and the panel to somewhere else on the page. It does not trap focus.
|
|
26
|
+
* An `aria-labelledby` on the host names the panel in place of `label`.
|
|
27
|
+
*
|
|
24
28
|
* @since 0.1.0
|
|
25
29
|
* @status stable
|
|
26
30
|
* @category overlays
|
|
@@ -32,7 +36,7 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
|
|
|
32
36
|
*
|
|
33
37
|
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before it closes, and cancelable.
|
|
34
38
|
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before it opens, and cancelable.
|
|
35
|
-
* @event {
|
|
39
|
+
* @event {ToggleEvent} toggle - Fired after the panel opens or closes, with `newState` and `oldState`.
|
|
36
40
|
*
|
|
37
41
|
* @csspart content - The scrolling region inside the panel.
|
|
38
42
|
* @csspart popover - The panel.
|
|
@@ -44,6 +48,7 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
|
|
|
44
48
|
* The panel's name, read by screen readers.
|
|
45
49
|
*/
|
|
46
50
|
label: string;
|
|
51
|
+
protected readonly aria: AriaForwardController;
|
|
47
52
|
/**
|
|
48
53
|
* Space between the trigger and the panel, in pixels.
|
|
49
54
|
*/
|
|
@@ -75,6 +80,18 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
|
|
|
75
80
|
show(): void;
|
|
76
81
|
/** Closes the panel and puts focus back on the trigger. */
|
|
77
82
|
hide(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Focus leaving the control closes the panel.
|
|
85
|
+
*
|
|
86
|
+
* A popover does not trap focus, so `Tab` past its last control walks on
|
|
87
|
+
* into the page, and a panel left open there covers what the reader moved
|
|
88
|
+
* to. Focus moving between the trigger, the panel and a command's invoker
|
|
89
|
+
* stays inside the control. With no `relatedTarget`, focus left the
|
|
90
|
+
* document or went nowhere, and a press outside is already its own signal.
|
|
91
|
+
*/
|
|
92
|
+
private readonly handleFocusOut;
|
|
93
|
+
connectedCallback(): void;
|
|
94
|
+
disconnectedCallback(): void;
|
|
78
95
|
private readonly handleTriggerClick;
|
|
79
96
|
/** Tells a slotted trigger the disclosure state, by property. See `tellDisclosure`. */
|
|
80
97
|
private tellTrigger;
|
|
@@ -4,13 +4,16 @@ 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 { anchorElement, CommandController, customElement, deepActiveElement, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorElement, CommandController, customElement, deepActiveElement, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpen(HelixElement) {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.label = 'Popover';
|
|
14
|
+
this.aria = new AriaForwardController(this, {
|
|
15
|
+
target: () => this.partNamed('popover'),
|
|
16
|
+
});
|
|
14
17
|
this.offset = 4;
|
|
15
18
|
this.placement = 'bottom-start';
|
|
16
19
|
this.panel = new PopoverController(this, {
|
|
@@ -40,6 +43,16 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
|
|
|
40
43
|
},
|
|
41
44
|
},
|
|
42
45
|
});
|
|
46
|
+
this.handleFocusOut = (event) => {
|
|
47
|
+
const next = event.relatedTarget;
|
|
48
|
+
if (!this.open || !(next instanceof Node)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (this.contains(next) || this.renderRoot.contains(next) || this.invoker?.contains(next)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.hide();
|
|
55
|
+
};
|
|
43
56
|
this.handleTriggerClick = () => {
|
|
44
57
|
if (this.open) {
|
|
45
58
|
this.hide();
|
|
@@ -67,6 +80,14 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
|
|
|
67
80
|
this.trigger.focus();
|
|
68
81
|
}
|
|
69
82
|
}
|
|
83
|
+
connectedCallback() {
|
|
84
|
+
super.connectedCallback();
|
|
85
|
+
this.addEventListener('focusout', this.handleFocusOut);
|
|
86
|
+
}
|
|
87
|
+
disconnectedCallback() {
|
|
88
|
+
super.disconnectedCallback();
|
|
89
|
+
this.removeEventListener('focusout', this.handleFocusOut);
|
|
90
|
+
}
|
|
70
91
|
tellTrigger() {
|
|
71
92
|
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
72
93
|
tellDisclosure(slot?.assignedElements({ flatten: false })[0], this.open);
|
|
@@ -48,10 +48,23 @@ export declare class HelixHeadlessProgress extends HelixElement {
|
|
|
48
48
|
* Accessible name for what is in progress.
|
|
49
49
|
*/
|
|
50
50
|
label: string;
|
|
51
|
+
/**
|
|
52
|
+
* The locale the percentage is written in, such as `fr` for `72 %`.
|
|
53
|
+
*
|
|
54
|
+
* Absent uses the runtime's own.
|
|
55
|
+
*/
|
|
56
|
+
locale: string;
|
|
51
57
|
/**
|
|
52
58
|
* The total the work is measured against.
|
|
53
59
|
*/
|
|
54
60
|
max: number;
|
|
61
|
+
/**
|
|
62
|
+
* Where the work starts, in the same units as `max`. Defaults to zero.
|
|
63
|
+
*
|
|
64
|
+
* For a measure that does not start at nothing, such as a migration from
|
|
65
|
+
* version 12 to version 20, where 12 is the empty bar.
|
|
66
|
+
*/
|
|
67
|
+
min: number;
|
|
55
68
|
/**
|
|
56
69
|
* Whether the value is drawn as a bar or as a ring.
|
|
57
70
|
*
|
|
@@ -82,7 +95,7 @@ export declare class HelixHeadlessProgress extends HelixElement {
|
|
|
82
95
|
/**
|
|
83
96
|
* What has been done so far, in the same units as `max`.
|
|
84
97
|
*
|
|
85
|
-
* Clamped between
|
|
98
|
+
* Clamped between `min` and `max` for both the fill and the announcement, so
|
|
86
99
|
* the two can never disagree about what is on screen.
|
|
87
100
|
*/
|
|
88
101
|
value: number;
|
|
@@ -96,6 +109,8 @@ export declare class HelixHeadlessProgress extends HelixElement {
|
|
|
96
109
|
* report progress.
|
|
97
110
|
*/
|
|
98
111
|
valueText: string;
|
|
112
|
+
/** The range the value is measured in, with a top above its bottom. */
|
|
113
|
+
private get range();
|
|
99
114
|
/** What is done, as a fraction of the whole, between 0 and 1. */
|
|
100
115
|
get fraction(): number;
|
|
101
116
|
protected willUpdate(changed: PropertyValues): void;
|
|
@@ -7,29 +7,47 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
const percents = new Map();
|
|
11
|
+
const percent = (share, locale) => {
|
|
12
|
+
let format = percents.get(locale);
|
|
13
|
+
if (!format) {
|
|
14
|
+
format = new Intl.NumberFormat(locale || undefined, {
|
|
15
|
+
maximumFractionDigits: 0,
|
|
16
|
+
style: 'percent',
|
|
17
|
+
});
|
|
18
|
+
percents.set(locale, format);
|
|
19
|
+
}
|
|
20
|
+
return format.format(share);
|
|
21
|
+
};
|
|
10
22
|
let HelixHeadlessProgress = class HelixHeadlessProgress extends HelixElement {
|
|
11
23
|
constructor() {
|
|
12
24
|
super(...arguments);
|
|
13
25
|
this.indeterminate = false;
|
|
14
26
|
this.label = 'Progress';
|
|
27
|
+
this.locale = '';
|
|
15
28
|
this.max = 100;
|
|
29
|
+
this.min = 0;
|
|
16
30
|
this.showValue = false;
|
|
17
31
|
this.value = 0;
|
|
18
32
|
this.valueText = '';
|
|
19
33
|
}
|
|
34
|
+
get range() {
|
|
35
|
+
const min = Number.isFinite(this.min) ? this.min : 0;
|
|
36
|
+
return { max: this.max > min ? this.max : min + 100, min };
|
|
37
|
+
}
|
|
20
38
|
get fraction() {
|
|
21
|
-
const
|
|
22
|
-
return Math.min(Math.max(this.value / max, 0), 1) || 0;
|
|
39
|
+
const { max, min } = this.range;
|
|
40
|
+
return Math.min(Math.max((this.value - min) / (max - min), 0), 1) || 0;
|
|
23
41
|
}
|
|
24
42
|
willUpdate(changed) {
|
|
25
43
|
super.willUpdate(changed);
|
|
26
44
|
hostAria(this.internals, { label: this.label, role: 'progressbar' });
|
|
27
|
-
|
|
28
|
-
this.internals.
|
|
29
|
-
|
|
45
|
+
const { max, min } = this.range;
|
|
46
|
+
this.internals.ariaValueMin = String(min);
|
|
47
|
+
this.internals.ariaValueMax = String(max);
|
|
30
48
|
this.internals.ariaValueNow = this.indeterminate
|
|
31
49
|
? null
|
|
32
|
-
: String(Math.min(Math.max(this.value ||
|
|
50
|
+
: String(Math.min(Math.max(this.value || min, min), max));
|
|
33
51
|
this.internals.ariaValueText = this.valueText || null;
|
|
34
52
|
}
|
|
35
53
|
render() {
|
|
@@ -45,7 +63,7 @@ let HelixHeadlessProgress = class HelixHeadlessProgress extends HelixElement {
|
|
|
45
63
|
</div>`}
|
|
46
64
|
${this.showValue && !this.indeterminate
|
|
47
65
|
? html `<span part="value" aria-hidden="true"
|
|
48
|
-
>${this.valueText ||
|
|
66
|
+
>${this.valueText || percent(this.fraction, this.locale)}</span
|
|
49
67
|
>`
|
|
50
68
|
: ''}`;
|
|
51
69
|
}
|
|
@@ -56,9 +74,15 @@ __decorate([
|
|
|
56
74
|
__decorate([
|
|
57
75
|
property()
|
|
58
76
|
], HelixHeadlessProgress.prototype, "label", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
property()
|
|
79
|
+
], HelixHeadlessProgress.prototype, "locale", void 0);
|
|
59
80
|
__decorate([
|
|
60
81
|
property({ type: Number })
|
|
61
82
|
], HelixHeadlessProgress.prototype, "max", void 0);
|
|
83
|
+
__decorate([
|
|
84
|
+
property({ type: Number })
|
|
85
|
+
], HelixHeadlessProgress.prototype, "min", void 0);
|
|
62
86
|
__decorate([
|
|
63
87
|
property({ reflect: true })
|
|
64
88
|
], HelixHeadlessProgress.prototype, "shape", void 0);
|
|
@@ -26,6 +26,10 @@ export type QrStyle = 'dots' | 'rounded' | 'square';
|
|
|
26
26
|
* the same mark makes the code unscannable. The default is `M`, and `H` when the
|
|
27
27
|
* `logo` slot is filled.
|
|
28
28
|
*
|
|
29
|
+
* A higher level holds fewer characters, so a value that fits at `M` can be too
|
|
30
|
+
* long once a logo raises the level to `H`. A value too long for the level
|
|
31
|
+
* draws no code, and the element fires `error`.
|
|
32
|
+
*
|
|
29
33
|
* @since 0.1.0
|
|
30
34
|
* @status stable
|
|
31
35
|
* @category media
|
|
@@ -34,6 +38,8 @@ export type QrStyle = 'dots' | 'rounded' | 'square';
|
|
|
34
38
|
*
|
|
35
39
|
* @slot logo - A logo for the center. A code with a logo scans only at a high correction level.
|
|
36
40
|
*
|
|
41
|
+
* @event {Event} error - The value is too long for a code at the correction level, so no code is drawn.
|
|
42
|
+
*
|
|
37
43
|
* @csspart code - The square code image.
|
|
38
44
|
* @csspart finders - The three corner squares, which can take their own color.
|
|
39
45
|
* @csspart logo - The box that holds the center logo.
|
|
@@ -84,6 +90,19 @@ export declare class HelixHeadlessQrCode extends HelixElement {
|
|
|
84
90
|
protected firstUpdated(changed: PropertyValues): void;
|
|
85
91
|
/** The level actually used, which the slot can raise. */
|
|
86
92
|
private get level();
|
|
93
|
+
/** The value and level that did not fit, so `error` fires once for each. */
|
|
94
|
+
private overflowed;
|
|
95
|
+
/**
|
|
96
|
+
* The code for the value at the level, or undefined where the value is too
|
|
97
|
+
* long for it.
|
|
98
|
+
*
|
|
99
|
+
* `encode` throws for a value past the level's capacity, and it threw inside
|
|
100
|
+
* the render: the update rejected and the last code stayed on screen. A
|
|
101
|
+
* logo raising the level to `H` was the easy way to get there, since `H`
|
|
102
|
+
* holds the fewest characters.
|
|
103
|
+
*/
|
|
104
|
+
private encoded;
|
|
105
|
+
protected updated(changed: PropertyValues): void;
|
|
87
106
|
private renderCode;
|
|
88
107
|
protected render(): TemplateResult;
|
|
89
108
|
}
|
|
@@ -65,6 +65,7 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
65
65
|
this.label = '';
|
|
66
66
|
this.value = '';
|
|
67
67
|
this.logo = false;
|
|
68
|
+
this.overflowed = '';
|
|
68
69
|
}
|
|
69
70
|
willUpdate(changed) {
|
|
70
71
|
super.willUpdate(changed);
|
|
@@ -79,11 +80,38 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
79
80
|
get level() {
|
|
80
81
|
return this.correction ?? (this.logo ? 'H' : 'M');
|
|
81
82
|
}
|
|
83
|
+
encoded() {
|
|
84
|
+
try {
|
|
85
|
+
return encode(this.value, { border: 0, ecc: this.level });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error instanceof RangeError) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
updated(changed) {
|
|
95
|
+
super.updated(changed);
|
|
96
|
+
const key = `${this.level}:${this.value}`;
|
|
97
|
+
if (this.value !== '' && this.encoded() === undefined) {
|
|
98
|
+
if (this.overflowed !== key) {
|
|
99
|
+
this.overflowed = key;
|
|
100
|
+
this.dispatchEvent(new Event('error', { bubbles: false, cancelable: false, composed: false }));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.overflowed = '';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
82
107
|
renderCode() {
|
|
83
108
|
if (this.value === '') {
|
|
84
109
|
return nothing;
|
|
85
110
|
}
|
|
86
|
-
const result =
|
|
111
|
+
const result = this.encoded();
|
|
112
|
+
if (result === undefined) {
|
|
113
|
+
return nothing;
|
|
114
|
+
}
|
|
87
115
|
const size = result.size;
|
|
88
116
|
const quiet = 4;
|
|
89
117
|
const box = size + quiet * 2;
|
|
@@ -29,6 +29,7 @@ declare const HelixHeadlessRadioGroup_base: (new (...args: any[]) => import("@fu
|
|
|
29
29
|
* @documentation https://fusion.dev/helix/components/radio
|
|
30
30
|
*
|
|
31
31
|
* @slot - The radios.
|
|
32
|
+
* @slot feedback - The error message, for content richer than a string. It shows while there is a message.
|
|
32
33
|
* @slot hint - The help text under the group, for content richer than a string.
|
|
33
34
|
* @slot label - The group's label, for a question that needs more than a string.
|
|
34
35
|
*
|
|
@@ -45,6 +46,18 @@ declare const HelixHeadlessRadioGroup_base: (new (...args: any[]) => import("@fu
|
|
|
45
46
|
* @cssstate invalid - The group has an error to show, from the browser's validation or from your `feedback`.
|
|
46
47
|
*/
|
|
47
48
|
export declare class HelixHeadlessRadioGroup extends HelixHeadlessRadioGroup_base {
|
|
49
|
+
/**
|
|
50
|
+
* Whether the group holds a tab stop of its own.
|
|
51
|
+
*
|
|
52
|
+
* A toolbar is one tab stop, so a toolbar the group sits in sets this to
|
|
53
|
+
* `false` while its stop is on another control, and every radio, the chosen
|
|
54
|
+
* one too, is then out of the tab order. The arrow keys inside the group
|
|
55
|
+
* work as before once focus is in it.
|
|
56
|
+
*
|
|
57
|
+
* No attribute: it is coordination between elements, and a consumer has no
|
|
58
|
+
* reason to set it.
|
|
59
|
+
*/
|
|
60
|
+
focusable: boolean;
|
|
48
61
|
/**
|
|
49
62
|
* The direction the choices run. `vertical` puts one choice on each line.
|
|
50
63
|
*
|
|
@@ -76,8 +89,36 @@ export declare class HelixHeadlessRadioGroup extends HelixHeadlessRadioGroup_bas
|
|
|
76
89
|
* the item's is the one that was doing nothing.
|
|
77
90
|
*/
|
|
78
91
|
private readonly handleSelection;
|
|
92
|
+
/**
|
|
93
|
+
* The radio holding the answer, or nothing.
|
|
94
|
+
*
|
|
95
|
+
* Nothing where `value` names no radio here: a chosen radio that was removed
|
|
96
|
+
* is no longer an answer, as a native group drops it from the form. `value`
|
|
97
|
+
* keeps the name, so a value written before its radios arrive takes once they
|
|
98
|
+
* do.
|
|
99
|
+
*/
|
|
100
|
+
private get answer();
|
|
101
|
+
/** Whether the group holds an answer the form can submit. */
|
|
102
|
+
private get answered();
|
|
103
|
+
/**
|
|
104
|
+
* Takes the answer from a radio whose markup says `selected`, where nothing
|
|
105
|
+
* else declared one.
|
|
106
|
+
*
|
|
107
|
+
* As `Toggle.Group` does, so `<helix-radio selected>` preselects as
|
|
108
|
+
* `<option selected>` and `<helix-toggle selected>` do, and a reset returns
|
|
109
|
+
* to it. Client only: the server's element shim has no children to read.
|
|
110
|
+
*/
|
|
111
|
+
private adopt;
|
|
79
112
|
/** Writes the answer onto the items, and nothing onto the host. */
|
|
80
113
|
private place;
|
|
114
|
+
/** The radio that holds the group's tab stop: the answer, or the first that can be chosen. */
|
|
115
|
+
private entry;
|
|
116
|
+
/**
|
|
117
|
+
* Focus goes to the radio that holds the stop, and to the radio that would
|
|
118
|
+
* hold it while a toolbar holds the stop instead, so a label press or a
|
|
119
|
+
* refused submission still lands in the group.
|
|
120
|
+
*/
|
|
121
|
+
protected get focusTarget(): HTMLElement | null;
|
|
81
122
|
/** Reports the answer and the verdict on it. */
|
|
82
123
|
private sync;
|
|
83
124
|
connectedCallback(): void;
|