@fusion.dev/helix-headless 0.145.0 → 0.146.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +7373 -3849
- package/dist/accordion/item/accordion-item.d.ts +14 -0
- package/dist/accordion/item/accordion-item.js +16 -6
- package/dist/accordion/root/accordion-root.d.ts +8 -5
- package/dist/announcement/root/announcement-root.d.ts +3 -2
- package/dist/announcement/root/announcement-root.js +3 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +25 -3
- package/dist/chat/root/chat-root.js +22 -5
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -1
- package/dist/code-block/root/code-block-root.js +58 -3
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +5 -0
- package/dist/copy-button/root/copy-button-root.js +10 -3
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +20 -52
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +21 -3
- package/dist/element-events.generated.js +31 -5
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +1 -1
- package/dist/input/root/input-root.d.ts +12 -2
- package/dist/input/root/input-root.js +11 -2
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +62 -13
- package/dist/list/root/list-root.js +70 -13
- package/dist/list/selection.d.ts +37 -7
- package/dist/list/selection.js +16 -7
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -3
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/root/megamenu-root.d.ts +51 -10
- package/dist/megamenu/root/megamenu-root.js +76 -5
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +47 -23
- package/dist/menu/root/menu-root.d.ts +14 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +10 -3
- package/dist/notifications/root/notifications-root.js +19 -7
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
- package/dist/object-inspector/root/object-inspector-root.js +117 -76
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/root/outline-root.d.ts +18 -0
- package/dist/outline/root/outline-root.js +23 -5
- package/dist/pagination/size/pagination-size.d.ts +1 -0
- package/dist/pagination/size/pagination-size.js +1 -1
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +9 -4
- package/dist/rating/root/rating-root.js +31 -7
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -0
- package/dist/scroll-area/scrollbar.js +9 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +7 -12
- package/dist/splitter/root/splitter-root.js +209 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +49 -3
- package/dist/steps/root/steps-root.js +44 -5
- package/dist/steps/step/step.d.ts +7 -0
- package/dist/steps/step/step.js +7 -2
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +0 -10
- package/dist/table/column/table-column.js +3 -19
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +2 -13
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +12 -0
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +14 -1
- package/dist/toast/item/toast-item.js +22 -5
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/video-root.d.ts +18 -5
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
- package/dist/virtual-list/fill.d.ts +0 -8
- package/dist/virtual-list/fill.js +1 -17
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
- package/dist/virtual-list/root/virtual-list-root.js +183 -40
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +4577 -835
- package/types/vue.d.ts +926 -168
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -5,14 +5,15 @@ 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 { AriaForwardController, CopyController, countLabel, customElement, drawStatus, elementById, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeActivateEvent, HelixElement, HelixFilterEvent, HelixFilteredEvent, inlineStep, requestChange, StatusController, scrollItemIntoView, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { AriaForwardController, CopyController, countLabel, customElement, drawStatus, elementById, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeCloseEvent, HelixBeforeOpenEvent, HelixElement, HelixFilterEvent, HelixFilteredEvent, inlineStep, requestChange, StatusController, scrollItemIntoView, searchableById, treeArrow, 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';
|
|
12
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
12
13
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
13
14
|
import { html as staticHtml } from 'lit/static-html.js';
|
|
14
15
|
import '../../copy-button/index.js';
|
|
15
|
-
import {
|
|
16
|
+
import { cursorFor, entries, flatten, search, seed, siblingBranches, withAncestors, } from '../rows.js';
|
|
16
17
|
let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends HelixElement {
|
|
17
18
|
constructor() {
|
|
18
19
|
super(...arguments);
|
|
@@ -38,6 +39,8 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
38
39
|
this.opened = new Set();
|
|
39
40
|
this.cursor = 0;
|
|
40
41
|
this.revealing = false;
|
|
42
|
+
this.focusing = false;
|
|
43
|
+
this.hadFocus = false;
|
|
41
44
|
this.typed = { at: 0, text: '' };
|
|
42
45
|
this.branches = new Set();
|
|
43
46
|
this.aria = new AriaForwardController(this, {
|
|
@@ -83,22 +86,23 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
83
86
|
break;
|
|
84
87
|
case 'ArrowRight':
|
|
85
88
|
case 'ArrowLeft':
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
switch (treeArrow(row, inlineStep(this, event.key) === 1 ? 1 : -1)) {
|
|
90
|
+
case 'open':
|
|
91
|
+
case 'close':
|
|
92
|
+
this.toggle(row, !row.open);
|
|
93
|
+
break;
|
|
94
|
+
case 'child':
|
|
91
95
|
this.move(this.cursor + 1);
|
|
96
|
+
break;
|
|
97
|
+
case 'parent': {
|
|
98
|
+
const parent = rows.findLastIndex((candidate, at) => at < this.cursor && candidate.depth === row.depth - 1);
|
|
99
|
+
if (parent >= 0) {
|
|
100
|
+
this.move(parent);
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
92
103
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
this.toggle(row, false);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
const parent = rows.findLastIndex((candidate, at) => at < this.cursor && candidate.depth === row.depth - 1);
|
|
99
|
-
if (parent >= 0) {
|
|
100
|
-
this.move(parent);
|
|
101
|
-
}
|
|
104
|
+
default:
|
|
105
|
+
break;
|
|
102
106
|
}
|
|
103
107
|
break;
|
|
104
108
|
case 'Enter':
|
|
@@ -108,7 +112,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
108
112
|
}
|
|
109
113
|
break;
|
|
110
114
|
case '*':
|
|
111
|
-
this.
|
|
115
|
+
this.requestOpen(siblingBranches(rows, row), true);
|
|
112
116
|
break;
|
|
113
117
|
default:
|
|
114
118
|
if (event.key.length !== 1 || event.altKey || event.ctrlKey || event.metaKey) {
|
|
@@ -136,9 +140,22 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
136
140
|
}
|
|
137
141
|
};
|
|
138
142
|
this.handleFilterKeydown = (event) => {
|
|
139
|
-
if (event.key === 'ArrowDown') {
|
|
143
|
+
if (event.key === 'ArrowDown' && this.rows.length > 0) {
|
|
140
144
|
event.preventDefault();
|
|
141
|
-
this.
|
|
145
|
+
this.revealing = true;
|
|
146
|
+
this.focusing = true;
|
|
147
|
+
this.requestUpdate();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
this.handleFocusIn = (event) => {
|
|
151
|
+
const index = Number(event.target.dataset?.index);
|
|
152
|
+
if (Number.isInteger(index) && index !== this.cursor) {
|
|
153
|
+
this.move(index);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
this.handleFocusOut = () => {
|
|
157
|
+
if (this.windowed) {
|
|
158
|
+
this.requestUpdate();
|
|
142
159
|
}
|
|
143
160
|
};
|
|
144
161
|
}
|
|
@@ -173,18 +190,11 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
173
190
|
}
|
|
174
191
|
}
|
|
175
192
|
openAround(paths) {
|
|
176
|
-
|
|
177
|
-
for (const path of paths) {
|
|
178
|
-
for (const above of ancestorsOf(path)) {
|
|
179
|
-
if (this.branches.has(above)) {
|
|
180
|
-
opened.add(above);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
this.opened = opened;
|
|
193
|
+
this.opened = withAncestors(this.opened, this.branches, paths);
|
|
185
194
|
}
|
|
186
195
|
willUpdate(changed) {
|
|
187
196
|
super.willUpdate(changed);
|
|
197
|
+
this.hadFocus = this.hasFocusedRow();
|
|
188
198
|
if (this.loadedFor !== this.for && searchableById(this) && !this.hydrating) {
|
|
189
199
|
this.loadedFor = this.for;
|
|
190
200
|
this.load();
|
|
@@ -212,26 +222,12 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
212
222
|
wanted !== undefined ||
|
|
213
223
|
['active', 'defaultDepth', 'expanded', 'filter', 'opened'].some((name) => changed.has(name))) {
|
|
214
224
|
this.rows = flatten(this.root, this.opened, this.found);
|
|
215
|
-
this.cursor = this.
|
|
225
|
+
this.cursor = cursorFor(this.rows, wanted ?? was, this.cursor, changed.has('filter'));
|
|
216
226
|
}
|
|
217
227
|
if (changed.has('filter') && this.hasUpdated) {
|
|
218
228
|
this.tell();
|
|
219
229
|
}
|
|
220
230
|
}
|
|
221
|
-
place(path, filtered) {
|
|
222
|
-
const rows = this.rows;
|
|
223
|
-
const at = (one) => rows.findIndex((row) => row.path === one);
|
|
224
|
-
const own = path === undefined ? -1 : at(path);
|
|
225
|
-
if (own >= 0 || path === undefined) {
|
|
226
|
-
return own >= 0 ? own : Math.min(this.cursor, Math.max(0, rows.length - 1));
|
|
227
|
-
}
|
|
228
|
-
const match = filtered ? rows.findIndex((row) => row.match) : -1;
|
|
229
|
-
const around = ancestorsOf(path)
|
|
230
|
-
.reverse()
|
|
231
|
-
.map(at)
|
|
232
|
-
.find((one) => one >= 0);
|
|
233
|
-
return match >= 0 ? match : (around ?? 0);
|
|
234
|
-
}
|
|
235
231
|
tell() {
|
|
236
232
|
if (this.found) {
|
|
237
233
|
this.status.say(countLabel(this.found.size, this.resultLabel, this.resultsLabel, this.lang));
|
|
@@ -250,6 +246,19 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
250
246
|
this.revealing = false;
|
|
251
247
|
this.reveal();
|
|
252
248
|
}
|
|
249
|
+
const lost = this.hadFocus &&
|
|
250
|
+
!this.hasFocusedRow() &&
|
|
251
|
+
this.ownerDocument.activeElement === this.ownerDocument.body;
|
|
252
|
+
if (this.focusing || lost) {
|
|
253
|
+
this.focusing = false;
|
|
254
|
+
this.focusActive();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
focusActive() {
|
|
258
|
+
const row = this.partNamed('tree')?.querySelector(`[data-index="${this.cursor}"]`);
|
|
259
|
+
if (row && this.shadowRoot?.activeElement !== row) {
|
|
260
|
+
row.focus({ preventScroll: true });
|
|
261
|
+
}
|
|
253
262
|
}
|
|
254
263
|
load() {
|
|
255
264
|
const text = this.for === '' ? '' : (elementById(this, this.for)?.textContent ?? '');
|
|
@@ -277,7 +286,10 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
277
286
|
const from = Number(this.cursor > Number(last.dataset.index) ? last.dataset.index : first.dataset.index);
|
|
278
287
|
tree.scrollTop += (this.cursor - from) * height;
|
|
279
288
|
this.virtualize.measure();
|
|
280
|
-
void this.updateComplete.then(() =>
|
|
289
|
+
void this.updateComplete.then(() => {
|
|
290
|
+
this.reveal(attempts - 1);
|
|
291
|
+
this.focusActive();
|
|
292
|
+
});
|
|
281
293
|
}
|
|
282
294
|
copyable(row) {
|
|
283
295
|
if (!row) {
|
|
@@ -288,15 +300,44 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
288
300
|
}
|
|
289
301
|
return JSON.stringify(row.value, null, 2) ?? String(row.value);
|
|
290
302
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
opened.add(row.path);
|
|
303
|
+
requestOpen(paths, open) {
|
|
304
|
+
if (paths.length === 0) {
|
|
305
|
+
return false;
|
|
295
306
|
}
|
|
296
|
-
|
|
297
|
-
|
|
307
|
+
const applied = requestChange({
|
|
308
|
+
apply: () => {
|
|
309
|
+
const opened = new Set(this.opened);
|
|
310
|
+
for (const path of paths) {
|
|
311
|
+
if (open) {
|
|
312
|
+
opened.add(path);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
opened.delete(path);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
this.opened = opened;
|
|
319
|
+
},
|
|
320
|
+
event: (next) => (next ? new HelixBeforeOpenEvent() : new HelixBeforeCloseEvent()),
|
|
321
|
+
host: this,
|
|
322
|
+
next: open,
|
|
323
|
+
});
|
|
324
|
+
if (applied) {
|
|
325
|
+
this.announceToggle(open);
|
|
298
326
|
}
|
|
299
|
-
|
|
327
|
+
return applied;
|
|
328
|
+
}
|
|
329
|
+
announceToggle(open) {
|
|
330
|
+
const states = { newState: open ? 'open' : 'closed', oldState: open ? 'closed' : 'open' };
|
|
331
|
+
if (typeof ToggleEvent === 'function') {
|
|
332
|
+
this.dispatchEvent(new ToggleEvent('toggle', states));
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const event = new Event('toggle', { bubbles: false, cancelable: false, composed: false });
|
|
336
|
+
Object.assign(event, states);
|
|
337
|
+
this.dispatchEvent(event);
|
|
338
|
+
}
|
|
339
|
+
toggle(row, open = !row.open) {
|
|
340
|
+
this.requestOpen([row.path], open);
|
|
300
341
|
}
|
|
301
342
|
move(to) {
|
|
302
343
|
const at = Math.max(0, Math.min(to, this.rows.length - 1));
|
|
@@ -319,20 +360,9 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
319
360
|
this.dispatchEvent(new HelixActivateEvent({ value: path }));
|
|
320
361
|
}
|
|
321
362
|
this.revealing = true;
|
|
363
|
+
this.focusing = true;
|
|
322
364
|
return true;
|
|
323
365
|
}
|
|
324
|
-
openSiblings(row) {
|
|
325
|
-
const parent = row.path.slice(0, row.path.lastIndexOf('/'));
|
|
326
|
-
const opened = new Set(this.opened);
|
|
327
|
-
for (const one of this.rows) {
|
|
328
|
-
if (one.branch &&
|
|
329
|
-
one.depth === row.depth &&
|
|
330
|
-
one.path.slice(0, one.path.lastIndexOf('/')) === parent) {
|
|
331
|
-
opened.add(one.path);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
this.opened = opened;
|
|
335
|
-
}
|
|
336
366
|
typeahead(letter) {
|
|
337
367
|
const now = Date.now();
|
|
338
368
|
const text = now - this.typed.at < 500 ? this.typed.text + letter : letter;
|
|
@@ -391,18 +421,17 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
391
421
|
const active = index === this.cursor;
|
|
392
422
|
return html `<div
|
|
393
423
|
part="row${active ? ' row-active' : ''}${row.match ? ' row-match' : ''}"
|
|
394
|
-
role="
|
|
424
|
+
role="row"
|
|
395
425
|
id=${`row-${index}`}
|
|
396
426
|
data-index=${index}
|
|
427
|
+
tabindex=${active ? '0' : '-1'}
|
|
397
428
|
aria-level=${row.depth + 1}
|
|
398
429
|
aria-posinset=${row.position}
|
|
399
|
-
aria-selected="false"
|
|
400
430
|
aria-setsize=${row.siblings}
|
|
401
431
|
aria-expanded=${row.branch ? String(row.open) : nothing}
|
|
402
432
|
style=${`--object-inspector-level: ${row.depth}`}
|
|
403
433
|
@click=${() => this.handleRowClick(index, row)}
|
|
404
|
-
|
|
405
|
-
${row.branch
|
|
434
|
+
><div role="gridcell" style="display: contents">${row.branch
|
|
406
435
|
? html `<svg
|
|
407
436
|
part="toggle"
|
|
408
437
|
?data-mirror=${!row.open}
|
|
@@ -412,9 +441,13 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
412
441
|
>
|
|
413
442
|
${unsafeSVG((row.open ? caretDown : caretRight).content)}
|
|
414
443
|
</svg>`
|
|
415
|
-
: nothing}${row.key === undefined ? nothing : html `<span part="key">${row.key}</span>: `}${this.renderValue(row)}
|
|
444
|
+
: nothing}${row.key === undefined ? nothing : html `<span part="key">${row.key}</span>: `}${this.renderValue(row)}</div>
|
|
416
445
|
</div>`;
|
|
417
446
|
}
|
|
447
|
+
hasFocusedRow() {
|
|
448
|
+
const focused = this.shadowRoot?.activeElement;
|
|
449
|
+
return focused?.getAttribute?.('role') === 'row';
|
|
450
|
+
}
|
|
418
451
|
renderCopyButton(row) {
|
|
419
452
|
return staticHtml `<${this.tag('copy-button')}
|
|
420
453
|
part="copy"
|
|
@@ -429,10 +462,18 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
429
462
|
}
|
|
430
463
|
render() {
|
|
431
464
|
const rows = this.rows;
|
|
432
|
-
const {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
465
|
+
const { first, last } = this.windowed ? this.virtualize.window : { first: 0, last: rows.length };
|
|
466
|
+
const kept = this.windowed && (this.cursor < first || this.cursor >= last) && this.hasFocusedRow()
|
|
467
|
+
? this.cursor
|
|
468
|
+
: undefined;
|
|
469
|
+
const { after, before } = this.windowed
|
|
470
|
+
? this.virtualize.spacers(kept)
|
|
471
|
+
: { after: 0, before: 0 };
|
|
472
|
+
const shown = rows.slice(first, last).map((row, at) => [row, first + at]);
|
|
473
|
+
const keptRow = kept === undefined ? undefined : rows[kept];
|
|
474
|
+
if (kept !== undefined && keptRow) {
|
|
475
|
+
shown.splice(kept < first ? 0 : shown.length, 0, [keptRow, kept]);
|
|
476
|
+
}
|
|
436
477
|
return html `${this.label ? html `<div part="header"><span part="label">${this.label}</span></div>` : nothing}${this.filterable
|
|
437
478
|
? html `<input
|
|
438
479
|
part="search-field"
|
|
@@ -450,16 +491,16 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
450
491
|
<div
|
|
451
492
|
part="tree"
|
|
452
493
|
id="tree"
|
|
453
|
-
role="
|
|
454
|
-
tabindex="0"
|
|
494
|
+
role="treegrid"
|
|
455
495
|
?data-scroller=${this.windowed}
|
|
456
496
|
aria-label=${this.label || this.treeLabel}
|
|
457
|
-
aria-activedescendant=${rows.length > 0 ? `row-${this.cursor}` : nothing}
|
|
458
497
|
@keydown=${this.handleKeydown}
|
|
498
|
+
@focusin=${this.handleFocusIn}
|
|
499
|
+
@focusout=${this.handleFocusOut}
|
|
459
500
|
@scroll=${() => this.virtualize.measure()}
|
|
460
501
|
>
|
|
461
502
|
${this.windowed ? html `<div part="before" role="presentation" style="block-size: ${before}px"></div>` : nothing}
|
|
462
|
-
${shown.
|
|
503
|
+
${repeat(shown, ([row]) => row.path, ([row, at]) => this.renderRow(row, at))}
|
|
463
504
|
${this.windowed ? html `<div part="after" role="presentation" style="block-size: ${after}px"></div>` : nothing}
|
|
464
505
|
</div>
|
|
465
506
|
${this.noCopy ? nothing : this.renderCopyButton(rows[this.cursor])}
|
|
@@ -55,3 +55,21 @@ export declare const seed: (root: unknown, depth: number, known?: Set<string>, o
|
|
|
55
55
|
branches: Set<string>;
|
|
56
56
|
opened: Set<string>;
|
|
57
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Where the active row goes once the rows have moved, as an index into `rows`.
|
|
60
|
+
*
|
|
61
|
+
* Onto `path` where it is still shown. Where a filter just hid it
|
|
62
|
+
* (`filtered`), onto the first match. Otherwise onto the nearest branch around
|
|
63
|
+
* it that is shown. With no path to keep, `cursor` held inside the rows.
|
|
64
|
+
*/
|
|
65
|
+
export declare const cursorFor: (rows: readonly Row[], path: string | undefined, cursor: number, filtered: boolean) => number;
|
|
66
|
+
/**
|
|
67
|
+
* The open branches with every branch around each of `paths` opened too,
|
|
68
|
+
* where the value has that branch (`branches`).
|
|
69
|
+
*/
|
|
70
|
+
export declare const withAncestors: (opened: ReadonlySet<string>, branches: ReadonlySet<string>, paths: Iterable<string>) => Set<string>;
|
|
71
|
+
/**
|
|
72
|
+
* The branches `*` opens from `row`: every branch at its depth under the same
|
|
73
|
+
* parent, itself included, that is not open yet.
|
|
74
|
+
*/
|
|
75
|
+
export declare const siblingBranches: (rows: readonly Row[], row: Row) => string[];
|
|
@@ -84,3 +84,36 @@ export const seed = (root, depth, known = new Set(), opened = new Set()) => {
|
|
|
84
84
|
visit(root, '', 0);
|
|
85
85
|
return { branches, opened: open };
|
|
86
86
|
};
|
|
87
|
+
export const cursorFor = (rows, path, cursor, filtered) => {
|
|
88
|
+
const at = (one) => rows.findIndex((row) => row.path === one);
|
|
89
|
+
const own = path === undefined ? -1 : at(path);
|
|
90
|
+
if (own >= 0 || path === undefined) {
|
|
91
|
+
return own >= 0 ? own : Math.min(cursor, Math.max(0, rows.length - 1));
|
|
92
|
+
}
|
|
93
|
+
const match = filtered ? rows.findIndex((row) => row.match) : -1;
|
|
94
|
+
const around = ancestorsOf(path)
|
|
95
|
+
.reverse()
|
|
96
|
+
.map(at)
|
|
97
|
+
.find((one) => one >= 0);
|
|
98
|
+
return match >= 0 ? match : (around ?? 0);
|
|
99
|
+
};
|
|
100
|
+
export const withAncestors = (opened, branches, paths) => {
|
|
101
|
+
const next = new Set(opened);
|
|
102
|
+
for (const path of paths) {
|
|
103
|
+
for (const above of ancestorsOf(path)) {
|
|
104
|
+
if (branches.has(above)) {
|
|
105
|
+
next.add(above);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return next;
|
|
110
|
+
};
|
|
111
|
+
export const siblingBranches = (rows, row) => {
|
|
112
|
+
const parent = row.path.slice(0, row.path.lastIndexOf('/'));
|
|
113
|
+
return rows
|
|
114
|
+
.filter((one) => one.branch &&
|
|
115
|
+
!one.open &&
|
|
116
|
+
one.depth === row.depth &&
|
|
117
|
+
one.path.slice(0, one.path.lastIndexOf('/')) === parent)
|
|
118
|
+
.map((one) => one.path);
|
|
119
|
+
};
|
|
@@ -63,9 +63,11 @@ export declare class HelixHeadlessOption extends HelixElement {
|
|
|
63
63
|
/**
|
|
64
64
|
* Whether this is the option the keyboard is on.
|
|
65
65
|
*
|
|
66
|
-
* Written by the listbox
|
|
67
|
-
*
|
|
68
|
-
*
|
|
66
|
+
* Written by the listbox once a reader moves the highlight. Style it with
|
|
67
|
+
* `:state(active)`, or `::part(item-active)` for an option inside another
|
|
68
|
+
* component's shadow root. The `data-active` attribute sets it from markup;
|
|
69
|
+
* it is also written back for stylesheets from before the state, and no
|
|
70
|
+
* stylesheet of the library's own selects it.
|
|
69
71
|
*/
|
|
70
72
|
active: boolean;
|
|
71
73
|
/**
|
|
@@ -20,6 +20,9 @@ import { type Branch } from '../levels.js';
|
|
|
20
20
|
*
|
|
21
21
|
* A heading slotted into `heading` names the navigation, in place of `label`.
|
|
22
22
|
*
|
|
23
|
+
* In a contents rail with a scrollbar of its own, `follow` keeps the link of
|
|
24
|
+
* the section in view showing as the reader scrolls the page.
|
|
25
|
+
*
|
|
23
26
|
* The current section is decided by the headings' positions. An
|
|
24
27
|
* `IntersectionObserver` with a band near the top fails both ways: when
|
|
25
28
|
* headings are far apart, none is in the band and no section is marked, and
|
|
@@ -73,6 +76,13 @@ export declare class HelixHeadlessOutline extends HelixElement {
|
|
|
73
76
|
* JavaScript rather than CSS decides.
|
|
74
77
|
*/
|
|
75
78
|
behavior: ScrollBehavior;
|
|
79
|
+
/**
|
|
80
|
+
* Keeps the link of the section in view in view itself, in an outline
|
|
81
|
+
* longer than the box it scrolls in, such as a contents rail with a
|
|
82
|
+
* scrollbar of its own. Only that box moves: never the page, and never the
|
|
83
|
+
* box the sections scroll in.
|
|
84
|
+
*/
|
|
85
|
+
follow: boolean;
|
|
76
86
|
/**
|
|
77
87
|
* The navigation's name, read by screen readers. A heading in the `heading`
|
|
78
88
|
* slot names it in place of this.
|
|
@@ -154,6 +164,14 @@ export declare class HelixHeadlessOutline extends HelixElement {
|
|
|
154
164
|
private mark;
|
|
155
165
|
/** Where the destination is set, whether measured or asked for. */
|
|
156
166
|
private markTo;
|
|
167
|
+
/**
|
|
168
|
+
* Scrolls the box the links scroll in to show `link`, under `follow`.
|
|
169
|
+
*
|
|
170
|
+
* The nearest box above the link that scrolls, and only where it is the
|
|
171
|
+
* rail's own: the page, the box the sections scroll in, or a box holding it
|
|
172
|
+
* would move the reading under the reader, which is the scroll this marks.
|
|
173
|
+
*/
|
|
174
|
+
private reveal;
|
|
157
175
|
/**
|
|
158
176
|
* Whether the page has no more scroll left.
|
|
159
177
|
*
|
|
@@ -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, elementById, HelixActivateEvent, HelixElement, IndicatorController, reflectElements, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, elementById, HelixActivateEvent, HelixElement, IndicatorController, plainClick, reflectElements, scrollItemIntoView, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { levelOf, nest } from '../levels.js';
|
|
@@ -18,6 +18,7 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
|
|
|
18
18
|
surface: () => this.partNamed('nav'),
|
|
19
19
|
});
|
|
20
20
|
this.behavior = 'auto';
|
|
21
|
+
this.follow = false;
|
|
21
22
|
this.label = 'On this page';
|
|
22
23
|
this.offset = 0;
|
|
23
24
|
this.reading = '';
|
|
@@ -32,10 +33,7 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
|
|
|
32
33
|
});
|
|
33
34
|
};
|
|
34
35
|
this.handleClick = (event) => {
|
|
35
|
-
if (event.defaultPrevented || event
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
36
|
+
if (event.defaultPrevented || !plainClick(event)) {
|
|
39
37
|
return;
|
|
40
38
|
}
|
|
41
39
|
const link = event.target?.closest?.('a[href^="#"]');
|
|
@@ -142,9 +140,26 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
|
|
|
142
140
|
if (next !== this.reading) {
|
|
143
141
|
this.reading = next;
|
|
144
142
|
this.indicator.place();
|
|
143
|
+
if (this.follow && active) {
|
|
144
|
+
this.reveal(active.link);
|
|
145
|
+
}
|
|
145
146
|
this.dispatchEvent(new HelixActivateEvent({ value: next }));
|
|
146
147
|
}
|
|
147
148
|
}
|
|
149
|
+
reveal(link) {
|
|
150
|
+
const sections = this.scroller;
|
|
151
|
+
const page = this.page;
|
|
152
|
+
for (let node = link.parentElement; node && node !== page; node = node.parentElement) {
|
|
153
|
+
const { overflowY } = getComputedStyle(node);
|
|
154
|
+
if (!/auto|scroll|overlay/.test(overflowY) || node.scrollHeight <= node.clientHeight) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (node !== sections && !node.contains(sections)) {
|
|
158
|
+
scrollItemIntoView(link, { scroller: node });
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
148
163
|
get atEnd() {
|
|
149
164
|
const doc = this.scroller;
|
|
150
165
|
return Math.ceil(doc.scrollTop + doc.clientHeight) >= doc.scrollHeight - 1;
|
|
@@ -282,6 +297,9 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
|
|
|
282
297
|
__decorate([
|
|
283
298
|
property()
|
|
284
299
|
], HelixHeadlessOutline.prototype, "behavior", void 0);
|
|
300
|
+
__decorate([
|
|
301
|
+
property({ type: Boolean })
|
|
302
|
+
], HelixHeadlessOutline.prototype, "follow", void 0);
|
|
285
303
|
__decorate([
|
|
286
304
|
property()
|
|
287
305
|
], HelixHeadlessOutline.prototype, "label", void 0);
|
|
@@ -49,6 +49,7 @@ import '../../select/index.js';
|
|
|
49
49
|
* @csspart control-label - The label beside the number.
|
|
50
50
|
* @csspart control-listbox - The list inside the panel.
|
|
51
51
|
* @csspart control-listbox-empty - The text shown when the filter hides every option.
|
|
52
|
+
* @csspart control-listbox-error - The inner list's `error` part, shown while its `load-error` is set.
|
|
52
53
|
* @csspart control-listbox-feedback - The inner list's message that says what is wrong with the value.
|
|
53
54
|
* @csspart control-listbox-filter-icon - The icon beside the filter field.
|
|
54
55
|
* @csspart control-listbox-filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -93,7 +93,7 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
|
|
|
93
93
|
part="control"
|
|
94
94
|
exportparts="feedback: control-feedback, hint: control-hint, indicator: control-indicator,
|
|
95
95
|
label: control-label, listbox: control-listbox, listbox-empty: control-listbox-empty,
|
|
96
|
-
listbox-feedback: control-listbox-feedback, listbox-filter-icon: control-listbox-filter-icon,
|
|
96
|
+
listbox-error: control-listbox-error, listbox-feedback: control-listbox-feedback, listbox-filter-icon: control-listbox-filter-icon,
|
|
97
97
|
listbox-filter-mark: control-listbox-filter-mark, listbox-hint: control-listbox-hint,
|
|
98
98
|
listbox-items: control-listbox-items, listbox-label: control-listbox-label,
|
|
99
99
|
listbox-live: control-listbox-live, listbox-loading: control-listbox-loading, listbox-search: control-listbox-search,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PinCase, PinType } from './root/pin-input-root.js';
|
|
2
|
+
/**
|
|
3
|
+
* Typed or pasted text as the code's characters: trimmed, with what `type`
|
|
4
|
+
* refuses dropped, and its letters cased as `letterCase` asks. Web Awesome's
|
|
5
|
+
* OTP input takes the same `case`.
|
|
6
|
+
*
|
|
7
|
+
* `numeric` keeps digits, `alphanumeric` keeps ASCII letters and digits, and
|
|
8
|
+
* `text` keeps everything.
|
|
9
|
+
*/
|
|
10
|
+
export declare const cleanCode: (text: string, type: PinType, letterCase?: PinCase) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const cleanCode = (text, type, letterCase = 'preserve') => {
|
|
2
|
+
const trimmed = text.trim();
|
|
3
|
+
const kept = type === 'numeric'
|
|
4
|
+
? trimmed.replace(/\D/g, '')
|
|
5
|
+
: type === 'alphanumeric'
|
|
6
|
+
? trimmed.replace(/[^0-9A-Za-z]/g, '')
|
|
7
|
+
: trimmed;
|
|
8
|
+
return letterCase === 'upper'
|
|
9
|
+
? kept.toUpperCase()
|
|
10
|
+
: letterCase === 'lower'
|
|
11
|
+
? kept.toLowerCase()
|
|
12
|
+
: kept;
|
|
13
|
+
};
|
|
@@ -2,6 +2,8 @@ import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core'
|
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/** What a cell accepts, which decides the keyboard a phone offers. */
|
|
4
4
|
export type PinType = 'alphanumeric' | 'numeric' | 'text';
|
|
5
|
+
/** How typed letters are cased: as typed, or turned upper or lower case. */
|
|
6
|
+
export type PinCase = 'lower' | 'preserve' | 'upper';
|
|
5
7
|
declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
6
8
|
/**
|
|
7
9
|
* @summary A field for a short code, with one box for each character.
|
|
@@ -33,6 +35,21 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
33
35
|
* and the right arrow moves to the next box. The label, hint, and feedback
|
|
34
36
|
* follow the page's direction.
|
|
35
37
|
*
|
|
38
|
+
* **Keyboard.** Each box is a tab stop of its own, as each is a real input.
|
|
39
|
+
*
|
|
40
|
+
* | Key | What it does |
|
|
41
|
+
* |---|---|
|
|
42
|
+
* | A character | Fills the box and moves to the next one. A longer run is read as a paste. |
|
|
43
|
+
* | Left, Right | Moves to the box before or after. |
|
|
44
|
+
* | Home, End | Moves to the first box, or to the box after the last character. |
|
|
45
|
+
* | Backspace | In an empty box, clears the box before it and moves there. |
|
|
46
|
+
* | Delete | Removes the character in the box and pulls the rest of the code back. |
|
|
47
|
+
* | Enter | Submits the form. |
|
|
48
|
+
*
|
|
49
|
+
* The row has `role="group"` and the field's name, and each box is named by
|
|
50
|
+
* `cell-label`, such as "Character 2 of 6". `helix-complete` is a
|
|
51
|
+
* `HelixCompleteEvent` sent once the last box is filled.
|
|
52
|
+
*
|
|
36
53
|
* @since 0.1.0
|
|
37
54
|
* @status stable
|
|
38
55
|
* @category forms
|
|
@@ -55,6 +72,7 @@ declare const HelixHeadlessPinInput_base: (new (...args: any[]) => import("@fusi
|
|
|
55
72
|
* @csspart label - The label above the boxes.
|
|
56
73
|
* @csspart separator - The text `format` draws between two boxes.
|
|
57
74
|
*
|
|
75
|
+
* @cssstate complete - Every box holds a character.
|
|
58
76
|
* @cssstate invalid - The control has an error to show, from the browser's validation or from your `feedback`.
|
|
59
77
|
*/
|
|
60
78
|
export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
@@ -78,6 +96,12 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
78
96
|
* took: a refused last character submits nothing.
|
|
79
97
|
*/
|
|
80
98
|
autosubmit: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* How typed and pasted letters are cased: `upper`, `lower`, or `preserve`
|
|
101
|
+
* to keep them as typed. Web Awesome's OTP input takes the same `case`, for
|
|
102
|
+
* a code a service reads in one case.
|
|
103
|
+
*/
|
|
104
|
+
case: PinCase;
|
|
81
105
|
/**
|
|
82
106
|
* Accessible name for one box, with `{index}` and `{length}` filled in.
|
|
83
107
|
*/
|
|
@@ -147,7 +171,7 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
|
|
|
147
171
|
private get cells();
|
|
148
172
|
/** The code as characters, padded to the row so every box has one to show. */
|
|
149
173
|
private get characters();
|
|
150
|
-
/** Everything this box would accept, with the rest dropped. */
|
|
174
|
+
/** Everything this box would accept, with the rest dropped and cased. */
|
|
151
175
|
private clean;
|
|
152
176
|
/**
|
|
153
177
|
* Writes a run of characters from one box onward.
|