@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
|
@@ -12,8 +12,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* component renders a pane per slide carrying `role="group"`,
|
|
13
13
|
* `aria-roledescription="slide"` and a name reading its position in the set,
|
|
14
14
|
* and assigns the slide into it: a screen-reader user hears where they are, and
|
|
15
|
-
* a slide that is itself a link is still a link
|
|
16
|
-
* was being written on top of it. See `assign`.
|
|
15
|
+
* a slide that is itself a link is still a link. See `assign`.
|
|
17
16
|
*
|
|
18
17
|
* **Rotation stops on focus and on hover, and once stopped it stays stopped.**
|
|
19
18
|
* The APG is explicit: rotation must not resume unless the reader asks for it,
|
|
@@ -57,9 +56,9 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
57
56
|
*/
|
|
58
57
|
static shadowRootOptions: ShadowRootInit;
|
|
59
58
|
/**
|
|
60
|
-
*
|
|
59
|
+
* Whether the carousel advances on its own.
|
|
61
60
|
*/
|
|
62
|
-
|
|
61
|
+
autoplay: boolean;
|
|
63
62
|
/**
|
|
64
63
|
* The slide in view, counted from zero.
|
|
65
64
|
*
|
|
@@ -74,26 +73,9 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
74
73
|
* extracted, because a slide is addressed by position and every one of those
|
|
75
74
|
* mixins is keyed by a name. One consumer is not a mixin: if a second numeric
|
|
76
75
|
* state turns up, this is what it is extracted from.
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
76
|
*/
|
|
80
77
|
get index(): number;
|
|
81
78
|
set index(next: number);
|
|
82
|
-
/**
|
|
83
|
-
* Which way the track runs.
|
|
84
|
-
*
|
|
85
|
-
* Behavior rather than presentation, which is why it is here: the scroll
|
|
86
|
-
* position and the nearest-slide arithmetic are both single-axis, and a
|
|
87
|
-
* styled-tier attribute cannot change which one they read. Two sites branch
|
|
88
|
-
* on it, `scrollTo` and the drag settle, and nothing else in the component
|
|
89
|
-
* knows about the axis at all.
|
|
90
|
-
*
|
|
91
|
-
* A vertical track needs a height, which a horizontal one does not: width
|
|
92
|
-
* comes from the page and height does not, so the styled tier gives it
|
|
93
|
-
* `--carousel-block-size` and a consumer sets that to whatever the slides
|
|
94
|
-
* want.
|
|
95
|
-
*/
|
|
96
|
-
orientation?: 'horizontal' | 'vertical';
|
|
97
79
|
/**
|
|
98
80
|
* Whether the previous and next controls are shown.
|
|
99
81
|
*
|
|
@@ -124,20 +106,35 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
124
106
|
* Slide to start on, where nothing declared one.
|
|
125
107
|
*/
|
|
126
108
|
defaultIndex: number;
|
|
109
|
+
/**
|
|
110
|
+
* How long each slide is held, in milliseconds.
|
|
111
|
+
*/
|
|
112
|
+
interval: number;
|
|
127
113
|
/** The slide in view, whoever set it, and `undefined` until somebody has. */
|
|
128
114
|
private indexState;
|
|
129
115
|
/**
|
|
130
|
-
*
|
|
116
|
+
* Accessible name for the carousel.
|
|
131
117
|
*/
|
|
132
|
-
|
|
118
|
+
label: string;
|
|
133
119
|
/**
|
|
134
|
-
* Whether
|
|
120
|
+
* Whether moving past either end wraps to the other.
|
|
135
121
|
*/
|
|
136
|
-
|
|
122
|
+
loop: boolean;
|
|
137
123
|
/**
|
|
138
|
-
*
|
|
124
|
+
* Which way the track runs.
|
|
125
|
+
*
|
|
126
|
+
* Behavior rather than presentation, which is why it is here: the scroll
|
|
127
|
+
* position and the nearest-slide arithmetic are both single-axis, and a
|
|
128
|
+
* styled-tier attribute cannot change which one they read. Two sites branch
|
|
129
|
+
* on it, `scrollTo` and the drag settle, and nothing else in the component
|
|
130
|
+
* knows about the axis at all.
|
|
131
|
+
*
|
|
132
|
+
* A vertical track needs a height, which a horizontal one does not: width
|
|
133
|
+
* comes from the page and height does not, so the styled tier gives it
|
|
134
|
+
* `--carousel-block-size` and a consumer sets that to whatever the slides
|
|
135
|
+
* want.
|
|
139
136
|
*/
|
|
140
|
-
|
|
137
|
+
orientation?: 'horizontal' | 'vertical';
|
|
141
138
|
/**
|
|
142
139
|
* Whether rotation is running.
|
|
143
140
|
*
|
|
@@ -149,14 +146,13 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
149
146
|
* How many slides are shown across the track at once. Absent shows one.
|
|
150
147
|
*
|
|
151
148
|
* **Here rather than on the styled tier, because it decides how many places
|
|
152
|
-
* the track can stop.**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* to the end while the slides stopped moving a third of the way through.
|
|
149
|
+
* the track can stop.** From the stylesheet it looks like a width, one rule
|
|
150
|
+
* per value setting a custom property that the slides divide the track by.
|
|
151
|
+
* But a carousel showing four of six slides has three positions, not six, and
|
|
152
|
+
* everything that counts positions is in this file. Declared up there, `goTo`
|
|
153
|
+
* clamps to the last *slide*, so three of the six indicators point at an
|
|
154
|
+
* offset the track has already reached: pressing next walks the dots to the
|
|
155
|
+
* end while the slides stop moving a third of the way through.
|
|
160
156
|
*
|
|
161
157
|
* No default, because it reflects. A reflected property with a value writes
|
|
162
158
|
* its attribute on upgrade, and the host then carries something a consumer's
|
|
@@ -254,12 +250,11 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
254
250
|
/**
|
|
255
251
|
* Owns the timer, from the state rather than from the call site.
|
|
256
252
|
*
|
|
257
|
-
* `start()` and `stop()`
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
* place clears it.
|
|
253
|
+
* Never hold the interval in `start()` and `stop()` and start one from
|
|
254
|
+
* `connectedCallback`: a DOM move re-runs connect and restarts rotation the
|
|
255
|
+
* reader stopped, and the server, which never runs connect at all, renders
|
|
256
|
+
* the control saying the opposite of what it will do. The state is what is
|
|
257
|
+
* declared and the timer follows it, which also means one place clears it.
|
|
263
258
|
*/
|
|
264
259
|
private runTimer;
|
|
265
260
|
/**
|
|
@@ -281,9 +276,8 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
281
276
|
*
|
|
282
277
|
* **`scrollend` is the only honest place to commit an index and much too late
|
|
283
278
|
* to show one.** It fires once momentum has fully settled, which on iOS is
|
|
284
|
-
* most of a second after the finger has left the glass, so the dots
|
|
285
|
-
* the old slide for the whole of the coast and then
|
|
286
|
-
* that way, as the delay on the indicator being too great.
|
|
279
|
+
* most of a second after the finger has left the glass, so the dots sit on
|
|
280
|
+
* the old slide for the whole of the coast and then jump.
|
|
287
281
|
*
|
|
288
282
|
* So showing and committing are separated. This moves the marker and nothing
|
|
289
283
|
* else: no state is written and no event is dispatched, because neither is
|
|
@@ -305,13 +299,13 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
305
299
|
* Reads where a reader's drag settled, and only a reader's.
|
|
306
300
|
*
|
|
307
301
|
* **The scroll we issued ourselves ends with a `scrollend` too, and taking it
|
|
308
|
-
* as a reading is what makes the dots jump back.**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
302
|
+
* as a reading is what makes the dots jump back.** Run on every one, the
|
|
303
|
+
* index a reader just chose is overwritten by whichever slide happened to be
|
|
304
|
+
* nearest the leading edge when the animation finished. Any disagreement
|
|
305
|
+
* there is enough: a snap settling a pixel short of a midpoint, a target
|
|
306
|
+
* clamped by the scroller's own maximum, a fractional layout, or a smooth
|
|
307
|
+
* scroll cut off by the next click. The component asked for slide four, the
|
|
308
|
+
* pixels said three, and the pixels won.
|
|
315
309
|
*
|
|
316
310
|
* Which is the wrong precedence in one direction only. A drag is the reader
|
|
317
311
|
* moving the track and the index has to follow it; a click is the reader
|
|
@@ -363,31 +357,25 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
363
357
|
* **The panes carry the ARIA and the consumer's element carries none**, which
|
|
364
358
|
* is the whole reason this is a manual assignment rather than a plain slot.
|
|
365
359
|
* The APG wants each slide to be a `group` with `aria-roledescription="slide"`
|
|
366
|
-
* and a name saying where it sits in the run, and
|
|
367
|
-
*
|
|
368
|
-
* wrong with that, and only one of them was about frameworks.
|
|
360
|
+
* and a name saying where it sits in the run, and writing those onto the
|
|
361
|
+
* elements a consumer wrote fails twice, only one of them about frameworks.
|
|
369
362
|
*
|
|
370
363
|
* **A React consumer's slides are nodes React is in the middle of hydrating.**
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
* reason and its comment on `shadowRootOptions` says so.
|
|
364
|
+
* Attributes landing before React reaches them are a DOM it did not render,
|
|
365
|
+
* which it reports as a mismatch and will not patch up: the ARIA survives and
|
|
366
|
+
* the announcement is correct, so the console is the only tell. Deferring the
|
|
367
|
+
* write does not help, a frame being a race rather than an ordering: measured
|
|
368
|
+
* in Chromium on the landing page, a tab opened in the foreground still
|
|
369
|
+
* reported the mismatch and a tab opened hidden did not, only because
|
|
370
|
+
* `requestAnimationFrame` had not run there yet. `Chat`'s comment on
|
|
371
|
+
* `shadowRootOptions` reaches the same conclusion.
|
|
380
372
|
*
|
|
381
373
|
* **And `role="group"` on a consumer's `<a href>` is not additive.** It
|
|
382
374
|
* replaces the implicit link role, so six insight cards on the landing page
|
|
383
|
-
* announced as groups and left the links list entirely.
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
* relabeled as a group.
|
|
388
|
-
*
|
|
389
|
-
* So nothing is written onto a consumer's element at all now, and the
|
|
390
|
-
* mismatch is gone by construction rather than by timing.
|
|
375
|
+
* announced as groups and left the links list entirely. No amount of
|
|
376
|
+
* deferring helps, because the write is the bug. A pane around the slide is
|
|
377
|
+
* what the pattern actually asks for: a group holding a link, rather than a
|
|
378
|
+
* link relabeled as a group.
|
|
391
379
|
*/
|
|
392
380
|
private assign;
|
|
393
381
|
protected render(): TemplateResult;
|
|
@@ -21,8 +21,7 @@ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
|
21
21
|
* component renders a pane per slide carrying `role="group"`,
|
|
22
22
|
* `aria-roledescription="slide"` and a name reading its position in the set,
|
|
23
23
|
* and assigns the slide into it: a screen-reader user hears where they are, and
|
|
24
|
-
* a slide that is itself a link is still a link
|
|
25
|
-
* was being written on top of it. See `assign`.
|
|
24
|
+
* a slide that is itself a link is still a link. See `assign`.
|
|
26
25
|
*
|
|
27
26
|
* **Rotation stops on focus and on hover, and once stopped it stays stopped.**
|
|
28
27
|
* The APG is explicit: rotation must not resume unless the reader asks for it,
|
|
@@ -55,27 +54,27 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
55
54
|
constructor() {
|
|
56
55
|
super(...arguments);
|
|
57
56
|
/**
|
|
58
|
-
*
|
|
57
|
+
* Whether the carousel advances on its own.
|
|
59
58
|
*/
|
|
60
|
-
this.
|
|
59
|
+
this.autoplay = false;
|
|
61
60
|
/**
|
|
62
61
|
* Slide to start on, where nothing declared one.
|
|
63
62
|
*/
|
|
64
63
|
this.defaultIndex = 0;
|
|
65
|
-
/** The slide in view, whoever set it, and `undefined` until somebody has. */
|
|
66
|
-
this.indexState = undefined;
|
|
67
64
|
/**
|
|
68
|
-
*
|
|
65
|
+
* How long each slide is held, in milliseconds.
|
|
69
66
|
*/
|
|
70
|
-
this.
|
|
67
|
+
this.interval = 5000;
|
|
68
|
+
/** The slide in view, whoever set it, and `undefined` until somebody has. */
|
|
69
|
+
this.indexState = undefined;
|
|
71
70
|
/**
|
|
72
|
-
*
|
|
71
|
+
* Accessible name for the carousel.
|
|
73
72
|
*/
|
|
74
|
-
this.
|
|
73
|
+
this.label = 'Carousel';
|
|
75
74
|
/**
|
|
76
|
-
*
|
|
75
|
+
* Whether moving past either end wraps to the other.
|
|
77
76
|
*/
|
|
78
|
-
this.
|
|
77
|
+
this.loop = false;
|
|
79
78
|
/**
|
|
80
79
|
* Whether rotation is running.
|
|
81
80
|
*
|
|
@@ -124,9 +123,8 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
124
123
|
*
|
|
125
124
|
* **`scrollend` is the only honest place to commit an index and much too late
|
|
126
125
|
* to show one.** It fires once momentum has fully settled, which on iOS is
|
|
127
|
-
* most of a second after the finger has left the glass, so the dots
|
|
128
|
-
* the old slide for the whole of the coast and then
|
|
129
|
-
* that way, as the delay on the indicator being too great.
|
|
126
|
+
* most of a second after the finger has left the glass, so the dots sit on
|
|
127
|
+
* the old slide for the whole of the coast and then jump.
|
|
130
128
|
*
|
|
131
129
|
* So showing and committing are separated. This moves the marker and nothing
|
|
132
130
|
* else: no state is written and no event is dispatched, because neither is
|
|
@@ -159,13 +157,13 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
159
157
|
* Reads where a reader's drag settled, and only a reader's.
|
|
160
158
|
*
|
|
161
159
|
* **The scroll we issued ourselves ends with a `scrollend` too, and taking it
|
|
162
|
-
* as a reading is what makes the dots jump back.**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
160
|
+
* as a reading is what makes the dots jump back.** Run on every one, the
|
|
161
|
+
* index a reader just chose is overwritten by whichever slide happened to be
|
|
162
|
+
* nearest the leading edge when the animation finished. Any disagreement
|
|
163
|
+
* there is enough: a snap settling a pixel short of a midpoint, a target
|
|
164
|
+
* clamped by the scroller's own maximum, a fractional layout, or a smooth
|
|
165
|
+
* scroll cut off by the next click. The component asked for slide four, the
|
|
166
|
+
* pixels said three, and the pixels won.
|
|
169
167
|
*
|
|
170
168
|
* Which is the wrong precedence in one direction only. A drag is the reader
|
|
171
169
|
* moving the track and the index has to follow it; a click is the reader
|
|
@@ -190,7 +188,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
190
188
|
to refuse, and `preventDefault()` could not un-drag it. This is the case
|
|
191
189
|
the controlled-change helper's own documentation distinguishes, a native
|
|
192
190
|
control that has already moved, and putting it on that path would offer a
|
|
193
|
-
refusal that cannot be
|
|
191
|
+
refusal that cannot be honored. */
|
|
194
192
|
if (nearest === this.index) {
|
|
195
193
|
return;
|
|
196
194
|
}
|
|
@@ -258,8 +256,6 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
258
256
|
* extracted, because a slide is addressed by position and every one of those
|
|
259
257
|
* mixins is keyed by a name. One consumer is not a mixin: if a second numeric
|
|
260
258
|
* state turns up, this is what it is extracted from.
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
259
|
*/
|
|
264
260
|
get index() {
|
|
265
261
|
return this.indexState ?? this.defaultIndex;
|
|
@@ -294,19 +290,15 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
294
290
|
}
|
|
295
291
|
/** The slides, in light-DOM order. Empty on the server, which has no tree. */
|
|
296
292
|
get slides() {
|
|
297
|
-
/* `?? []` is the server, and
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
spread of `undefined`. Third time in this library, after the menu item
|
|
301
|
-
and the table, and the only one of the three the note was written on.
|
|
302
|
-
Knowing where a getter must not be reached is not the same as it not
|
|
303
|
-
being reached, which is what the guard is for.
|
|
293
|
+
/* `?? []` is the server, and a note saying "client only" is not a guard:
|
|
294
|
+
`render` reads this to count the indicators, so an unhandled spread of
|
|
295
|
+
`undefined` kills every carousel SSR pass.
|
|
304
296
|
|
|
305
297
|
Empty is also the honest answer rather than damage control. The
|
|
306
298
|
indicators are one per position and a position is counted from the
|
|
307
|
-
children, which the server cannot see, so they
|
|
308
|
-
|
|
309
|
-
|
|
299
|
+
children, which the server cannot see, so they arrive with the upgrade.
|
|
300
|
+
Nothing moves when they do: the tags are hidden until they are
|
|
301
|
+
defined. */
|
|
310
302
|
return [...(this.children ?? [])].filter((child) => child instanceof HTMLElement);
|
|
311
303
|
}
|
|
312
304
|
/** Moves to a slide, wrapping only where `loop` says to. */
|
|
@@ -390,12 +382,6 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
390
382
|
if (!slide || !track) {
|
|
391
383
|
return;
|
|
392
384
|
}
|
|
393
|
-
/* The preference is read here, because this is where the motion is.
|
|
394
|
-
*
|
|
395
|
-
* `scroll-behavior: auto` in a reduce block does nothing: it restates the
|
|
396
|
-
* initial value, and the scroll that actually animates is this call, which
|
|
397
|
-
* names `smooth` outright and overrides the property either way. A reader
|
|
398
|
-
* who asked not to be moved was moved. */
|
|
399
385
|
const vertical = this.orientation === 'vertical';
|
|
400
386
|
const target = this.edgeOf(slide, track, this.bleed(track));
|
|
401
387
|
/* Already there, and saying so rather than asking anyway.
|
|
@@ -413,8 +399,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
413
399
|
*
|
|
414
400
|
* `scroll-behavior: auto` in a reduce block does nothing: it restates the
|
|
415
401
|
* initial value, and the scroll that actually animates is this call, which
|
|
416
|
-
* names `smooth` outright and overrides the property either way.
|
|
417
|
-
* who asked not to be moved was moved. */
|
|
402
|
+
* names `smooth` outright and overrides the property either way. */
|
|
418
403
|
const still = globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
|
|
419
404
|
/* The scroll about to run is ours, so the `scrollend` it produces is not a
|
|
420
405
|
reader saying where they went. See `handleScroll`. */
|
|
@@ -443,12 +428,11 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
443
428
|
/**
|
|
444
429
|
* Owns the timer, from the state rather than from the call site.
|
|
445
430
|
*
|
|
446
|
-
* `start()` and `stop()`
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* place clears it.
|
|
431
|
+
* Never hold the interval in `start()` and `stop()` and start one from
|
|
432
|
+
* `connectedCallback`: a DOM move re-runs connect and restarts rotation the
|
|
433
|
+
* reader stopped, and the server, which never runs connect at all, renders
|
|
434
|
+
* the control saying the opposite of what it will do. The state is what is
|
|
435
|
+
* declared and the timer follows it, which also means one place clears it.
|
|
452
436
|
*/
|
|
453
437
|
runTimer() {
|
|
454
438
|
clearInterval(this.timer);
|
|
@@ -520,24 +504,20 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
520
504
|
super.updated(changed);
|
|
521
505
|
/* The track follows `index`, whoever moved it.
|
|
522
506
|
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* updated and the slides sat still. Every other path in was equally
|
|
527
|
-
* stranded, a plain `carousel.index = 2` included, apply being the only
|
|
528
|
-
* caller. Here it is one place and it covers all of them. */
|
|
507
|
+
* Not from inside `goTo`'s apply callback: that returns early in controlled
|
|
508
|
+
* mode, so the dots update and the slides sit still, and it is not the only
|
|
509
|
+
* path in either, a plain `carousel.index = 2` reaching no apply at all. */
|
|
529
510
|
if (changed.has('index')) {
|
|
530
511
|
this.scrollToIndex();
|
|
531
512
|
}
|
|
532
513
|
this.runTimer();
|
|
533
514
|
/* Back inside the set when the set shrinks.
|
|
534
515
|
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
* overwritten. */
|
|
516
|
+
* The indicators carry a roving tab stop keyed on `index`, so a carousel
|
|
517
|
+
* whose slides are removed under it is left with no tab stop, no current
|
|
518
|
+
* dot and a focus restore pointing at nothing. In `updated` rather than
|
|
519
|
+
* `willUpdate` because `slides` is empty on the server, and through `goTo`
|
|
520
|
+
* so a controlled consumer is told rather than overwritten. */
|
|
541
521
|
const count = this.slides.length;
|
|
542
522
|
if (count > 0 && this.index > count - 1) {
|
|
543
523
|
this.goTo(count - 1);
|
|
@@ -550,31 +530,25 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
550
530
|
* **The panes carry the ARIA and the consumer's element carries none**, which
|
|
551
531
|
* is the whole reason this is a manual assignment rather than a plain slot.
|
|
552
532
|
* The APG wants each slide to be a `group` with `aria-roledescription="slide"`
|
|
553
|
-
* and a name saying where it sits in the run, and
|
|
554
|
-
*
|
|
555
|
-
* wrong with that, and only one of them was about frameworks.
|
|
533
|
+
* and a name saying where it sits in the run, and writing those onto the
|
|
534
|
+
* elements a consumer wrote fails twice, only one of them about frameworks.
|
|
556
535
|
*
|
|
557
536
|
* **A React consumer's slides are nodes React is in the middle of hydrating.**
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
* reason and its comment on `shadowRootOptions` says so.
|
|
537
|
+
* Attributes landing before React reaches them are a DOM it did not render,
|
|
538
|
+
* which it reports as a mismatch and will not patch up: the ARIA survives and
|
|
539
|
+
* the announcement is correct, so the console is the only tell. Deferring the
|
|
540
|
+
* write does not help, a frame being a race rather than an ordering: measured
|
|
541
|
+
* in Chromium on the landing page, a tab opened in the foreground still
|
|
542
|
+
* reported the mismatch and a tab opened hidden did not, only because
|
|
543
|
+
* `requestAnimationFrame` had not run there yet. `Chat`'s comment on
|
|
544
|
+
* `shadowRootOptions` reaches the same conclusion.
|
|
567
545
|
*
|
|
568
546
|
* **And `role="group"` on a consumer's `<a href>` is not additive.** It
|
|
569
547
|
* replaces the implicit link role, so six insight cards on the landing page
|
|
570
|
-
* announced as groups and left the links list entirely.
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
* relabeled as a group.
|
|
575
|
-
*
|
|
576
|
-
* So nothing is written onto a consumer's element at all now, and the
|
|
577
|
-
* mismatch is gone by construction rather than by timing.
|
|
548
|
+
* announced as groups and left the links list entirely. No amount of
|
|
549
|
+
* deferring helps, because the write is the bug. A pane around the slide is
|
|
550
|
+
* what the pattern actually asks for: a group holding a link, rather than a
|
|
551
|
+
* link relabeled as a group.
|
|
578
552
|
*/
|
|
579
553
|
assign() {
|
|
580
554
|
const panes = this.renderRoot?.querySelectorAll?.('[part="slide"] slot');
|
|
@@ -659,16 +633,14 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
659
633
|
${
|
|
660
634
|
/* Plain buttons, not a half-built tablist.
|
|
661
635
|
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* right word for "the one you are on" where nothing is being
|
|
671
|
-
* selected. */
|
|
636
|
+
* `role="tab"` in a `role="tablist"` promises tabpanels, and
|
|
637
|
+
* the slides are `role="group"`: the APG has two carousel
|
|
638
|
+
* patterns and taking the announcement of one over the
|
|
639
|
+
* structure of the other tells a reader to expect panels that
|
|
640
|
+
* do not exist. This is the basic pattern, buttons that move
|
|
641
|
+
* the carousel with the current one marked, and `aria-current`
|
|
642
|
+
* is the right word for "the one you are on" where nothing is
|
|
643
|
+
* being selected. */
|
|
672
644
|
''}
|
|
673
645
|
${Array.from({ length: this.positions }).map((_place, at) => html `<button
|
|
674
646
|
part="indicator"
|
|
@@ -685,14 +657,11 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
685
657
|
}
|
|
686
658
|
};
|
|
687
659
|
__decorate([
|
|
688
|
-
property()
|
|
689
|
-
], HelixHeadlessCarousel.prototype, "
|
|
660
|
+
property({ type: Boolean })
|
|
661
|
+
], HelixHeadlessCarousel.prototype, "autoplay", void 0);
|
|
690
662
|
__decorate([
|
|
691
663
|
property({ type: Number })
|
|
692
664
|
], HelixHeadlessCarousel.prototype, "index", null);
|
|
693
|
-
__decorate([
|
|
694
|
-
property({ reflect: true })
|
|
695
|
-
], HelixHeadlessCarousel.prototype, "orientation", void 0);
|
|
696
665
|
__decorate([
|
|
697
666
|
property({ reflect: true })
|
|
698
667
|
], HelixHeadlessCarousel.prototype, "controls", void 0);
|
|
@@ -700,14 +669,17 @@ __decorate([
|
|
|
700
669
|
property({ attribute: 'default-index', type: Number })
|
|
701
670
|
], HelixHeadlessCarousel.prototype, "defaultIndex", void 0);
|
|
702
671
|
__decorate([
|
|
703
|
-
property({ type:
|
|
704
|
-
], HelixHeadlessCarousel.prototype, "
|
|
672
|
+
property({ type: Number })
|
|
673
|
+
], HelixHeadlessCarousel.prototype, "interval", void 0);
|
|
674
|
+
__decorate([
|
|
675
|
+
property()
|
|
676
|
+
], HelixHeadlessCarousel.prototype, "label", void 0);
|
|
705
677
|
__decorate([
|
|
706
678
|
property({ type: Boolean })
|
|
707
|
-
], HelixHeadlessCarousel.prototype, "
|
|
679
|
+
], HelixHeadlessCarousel.prototype, "loop", void 0);
|
|
708
680
|
__decorate([
|
|
709
|
-
property({
|
|
710
|
-
], HelixHeadlessCarousel.prototype, "
|
|
681
|
+
property({ reflect: true })
|
|
682
|
+
], HelixHeadlessCarousel.prototype, "orientation", void 0);
|
|
711
683
|
__decorate([
|
|
712
684
|
state()
|
|
713
685
|
], HelixHeadlessCarousel.prototype, "rotating", void 0);
|
|
@@ -39,15 +39,27 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
39
39
|
*/
|
|
40
40
|
export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Read it, or set it to seed a draft.
|
|
42
|
+
* Whether the composer refuses input, while a turn is in flight say.
|
|
45
43
|
*/
|
|
46
|
-
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Accessible name for the field.
|
|
47
|
+
*/
|
|
48
|
+
label: string;
|
|
47
49
|
/**
|
|
48
50
|
* Shown in an empty field.
|
|
49
51
|
*/
|
|
50
52
|
placeholder: string;
|
|
53
|
+
/**
|
|
54
|
+
* How many rows the field opens at.
|
|
55
|
+
*
|
|
56
|
+
* It grows from there.
|
|
57
|
+
*/
|
|
58
|
+
rows: number;
|
|
59
|
+
/**
|
|
60
|
+
* Label for the control that sends.
|
|
61
|
+
*/
|
|
62
|
+
sendLabel: string;
|
|
51
63
|
/**
|
|
52
64
|
* What sends: pressing Enter, or only the control.
|
|
53
65
|
*
|
|
@@ -57,23 +69,11 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
57
69
|
*/
|
|
58
70
|
submitOn: 'button' | 'enter';
|
|
59
71
|
/**
|
|
60
|
-
*
|
|
61
|
-
*/
|
|
62
|
-
disabled: boolean;
|
|
63
|
-
/**
|
|
64
|
-
* Accessible name for the field.
|
|
65
|
-
*/
|
|
66
|
-
label: string;
|
|
67
|
-
/**
|
|
68
|
-
* Label for the control that sends.
|
|
69
|
-
*/
|
|
70
|
-
sendLabel: string;
|
|
71
|
-
/**
|
|
72
|
-
* How many rows the field opens at.
|
|
72
|
+
* What the reader has written.
|
|
73
73
|
*
|
|
74
|
-
*
|
|
74
|
+
* Read it, or set it to seed a draft.
|
|
75
75
|
*/
|
|
76
|
-
|
|
76
|
+
value: string;
|
|
77
77
|
private draft;
|
|
78
78
|
/**
|
|
79
79
|
* @internal Read by the transcript to find the composer among its children.
|
|
@@ -105,24 +105,20 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
105
105
|
*
|
|
106
106
|
* **A glyph with the label as its accessible name, rather than the label as
|
|
107
107
|
* text.** The word "Send" beside a field is the widest thing in the row and
|
|
108
|
-
* says nothing a return key does not
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* `send-label` is unchanged and is now the accessible name rather than the
|
|
114
|
-
* visible one, so a screen reader hears the same word it always did.
|
|
108
|
+
* says nothing a return key does not. The return glyph is the mark because
|
|
109
|
+
* Enter is what actually sends, which `submit-on` says out loud: the control
|
|
110
|
+
* and the key are one affordance and should look like it. `send-label` is the
|
|
111
|
+
* accessible name rather than a visible one, so a screen reader still hears
|
|
112
|
+
* the word.
|
|
115
113
|
*/
|
|
116
114
|
protected renderSend(): TemplateResult;
|
|
117
115
|
/**
|
|
118
116
|
* The field, and a row of tools under it.
|
|
119
117
|
*
|
|
120
|
-
* **
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* into. Under it, the field spans the whole composer at every width and the
|
|
125
|
-
* tools have a line of their own to grow along.
|
|
118
|
+
* **The tools take a line of their own rather than sharing the field's.** On
|
|
119
|
+
* one line every tool a consumer adds takes width away from the thing being
|
|
120
|
+
* typed into; under it, the field spans the whole composer at every width and
|
|
121
|
+
* the tools have room to grow along.
|
|
126
122
|
*
|
|
127
123
|
* Send is at the trailing end of that line rather than in the field, which is
|
|
128
124
|
* the same corner and costs no overlay: a control positioned inside a
|
|
@@ -138,7 +134,7 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
138
134
|
* whatever `<helix-chat>` it is slotted into, and neither element declares an
|
|
139
135
|
* `input`: a consumer binding one on either received an undeclared event whose
|
|
140
136
|
* target was a control they cannot reach. What a composer offers is
|
|
141
|
-
* `helix-send`, once, when the reader is done.
|
|
137
|
+
* `helix-send`, once, when the reader is done.
|
|
142
138
|
*/
|
|
143
139
|
private readonly handleInput;
|
|
144
140
|
private readonly handleSend;
|