@fusion.dev/helix-headless 0.142.1 → 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
|
@@ -21,10 +21,12 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
21
21
|
this.autocomplete = '';
|
|
22
22
|
this.decrementLabel = 'Decrease';
|
|
23
23
|
this.incrementLabel = 'Increase';
|
|
24
|
+
this.locale = '';
|
|
24
25
|
this.placeholder = '';
|
|
25
26
|
this.readOnly = false;
|
|
26
27
|
this.scrub = false;
|
|
27
28
|
this.step = 1;
|
|
29
|
+
this.valueText = '';
|
|
28
30
|
this.scrubFrom = 0;
|
|
29
31
|
this.scrubValue = 0;
|
|
30
32
|
this.scrubStart = '';
|
|
@@ -75,16 +77,13 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
75
77
|
restoreValue(control, this.value);
|
|
76
78
|
};
|
|
77
79
|
this.handleBlur = () => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!control || parsed === null) {
|
|
81
|
-
return;
|
|
80
|
+
if (this.settle()) {
|
|
81
|
+
this.announceChange();
|
|
82
82
|
}
|
|
83
|
-
this.requestValue(String(this.clamp(parsed)));
|
|
84
|
-
restoreValue(control, this.value);
|
|
85
83
|
};
|
|
86
84
|
this.handleChange = (event) => {
|
|
87
85
|
event.stopPropagation();
|
|
86
|
+
this.settle();
|
|
88
87
|
this.announceChange();
|
|
89
88
|
};
|
|
90
89
|
this.handleKeydown = (event) => {
|
|
@@ -117,21 +116,32 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
117
116
|
}
|
|
118
117
|
event.preventDefault();
|
|
119
118
|
};
|
|
119
|
+
this.handleKeypress = (event) => {
|
|
120
|
+
if (event.key === 'Enter' && !event.defaultPrevented) {
|
|
121
|
+
this.submitImplicitly();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
120
124
|
}
|
|
121
|
-
static { this.shadowRootOptions = {
|
|
122
|
-
...HelixFormElement.shadowRootOptions,
|
|
123
|
-
delegatesFocus: true,
|
|
124
|
-
}; }
|
|
125
125
|
get control() {
|
|
126
126
|
return this.partNamed('control');
|
|
127
127
|
}
|
|
128
128
|
get numeric() {
|
|
129
|
-
|
|
129
|
+
const text = this.value.trim();
|
|
130
|
+
if (text === '') {
|
|
130
131
|
return null;
|
|
131
132
|
}
|
|
132
|
-
const
|
|
133
|
+
const read = decimalComma(this.locale) && text.includes(',') && !text.includes('.')
|
|
134
|
+
? text.replace(',', '.')
|
|
135
|
+
: text;
|
|
136
|
+
const parsed = read.includes(',') ? Number.NaN : Number(read);
|
|
133
137
|
return Number.isFinite(parsed) ? parsed : null;
|
|
134
138
|
}
|
|
139
|
+
onStep(value) {
|
|
140
|
+
const step = Math.abs(this.step) || 1;
|
|
141
|
+
const anchor = this.min ?? 0;
|
|
142
|
+
const steps = (value - anchor) / step;
|
|
143
|
+
return Math.abs(steps - Math.round(steps)) < 1e-9;
|
|
144
|
+
}
|
|
135
145
|
clamp(value) {
|
|
136
146
|
const step = Math.abs(this.step) || 1;
|
|
137
147
|
const anchor = this.min ?? 0;
|
|
@@ -168,13 +178,10 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
168
178
|
this.nudge(large ? -(this.largeStep ?? 10) : -1);
|
|
169
179
|
}
|
|
170
180
|
renderLabel() {
|
|
171
|
-
if (!this.scrub) {
|
|
181
|
+
if (!this.scrub || !this.labeled) {
|
|
172
182
|
return super.renderLabel();
|
|
173
183
|
}
|
|
174
184
|
const hidden = this.label === '' ? this.getAttribute('aria-label') : null;
|
|
175
|
-
if (this.label === '' && !hidden) {
|
|
176
|
-
return nothing;
|
|
177
|
-
}
|
|
178
185
|
return html `<label
|
|
179
186
|
part="label"
|
|
180
187
|
for=${this.controlId}
|
|
@@ -186,6 +193,17 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
186
193
|
><slot name="label">${this.label || hidden}</slot></label
|
|
187
194
|
>`;
|
|
188
195
|
}
|
|
196
|
+
settle() {
|
|
197
|
+
const control = this.control;
|
|
198
|
+
const parsed = this.numeric;
|
|
199
|
+
if (!control || parsed === null) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const before = this.value;
|
|
203
|
+
this.requestValue(String(this.clamp(parsed)));
|
|
204
|
+
restoreValue(control, this.value);
|
|
205
|
+
return this.value !== before;
|
|
206
|
+
}
|
|
189
207
|
sync() {
|
|
190
208
|
const control = this.control;
|
|
191
209
|
this.internals.setFormValue(this.value);
|
|
@@ -212,6 +230,14 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
212
230
|
max: this.max,
|
|
213
231
|
}), control);
|
|
214
232
|
}
|
|
233
|
+
else if (parsed !== null && !this.onStep(parsed)) {
|
|
234
|
+
const step = Math.abs(this.step) || 1;
|
|
235
|
+
const anchor = this.min ?? 0;
|
|
236
|
+
const below = this.clamp(anchor + Math.floor((parsed - anchor) / step) * step);
|
|
237
|
+
const above = this.clamp(anchor + Math.ceil((parsed - anchor) / step) * step);
|
|
238
|
+
this.internals.setValidity({ stepMismatch: true }, fillTemplate(this.stepMismatchMessage ||
|
|
239
|
+
'Please enter a valid value. The two nearest valid values are {below} and {above}.', { above, below }), control);
|
|
240
|
+
}
|
|
215
241
|
else {
|
|
216
242
|
this.internals.setValidity({}, '', control);
|
|
217
243
|
}
|
|
@@ -239,6 +265,9 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
239
265
|
this.releaseCaret = undefined;
|
|
240
266
|
this.sync();
|
|
241
267
|
}
|
|
268
|
+
get blocksImplicitSubmission() {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
242
271
|
render() {
|
|
243
272
|
const parsed = this.numeric;
|
|
244
273
|
const atMin = parsed !== null && this.min !== undefined && parsed <= this.min;
|
|
@@ -274,6 +303,9 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
274
303
|
aria-valuemin=${this.min ?? nothing}
|
|
275
304
|
aria-valuemax=${this.max ?? nothing}
|
|
276
305
|
aria-valuenow=${parsed ?? nothing}
|
|
306
|
+
aria-valuetext=${this.valueText && parsed !== null
|
|
307
|
+
? fillTemplate(this.valueText, { value: this.value })
|
|
308
|
+
: nothing}
|
|
277
309
|
?disabled=${this.isDisabled}
|
|
278
310
|
?readonly=${this.readOnly}
|
|
279
311
|
?required=${this.required}
|
|
@@ -281,6 +313,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
|
|
|
281
313
|
@change=${this.handleChange}
|
|
282
314
|
@input=${this.handleInput}
|
|
283
315
|
@keydown=${this.handleKeydown}
|
|
316
|
+
@keypress=${this.handleKeypress}
|
|
284
317
|
/>
|
|
285
318
|
<slot name="end"></slot>
|
|
286
319
|
<button
|
|
@@ -320,6 +353,9 @@ __decorate([
|
|
|
320
353
|
__decorate([
|
|
321
354
|
property({ attribute: 'large-step', type: Number })
|
|
322
355
|
], HelixHeadlessNumberInput.prototype, "largeStep", void 0);
|
|
356
|
+
__decorate([
|
|
357
|
+
property()
|
|
358
|
+
], HelixHeadlessNumberInput.prototype, "locale", void 0);
|
|
323
359
|
__decorate([
|
|
324
360
|
property({ type: Number })
|
|
325
361
|
], HelixHeadlessNumberInput.prototype, "max", void 0);
|
|
@@ -344,10 +380,26 @@ __decorate([
|
|
|
344
380
|
__decorate([
|
|
345
381
|
property({ type: Number })
|
|
346
382
|
], HelixHeadlessNumberInput.prototype, "step", void 0);
|
|
383
|
+
__decorate([
|
|
384
|
+
property({ attribute: 'step-mismatch-message' })
|
|
385
|
+
], HelixHeadlessNumberInput.prototype, "stepMismatchMessage", void 0);
|
|
386
|
+
__decorate([
|
|
387
|
+
property({ attribute: 'value-text' })
|
|
388
|
+
], HelixHeadlessNumberInput.prototype, "valueText", void 0);
|
|
347
389
|
HelixHeadlessNumberInput = __decorate([
|
|
348
390
|
customElement('helix-headless-number-input')
|
|
349
391
|
], HelixHeadlessNumberInput);
|
|
350
392
|
export { HelixHeadlessNumberInput };
|
|
393
|
+
const commas = new Map();
|
|
394
|
+
const decimalComma = (locale) => {
|
|
395
|
+
let comma = commas.get(locale);
|
|
396
|
+
if (comma === undefined) {
|
|
397
|
+
const parts = new Intl.NumberFormat(locale || undefined).formatToParts(1.5);
|
|
398
|
+
comma = parts.find((part) => part.type === 'decimal')?.value === ',';
|
|
399
|
+
commas.set(locale, comma);
|
|
400
|
+
}
|
|
401
|
+
return comma;
|
|
402
|
+
};
|
|
351
403
|
const decimals = (value) => {
|
|
352
404
|
const text = String(value);
|
|
353
405
|
const exponent = /e-(\d+)$/.exec(text);
|
|
@@ -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
|
import '../../copy-button/index.js';
|
|
4
4
|
/** One visible line of the tree: a value, where it sits, and whether it is open. */
|
|
@@ -28,9 +28,15 @@ interface Row {
|
|
|
28
28
|
*
|
|
29
29
|
* The tree is one tab stop. Up and Down move between rows, Right opens a branch
|
|
30
30
|
* or moves into it, Left closes it or moves to its parent, and Home and End
|
|
31
|
-
* move to the first and last rows.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* move to the first and last rows. Typing moves to the next row whose key
|
|
32
|
+
* starts with what was typed, and `*` opens every branch beside the active
|
|
33
|
+
* row. Focus stays on the tree, and `aria-activedescendant` marks the active
|
|
34
|
+
* row. Each row carries its real level, position, and set size, including in
|
|
35
|
+
* a windowed tree.
|
|
36
|
+
*
|
|
37
|
+
* A new `value` keeps the branches a reader opened or closed, and the active
|
|
38
|
+
* row, where the new value still has them. A branch the old value did not have
|
|
39
|
+
* opens to `default-depth`.
|
|
34
40
|
*
|
|
35
41
|
* The copy button copies the active row, a branch as JSON and a string as its
|
|
36
42
|
* text. So do Command+C and Control+C while the tree has focus and no text is
|
|
@@ -110,6 +116,14 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
110
116
|
* page's markup should not take the page down over a comma.
|
|
111
117
|
*/
|
|
112
118
|
for: string;
|
|
119
|
+
/** How an array of one entry counts it. `{count}` is replaced with the count. */
|
|
120
|
+
itemLabel: string;
|
|
121
|
+
/** How an array of any other number of entries counts them. `{count}` is replaced with the count. */
|
|
122
|
+
itemsLabel: string;
|
|
123
|
+
/** How an object of one key counts it. `{count}` is replaced with the count. */
|
|
124
|
+
keyLabel: string;
|
|
125
|
+
/** How an object of any other number of keys counts them. `{count}` is replaced with the count. */
|
|
126
|
+
keysLabel: string;
|
|
113
127
|
/**
|
|
114
128
|
* Accessible name for the tree, and the text of the header where there is one.
|
|
115
129
|
*/
|
|
@@ -128,6 +142,11 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
128
142
|
* reach a value.
|
|
129
143
|
*/
|
|
130
144
|
noCopy: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* The tree's accessible name when `label` is empty and the host names it
|
|
147
|
+
* with neither `aria-label` nor `aria-labelledby`.
|
|
148
|
+
*/
|
|
149
|
+
treeLabel: string;
|
|
131
150
|
/**
|
|
132
151
|
* The value to show, when your code already holds it as an object.
|
|
133
152
|
*
|
|
@@ -152,6 +171,12 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
152
171
|
private active;
|
|
153
172
|
/** Set by a keyboard move, so the next render brings the active row into view. */
|
|
154
173
|
private revealing;
|
|
174
|
+
/** What has been typed toward a key, and when the last letter came. */
|
|
175
|
+
private typed;
|
|
176
|
+
/** The branches of the last value seen, by path, so a new value can tell old ones from new. */
|
|
177
|
+
private branches;
|
|
178
|
+
/** Carries a host `aria-label` and `aria-labelledby` to the tree, which is what takes focus. */
|
|
179
|
+
protected readonly aria: AriaForwardController;
|
|
155
180
|
/**
|
|
156
181
|
* How tall a row is taken to be before it has been drawn, in pixels.
|
|
157
182
|
*
|
|
@@ -169,7 +194,15 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
169
194
|
private readonly copier;
|
|
170
195
|
/** Every visible row, in order, for the tree as it stands. */
|
|
171
196
|
private flatten;
|
|
172
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* Opens every branch shallower than `defaultDepth`.
|
|
199
|
+
*
|
|
200
|
+
* `keep` is for a new value: a branch the last value also had keeps whether
|
|
201
|
+
* a reader opened or closed it, and only a new one takes the default.
|
|
202
|
+
* **Assigning a value used to close everything**, so an inspector showing
|
|
203
|
+
* live data, a polled response or a debug panel, threw away the reader's
|
|
204
|
+
* place on every update.
|
|
205
|
+
*/
|
|
173
206
|
private seed;
|
|
174
207
|
protected willUpdate(changed: PropertyValues): void;
|
|
175
208
|
protected firstUpdated(changed: PropertyValues): void;
|
|
@@ -193,6 +226,16 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
193
226
|
private toggle;
|
|
194
227
|
private move;
|
|
195
228
|
private readonly handleKeydown;
|
|
229
|
+
/** Opens every branch at the active row's level under the same parent, as `*` asks. */
|
|
230
|
+
private openSiblings;
|
|
231
|
+
/**
|
|
232
|
+
* Moves to the next row whose key starts with what was typed.
|
|
233
|
+
*
|
|
234
|
+
* Letters typed within half a second of each other run together, so `me`
|
|
235
|
+
* finds `meta` past `message`. A repeated single letter cycles through the
|
|
236
|
+
* keys that start with it.
|
|
237
|
+
*/
|
|
238
|
+
private typeahead;
|
|
196
239
|
private handleRowClick;
|
|
197
240
|
private renderValue;
|
|
198
241
|
/**
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessObjectInspector_1;
|
|
8
|
-
import { CopyController, customElement, elementById, fillTemplate, HelixElement, inlineStep, scrollItemIntoView, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { AriaForwardController, CopyController, customElement, elementById, fillTemplate, formatNumbers, HelixElement, inlineStep, scrollItemIntoView, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { caretDown, caretRight } from '@fusion.dev/helix-icons';
|
|
10
10
|
import { html, nothing } from 'lit';
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -22,14 +22,25 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
22
22
|
this.copyValueLabel = 'Copy value';
|
|
23
23
|
this.defaultDepth = 1;
|
|
24
24
|
this.for = '';
|
|
25
|
+
this.itemLabel = '{count} item';
|
|
26
|
+
this.itemsLabel = '{count} items';
|
|
27
|
+
this.keyLabel = '{count} key';
|
|
28
|
+
this.keysLabel = '{count} keys';
|
|
25
29
|
this.label = '';
|
|
26
30
|
this.noCopy = false;
|
|
31
|
+
this.treeLabel = 'Value';
|
|
27
32
|
this.value = undefined;
|
|
28
33
|
this.windowed = false;
|
|
29
34
|
this.read = undefined;
|
|
30
35
|
this.opened = new Set();
|
|
31
36
|
this.active = 0;
|
|
32
37
|
this.revealing = false;
|
|
38
|
+
this.typed = { at: 0, text: '' };
|
|
39
|
+
this.branches = new Set();
|
|
40
|
+
this.aria = new AriaForwardController(this, {
|
|
41
|
+
label: true,
|
|
42
|
+
target: () => this.partNamed('tree'),
|
|
43
|
+
});
|
|
33
44
|
this.virtualize = new VirtualizeController(this, {
|
|
34
45
|
container: () => (this.windowed ? this.partNamed('tree') : null),
|
|
35
46
|
count: () => this.rows.length,
|
|
@@ -92,8 +103,14 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
92
103
|
this.toggle(row);
|
|
93
104
|
}
|
|
94
105
|
break;
|
|
106
|
+
case '*':
|
|
107
|
+
this.openSiblings(row);
|
|
108
|
+
break;
|
|
95
109
|
default:
|
|
96
|
-
|
|
110
|
+
if (event.key.length !== 1 || event.altKey || event.ctrlKey || event.metaKey) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.typeahead(event.key);
|
|
97
114
|
}
|
|
98
115
|
event.preventDefault();
|
|
99
116
|
};
|
|
@@ -131,20 +148,28 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
131
148
|
visit(this.root, '', 0, 1, 1);
|
|
132
149
|
return rows;
|
|
133
150
|
}
|
|
134
|
-
seed() {
|
|
151
|
+
seed(keep) {
|
|
135
152
|
const opened = new Set();
|
|
153
|
+
const branches = new Set();
|
|
136
154
|
const visit = (value, path, depth) => {
|
|
137
|
-
if (!branchy(value)
|
|
155
|
+
if (!branchy(value)) {
|
|
138
156
|
return;
|
|
139
157
|
}
|
|
140
|
-
|
|
158
|
+
branches.add(path);
|
|
159
|
+
const known = keep && this.branches.has(path);
|
|
160
|
+
if (known ? this.opened.has(path) : depth < this.defaultDepth) {
|
|
161
|
+
opened.add(path);
|
|
162
|
+
}
|
|
141
163
|
for (const [name, item] of entries(value)) {
|
|
142
164
|
visit(item, child(path, name), depth + 1);
|
|
143
165
|
}
|
|
144
166
|
};
|
|
145
167
|
visit(this.root, '', 0);
|
|
168
|
+
this.branches = branches;
|
|
146
169
|
this.opened = opened;
|
|
147
|
-
|
|
170
|
+
if (!keep) {
|
|
171
|
+
this.active = 0;
|
|
172
|
+
}
|
|
148
173
|
}
|
|
149
174
|
willUpdate(changed) {
|
|
150
175
|
super.willUpdate(changed);
|
|
@@ -152,15 +177,17 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
152
177
|
this.loadedFor = this.for;
|
|
153
178
|
this.load();
|
|
154
179
|
}
|
|
180
|
+
const was = this.rows[this.active]?.path;
|
|
155
181
|
if (changed.has('value') || changed.has('read') || changed.has('defaultDepth')) {
|
|
156
|
-
this.seed();
|
|
182
|
+
this.seed(!changed.has('defaultDepth'));
|
|
157
183
|
}
|
|
158
184
|
if (changed.has('value') ||
|
|
159
185
|
changed.has('read') ||
|
|
160
186
|
changed.has('opened') ||
|
|
161
187
|
changed.has('defaultDepth')) {
|
|
162
188
|
this.rows = this.flatten();
|
|
163
|
-
|
|
189
|
+
const found = was === undefined ? -1 : this.rows.findIndex((row) => row.path === was);
|
|
190
|
+
this.active = found >= 0 ? found : Math.min(this.active, Math.max(0, this.rows.length - 1));
|
|
164
191
|
}
|
|
165
192
|
}
|
|
166
193
|
firstUpdated(changed) {
|
|
@@ -229,6 +256,35 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
229
256
|
this.active = Math.max(0, Math.min(to, last));
|
|
230
257
|
this.revealing = true;
|
|
231
258
|
}
|
|
259
|
+
openSiblings(row) {
|
|
260
|
+
const parent = row.path.slice(0, row.path.lastIndexOf('/'));
|
|
261
|
+
const opened = new Set(this.opened);
|
|
262
|
+
for (const one of this.rows) {
|
|
263
|
+
if (one.branch &&
|
|
264
|
+
one.depth === row.depth &&
|
|
265
|
+
one.path.slice(0, one.path.lastIndexOf('/')) === parent) {
|
|
266
|
+
opened.add(one.path);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
this.opened = opened;
|
|
270
|
+
}
|
|
271
|
+
typeahead(letter) {
|
|
272
|
+
const now = Date.now();
|
|
273
|
+
const text = now - this.typed.at < 500 ? this.typed.text + letter : letter;
|
|
274
|
+
this.typed = { at: now, text };
|
|
275
|
+
const wanted = text.toLocaleLowerCase();
|
|
276
|
+
const repeated = [...wanted].every((one) => one === wanted[0]);
|
|
277
|
+
const rows = this.rows;
|
|
278
|
+
const start = wanted.length === 1 || repeated ? this.active + 1 : this.active;
|
|
279
|
+
for (let step = 0; step < rows.length; step += 1) {
|
|
280
|
+
const at = (start + step) % rows.length;
|
|
281
|
+
const key = rows[at]?.key?.toLocaleLowerCase();
|
|
282
|
+
if (key?.startsWith(repeated ? (wanted[0] ?? '') : wanted)) {
|
|
283
|
+
this.move(at);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
232
288
|
handleRowClick(index, row) {
|
|
233
289
|
this.active = index;
|
|
234
290
|
if (row.branch) {
|
|
@@ -240,9 +296,18 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
240
296
|
if (row.branch) {
|
|
241
297
|
const count = entries(value).length;
|
|
242
298
|
const array = Array.isArray(value);
|
|
243
|
-
const
|
|
299
|
+
const one = new Intl.PluralRules(this.lang || undefined).select(count) === 'one';
|
|
300
|
+
const words = array
|
|
301
|
+
? one
|
|
302
|
+
? this.itemLabel
|
|
303
|
+
: this.itemsLabel
|
|
304
|
+
: one
|
|
305
|
+
? this.keyLabel
|
|
306
|
+
: this.keysLabel;
|
|
244
307
|
return html `<span part="summary">${array ? '[…]' : '{…}'}</span>
|
|
245
|
-
<span part="count" dir="auto"
|
|
308
|
+
<span part="count" dir="auto"
|
|
309
|
+
>${fillTemplate(words, { count: formatNumbers(this.lang)(count) })}</span
|
|
310
|
+
>`;
|
|
246
311
|
}
|
|
247
312
|
if (typeof value === 'string') {
|
|
248
313
|
return html `<span part="string" dir="ltr">${JSON.stringify(value)}</span>`;
|
|
@@ -310,7 +375,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
310
375
|
role="tree"
|
|
311
376
|
tabindex="0"
|
|
312
377
|
?data-scroller=${this.windowed}
|
|
313
|
-
aria-label=${this.label ||
|
|
378
|
+
aria-label=${this.label || this.treeLabel}
|
|
314
379
|
aria-activedescendant=${rows.length > 0 ? `row-${this.active}` : nothing}
|
|
315
380
|
@keydown=${this.handleKeydown}
|
|
316
381
|
@scroll=${() => this.virtualize.measure()}
|
|
@@ -335,12 +400,27 @@ __decorate([
|
|
|
335
400
|
__decorate([
|
|
336
401
|
property()
|
|
337
402
|
], HelixHeadlessObjectInspector.prototype, "for", void 0);
|
|
403
|
+
__decorate([
|
|
404
|
+
property({ attribute: 'item-label' })
|
|
405
|
+
], HelixHeadlessObjectInspector.prototype, "itemLabel", void 0);
|
|
406
|
+
__decorate([
|
|
407
|
+
property({ attribute: 'items-label' })
|
|
408
|
+
], HelixHeadlessObjectInspector.prototype, "itemsLabel", void 0);
|
|
409
|
+
__decorate([
|
|
410
|
+
property({ attribute: 'key-label' })
|
|
411
|
+
], HelixHeadlessObjectInspector.prototype, "keyLabel", void 0);
|
|
412
|
+
__decorate([
|
|
413
|
+
property({ attribute: 'keys-label' })
|
|
414
|
+
], HelixHeadlessObjectInspector.prototype, "keysLabel", void 0);
|
|
338
415
|
__decorate([
|
|
339
416
|
property()
|
|
340
417
|
], HelixHeadlessObjectInspector.prototype, "label", void 0);
|
|
341
418
|
__decorate([
|
|
342
419
|
property({ attribute: 'no-copy', type: Boolean })
|
|
343
420
|
], HelixHeadlessObjectInspector.prototype, "noCopy", void 0);
|
|
421
|
+
__decorate([
|
|
422
|
+
property({ attribute: 'tree-label' })
|
|
423
|
+
], HelixHeadlessObjectInspector.prototype, "treeLabel", void 0);
|
|
344
424
|
__decorate([
|
|
345
425
|
property({ attribute: false })
|
|
346
426
|
], HelixHeadlessObjectInspector.prototype, "value", void 0);
|
|
@@ -53,13 +53,16 @@ export declare const optionsAmong: (elements: readonly Element[]) => HelixHeadle
|
|
|
53
53
|
* @csspart label - The option's label.
|
|
54
54
|
* @csspart text - The label and the description under it, as one column.
|
|
55
55
|
*
|
|
56
|
+
* @cssstate active - While the keyboard is on the option, which is the option `aria-activedescendant` names.
|
|
56
57
|
* @cssstate selected - While the option is chosen.
|
|
57
58
|
*/
|
|
58
59
|
export declare class HelixHeadlessOption extends HelixElement {
|
|
59
60
|
/**
|
|
60
61
|
* Whether this is the option the keyboard is on.
|
|
61
62
|
*
|
|
62
|
-
* Written by the listbox.
|
|
63
|
+
* Written by the listbox, which writes it once a reader moves the highlight.
|
|
64
|
+
* It shows as `:state(active)`, and as a `data-active` attribute for the
|
|
65
|
+
* stylesheets written before the state existed.
|
|
63
66
|
*/
|
|
64
67
|
active: boolean;
|
|
65
68
|
/**
|
|
@@ -44,6 +44,7 @@ let HelixHeadlessOption = class HelixHeadlessOption extends HelixElement {
|
|
|
44
44
|
willUpdate(changed) {
|
|
45
45
|
super.willUpdate(changed);
|
|
46
46
|
this.toggleState('selected', this.selected);
|
|
47
|
+
this.toggleState('active', this.active);
|
|
47
48
|
}
|
|
48
49
|
render() {
|
|
49
50
|
this.internals.role = 'option';
|
|
@@ -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.
|