@fusion.dev/helix-headless 0.0.0-dev → 0.0.2
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 +4513 -4483
- package/dist/accordion/item/accordion-item.d.ts +13 -15
- package/dist/accordion/item/accordion-item.js +15 -17
- package/dist/announcement/root/announcement-root.d.ts +7 -25
- package/dist/announcement/root/announcement-root.js +7 -20
- package/dist/app-header/root/app-header-root.d.ts +10 -17
- package/dist/app-header/root/app-header-root.js +9 -18
- package/dist/avatar/group/avatar-group.d.ts +10 -19
- package/dist/avatar/group/avatar-group.js +12 -17
- package/dist/avatar/root/avatar-root.d.ts +8 -8
- package/dist/avatar/root/avatar-root.js +19 -20
- package/dist/badge/root/badge-root.d.ts +6 -6
- package/dist/badge/root/badge-root.js +13 -13
- package/dist/bar-chart/root/bar-chart-root.d.ts +21 -29
- package/dist/bar-chart/root/bar-chart-root.js +42 -57
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +12 -18
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +13 -16
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -28
- package/dist/button/root/button-root.d.ts +84 -94
- package/dist/button/root/button-root.js +82 -92
- package/dist/callout/root/callout-root.d.ts +4 -5
- package/dist/carousel/root/carousel-root.d.ts +59 -71
- package/dist/carousel/root/carousel-root.js +73 -101
- package/dist/chat/composer/chat-composer.d.ts +29 -33
- package/dist/chat/composer/chat-composer.js +40 -44
- package/dist/chat/message/chat-message.d.ts +25 -25
- package/dist/chat/message/chat-message.js +26 -26
- package/dist/chat/root/chat-root.d.ts +28 -41
- package/dist/chat/root/chat-root.js +27 -40
- package/dist/checkbox/root/checkbox-root.d.ts +10 -12
- package/dist/checkbox/root/checkbox-root.js +29 -35
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +32 -45
- package/dist/checkbox-group/root/checkbox-group-root.js +53 -79
- package/dist/code-block/root/code-block-root.d.ts +3 -4
- package/dist/code-block/root/code-block-root.js +8 -12
- package/dist/color-input/root/color-input-root.d.ts +36 -37
- package/dist/color-input/root/color-input-root.js +29 -34
- package/dist/color-picker/color.d.ts +7 -8
- package/dist/color-picker/color.js +7 -8
- package/dist/color-picker/root/color-picker-root.d.ts +55 -57
- package/dist/color-picker/root/color-picker-root.js +60 -64
- package/dist/combobox/root/combobox-root.d.ts +53 -58
- package/dist/combobox/root/combobox-root.js +85 -94
- package/dist/command/root/command-root.d.ts +8 -8
- package/dist/command/root/command-root.js +29 -33
- package/dist/copy-button/root/copy-button-root.d.ts +21 -24
- package/dist/copy-button/root/copy-button-root.js +25 -35
- package/dist/data-table/root/data-table-root.d.ts +77 -76
- package/dist/data-table/root/data-table-root.js +95 -84
- package/dist/data-table/root/order.d.ts +2 -2
- package/dist/data-table/root/order.js +1 -3
- package/dist/date-input/root/date-input-root.d.ts +88 -93
- package/dist/date-input/root/date-input-root.js +147 -158
- package/dist/date-picker/root/date-picker-root.d.ts +75 -83
- package/dist/date-picker/root/date-picker-root.js +120 -143
- package/dist/dialog/root/dialog-root.d.ts +41 -24
- package/dist/dialog/root/dialog-root.js +47 -24
- package/dist/divider/root/divider-root.d.ts +5 -6
- package/dist/divider/root/divider-root.js +4 -5
- package/dist/donut-chart/root/donut-chart-root.d.ts +22 -25
- package/dist/donut-chart/root/donut-chart-root.js +37 -51
- package/dist/drawer/root/drawer-root.d.ts +24 -29
- package/dist/drawer/root/drawer-root.js +15 -22
- package/dist/drilldown/item/drilldown-item.d.ts +14 -14
- package/dist/drilldown/item/drilldown-item.js +24 -26
- package/dist/drilldown/root/drilldown-root.d.ts +8 -10
- package/dist/drilldown/root/drilldown-root.js +6 -7
- package/dist/element-events.generated.js +1 -1
- package/dist/file-input/root/file-input-root.d.ts +20 -24
- package/dist/file-input/root/file-input-root.js +42 -57
- package/dist/format-date/root/format-date-root.js +1 -1
- package/dist/heatmap/root/buckets.d.ts +8 -8
- package/dist/heatmap/root/buckets.js +8 -8
- package/dist/heatmap/root/heatmap-root.d.ts +57 -63
- package/dist/heatmap/root/heatmap-root.js +72 -83
- package/dist/icon/root/icon-root.d.ts +4 -4
- package/dist/icon/root/icon-root.js +9 -9
- package/dist/icon-button/root/icon-button-root.d.ts +4 -6
- package/dist/icon-button/root/icon-button-root.js +4 -6
- package/dist/image/root/image-root.d.ts +49 -59
- package/dist/image/root/image-root.js +55 -65
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/input/root/input-root.d.ts +61 -85
- package/dist/input/root/input-root.js +79 -106
- package/dist/kbd/root/kbd-root.d.ts +8 -7
- package/dist/kbd/root/kbd-root.js +71 -11
- package/dist/legend/root/legend-root.d.ts +1 -1
- package/dist/legend/root/legend-root.js +4 -5
- package/dist/line-chart/root/line-chart-root.d.ts +26 -30
- package/dist/line-chart/root/line-chart-root.js +10 -10
- package/dist/list/item/list-item.d.ts +14 -18
- package/dist/list/item/list-item.js +18 -22
- package/dist/list/root/list-root.d.ts +4 -4
- package/dist/list/root/list-root.js +3 -3
- package/dist/listbox/root/listbox-root.d.ts +31 -58
- package/dist/listbox/root/listbox-root.js +66 -109
- package/dist/megamenu/root/megamenu-root.d.ts +34 -35
- package/dist/megamenu/root/megamenu-root.js +53 -58
- package/dist/menu/item/menu-item.d.ts +39 -53
- package/dist/menu/item/menu-item.js +50 -64
- package/dist/menu/root/menu-root.d.ts +30 -40
- package/dist/menu/root/menu-root.js +49 -82
- package/dist/meter/root/meter-root.d.ts +49 -53
- package/dist/meter/root/meter-root.js +22 -27
- package/dist/navigation/root/navigation-root.js +11 -19
- package/dist/notifications/notification/notification.d.ts +16 -22
- package/dist/notifications/notification/notification.js +21 -27
- package/dist/notifications/root/notifications-root.d.ts +31 -39
- package/dist/notifications/root/notifications-root.js +41 -52
- package/dist/number-input/root/number-input-root.d.ts +31 -33
- package/dist/number-input/root/number-input-root.js +37 -39
- package/dist/option/root/option-root.d.ts +73 -74
- package/dist/option/root/option-root.js +62 -64
- package/dist/outline/root/outline-root.d.ts +38 -44
- package/dist/outline/root/outline-root.js +66 -82
- package/dist/pagination/root/pagination-root.d.ts +87 -92
- package/dist/pagination/root/pagination-root.js +116 -123
- package/dist/pagination/size/pagination-size.d.ts +31 -50
- package/dist/pagination/size/pagination-size.js +35 -55
- package/dist/pagination/summary/pagination-summary.d.ts +12 -12
- package/dist/pagination/summary/pagination-summary.js +18 -18
- package/dist/pin-input/root/pin-input-root.d.ts +53 -70
- package/dist/pin-input/root/pin-input-root.js +74 -94
- package/dist/popover/root/popover-root.d.ts +15 -20
- package/dist/popover/root/popover-root.js +19 -36
- package/dist/progress/root/progress-root.d.ts +12 -14
- package/dist/progress/root/progress-root.js +22 -25
- package/dist/qr-code/root/qr-code-root.d.ts +11 -11
- package/dist/qr-code/root/qr-code-root.js +12 -14
- package/dist/radio/group/radio-group.js +19 -26
- package/dist/radio/root/radio-root.d.ts +12 -13
- package/dist/radio/root/radio-root.js +12 -13
- package/dist/rating/root/rating-root.d.ts +25 -30
- package/dist/rating/root/rating-root.js +43 -50
- package/dist/scroll-area/root/scroll-area-root.d.ts +11 -14
- package/dist/scroll-area/root/scroll-area-root.js +39 -33
- package/dist/select/root/select-root.d.ts +7 -12
- package/dist/select/root/select-root.js +40 -55
- package/dist/slider/root/slider-root.d.ts +53 -60
- package/dist/slider/root/slider-root.js +74 -85
- package/dist/sparkline/root/sparkline-root.d.ts +43 -47
- package/dist/sparkline/root/sparkline-root.js +23 -32
- package/dist/speed-dial/item/speed-dial-item.d.ts +6 -6
- package/dist/speed-dial/item/speed-dial-item.js +9 -9
- package/dist/speed-dial/root/speed-dial-root.d.ts +21 -25
- package/dist/speed-dial/root/speed-dial-root.js +32 -40
- package/dist/splitter/root/splitter-root.d.ts +98 -111
- package/dist/splitter/root/splitter-root.js +96 -123
- package/dist/stat/root/stat-root.d.ts +2 -7
- package/dist/stat/root/stat-root.js +0 -5
- package/dist/steps/step/step.d.ts +19 -24
- package/dist/steps/step/step.js +27 -32
- package/dist/switch/root/switch-root.js +2 -2
- package/dist/table/column/table-column.d.ts +54 -60
- package/dist/table/column/table-column.js +95 -68
- package/dist/table/root/table-root.d.ts +5 -6
- package/dist/table/root/table-root.js +7 -10
- package/dist/tabs/panel/tab-panel.d.ts +21 -25
- package/dist/tabs/panel/tab-panel.js +25 -29
- package/dist/tabs/root/tabs-root.d.ts +25 -34
- package/dist/tabs/root/tabs-root.js +22 -28
- package/dist/tabs/tab/tab.d.ts +12 -12
- package/dist/tabs/tab/tab.js +19 -20
- package/dist/textarea/root/textarea-root.d.ts +36 -36
- package/dist/textarea/root/textarea-root.js +43 -47
- package/dist/time-input/root/time-input-root.d.ts +58 -68
- package/dist/time-input/root/time-input-root.js +62 -77
- package/dist/time-picker/root/time-picker-root.d.ts +73 -79
- package/dist/time-picker/root/time-picker-root.js +72 -84
- package/dist/timeline/item/timeline-item.d.ts +8 -11
- package/dist/timeline/item/timeline-item.js +8 -11
- package/dist/timeline/root/timeline-root.d.ts +5 -7
- package/dist/timeline/root/timeline-root.js +5 -7
- package/dist/toast/item/toast-item.d.ts +9 -27
- package/dist/toast/item/toast-item.js +19 -41
- package/dist/toast/root/toast-root.d.ts +10 -14
- package/dist/toast/root/toast-root.js +4 -5
- package/dist/toggle/group/toggle-group.d.ts +6 -15
- package/dist/toggle/group/toggle-group.js +21 -36
- package/dist/toggle/root/toggle-root.d.ts +26 -27
- package/dist/toggle/root/toggle-root.js +30 -31
- package/dist/toolbar/root/toolbar-root.d.ts +7 -10
- package/dist/toolbar/root/toolbar-root.js +10 -14
- package/dist/tooltip/root/tooltip-root.d.ts +52 -59
- package/dist/tooltip/root/tooltip-root.js +98 -93
- package/dist/tour/root/tour-root.d.ts +19 -23
- package/dist/tour/root/tour-root.js +31 -41
- package/dist/tour/stop/tour-stop.d.ts +14 -15
- package/dist/tour/stop/tour-stop.js +31 -34
- package/dist/tree/item/tree-item.d.ts +30 -35
- package/dist/tree/item/tree-item.js +43 -55
- package/dist/tree/root/tree-root.d.ts +7 -10
- package/dist/tree/root/tree-root.js +33 -42
- package/dist/trend/root/trend-root.d.ts +3 -5
- package/dist/trend/root/trend-root.js +5 -9
- package/dist/video/root/video-root.d.ts +100 -124
- package/dist/video/root/video-root.js +142 -176
- package/dist/video-playlist/item/video-playlist-item.d.ts +16 -16
- package/dist/video-playlist/item/video-playlist-item.js +24 -24
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -8
- package/dist/video-playlist/menu/video-playlist-menu.js +20 -29
- package/dist/video-playlist/root/video-playlist-root.d.ts +16 -11
- package/dist/video-playlist/root/video-playlist-root.js +21 -25
- package/dist/virtual-list/root/virtual-list-root.d.ts +8 -12
- package/dist/virtual-list/root/virtual-list-root.js +11 -16
- package/jsx.d.ts +9797 -12561
- package/package.json +6 -6
- package/vue.d.ts +2684 -3228
|
@@ -41,11 +41,6 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
|
|
|
41
41
|
* dismiss control raise the same event, so a consumer handles one path and not
|
|
42
42
|
* two.
|
|
43
43
|
*
|
|
44
|
-
* The properties below are written by this component and read by whoever draws
|
|
45
|
-
* it. A consumer sets none of them: they carry a number this element computed
|
|
46
|
-
* and CSS cannot, which is what lets a stylesheet on this tier draw the thing
|
|
47
|
-
* without measuring anything itself.
|
|
48
|
-
*
|
|
49
44
|
* @since 0.1.0
|
|
50
45
|
* @status experimental
|
|
51
46
|
* @documentation https://helix.fusion.dev/components/toast
|
|
@@ -82,8 +77,7 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
|
|
|
82
77
|
/**
|
|
83
78
|
* What kind of message it is, which picks the mark and its name.
|
|
84
79
|
*
|
|
85
|
-
*
|
|
86
|
-
* reports a status and never a brand role.
|
|
80
|
+
* A subset of the tone axis: a toast reports a status and never a brand role.
|
|
87
81
|
*/
|
|
88
82
|
tone?: 'danger' | 'info' | 'success' | 'warning';
|
|
89
83
|
/** When the current run of the timer began, or nothing while it is paused. */
|
|
@@ -94,24 +88,15 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
|
|
|
94
88
|
/**
|
|
95
89
|
* Whether the message is still showing.
|
|
96
90
|
*
|
|
97
|
-
* The
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* control looked broken to anyone who pressed it. `Dialog` closes itself,
|
|
101
|
-
* `Accordion` closes itself, and there was no reason a message should not.
|
|
102
|
-
*
|
|
103
|
-
* Declared by the markup and it is the consumer's: the item announces and
|
|
104
|
-
* waits. Not declared and it is the item's: it goes when it is asked to, and
|
|
105
|
-
* the consumer still hears `helix-dismiss` and takes it out of their own
|
|
106
|
-
* list. Read once, at the first update.
|
|
91
|
+
* The item always applies: it goes when it is asked to, having announced
|
|
92
|
+
* `helix-dismiss` first, and a consumer who owns the list refuses that event
|
|
93
|
+
* to take the decision instead.
|
|
107
94
|
*
|
|
108
95
|
* **No `default-open`, unlike the four mixins.** A `default-` seed exists so
|
|
109
96
|
* markup can choose a starting state without claiming ownership, and there is
|
|
110
97
|
* only one starting state that makes sense: a message that has been rendered
|
|
111
98
|
* is showing. An attribute whose only legal value is the default is an
|
|
112
99
|
* attribute nobody can use.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
100
|
*/
|
|
116
101
|
get open(): boolean;
|
|
117
102
|
set open(next: boolean);
|
|
@@ -134,14 +119,11 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
|
|
|
134
119
|
* How many reasons there are to hold the clock, rather than whether there is
|
|
135
120
|
* one.
|
|
136
121
|
*
|
|
137
|
-
* Hover and focus
|
|
138
|
-
* a
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* The two are genuinely independent: a pointer can leave while focus stays,
|
|
143
|
-
* and focus can leave while the pointer stays. Only the last one out starts
|
|
144
|
-
* it again.
|
|
122
|
+
* Hover and focus stop the same timer, and the two are genuinely independent:
|
|
123
|
+
* a pointer can leave while focus stays, and focus can leave while the
|
|
124
|
+
* pointer stays. Uncounted, a reader who tabs into a message and then moves
|
|
125
|
+
* the pointer off it has the clock restarted underneath them, which is the
|
|
126
|
+
* case the pause exists for. Only the last one out starts it again.
|
|
145
127
|
*/
|
|
146
128
|
private holds;
|
|
147
129
|
private readonly handlePause;
|
|
@@ -49,11 +49,6 @@ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
|
49
49
|
* dismiss control raise the same event, so a consumer handles one path and not
|
|
50
50
|
* two.
|
|
51
51
|
*
|
|
52
|
-
* The properties below are written by this component and read by whoever draws
|
|
53
|
-
* it. A consumer sets none of them: they carry a number this element computed
|
|
54
|
-
* and CSS cannot, which is what lets a stylesheet on this tier draw the thing
|
|
55
|
-
* without measuring anything itself.
|
|
56
|
-
*
|
|
57
52
|
* @since 0.1.0
|
|
58
53
|
* @status experimental
|
|
59
54
|
* @documentation https://helix.fusion.dev/components/toast
|
|
@@ -91,14 +86,11 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
91
86
|
* How many reasons there are to hold the clock, rather than whether there is
|
|
92
87
|
* one.
|
|
93
88
|
*
|
|
94
|
-
* Hover and focus
|
|
95
|
-
* a
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* The two are genuinely independent: a pointer can leave while focus stays,
|
|
100
|
-
* and focus can leave while the pointer stays. Only the last one out starts
|
|
101
|
-
* it again.
|
|
89
|
+
* Hover and focus stop the same timer, and the two are genuinely independent:
|
|
90
|
+
* a pointer can leave while focus stays, and focus can leave while the
|
|
91
|
+
* pointer stays. Uncounted, a reader who tabs into a message and then moves
|
|
92
|
+
* the pointer off it has the clock restarted underneath them, which is the
|
|
93
|
+
* case the pause exists for. Only the last one out starts it again.
|
|
102
94
|
*/
|
|
103
95
|
this.holds = 0;
|
|
104
96
|
this.handlePause = () => {
|
|
@@ -115,24 +107,15 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
115
107
|
/**
|
|
116
108
|
* Whether the message is still showing.
|
|
117
109
|
*
|
|
118
|
-
* The
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* control looked broken to anyone who pressed it. `Dialog` closes itself,
|
|
122
|
-
* `Accordion` closes itself, and there was no reason a message should not.
|
|
123
|
-
*
|
|
124
|
-
* Declared by the markup and it is the consumer's: the item announces and
|
|
125
|
-
* waits. Not declared and it is the item's: it goes when it is asked to, and
|
|
126
|
-
* the consumer still hears `helix-dismiss` and takes it out of their own
|
|
127
|
-
* list. Read once, at the first update.
|
|
110
|
+
* The item always applies: it goes when it is asked to, having announced
|
|
111
|
+
* `helix-dismiss` first, and a consumer who owns the list refuses that event
|
|
112
|
+
* to take the decision instead.
|
|
128
113
|
*
|
|
129
114
|
* **No `default-open`, unlike the four mixins.** A `default-` seed exists so
|
|
130
115
|
* markup can choose a starting state without claiming ownership, and there is
|
|
131
116
|
* only one starting state that makes sense: a message that has been rendered
|
|
132
117
|
* is showing. An attribute whose only legal value is the default is an
|
|
133
118
|
* attribute nobody can use.
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
119
|
*/
|
|
137
120
|
get open() {
|
|
138
121
|
return this.openState ?? true;
|
|
@@ -169,9 +152,7 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
169
152
|
exact. A toast is not an overlay that opens and closes: `next` below is
|
|
170
153
|
`false` and nothing here ever calls `requestOpen(true)`, so it only
|
|
171
154
|
ever asks in one direction, and the verb for that direction is
|
|
172
|
-
`dismiss`.
|
|
173
|
-
list and an announcement closing itself, which is the same act from the
|
|
174
|
-
element's side. A consumer controlling `open` therefore answers
|
|
155
|
+
`dismiss`. A consumer controlling `open` therefore answers
|
|
175
156
|
`onhelix-dismiss`, and the generated types ask for exactly that. */
|
|
176
157
|
event: () => this.dismissEvent(),
|
|
177
158
|
host: this,
|
|
@@ -214,25 +195,22 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
214
195
|
}
|
|
215
196
|
willUpdate(changed) {
|
|
216
197
|
super.willUpdate(changed);
|
|
217
|
-
/* Before anything else reads it, and only the first time. Everything that
|
|
218
|
-
declares the mode has arrived by now: attributes from markup or from a
|
|
219
|
-
server's output, and properties a framework assigned on mount. */
|
|
220
198
|
/* Mirrored for CSS rather than reflected onto `open` itself, which is the
|
|
221
199
|
library's rule about state: a reflected `open` is indistinguishable from
|
|
222
200
|
one the consumer declared, and that attribute is what ownership is read
|
|
223
201
|
from. `data-closed` can never be mistaken for a declaration. */
|
|
224
|
-
/* **`data-closed`, because open is the resting state.**
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
202
|
+
/* **`data-closed`, because open is the resting state.** A toast opens by
|
|
203
|
+
default, so a `data-open` would appear on a consumer's server-rendered
|
|
204
|
+
`<helix-toast-item>` without React having sent it. Inverting keeps the
|
|
205
|
+
`data-` hook for the headless consumer this publishes it for, and moves
|
|
206
|
+
the write to the side that only happens after somebody dismisses the
|
|
207
|
+
message, which is long past hydration. */
|
|
230
208
|
this.toggleAttribute('data-closed', !this.open);
|
|
231
209
|
/* And `hidden` beside it, because `data-closed` is a hook and not a
|
|
232
|
-
mechanism.
|
|
233
|
-
`
|
|
234
|
-
|
|
235
|
-
|
|
210
|
+
mechanism. With the hiding living only in the styled sheet's
|
|
211
|
+
`opacity: 0` and `visibility: hidden`, a consumer on this tier has a
|
|
212
|
+
dismissed message that never goes away: measured, a closed base toast
|
|
213
|
+
printed its text on the page.
|
|
236
214
|
It costs the styled tier nothing, the same as the accordion: `:host` sets
|
|
237
215
|
`display: grid` unconditionally so the author rule beats the UA sheet,
|
|
238
216
|
and the exit still animates its row down from `1fr`. */
|
|
@@ -17,11 +17,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
17
17
|
* the page for everyone rather than only for the people who cannot see it.
|
|
18
18
|
*
|
|
19
19
|
* **It never creates or destroys anything.** The consumer renders items and
|
|
20
|
-
* removes them; asking to go is a cancelable `helix-dismiss` from the item.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* that the item no longer waits to be told before hiding, unless the consumer
|
|
20
|
+
* removes them; asking to go is a cancelable `helix-dismiss` from the item. An
|
|
21
|
+
* item that has gone hides itself and stays in the tree, so a consumer whose
|
|
22
|
+
* state still lists it does not have their framework fighting a node this
|
|
23
|
+
* component took away. It hides without waiting to be told, unless the consumer
|
|
25
24
|
* declared `open` and said the state is theirs.
|
|
26
25
|
* There is no `toast.show()`, because an imperative queue inside a component is
|
|
27
26
|
* a second copy of the application's state that nothing can render from: an app
|
|
@@ -51,15 +50,12 @@ export declare class HelixHeadlessToast extends HelixElement {
|
|
|
51
50
|
* toasts is a fact about the page: a stack whose members disagreed about
|
|
52
51
|
* where they were would not be a stack.
|
|
53
52
|
*
|
|
54
|
-
* **Optional, and bottom-end is the absence of it.**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* The SSR spec could never have caught it: it passed a placement explicitly,
|
|
62
|
-
* so the attribute it asserted was one the consumer had written.
|
|
53
|
+
* **Optional, and bottom-end is the absence of it.** Reflecting *and*
|
|
54
|
+
* defaulting is the pair that writes onto a host: every toast region anybody
|
|
55
|
+
* rendered would gain a `placement="bottom-end"` nobody typed, which a React
|
|
56
|
+
* consumer's server markup does not have. The styled sheet carries the resting
|
|
57
|
+
* arrangement in its own `:host` rule and the selectors describe only the
|
|
58
|
+
* departures, which is what `orientation` does.
|
|
63
59
|
*/
|
|
64
60
|
placement?: 'bottom-center' | 'bottom-end' | 'bottom-start' | 'top-center' | 'top-end' | 'top-start';
|
|
65
61
|
protected willUpdate(changed: PropertyValues): void;
|
|
@@ -24,11 +24,10 @@ import { property } from 'lit/decorators.js';
|
|
|
24
24
|
* the page for everyone rather than only for the people who cannot see it.
|
|
25
25
|
*
|
|
26
26
|
* **It never creates or destroys anything.** The consumer renders items and
|
|
27
|
-
* removes them; asking to go is a cancelable `helix-dismiss` from the item.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* that the item no longer waits to be told before hiding, unless the consumer
|
|
27
|
+
* removes them; asking to go is a cancelable `helix-dismiss` from the item. An
|
|
28
|
+
* item that has gone hides itself and stays in the tree, so a consumer whose
|
|
29
|
+
* state still lists it does not have their framework fighting a node this
|
|
30
|
+
* component took away. It hides without waiting to be told, unless the consumer
|
|
32
31
|
* declared `open` and said the state is theirs.
|
|
33
32
|
* There is no `toast.show()`, because an imperative queue inside a component is
|
|
34
33
|
* a second copy of the application's state that nothing can render from: an app
|
|
@@ -54,14 +54,7 @@ declare const HelixHeadlessToggleGroup_base: (new (...args: any[]) => import("@f
|
|
|
54
54
|
* @csspart track - The bar the items sit in.
|
|
55
55
|
*/
|
|
56
56
|
export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_base {
|
|
57
|
-
/**
|
|
58
|
-
* Marks the chosen item, which used to happen inside the placing method.
|
|
59
|
-
*
|
|
60
|
-
* They were one method because the geometry needed the active item anyway,
|
|
61
|
-
* and that made a selection change look like a layout concern. `resolveActiveItem`
|
|
62
|
-
* rather than the first item, because a group opening on a disabled segment
|
|
63
|
-
* marked it as chosen.
|
|
64
|
-
*/
|
|
57
|
+
/** Marks the chosen item, separately from placing the indicator. */
|
|
65
58
|
private sync;
|
|
66
59
|
private readonly indicator;
|
|
67
60
|
private observer;
|
|
@@ -87,14 +80,12 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
|
|
|
87
80
|
protected updated(changed: PropertyValues): void;
|
|
88
81
|
protected willUpdate(changed: PropertyValues): void;
|
|
89
82
|
/**
|
|
90
|
-
* The verdict on the answer
|
|
91
|
-
* getting.
|
|
83
|
+
* The verdict on the answer `required` asks for.
|
|
92
84
|
*
|
|
93
|
-
* `required`
|
|
94
|
-
*
|
|
95
|
-
* unanswered group
|
|
96
|
-
*
|
|
97
|
-
* reader that something will stop them.
|
|
85
|
+
* `required` arrives with `MixinField` and enforces nothing on its own: the
|
|
86
|
+
* attribute reflects and the marker renders beside the label, and without this
|
|
87
|
+
* a form with an unanswered group submits anyway. The marker is a promise to
|
|
88
|
+
* the reader that something will stop them.
|
|
98
89
|
*
|
|
99
90
|
* The anchor is the track rather than the host, so the browser's own bubble
|
|
100
91
|
* points at the control rather than at a box with nothing in it.
|
|
@@ -63,7 +63,6 @@ import { HelixHeadlessToggle } from '../root/toggle-root.js';
|
|
|
63
63
|
let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinControllerValue(MixinField(HelixFormElement)) {
|
|
64
64
|
constructor() {
|
|
65
65
|
super(...arguments);
|
|
66
|
-
/* The mark. The selection sync it used to share a method with is `sync()`. */
|
|
67
66
|
this.indicator = new IndicatorController(this, {
|
|
68
67
|
// The same exact match `sync` makes: nothing chosen means nothing marked,
|
|
69
68
|
// and the controller takes the mark away rather than parking it on item one.
|
|
@@ -80,10 +79,9 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
80
79
|
is an unused one, and the honest reading is that the subclass tier is where
|
|
81
80
|
a consumer would reach for it. */
|
|
82
81
|
this.keys = new KeyboardNavigationController(this, { items: () => this.items });
|
|
83
|
-
/* Stated once, and the group never thinks about it again.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
group would have got none at all. */
|
|
82
|
+
/* Stated once, and the group never thinks about it again. The controller is
|
|
83
|
+
what stops the cascade being hand-called from whichever methods a component
|
|
84
|
+
happens to have. */
|
|
87
85
|
this.cascade = new DisabledCascadeController(this, {
|
|
88
86
|
items: () => this.items,
|
|
89
87
|
});
|
|
@@ -91,25 +89,15 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
91
89
|
this.requestValue(event.detail.value);
|
|
92
90
|
};
|
|
93
91
|
}
|
|
94
|
-
/**
|
|
95
|
-
* Marks the chosen item, which used to happen inside the placing method.
|
|
96
|
-
*
|
|
97
|
-
* They were one method because the geometry needed the active item anyway,
|
|
98
|
-
* and that made a selection change look like a layout concern. `resolveActiveItem`
|
|
99
|
-
* rather than the first item, because a group opening on a disabled segment
|
|
100
|
-
* marked it as chosen.
|
|
101
|
-
*/
|
|
92
|
+
/** Marks the chosen item, separately from placing the indicator. */
|
|
102
93
|
sync() {
|
|
103
|
-
/* An exact match and nothing else
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* while the group reported nothing. A `required` group showed an answer it
|
|
109
|
-
* did not have, and a reader who submitted without touching it was told a
|
|
110
|
-
* value was missing while looking at one.
|
|
94
|
+
/* An exact match and nothing else, never `resolveActiveItem`, which falls
|
|
95
|
+
* back to the first enabled item: a group with no value would mark one
|
|
96
|
+
* anyway, `aria-checked="true"` and the thumb under it and full selected
|
|
97
|
+
* styling, while the group reported nothing. A `required` group would then
|
|
98
|
+
* tell a reader a value is missing while they are looking at one.
|
|
111
99
|
*
|
|
112
|
-
*
|
|
100
|
+
* That fallback is right where it came from. A tab set always shows a panel,
|
|
113
101
|
* so something has to be current; a group that reports a form value has the
|
|
114
102
|
* honest option of reporting none. */
|
|
115
103
|
const active = this.items.find((item) => item.value === this.value);
|
|
@@ -151,8 +139,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
151
139
|
* reordering a list left this permanently dead: the observer gone, nothing
|
|
152
140
|
* to rebuild it, and the component still rendering as though it were
|
|
153
141
|
* watching. Guarded on `hasUpdated`, because the first connection happens
|
|
154
|
-
* before the first render and there is nothing to watch yet.
|
|
155
|
-
* `check:observers` holds it. */
|
|
142
|
+
* before the first render and there is nothing to watch yet. */
|
|
156
143
|
if (this.hasUpdated) {
|
|
157
144
|
this.measure();
|
|
158
145
|
this.watch();
|
|
@@ -209,14 +196,12 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
209
196
|
this.internals.setFormValue(this.value === '' ? null : this.value);
|
|
210
197
|
}
|
|
211
198
|
/**
|
|
212
|
-
* The verdict on the answer
|
|
213
|
-
* getting.
|
|
199
|
+
* The verdict on the answer `required` asks for.
|
|
214
200
|
*
|
|
215
|
-
* `required`
|
|
216
|
-
*
|
|
217
|
-
* unanswered group
|
|
218
|
-
*
|
|
219
|
-
* reader that something will stop them.
|
|
201
|
+
* `required` arrives with `MixinField` and enforces nothing on its own: the
|
|
202
|
+
* attribute reflects and the marker renders beside the label, and without this
|
|
203
|
+
* a form with an unanswered group submits anyway. The marker is a promise to
|
|
204
|
+
* the reader that something will stop them.
|
|
220
205
|
*
|
|
221
206
|
* The anchor is the track rather than the host, so the browser's own bubble
|
|
222
207
|
* points at the control rather than at a box with nothing in it.
|
|
@@ -238,11 +223,11 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
238
223
|
* in it.
|
|
239
224
|
*/
|
|
240
225
|
render() {
|
|
241
|
-
/* The track is an element
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
226
|
+
/* The track is an element rather than the host, and has to be: the label,
|
|
227
|
+
the hint and the message are the host's children too, so a track on the
|
|
228
|
+
host makes them flex items in the same row as the segments. The track also
|
|
229
|
+
owns the box the indicator is measured against, which is why `place` reads
|
|
230
|
+
it rather than `this`. */
|
|
246
231
|
/* **Inside the track when it is placed at the start, not beside it.** A
|
|
247
232
|
label sitting outside reads as a field's label that happens to be on one
|
|
248
233
|
line; inside, with a rule after it, the group reads as one control that
|
|
@@ -24,9 +24,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
24
24
|
*/
|
|
25
25
|
export declare class HelixHeadlessToggle extends HelixElement {
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Whether the item can be chosen.
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
disabled: boolean;
|
|
30
30
|
/**
|
|
31
31
|
* Whether the markup declared this one chosen, which is what a reset returns to.
|
|
32
32
|
*
|
|
@@ -36,24 +36,29 @@ export declare class HelixHeadlessToggle extends HelixElement {
|
|
|
36
36
|
* the markup said at upgrade, before anything could overwrite it: read the
|
|
37
37
|
* attribute later and the listbox's own writes answer instead.
|
|
38
38
|
*
|
|
39
|
-
* **The deeper half is
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* on, which is a change of its own rather than a property being added.
|
|
39
|
+
* **The deeper half is not this.** State reflecting under the declaration's
|
|
40
|
+
* name is the fault `TreeItem` avoids by mirroring to `data-selected`.
|
|
41
|
+
* Splitting them means moving what every stylesheet selects on, which is a
|
|
42
|
+
* change of its own rather than a property being added.
|
|
44
43
|
*/
|
|
45
44
|
get defaultSelected(): boolean;
|
|
46
45
|
set defaultSelected(next: boolean);
|
|
47
46
|
/** What the markup said, read once at construction for the reason above. */
|
|
48
47
|
private seeded;
|
|
49
48
|
/**
|
|
50
|
-
* Whether this item
|
|
49
|
+
* Whether this item holds the group's tab stop while nothing is chosen.
|
|
50
|
+
*
|
|
51
|
+
* The stop normally rides on the selection, and an unanswered group has no
|
|
52
|
+
* selection, so without this the keyboard cannot reach it. Written by the
|
|
53
|
+
* group, with no attribute: it is coordination between elements, and
|
|
54
|
+
* `tabindex` on a host the consumer rendered is the change a React consumer's
|
|
55
|
+
* hydration reports and does not patch up.
|
|
51
56
|
*/
|
|
52
|
-
|
|
57
|
+
focusable: boolean;
|
|
53
58
|
/**
|
|
54
|
-
* Whether
|
|
59
|
+
* Whether this item is the current one.
|
|
55
60
|
*/
|
|
56
|
-
|
|
61
|
+
selected: boolean;
|
|
57
62
|
/**
|
|
58
63
|
* Moves focus to this item's own control.
|
|
59
64
|
*
|
|
@@ -65,29 +70,23 @@ export declare class HelixHeadlessToggle extends HelixElement {
|
|
|
65
70
|
/** Chooses this item and announces it. */
|
|
66
71
|
select(): void;
|
|
67
72
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* The stop normally rides on the selection, and an unanswered group has no
|
|
71
|
-
* selection, so it had no stop and the keyboard could not reach it. Written
|
|
72
|
-
* by the group, with no attribute: it is coordination between elements, and
|
|
73
|
-
* `tabindex` on a host the consumer rendered is the change a React consumer's
|
|
74
|
-
* hydration reports and does not patch up.
|
|
73
|
+
* Identifies the item to the group.
|
|
75
74
|
*/
|
|
76
|
-
|
|
75
|
+
value: string;
|
|
77
76
|
/**
|
|
78
77
|
* Mirrors the chosen state where a stylesheet can select on it.
|
|
79
78
|
*
|
|
80
|
-
* **A custom state
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
79
|
+
* **A custom state rather than the `selected` attribute.** The parent writes
|
|
80
|
+
* this: a listbox choosing a row, a tab strip moving the tab, a radio group
|
|
81
|
+
* answering for its set. Reflected, that puts the element's own bookkeeping
|
|
82
|
+
* onto markup a consumer wrote and a consumer's server never sent, which
|
|
83
|
+
* React reconciles and reports as a mismatch, and which a serialized element
|
|
84
|
+
* pasted back declares as a choice nobody made. `ElementInternals` holds it
|
|
85
|
+
* instead, where it is not in the DOM at all.
|
|
87
86
|
*
|
|
88
87
|
* Reading `selected` is unaffected and so is writing it: the attribute still
|
|
89
88
|
* seeds the property, which is what `<helix-toggle selected>` in a consumer's
|
|
90
|
-
* markup means.
|
|
89
|
+
* markup means. There is no write back.
|
|
91
90
|
*/
|
|
92
91
|
protected willUpdate(changed: PropertyValues): void;
|
|
93
92
|
protected render(): TemplateResult;
|
|
@@ -32,30 +32,30 @@ import { property } from 'lit/decorators.js';
|
|
|
32
32
|
let HelixHeadlessToggle = class HelixHeadlessToggle extends HelixElement {
|
|
33
33
|
constructor() {
|
|
34
34
|
super(...arguments);
|
|
35
|
-
/**
|
|
36
|
-
* Identifies the item to the group.
|
|
37
|
-
*/
|
|
38
|
-
this.value = '';
|
|
39
|
-
/** What the markup said, read once at construction for the reason above. */
|
|
40
|
-
this.seeded = this.hasAttribute('selected');
|
|
41
|
-
/**
|
|
42
|
-
* Whether this item is the current one.
|
|
43
|
-
*/
|
|
44
|
-
this.selected = false;
|
|
45
35
|
/**
|
|
46
36
|
* Whether the item can be chosen.
|
|
47
37
|
*/
|
|
48
38
|
this.disabled = false;
|
|
39
|
+
/** What the markup said, read once at construction for the reason above. */
|
|
40
|
+
this.seeded = this.hasAttribute('selected');
|
|
49
41
|
/**
|
|
50
42
|
* Whether this item holds the group's tab stop while nothing is chosen.
|
|
51
43
|
*
|
|
52
44
|
* The stop normally rides on the selection, and an unanswered group has no
|
|
53
|
-
* selection, so
|
|
54
|
-
*
|
|
45
|
+
* selection, so without this the keyboard cannot reach it. Written by the
|
|
46
|
+
* group, with no attribute: it is coordination between elements, and
|
|
55
47
|
* `tabindex` on a host the consumer rendered is the change a React consumer's
|
|
56
48
|
* hydration reports and does not patch up.
|
|
57
49
|
*/
|
|
58
50
|
this.focusable = false;
|
|
51
|
+
/**
|
|
52
|
+
* Whether this item is the current one.
|
|
53
|
+
*/
|
|
54
|
+
this.selected = false;
|
|
55
|
+
/**
|
|
56
|
+
* Identifies the item to the group.
|
|
57
|
+
*/
|
|
58
|
+
this.value = '';
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Whether the markup declared this one chosen, which is what a reset returns to.
|
|
@@ -66,11 +66,10 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends HelixElement {
|
|
|
66
66
|
* the markup said at upgrade, before anything could overwrite it: read the
|
|
67
67
|
* attribute later and the listbox's own writes answer instead.
|
|
68
68
|
*
|
|
69
|
-
* **The deeper half is
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* on, which is a change of its own rather than a property being added.
|
|
69
|
+
* **The deeper half is not this.** State reflecting under the declaration's
|
|
70
|
+
* name is the fault `TreeItem` avoids by mirroring to `data-selected`.
|
|
71
|
+
* Splitting them means moving what every stylesheet selects on, which is a
|
|
72
|
+
* change of its own rather than a property being added.
|
|
74
73
|
*/
|
|
75
74
|
get defaultSelected() {
|
|
76
75
|
return this.seeded;
|
|
@@ -98,17 +97,17 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends HelixElement {
|
|
|
98
97
|
/**
|
|
99
98
|
* Mirrors the chosen state where a stylesheet can select on it.
|
|
100
99
|
*
|
|
101
|
-
* **A custom state
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
100
|
+
* **A custom state rather than the `selected` attribute.** The parent writes
|
|
101
|
+
* this: a listbox choosing a row, a tab strip moving the tab, a radio group
|
|
102
|
+
* answering for its set. Reflected, that puts the element's own bookkeeping
|
|
103
|
+
* onto markup a consumer wrote and a consumer's server never sent, which
|
|
104
|
+
* React reconciles and reports as a mismatch, and which a serialized element
|
|
105
|
+
* pasted back declares as a choice nobody made. `ElementInternals` holds it
|
|
106
|
+
* instead, where it is not in the DOM at all.
|
|
108
107
|
*
|
|
109
108
|
* Reading `selected` is unaffected and so is writing it: the attribute still
|
|
110
109
|
* seeds the property, which is what `<helix-toggle selected>` in a consumer's
|
|
111
|
-
* markup means.
|
|
110
|
+
* markup means. There is no write back.
|
|
112
111
|
*/
|
|
113
112
|
willUpdate(changed) {
|
|
114
113
|
super.willUpdate(changed);
|
|
@@ -128,18 +127,18 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends HelixElement {
|
|
|
128
127
|
</button>`;
|
|
129
128
|
}
|
|
130
129
|
};
|
|
131
|
-
__decorate([
|
|
132
|
-
property()
|
|
133
|
-
], HelixHeadlessToggle.prototype, "value", void 0);
|
|
134
|
-
__decorate([
|
|
135
|
-
property({ type: Boolean })
|
|
136
|
-
], HelixHeadlessToggle.prototype, "selected", void 0);
|
|
137
130
|
__decorate([
|
|
138
131
|
property({ reflect: true, type: Boolean })
|
|
139
132
|
], HelixHeadlessToggle.prototype, "disabled", void 0);
|
|
140
133
|
__decorate([
|
|
141
134
|
property({ attribute: false })
|
|
142
135
|
], HelixHeadlessToggle.prototype, "focusable", void 0);
|
|
136
|
+
__decorate([
|
|
137
|
+
property({ type: Boolean })
|
|
138
|
+
], HelixHeadlessToggle.prototype, "selected", void 0);
|
|
139
|
+
__decorate([
|
|
140
|
+
property()
|
|
141
|
+
], HelixHeadlessToggle.prototype, "value", void 0);
|
|
143
142
|
HelixHeadlessToggle = __decorate([
|
|
144
143
|
customElement('helix-headless-toggle')
|
|
145
144
|
], HelixHeadlessToggle);
|
|
@@ -42,12 +42,10 @@ export declare class HelixHeadlessToolbar extends HelixElement {
|
|
|
42
42
|
* toolbar holds anything, including elements this package has never heard of.
|
|
43
43
|
* Client only, there being no tree to walk on the server.
|
|
44
44
|
*
|
|
45
|
-
* **It does not ask a child whether it is focusable
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* that is neither disabled nor hidden and still cannot take focus is counted
|
|
50
|
-
* here and skipped there.
|
|
45
|
+
* **It does not ask a child whether it is focusable.** Reading a `focusable`
|
|
46
|
+
* property is what `setTabStop` does when moving the stop, not what this does
|
|
47
|
+
* when choosing the set, so an element that is neither disabled nor hidden and
|
|
48
|
+
* still cannot take focus is counted here and skipped there.
|
|
51
49
|
*/
|
|
52
50
|
private get controls();
|
|
53
51
|
/**
|
|
@@ -75,10 +73,9 @@ export declare class HelixHeadlessToolbar extends HelixElement {
|
|
|
75
73
|
* Gives the tab stop back to a control that still exists.
|
|
76
74
|
*
|
|
77
75
|
* `controls` excludes anything disabled or hidden, so disabling the control
|
|
78
|
-
* holding the stop
|
|
79
|
-
* already at `-1
|
|
80
|
-
*
|
|
81
|
-
* disabling itself once the form is clean.
|
|
76
|
+
* holding the stop drops it out of the list while every other control is
|
|
77
|
+
* already at `-1`, leaving a toolbar the keyboard cannot reach at all. A Save
|
|
78
|
+
* button disabling itself once the form is clean is enough to do it.
|
|
82
79
|
*
|
|
83
80
|
* `foreign` stays false, the same as the first claim: a control this package
|
|
84
81
|
* has never heard of that was never given `tabindex="-1"` is still in the
|