@fusion.dev/helix-headless 0.170.0 → 0.172.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 +1045 -154
- package/dist/chat/composer/chat-composer.d.ts +30 -2
- package/dist/chat/composer/chat-composer.js +29 -4
- package/dist/chat/root/chat-root.d.ts +73 -7
- package/dist/chat/root/chat-root.js +90 -5
- package/dist/code-block/root/code-block-root.d.ts +20 -2
- package/dist/code-block/root/code-block-root.js +29 -8
- package/dist/color-input/root/color-input-root.d.ts +15 -1
- package/dist/color-input/root/color-input-root.js +19 -1
- package/dist/color-picker/root/color-picker-root.d.ts +54 -7
- package/dist/color-picker/root/color-picker-root.js +62 -1
- package/dist/combobox/root/combobox-root.d.ts +16 -6
- package/dist/combobox/root/combobox-root.js +9 -2
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +8 -0
- package/dist/data-table/root/data-table-root.d.ts +5 -1
- package/dist/data-table/root/data-table-root.js +1 -0
- package/dist/dialog/root/dialog-root.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +4 -0
- package/dist/drawer/root/drawer-root.js +1 -0
- package/dist/element-events.generated.js +1 -0
- package/dist/filter-input/chip/filter-chip.d.ts +13 -3
- package/dist/filter-input/chip/filter-chip.js +5 -0
- package/dist/filter-input/menu/filter-menu.js +0 -1
- package/dist/filter-input/root/filter-input-root.d.ts +71 -4
- package/dist/filter-input/root/filter-input-root.js +87 -2
- package/dist/format-date/root/format-date-root.d.ts +3 -1
- package/dist/input/root/input-root.d.ts +6 -0
- package/dist/input/root/input-root.js +13 -0
- package/dist/lightbox/root/lightbox-root.js +1 -0
- package/dist/listbox/root/listbox-root.d.ts +8 -1
- package/dist/listbox/root/listbox-root.js +9 -3
- package/dist/menu/item/menu-item.d.ts +2 -0
- package/dist/menu/item/menu-item.js +2 -0
- package/dist/menu/root/menu-root.d.ts +73 -12
- package/dist/menu/root/menu-root.js +103 -7
- package/dist/number-input/root/number-input-root.d.ts +16 -6
- package/dist/number-input/root/number-input-root.js +15 -4
- package/dist/popover/root/popover-root.d.ts +59 -6
- package/dist/popover/root/popover-root.js +51 -3
- package/dist/select/root/select-root.d.ts +2 -2
- package/dist/select/root/select-root.js +4 -2
- package/dist/steps/root/steps-root.d.ts +32 -8
- package/dist/steps/root/steps-root.js +70 -9
- package/dist/steps/step/step.d.ts +9 -1
- package/dist/steps/step/step.js +5 -0
- package/dist/textarea/root/textarea-root.d.ts +8 -0
- package/dist/textarea/root/textarea-root.js +16 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +19 -1
- package/dist/video-playlist/root/video-playlist-root.js +14 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +8 -0
- package/dist/virtual-list/root/virtual-list-root.js +7 -2
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +800 -144
- package/types/vue.d.ts +165 -31
- package/types/words.d.ts +20 -2
package/types/vue.d.ts
CHANGED
|
@@ -2584,6 +2584,10 @@ export type HelixHeadlessChatComposerHelixTypingElementEvent =
|
|
|
2584
2584
|
HelixHeadlessChatComposerElementEvent<HelixTypingEvent>;
|
|
2585
2585
|
|
|
2586
2586
|
export type HelixHeadlessChatComposerVueProps = {
|
|
2587
|
+
/** A message about the draft, shown under the field. While set, the composer
|
|
2588
|
+
is invalid, does not send, and does not submit, as a field's `feedback`
|
|
2589
|
+
does, and the message is announced as it appears. */
|
|
2590
|
+
feedback?: (HelixHeadlessChatComposer["feedback"]) | undefined;
|
|
2587
2591
|
/** The field's name, read by screen readers. */
|
|
2588
2592
|
label?: (HelixHeadlessChatComposer["label"]) | undefined;
|
|
2589
2593
|
/** The most characters a draft can have. The field stops taking more. */
|
|
@@ -3200,6 +3204,12 @@ export type HelixHeadlessCodeBlockHelixToggleElementEvent =
|
|
|
3200
3204
|
HelixHeadlessCodeBlockElementEvent<HelixToggleEvent>;
|
|
3201
3205
|
|
|
3202
3206
|
export type HelixHeadlessCodeBlockVueProps = {
|
|
3207
|
+
/** The lines to mark as inserted, as numbers and ranges counted from 1, such
|
|
3208
|
+
as `3-4`. Drawn as `mark-lines` is, in the added color. Not for a diff. */
|
|
3209
|
+
"added-lines"?: (HelixHeadlessCodeBlock["addedLines"]) | undefined;
|
|
3210
|
+
/** The lines to mark as inserted, as numbers and ranges counted from 1, such
|
|
3211
|
+
as `3-4`. Drawn as `mark-lines` is, in the added color. Not for a diff. */
|
|
3212
|
+
addedLines?: (HelixHeadlessCodeBlock["addedLines"]) | undefined;
|
|
3203
3213
|
/** The name of a block that scrolls, which is a tab stop while it does.
|
|
3204
3214
|
|
|
3205
3215
|
Where the block has a name, the scroller says it too, such as "Code,
|
|
@@ -3358,6 +3368,12 @@ A false boolean reflects as the attribute's absence, so this costs no
|
|
|
3358
3368
|
reflected property taking no default is satisfied by the default being
|
|
3359
3369
|
`false`. */
|
|
3360
3370
|
noCopy?: (HelixHeadlessCodeBlock["noCopy"]) | undefined;
|
|
3371
|
+
/** The lines to mark as deleted, as numbers and ranges counted from 1. Drawn
|
|
3372
|
+
as `mark-lines` is, in the removed color. Not for a diff. */
|
|
3373
|
+
"removed-lines"?: (HelixHeadlessCodeBlock["removedLines"]) | undefined;
|
|
3374
|
+
/** The lines to mark as deleted, as numbers and ranges counted from 1. Drawn
|
|
3375
|
+
as `mark-lines` is, in the removed color. Not for a diff. */
|
|
3376
|
+
removedLines?: (HelixHeadlessCodeBlock["removedLines"]) | undefined;
|
|
3361
3377
|
/** The words of a button that shows a folded run of unchanged lines, in a
|
|
3362
3378
|
diff with `context-lines`. `{count}` is how many. */
|
|
3363
3379
|
"show-unchanged-label"?: (HelixHeadlessCodeBlock["showUnchangedLabel"]) | undefined;
|
|
@@ -3956,10 +3972,11 @@ would give one control two of each. What is left is the validity call and
|
|
|
3956
3972
|
the anchor the browser points its bubble at.
|
|
3957
3973
|
|
|
3958
3974
|
**Text that is not a color is bad input**, so a form does not submit
|
|
3959
|
-
`#00` from a half-typed value. The picker
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3975
|
+
`#00` from a half-typed value. The picker marks it, and says
|
|
3976
|
+
`badInputMessage` under itself, once the reader leaves the value field or
|
|
3977
|
+
presses Enter, and a missing color once the reader has committed one or a
|
|
3978
|
+
form has refused the picker. Color Input shows its own message against the
|
|
3979
|
+
field the reader typed into. */
|
|
3963
3980
|
required?: (HelixHeadlessColorPicker["required"]) | undefined;
|
|
3964
3981
|
/** What the square's horizontal ramp is called. */
|
|
3965
3982
|
"saturation-label"?: (HelixHeadlessColorPicker["saturationLabel"]) | undefined;
|
|
@@ -4227,12 +4244,13 @@ language. */
|
|
|
4227
4244
|
locale?: (HelixHeadlessCombobox["locale"]) | undefined;
|
|
4228
4245
|
/** Whether more than one option can be chosen.
|
|
4229
4246
|
|
|
4230
|
-
The list already does the work: `value`
|
|
4231
|
-
toggles rather than replaces, and the arrows move without
|
|
4232
|
-
this adds is the tags, and keeping the panel open between
|
|
4247
|
+
The list already does the work: `value` is the chosen values joined with
|
|
4248
|
+
commas, a press toggles rather than replaces, and the arrows move without
|
|
4249
|
+
choosing. What this adds is the tags, and keeping the panel open between
|
|
4250
|
+
picks.
|
|
4233
4251
|
|
|
4234
|
-
|
|
4235
|
-
|
|
4252
|
+
An option's value may hold a comma, and it is read as one value, as
|
|
4253
|
+
`Select` and `Listbox` read it. So may an answer the reader created.
|
|
4236
4254
|
|
|
4237
4255
|
**The list is told, and the field is not.** `aria-multiselectable` belongs
|
|
4238
4256
|
to `listbox`, `grid`, `tree` and `tablist`, and `combobox` dropped it in
|
|
@@ -4507,6 +4525,18 @@ so a palette filtered on a server sends one `helix-filter` for a word.
|
|
|
4507
4525
|
so a palette filtered on a server sends one `helix-filter` for a word.
|
|
4508
4526
|
`0` filters on every keystroke. See Listbox's `filter-delay`. */
|
|
4509
4527
|
filterDelay?: (HelixHeadlessCommand["filterDelay"]) | undefined;
|
|
4528
|
+
/** Where Home and End go from the filter field.
|
|
4529
|
+
|
|
4530
|
+
Absent, they move the caret, as APG's combobox has them. `list` moves the
|
|
4531
|
+
highlight to the first or the last command, as React Aria's Autocomplete
|
|
4532
|
+
does, and Shift with either still selects the text. */
|
|
4533
|
+
"home-end"?: (HelixHeadlessCommand["homeEnd"]) | undefined;
|
|
4534
|
+
/** Where Home and End go from the filter field.
|
|
4535
|
+
|
|
4536
|
+
Absent, they move the caret, as APG's combobox has them. `list` moves the
|
|
4537
|
+
highlight to the first or the last command, as React Aria's Autocomplete
|
|
4538
|
+
does, and Shift with either still selects the text. */
|
|
4539
|
+
homeEnd?: (HelixHeadlessCommand["homeEnd"]) | undefined;
|
|
4510
4540
|
/** The key that opens the palette, written as `mod+k`, `shift+p`, or `k`,
|
|
4511
4541
|
in Kbd's chord spelling: `mod` is Command or Control, `ctrl`, `cmd`,
|
|
4512
4542
|
`alt` and `shift` the keys they name.
|
|
@@ -4524,6 +4554,10 @@ and `open`, `toggle` and the dialog's parts do nothing. */
|
|
|
4524
4554
|
inline?: (HelixHeadlessCommand["inline"]) | undefined;
|
|
4525
4555
|
/** Accessible name for the overlay, which has no visible heading. */
|
|
4526
4556
|
label?: (HelixHeadlessCommand["label"]) | undefined;
|
|
4557
|
+
/** How the commands are laid out, as Listbox's `layout`: `grid` draws them in
|
|
4558
|
+
rows and columns, for a palette of icons or emoji, and the arrow keys
|
|
4559
|
+
follow the rows and the columns. Absent is one command under another. */
|
|
4560
|
+
layout?: (HelixHeadlessCommand["layout"]) | undefined;
|
|
4527
4561
|
/** What the list says when its commands could not be loaded, such as after a
|
|
4528
4562
|
request to a server fails. Empty, null or no attribute is no error, so
|
|
4529
4563
|
removing the attribute clears it. Passed to the list, which shows it
|
|
@@ -5157,7 +5191,11 @@ thousand rows, where the page is a reasonable fetch and a poor render.
|
|
|
5157
5191
|
|
|
5158
5192
|
Off by default. Windowing costs a scroll listener, a measurement per row
|
|
5159
5193
|
drawn, and a `block-size` on the scrolling box, and a table of twenty rows
|
|
5160
|
-
should pay none of them.
|
|
5194
|
+
should pay none of them.
|
|
5195
|
+
|
|
5196
|
+
While windowed, the `table` part scrolls on this tier: it carries
|
|
5197
|
+
`data-scroller`, and `core` ships `[data-scroller] { overflow: auto }` into
|
|
5198
|
+
every shadow root. You still need to give it a block size. */
|
|
5161
5199
|
windowed?: (HelixHeadlessDataTable["windowed"]) | undefined;
|
|
5162
5200
|
/** The text shown and announced when there are no rows and none are loading. */
|
|
5163
5201
|
"empty-text"?: (HelixHeadlessDataTable["emptyText"]) | undefined;
|
|
@@ -6968,6 +7006,13 @@ makes an unusual filter look unusual. */
|
|
|
6968
7006
|
operatorLabel?: (HelixHeadlessFilterChip["operatorLabel"]) | undefined;
|
|
6969
7007
|
/** Whether the element shows a control that dismisses it. */
|
|
6970
7008
|
dismissible?: (HelixHeadlessFilterChip["dismissible"]) | undefined;
|
|
7009
|
+
/** Whether the remove button is a tab stop of its own.
|
|
7010
|
+
|
|
7011
|
+
`FilterInput` writes `false` on the chips in its `tags` slot: the field's
|
|
7012
|
+
text is its one tab stop, and the arrow keys move from the text to the
|
|
7013
|
+
chips, as in a `multiple` Combobox. No attribute: it is coordination
|
|
7014
|
+
between elements, as `Tag.dismissTabStop` is. */
|
|
7015
|
+
dismissTabStop?: (HelixHeadlessFilterChip["dismissTabStop"]) | undefined;
|
|
6971
7016
|
};
|
|
6972
7017
|
|
|
6973
7018
|
export type HelixHeadlessFilterChipVueEvents = {
|
|
@@ -7092,6 +7137,18 @@ export type HelixHeadlessFilterInputToggleElementEvent =
|
|
|
7092
7137
|
HelixHeadlessFilterInputElementEvent<ToggleEvent>;
|
|
7093
7138
|
|
|
7094
7139
|
export type HelixHeadlessFilterInputVueProps = {
|
|
7140
|
+
/** Whether the field keeps a `FilterChip` for each filter in its `tags` slot,
|
|
7141
|
+
from the `helix-facet` events it hears.
|
|
7142
|
+
|
|
7143
|
+
Off, you build the chips, which is what you do when your own model holds
|
|
7144
|
+
the filters. On, a filter typed, picked, or changed adds or updates the
|
|
7145
|
+
chip for its field, one with no values takes it away (unless its
|
|
7146
|
+
comparison takes none, such as "is empty"), and removing the chip clears
|
|
7147
|
+
the filter. A `helix-facet` you cancel changes no chip.
|
|
7148
|
+
|
|
7149
|
+
The chips are elements the field adds to its own children, so leave this
|
|
7150
|
+
off where a framework renders those children and would remove them. */
|
|
7151
|
+
chips?: (HelixHeadlessFilterInput["chips"]) | undefined;
|
|
7095
7152
|
/** Shows a button that empties the field.
|
|
7096
7153
|
|
|
7097
7154
|
The text only. The tokens are the consumer's markup and this element is not
|
|
@@ -7113,6 +7170,29 @@ what you slot and you narrow it. */
|
|
|
7113
7170
|
being typed, as React Aria's Autocomplete filters. Off, the panel shows
|
|
7114
7171
|
what you slot and you narrow it. */
|
|
7115
7172
|
filterSuggestions?: (HelixHeadlessFilterInput["filterSuggestions"]) | undefined;
|
|
7173
|
+
/** Whether the suggestions are still loading, such as while a request for the
|
|
7174
|
+
values of a typed key is out.
|
|
7175
|
+
|
|
7176
|
+
The panel opens on `loading-text`, or the `loading` slot, while the field
|
|
7177
|
+
has focus, and a screen reader hears it. Slot the options and clear this
|
|
7178
|
+
when they arrive. */
|
|
7179
|
+
loading?: (HelixHeadlessFilterInput["loading"]) | undefined;
|
|
7180
|
+
/** Text the panel shows while the suggestions load. */
|
|
7181
|
+
"loading-text"?: (HelixHeadlessFilterInput["loadingText"]) | undefined;
|
|
7182
|
+
/** Text the panel shows while the suggestions load. */
|
|
7183
|
+
loadingText?: (HelixHeadlessFilterInput["loadingText"]) | undefined;
|
|
7184
|
+
/** Text the panel shows when `filter-suggestions` hides every suggestion, such
|
|
7185
|
+
as "No matching filters".
|
|
7186
|
+
|
|
7187
|
+
Empty, or no `no-results` slot, and the panel closes instead, as it does
|
|
7188
|
+
when it has nothing to offer. */
|
|
7189
|
+
"no-results-text"?: (HelixHeadlessFilterInput["noResultsText"]) | undefined;
|
|
7190
|
+
/** Text the panel shows when `filter-suggestions` hides every suggestion, such
|
|
7191
|
+
as "No matching filters".
|
|
7192
|
+
|
|
7193
|
+
Empty, or no `no-results` slot, and the panel closes instead, as it does
|
|
7194
|
+
when it has nothing to offer. */
|
|
7195
|
+
noResultsText?: (HelixHeadlessFilterInput["noResultsText"]) | undefined;
|
|
7116
7196
|
/** The text shown while the field is empty.
|
|
7117
7197
|
|
|
7118
7198
|
Not a label: it goes when typing starts. */
|
|
@@ -10815,6 +10895,14 @@ or on Alt+Down or Alt+Up. */
|
|
|
10815
10895
|
|
|
10816
10896
|
It moves if that side does not fit. */
|
|
10817
10897
|
placement?: (HelixHeadlessMenu["placement"]) | undefined;
|
|
10898
|
+
/** What a screen reader hears when the filter narrows the rows. `{count}` is
|
|
10899
|
+
how many rows are left, written in the locale, and each language writes
|
|
10900
|
+
the forms it has, as Listbox's `results-label` does. */
|
|
10901
|
+
"results-label"?: (HelixHeadlessMenu["resultsLabel"]) | undefined;
|
|
10902
|
+
/** What a screen reader hears when the filter narrows the rows. `{count}` is
|
|
10903
|
+
how many rows are left, written in the locale, and each language writes
|
|
10904
|
+
the forms it has, as Listbox's `results-label` does. */
|
|
10905
|
+
resultsLabel?: (HelixHeadlessMenu["resultsLabel"]) | undefined;
|
|
10818
10906
|
/** How a submenu opens. `drill` shows it in place of the page showing, with
|
|
10819
10907
|
a way back. `flyout` opens it in a panel of its own beside its row. */
|
|
10820
10908
|
submenus?: (HelixHeadlessMenu["submenus"]) | undefined;
|
|
@@ -10856,9 +10944,19 @@ Aria's `Autocomplete` takes `filter`. See Listbox's `filterMatch`.
|
|
|
10856
10944
|
Absent, a row is kept where its words hold the filter, in any case. A
|
|
10857
10945
|
property only, there being no way to write a function in markup. */
|
|
10858
10946
|
filterMatch?: (HelixHeadlessMenu["filterMatch"]) | undefined;
|
|
10947
|
+
/** The values of the choice rows that are checked, anywhere in the menu, in
|
|
10948
|
+
document order.
|
|
10949
|
+
|
|
10950
|
+
Set it to check exactly those rows and uncheck every other choice row, as
|
|
10951
|
+
React Aria's `selectedKeys` controls a menu's selection from one place.
|
|
10952
|
+
Each row keeps its own `checked` too, which this reads and writes. `change`
|
|
10953
|
+
is sent on the menu when a reader's choice changes it. */
|
|
10954
|
+
checkedValues?: (HelixHeadlessMenu["checkedValues"]) | undefined;
|
|
10859
10955
|
};
|
|
10860
10956
|
|
|
10861
10957
|
export type HelixHeadlessMenuVueEvents = {
|
|
10958
|
+
/** A reader's choice checked or unchecked rows. Read `checkedValues` for the rows that are checked now. */
|
|
10959
|
+
change: HelixHeadlessMenuElementEvent;
|
|
10862
10960
|
/** The menu is about to close. Cancelable: cancel it to keep it open. */
|
|
10863
10961
|
"helix-before-close": HelixHeadlessMenuHelixBeforeCloseElementEvent;
|
|
10864
10962
|
/** The menu is about to open. Cancelable: cancel it to keep it closed. */
|
|
@@ -11364,9 +11462,13 @@ speaks it: `feedback` replaces the message under the field and does not
|
|
|
11364
11462
|
reach the bubble. Unset is the sentence registered for the page's
|
|
11365
11463
|
language, then the English. */
|
|
11366
11464
|
badInputMessage?: (HelixHeadlessNumberInput["badInputMessage"]) | undefined;
|
|
11367
|
-
/** The name of the step down button, read by screen readers.
|
|
11465
|
+
/** The name of the step down button, read by screen readers. The field's
|
|
11466
|
+
label follows it, so a reader hears "Decrease Quantity", as React Aria
|
|
11467
|
+
names its steppers. */
|
|
11368
11468
|
"decrement-label"?: (HelixHeadlessNumberInput["decrementLabel"]) | undefined;
|
|
11369
|
-
/** The name of the step down button, read by screen readers.
|
|
11469
|
+
/** The name of the step down button, read by screen readers. The field's
|
|
11470
|
+
label follows it, so a reader hears "Decrease Quantity", as React Aria
|
|
11471
|
+
names its steppers. */
|
|
11370
11472
|
decrementLabel?: (HelixHeadlessNumberInput["decrementLabel"]) | undefined;
|
|
11371
11473
|
/** `Intl.NumberFormat` options the number is shown with while the field is
|
|
11372
11474
|
not being edited: a currency, a percent, a unit, or a number of decimals.
|
|
@@ -11384,9 +11486,13 @@ Written as JSON in the attribute.
|
|
|
11384
11486
|
<helix-number-input format-options='{"style":"currency","currency":"EUR"}'></helix-number-input>
|
|
11385
11487
|
``` */
|
|
11386
11488
|
formatOptions?: (HelixHeadlessNumberInput["formatOptions"]) | undefined;
|
|
11387
|
-
/** The name of the step up button, read by screen readers.
|
|
11489
|
+
/** The name of the step up button, read by screen readers. The field's
|
|
11490
|
+
label follows it, so a reader hears "Increase Quantity", as React Aria
|
|
11491
|
+
names its steppers. */
|
|
11388
11492
|
"increment-label"?: (HelixHeadlessNumberInput["incrementLabel"]) | undefined;
|
|
11389
|
-
/** The name of the step up button, read by screen readers.
|
|
11493
|
+
/** The name of the step up button, read by screen readers. The field's
|
|
11494
|
+
label follows it, so a reader hears "Increase Quantity", as React Aria
|
|
11495
|
+
names its steppers. */
|
|
11390
11496
|
incrementLabel?: (HelixHeadlessNumberInput["incrementLabel"]) | undefined;
|
|
11391
11497
|
/** How many steps `PageUp` and `PageDown` move.
|
|
11392
11498
|
|
|
@@ -12550,17 +12656,42 @@ export type HelixHeadlessPopoverToggleElementEvent =
|
|
|
12550
12656
|
HelixHeadlessPopoverElementEvent<ToggleEvent>;
|
|
12551
12657
|
|
|
12552
12658
|
export type HelixHeadlessPopoverVueProps = {
|
|
12659
|
+
/** The element the panel opens against, where that is not the trigger: its
|
|
12660
|
+
`id` in the same document or shadow root, or the element itself. Left
|
|
12661
|
+
empty, the panel opens against the trigger, or against the button whose
|
|
12662
|
+
command opened it. */
|
|
12663
|
+
anchor?: (HelixHeadlessPopover["anchor"]) | undefined;
|
|
12553
12664
|
/** Draws a point on the panel's edge facing the trigger.
|
|
12554
12665
|
|
|
12555
12666
|
Off by default, which is the house style: a panel that opens from its
|
|
12556
12667
|
trigger already reads as belonging to it. */
|
|
12557
12668
|
arrow?: (HelixHeadlessPopover["arrow"]) | undefined;
|
|
12669
|
+
/** How close to the window's edges the panel may come, in pixels, when it
|
|
12670
|
+
slides, shrinks or moves to the other side to fit. Left unset, it slides
|
|
12671
|
+
and shrinks to 8 pixels from an edge and moves to the other side only
|
|
12672
|
+
once it would cross one. */
|
|
12673
|
+
"container-padding"?: (HelixHeadlessPopover["containerPadding"] | `${number}`) | undefined;
|
|
12674
|
+
/** How close to the window's edges the panel may come, in pixels, when it
|
|
12675
|
+
slides, shrinks or moves to the other side to fit. Left unset, it slides
|
|
12676
|
+
and shrinks to 8 pixels from an edge and moves to the other side only
|
|
12677
|
+
once it would cross one. */
|
|
12678
|
+
containerPadding?: (HelixHeadlessPopover["containerPadding"]) | undefined;
|
|
12679
|
+
/** How far to slide the panel along the side it is on, in pixels: to the
|
|
12680
|
+
right on the top or the bottom, and down on the left or the right. */
|
|
12681
|
+
"cross-offset"?: (HelixHeadlessPopover["crossOffset"] | `${number}`) | undefined;
|
|
12682
|
+
/** How far to slide the panel along the side it is on, in pixels: to the
|
|
12683
|
+
right on the top or the bottom, and down on the left or the right. */
|
|
12684
|
+
crossOffset?: (HelixHeadlessPopover["crossOffset"]) | undefined;
|
|
12558
12685
|
/** The panel's name where nothing else names it: no `label`, no heading in
|
|
12559
12686
|
the panel, and no `aria-labelledby` on the host. */
|
|
12560
12687
|
"fallback-label"?: (HelixHeadlessPopover["fallbackLabel"]) | undefined;
|
|
12561
12688
|
/** The panel's name where nothing else names it: no `label`, no heading in
|
|
12562
12689
|
the panel, and no `aria-labelledby` on the host. */
|
|
12563
12690
|
fallbackLabel?: (HelixHeadlessPopover["fallbackLabel"]) | undefined;
|
|
12691
|
+
/** Whether the panel moves to the other side of the trigger when its own
|
|
12692
|
+
side has no room. On by default. Write `flip="false"` to keep it on its
|
|
12693
|
+
side, where it shrinks to fit, as React Aria's `shouldFlip` turns off. */
|
|
12694
|
+
flip?: (HelixHeadlessPopover["flip"]) | undefined;
|
|
12564
12695
|
/** The panel's name, read by screen readers. Left empty, the first heading in
|
|
12565
12696
|
the panel names it, and then `fallback-label`. */
|
|
12566
12697
|
label?: (HelixHeadlessPopover["label"]) | undefined;
|
|
@@ -14545,7 +14676,8 @@ export type HelixHeadlessStepsHelixSelectElementEvent =
|
|
|
14545
14676
|
|
|
14546
14677
|
export type HelixHeadlessStepsVueProps = {
|
|
14547
14678
|
/** Whether the arrow keys move focus between the stages' names, along the
|
|
14548
|
-
way the steps run. Off by default, so the
|
|
14679
|
+
way the steps run, and the names are one tab stop. Off by default, so the
|
|
14680
|
+
arrows keep scrolling the page. */
|
|
14549
14681
|
arrows?: (HelixHeadlessSteps["arrows"]) | undefined;
|
|
14550
14682
|
/** What marks a stage `complete`.
|
|
14551
14683
|
|
|
@@ -14662,7 +14794,9 @@ with the page. */
|
|
|
14662
14794
|
/** Whether a reader may pass the stage without finishing it, in a sequence
|
|
14663
14795
|
with `linear`. Ark UI's skippable step. */
|
|
14664
14796
|
optional?: (HelixHeadlessStep["optional"]) | undefined;
|
|
14665
|
-
/** The value the step sends in `helix-select
|
|
14797
|
+
/** The value the step sends in `helix-select`, and what names the step in its
|
|
14798
|
+
sequence's `active`. Without one, the sequence names the step by its place,
|
|
14799
|
+
counted from 1. */
|
|
14666
14800
|
value?: (HelixHeadlessStep["value"]) | undefined;
|
|
14667
14801
|
};
|
|
14668
14802
|
|
|
@@ -18984,7 +19118,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
18984
19118
|
HelixHeadlessCarouselVueProps,
|
|
18985
19119
|
HelixHeadlessCarouselVueEvents
|
|
18986
19120
|
>;
|
|
18987
|
-
/** The composer is a separate element so you can replace it. If you need attachments, slash commands, or a model picker, replace the composer and keep the transcript. By default, Enter sends and Shift+Enter starts a new line, the convention in messaging apps. Document editors mostly use the opposite, so 'submit-on' takes 'enter' or 'button'. Use 'button' for a long-form composer. The composer clears only when no listener cancels the send, so the text is kept when you cancel a send that failed. **In a form, the draft is the composer's value**, submitted under 'name'. A form reset puts back the 'value' the markup declared, and a '<fieldset disabled>' turns the composer off. Sending is still 'helix-send', and it does not submit the form. **'required', 'minlength' and 'maxlength' are checked by the browser**, as on a '<textarea>', and the message is the browser's. 'maxlength' stops the field taking more. A draft that fails them does not send, and the composer takes ':state(invalid)' and 'aria-invalid' once the reader has tried to send it, the form was submitted, or the reader edited the field and left it. Tabbing past an empty composer marks nothing. **'typing' says whether the user is writing**, and 'helix-typing' is sent each time it changes: when they start, and when they send or stop for 'typing-timeout' milliseconds. Pass it on to show "is typing" to the other side. */
|
|
19121
|
+
/** The composer is a separate element so you can replace it. If you need attachments, slash commands, or a model picker, replace the composer and keep the transcript. By default, Enter sends and Shift+Enter starts a new line, the convention in messaging apps. Document editors mostly use the opposite, so 'submit-on' takes 'enter' or 'button'. Use 'button' for a long-form composer. The composer clears only when no listener cancels the send, so the text is kept when you cancel a send that failed. **In a form, the draft is the composer's value**, submitted under 'name'. A form reset puts back the 'value' the markup declared, and a '<fieldset disabled>' turns the composer off. Sending is still 'helix-send', and it does not submit the form. **'required', 'minlength' and 'maxlength' are checked by the browser**, as on a '<textarea>', and the message is the browser's. 'maxlength' stops the field taking more. A draft that fails them does not send, and the composer takes ':state(invalid)' and 'aria-invalid' once the reader has tried to send it, the form was submitted, or the reader edited the field and left it. Sending an empty required composer counts as trying. Tabbing past an empty composer marks nothing. **'feedback' is a message of your own about the draft**, such as one your server sent back. While it is set, the composer is invalid at once, does not send or submit, shows the message under the field, and a screen reader hears it as it appears. Clear it to let the draft go. **'typing' says whether the user is writing**, and 'helix-typing' is sent each time it changes: when they start, and when they send or stop for 'typing-timeout' milliseconds. Pass it on to show "is typing" to the other side. */
|
|
18988
19122
|
"helix-headless-chat-composer": DefineCustomElement<
|
|
18989
19123
|
HelixHeadlessChatComposer,
|
|
18990
19124
|
HelixHeadlessChatComposerVueProps,
|
|
@@ -18996,7 +19130,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
18996
19130
|
HelixHeadlessChatMessageVueProps,
|
|
18997
19131
|
HelixHeadlessChatMessageVueEvents
|
|
18998
19132
|
>;
|
|
18999
|
-
/** Chat has no positioning, no backdrop, and no trigger, so you can put it in any container, such as a page, a sidebar, a modal, or a floating panel. The transcript stays pinned to the bottom, including while a streamed answer grows, until the user scrolls more than 'threshold' away from it. With 'history' set to 'more', reaching the top fires 'helix-history'. Set 'loading' while you fetch, then prepend the older turns. The turn the user was reading stays in place on screen. The log is 'aria-live="off"'. A separate status region announces each new turn once, when it has finished arriving. It skips the user's own turns unless they failed to send, turns loaded as history, and the turns already there when the transcript opened. A turn is said with its author first, such as "Ada: It ships today" ('arrival-label'), where its author can be named. Pass the turns as children or as 'turns' data. Do not use both. Children render from the server and suit most conversations. 'turns' draws a long transcript one window at a time, so the log needs a block size of its own. **A conversation is built from three elements.** The chat holds the transcript, a 'Chat.Message' stands for each turn, and a 'Chat.Composer' sits in the 'composer' slot. When the user sends, 'helix-send' reaches the chat: add their turn with 'author="me"' and 'state="sending"', then set 'state' to 'sent' or 'failed' when your server answers. Add the reply as a turn with 'state="streaming"', write its text as it arrives, and set 'state' to 'sent' when it is complete. While the user types, the composer sends 'helix-typing', which you can pass on to the other side. When the other side types, set 'typing' to their name: the status band draws three dots and "Ada is typing" ('typing-label'), which a screen reader hears, and clearing it takes them away. Anything slotted into 'status' is drawn first. **Keyboard.** The transcript moves between turns the way a feed does. Each turn says its place, such as "3 of 40", windowed or not. | Key | What it does | |---|---| | Page Down, Page Up | On a turn or inside one, moves focus to the next or the previous turn. On the transcript itself, moves focus to the turn at the top of the view. | | Control with End | Moves focus to the composer. | | Control with Home | Moves focus to the first control above the transcript, or to the transcript. | While you are scrolled away from the newest turn, the 'resume' region shows a button that takes you back, named by 'resume-label', "Jump to latest". Slot your own control into 'resume' to replace it. A screen reader names each turn by its author and its time, such as "You, 2 minutes ago". Set 'me-label' and 'message-label' to say it in your language, and give each turn by 'them' an 'author-label'. A turn with neither an author label nor a time is named by 'turn-label', "Message". A turn from 'turns' is drawn in the chat's shadow root, so style it through the forwarded 'message-*' parts. A turn by 'me' also gets each part with '-mine' added, and the turn's state adds 'message-meta-failed', 'message-content-sending', and 'message-content-streaming'. To style each participant differently, give 'author-styles' the declarations for each author, such as '{"ada": "--chat-message-background-color: …"}': the message drawn for each of their turns takes them as its 'style', so the message's custom properties change for that author alone. Turns passed as children are styled by their 'author', such as 'helix-chat-message[author="ada"]'. */
|
|
19133
|
+
/** Chat has no positioning, no backdrop, and no trigger, so you can put it in any container, such as a page, a sidebar, a modal, or a floating panel. The transcript stays pinned to the bottom, including while a streamed answer grows, until the user scrolls more than 'threshold' away from it. With 'history' set to 'more', reaching the top fires 'helix-history'. Set 'loading' while you fetch, then prepend the older turns. The turn the user was reading stays in place on screen. The transcript is a 'log', the role for content added in order where the newest matters most, and it answers the APG feed's keys. The 'feed' role reads its articles as a list from the top, with no newest end to stay pinned to, so the log keeps the role a conversation has. While 'loading' is set or older turns load, the log carries 'aria-busy', as the APG asks of a feed. The log is 'aria-live="off"'. A separate status region announces each new turn once, when it has finished arriving. It skips the user's own turns unless they failed to send, turns loaded as history, and the turns already there when the transcript opened. A turn is said with its author first, such as "Ada: It ships today" ('arrival-label'), where its author can be named. Pass the turns as children or as 'turns' data. Do not use both: a chat given both draws every turn from 'turns' and then the children, and says so once in the console. Children render from the server and suit most conversations. 'turns' draws a long transcript one window at a time, so the log needs a block size of its own. The log scrolls on this tier. It carries 'data-scroller', and 'core' ships '[data-scroller] { overflow: auto }' into every shadow root, so pinning, history and the window work with no stylesheet. You still need to give the log a block size, such as 'helix-headless-chat::part(log) { block-size: 20rem }'. **A conversation is built from three elements.** The chat holds the transcript, a 'Chat.Message' stands for each turn, and a 'Chat.Composer' sits in the 'composer' slot. When the user sends, 'helix-send' reaches the chat: add their turn with 'author="me"' and 'state="sending"', then set 'state' to 'sent' or 'failed' when your server answers. Add the reply as a turn with 'state="streaming"', write its text as it arrives, and set 'state' to 'sent' when it is complete. While the user types, the composer sends 'helix-typing', which you can pass on to the other side. When the other side types, set 'typing' to their name: the status band draws three dots and "Ada is typing" ('typing-label'), which a screen reader hears, and clearing it takes them away. Anything slotted into 'status' is drawn first. **Keyboard.** The transcript moves between turns the way a feed does. Each turn says its place, such as "3 of 40", windowed or not. The transcript is a tab stop while it holds a turn, and the turn a reader moved to is one too. Moving to an older turn unpins a transcript that scrolls and scrolls the turn into view, and moving to the newest pins it again. When the turn holding focus is removed, focus moves to the turn that took its place, or to the one before it where it was the last. | Key | What it does | |---|---| | Page Down, Page Up | On a turn or inside one, moves focus to the next or the previous turn. On the transcript itself, moves focus to the turn at the top of the view. | | Control with End | Moves focus to the composer. | | Control with Home | Moves focus to the first control above the transcript, or to the transcript. | While you are scrolled away from the newest turn, the 'resume' region shows a button that takes you back, named by 'resume-label', "Jump to latest". Slot your own control into 'resume' to replace it. A screen reader names each turn by its author and its time, such as "You, 2 minutes ago". Set 'me-label' and 'message-label' to say it in your language, and give each turn by 'them' an 'author-label'. A turn with neither an author label nor a time is named by 'turn-label', "Message". A turn from 'turns' is drawn in the chat's shadow root, so style it through the forwarded 'message-*' parts. A turn by 'me' also gets each part with '-mine' added, and the turn's state adds 'message-meta-failed', 'message-content-sending', and 'message-content-streaming'. To style each participant differently, give 'author-styles' the declarations for each author, such as '{"ada": "--chat-message-background-color: …"}': the message drawn for each of their turns takes them as its 'style', so the message's custom properties change for that author alone. Turns passed as children are styled by their 'author', such as 'helix-chat-message[author="ada"]'. */
|
|
19000
19134
|
"helix-headless-chat": DefineCustomElement<
|
|
19001
19135
|
HelixHeadlessChat,
|
|
19002
19136
|
HelixHeadlessChatVueProps,
|
|
@@ -19014,7 +19148,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19014
19148
|
HelixHeadlessCheckboxVueProps,
|
|
19015
19149
|
HelixHeadlessCheckboxVueEvents
|
|
19016
19150
|
>;
|
|
19017
|
-
/** Renders a '<pre><code>' pair: 'pre' keeps the whitespace, and 'code' marks it as code. Long lines scroll inside the block and do not wrap, because a line break can be significant in code. A copy button is on by default. Set 'no-copy' to remove it. The button copies the slotted text, so there is no second copy of the code to keep in sync. For a fragment of code inside a sentence, use 'Code'. Set 'line-numbers' to number the lines in a gutter beside the code, hidden from the accessibility tree and left out of a copy. Set 'mark-lines' to mark lines a reader should look at, such as '2, 4-6': the block draws a band behind each run, placed where the lines are laid out, so it follows a highlighter's markup and lines that wrap. Set 'wrap' to wrap long lines rather than scroll them; a gutter then numbers each line where it starts. Set 'wrappable' for a button in the header that turns 'wrap' on and off, pressed while the lines wrap. The header holds the name, the 'actions' slot, and the copy button. Slot a control into 'actions', such as a button that sets 'wrap' or one that opens the code in an editor, and the block draws a header for it even with no name. 'copy-icon' and 'copied-icon' replace the copy button's two icons. Set 'highlight' to a function that turns the code into highlighted markup, such as one wrapping Shiki or Prism, and the block draws what it returns; it is handed the block's 'language', so one function serves every block. The code stays in the slot, so the copy button and the page's own text are the code as written. Set 'expandable' on a block whose height is capped, such as by '--code-block-max-block-size', and a button under it shows every line and then fewer again, as a docs site's long example does. The button is drawn only while the cap hides something, says whether the block is expanded with 'aria-expanded', names the block it opens with 'aria-controls', and the block carries ':state(expanded)' while it is. Set 'diff' to show a change. Put a unified diff, the output of 'git diff' or 'diff -u', in the same slot, and the block draws the lines it added and removed. The block never computes a diff itself. Line numbers come from the hunk headers and are hidden from the accessibility tree. Changed lines are '<ins>' and '<del>' with the '+' and '-' kept as text, so the change does not depend on color. Where a removed line is paired with the added line that replaced it, the words each does not share with the other are the 'changed' part, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name, and its copy button copies the new version of the file. 'variant="split"' shows the old version beside the new, each removal opposite its replacement. 'context-lines' folds each long run of unchanged lines, keeping that many beside each change, behind a button that shows them and hides them again, as a code host draws a diff written with more context than a reader needs. **A block that scrolls is a tab stop.** While its lines run past its width or its cap, the scroller is a region named for the block, such as "Code, app.ts", that Tab reaches, so a keyboard scrolls it with the arrow keys in every browser. Chromium and Firefox make a scrolling box focusable on their own, and Safari does not. A block that fits is no stop at all. **The code the block draws is marked untranslated**, 'translate="no"' on its '<pre>', so a page translator leaves highlighted lines and a diff as written. Code in the slot takes its translation mode from the element, which writes nothing onto itself, so set 'translate="no"' on the element to keep a translator off plain code too. On the server, the slot renders as ordinary code, so a diff first appears as the patch text in a '<pre>'. The client makes the same first render, which keeps hydration clean, and draws the diff once it can read the content. Diff mode is experimental. The rest of the family is stable. **Several blocks are files**, one shown at a time under a row of tabs, as Sandbox shows its source panes. Put Code Blocks in the default slot of a Code Block, and each is a file named on its tab by its 'label' or, without one, its 'language'. 'file' holds the name of the file shown. The tabs are a tab list: the arrow keys move to a tab and show its file, the two swapping on a right-to-left page, and Home and End go to the first and the last. Choosing one sends 'helix-before-change' with the file's name, which you can cancel, and 'change' once 'file' holds it. The files not shown carry 'hidden', and the one shown draws no name of its own, its tab naming it. One block draws no tabs. A server cannot see the blocks inside, so the client draws the tabs once it upgrades. */
|
|
19151
|
+
/** Renders a '<pre><code>' pair: 'pre' keeps the whitespace, and 'code' marks it as code. Long lines scroll inside the block and do not wrap, because a line break can be significant in code. A copy button is on by default. Set 'no-copy' to remove it. The button copies the slotted text, so there is no second copy of the code to keep in sync. For a fragment of code inside a sentence, use 'Code'. Set 'line-numbers' to number the lines in a gutter beside the code, hidden from the accessibility tree and left out of a copy. Set 'mark-lines' to mark lines a reader should look at, such as '2, 4-6': the block draws a band behind each run, placed where the lines are laid out, so it follows a highlighter's markup and lines that wrap. 'added-lines' and 'removed-lines' mark lines the same way as inserted and deleted, as Expressive Code's 'ins' and 'del' do, in code that is not a diff. The bands are drawn and hidden from screen readers, so say in the text around the block what a marked line means. Set 'wrap' to wrap long lines rather than scroll them; a gutter then numbers each line where it starts. Set 'wrappable' for a button in the header that turns 'wrap' on and off, pressed while the lines wrap. The header holds the name, the 'actions' slot, and the copy button. Slot a control into 'actions', such as a button that sets 'wrap' or one that opens the code in an editor, and the block draws a header for it even with no name. 'copy-icon' and 'copied-icon' replace the copy button's two icons. Set 'highlight' to a function that turns the code into highlighted markup, such as one wrapping Shiki or Prism, and the block draws what it returns; it is handed the block's 'language', so one function serves every block. The code stays in the slot, so the copy button and the page's own text are the code as written. Set 'expandable' on a block whose height is capped, such as by '--code-block-max-block-size', and a button under it shows every line and then fewer again, as a docs site's long example does. The button is drawn only while the cap hides something, says whether the block is expanded with 'aria-expanded', names the block it opens with 'aria-controls', and the block carries ':state(expanded)' while it is. Set 'diff' to show a change. Put a unified diff, the output of 'git diff' or 'diff -u', in the same slot, and the block draws the lines it added and removed. The block never computes a diff itself. Line numbers come from the hunk headers and are hidden from the accessibility tree. Changed lines are '<ins>' and '<del>' with the '+' and '-' kept as text, so the change does not depend on color. Where a removed line is paired with the added line that replaced it, the words each does not share with the other are the 'changed' part, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name, and its copy button copies the new version of the file. 'variant="split"' shows the old version beside the new, each removal opposite its replacement. 'context-lines' folds each long run of unchanged lines, keeping that many beside each change, behind a button that shows them and hides them again, as a code host draws a diff written with more context than a reader needs. **A block that scrolls is a tab stop.** While its lines run past its width or its cap, the scroller is a region named for the block, such as "Code, app.ts", that Tab reaches, so a keyboard scrolls it with the arrow keys in every browser. Chromium and Firefox make a scrolling box focusable on their own, and Safari does not. A block that fits is no stop at all. **The code the block draws is marked untranslated**, 'translate="no"' on its '<pre>', so a page translator leaves highlighted lines and a diff as written. Code in the slot takes its translation mode from the element, which writes nothing onto itself, so set 'translate="no"' on the element to keep a translator off plain code too. On the server, the slot renders as ordinary code, so a diff first appears as the patch text in a '<pre>'. The client makes the same first render, which keeps hydration clean, and draws the diff once it can read the content. Diff mode is experimental. The rest of the family is stable. **Several blocks are files**, one shown at a time under a row of tabs, as Sandbox shows its source panes. Put Code Blocks in the default slot of a Code Block, and each is a file named on its tab by its 'label' or, without one, its 'language'. 'file' holds the name of the file shown. The tabs are a tab list: the arrow keys move to a tab and show its file, the two swapping on a right-to-left page, and Home and End go to the first and the last. Choosing one sends 'helix-before-change' with the file's name, which you can cancel, and 'change' once 'file' holds it. The files not shown carry 'hidden', and the one shown draws no name of its own, its tab naming it. One block draws no tabs. A server cannot see the blocks inside, so the client draws the tabs once it upgrades. */
|
|
19018
19152
|
"helix-headless-code-block": DefineCustomElement<
|
|
19019
19153
|
HelixHeadlessCodeBlock,
|
|
19020
19154
|
HelixHeadlessCodeBlockVueProps,
|
|
@@ -19026,7 +19160,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19026
19160
|
HelixHeadlessCodeVueProps,
|
|
19027
19161
|
HelixHeadlessCodeVueEvents
|
|
19028
19162
|
>;
|
|
19029
|
-
/** A text field with a button that opens 'ColorPicker' in an overlay. 'ColorPicker' provides the square, the ramps, the eyedropper, and the syntax toggle, and you can also use it on its own, flat on the page. Color Input adds the field, the overlay, and the form value, the same arrangement Date Input has with 'DatePicker'. You can type or paste a color into the field without opening the picker. Color Input is a custom control, unlike '<input type="color">', so you can style the panel to match your interface. The field reads every color syntax, including '#f00', '#ff0000', 'rgb(255 0 0)', 'rgba(255,0,0,.5)', 'rgb(255 0 0 / 50%)', 'hsl(0 100% 50%)', 'oklch(62.8% 0.258 29.2)', and 'hsb(0, 100%, 100%)'. It writes colors in the syntax that 'format' names. The field shows the value without reformatting it, because half-typed input does not survive a round trip through a formatter. Date Input does the same with dates. Typing sends 'input' on each keystroke and 'change' when you leave the field, as a text field does, so the message about a color it cannot read waits until you are done. Dragging in the panel sends 'input' as the color moves and 'change' when it settles. The trigger and ArrowDown open the panel with focus in the square. Tab moves between the panel's controls without leaving it, and Escape closes it and returns focus to the field. The component sets '--color-input-swatch', so do not set it yourself. It holds the resolved color, so the styled tier can paint the swatch without parsing the value. */
|
|
19163
|
+
/** A text field with a button that opens 'ColorPicker' in an overlay. 'ColorPicker' provides the square, the ramps, the eyedropper, and the syntax toggle, and you can also use it on its own, flat on the page. Color Input adds the field, the overlay, and the form value, the same arrangement Date Input has with 'DatePicker'. You can type or paste a color into the field without opening the picker. Color Input is a custom control, unlike '<input type="color">', so you can style the panel to match your interface. The field reads every color syntax, including '#f00', '#ff0000', 'rgb(255 0 0)', 'rgba(255,0,0,.5)', 'rgb(255 0 0 / 50%)', 'hsl(0 100% 50%)', 'oklch(62.8% 0.258 29.2)', and 'hsb(0, 100%, 100%)'. It writes colors in the syntax that 'format' names. The field shows the value without reformatting it, because half-typed input does not survive a round trip through a formatter. Date Input does the same with dates. Typing sends 'input' on each keystroke and 'change' when you leave the field, as a text field does, so the message about a color it cannot read waits until you are done. Dragging in the panel sends 'input' as the color moves and 'change' when it settles. The trigger and ArrowDown open the panel with focus in the square. Tab moves between the panel's controls without leaving it, and Escape closes it and returns focus to the control that opened it: the trigger after a press, and the field after ArrowDown. The component sets '--color-input-swatch', so do not set it yourself. It holds the resolved color, so the styled tier can paint the swatch without parsing the value. */
|
|
19030
19164
|
"helix-headless-color-input": DefineCustomElement<
|
|
19031
19165
|
HelixHeadlessColorInput,
|
|
19032
19166
|
HelixHeadlessColorInputVueProps,
|
|
@@ -19044,7 +19178,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19044
19178
|
HelixHeadlessComboboxVueProps,
|
|
19045
19179
|
HelixHeadlessComboboxVueEvents
|
|
19046
19180
|
>;
|
|
19047
|
-
/** The list is a 'Listbox', which handles filtering, the empty state, the match highlight, 'aria-activedescendant', scrolling an option into view, and moving between options with the keyboard. The palette adds a dialog and a hotkey that opens it. The palette keeps no value. It is not a form control and submits nothing. Choosing an option dispatches 'helix-select' once. To remember the last command, store it yourself. An option with 'href' is a link to a page, which the browser follows once the palette has closed. The hotkey listener is on the document, so the hotkey works from anywhere on the page, including inside another control's text field, whether or not the palette is open. 'mod' means Command on a Mac and Control elsewhere, so you write one binding. With 'inline', the palette is drawn in the page with no dialog, as a search over a list that is always shown. **Pages.** A command can open a page of commands of its own, as a palette offers "Change theme" and then the themes. Give the option 'opens' with a name, and slot the page's commands as 'page:' and that name: '''html <helix-command> <helix-option value="theme" opens="theme">Change theme</helix-option> <helix-option value="dark" slot="page:theme">Dark</helix-option> <helix-option value="light" slot="page:theme">Light</helix-option> </helix-command> ''' Choosing the opener says 'helix-select' with its value, and canceling it keeps the page that is shown. The list then shows the page, named by the opener's words, and a screen reader hears those words. Backspace in an empty filter goes back, and a screen reader hears the name of the page it goes back to. 'page' says which page is shown. The filter is cleared when the palette closes, so each opening starts from the full list. Combobox and Select do the same. As typing narrows the list, a screen reader hears how many commands are left, such as "3 commands". **Keyboard.** Focus goes to the filter field as the palette opens, and the highlight moves through the commands while you type. | Key | What it does | |---|---| | 'hotkey', Command or Control with K by default | Opens the palette from anywhere on the page, or closes it. With 'inline', puts focus in its filter field. | | Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. | | Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. | | Home, End, Left, Right | Move the caret in the filter field. | | Enter | Runs the highlighted command, or follows it where it is a link, and closes the palette. On a command with 'opens', shows its page. | | Command or Control with Enter | Takes the highlighted command's 'alternate' destination, where it has one. | | Backspace | In an empty filter on a page, goes back to the page before. | | Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. | | Tab | Stays in the palette, which is modal. With 'inline', moves on through the page. | **ARIA.** The palette is a modal 'dialog' named by 'label', or with 'inline' no dialog at all. Inside it the filter field is a text field with 'aria-autocomplete="list"', 'aria-controls' on the list, and 'aria-activedescendant' on the highlighted command, as the field of React Aria's 'Autocomplete' is. The commands are a 'listbox' of 'option's. How many commands typing left, the empty text and the loading text are said in a polite live region. */
|
|
19181
|
+
/** The list is a 'Listbox', which handles filtering, the empty state, the match highlight, 'aria-activedescendant', scrolling an option into view, and moving between options with the keyboard. The palette adds a dialog and a hotkey that opens it. The palette keeps no value. It is not a form control and submits nothing. Choosing an option dispatches 'helix-select' once. To remember the last command, store it yourself. An option with 'href' is a link to a page, which the browser follows once the palette has closed. The hotkey listener is on the document, so the hotkey works from anywhere on the page, including inside another control's text field, whether or not the palette is open. 'mod' means Command on a Mac and Control elsewhere, so you write one binding. With 'inline', the palette is drawn in the page with no dialog, as a search over a list that is always shown. **Pages.** A command can open a page of commands of its own, as a palette offers "Change theme" and then the themes. Give the option 'opens' with a name, and slot the page's commands as 'page:' and that name: '''html <helix-command> <helix-option value="theme" opens="theme">Change theme</helix-option> <helix-option value="dark" slot="page:theme">Dark</helix-option> <helix-option value="light" slot="page:theme">Light</helix-option> </helix-command> ''' Choosing the opener says 'helix-select' with its value, and canceling it keeps the page that is shown. The list then shows the page, named by the opener's words, and a screen reader hears those words. Backspace in an empty filter goes back, and a screen reader hears the name of the page it goes back to. 'page' says which page is shown. The filter is cleared when the palette closes, so each opening starts from the full list. Combobox and Select do the same. As typing narrows the list, a screen reader hears how many commands are left, such as "3 commands". **Keyboard.** Focus goes to the filter field as the palette opens, and the highlight moves through the commands while you type. | Key | What it does | |---|---| | 'hotkey', Command or Control with K by default | Opens the palette from anywhere on the page, or closes it. With 'inline', puts focus in its filter field. | | Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. | | Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. | | Home, End | Move the caret in the filter field. With 'home-end="list"', move the highlight to the first or the last command. | | Left, Right | Move the caret in the filter field. | | Enter | Runs the highlighted command, or follows it where it is a link, and closes the palette. On a command with 'opens', shows its page. | | Command or Control with Enter | Takes the highlighted command's 'alternate' destination, where it has one. | | Backspace | In an empty filter on a page, goes back to the page before. | | Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. | | Tab | Stays in the palette, which is modal. With 'inline', moves on through the page. | **ARIA.** The palette is a modal 'dialog' named by 'label', or with 'inline' no dialog at all. Inside it the filter field is a text field with 'aria-autocomplete="list"', 'aria-controls' on the list, and 'aria-activedescendant' on the highlighted command, as the field of React Aria's 'Autocomplete' is. The commands are a 'listbox' of 'option's. How many commands typing left, the empty text and the loading text are said in a polite live region. */
|
|
19048
19182
|
"helix-headless-command": DefineCustomElement<
|
|
19049
19183
|
HelixHeadlessCommand,
|
|
19050
19184
|
HelixHeadlessCommandVueProps,
|
|
@@ -19104,7 +19238,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19104
19238
|
HelixHeadlessDonutChartVueProps,
|
|
19105
19239
|
HelixHeadlessDonutChartVueEvents
|
|
19106
19240
|
>;
|
|
19107
|
-
/** Uses 'MixinControllerOpen', so 'open', 'defaultOpen', and the 'helix-before-open' and 'helix-before-close' events work the same way as on an accordion item. The drawer is modal by default, which means four things: - focus is trapped inside: 'Tab' from the last control goes to the first, and 'Shift+Tab' from the first to the last, as in 'Dialog' - Escape and a press outside close it - the page behind is covered - the page behind does not scroll A drawer with 'modal="false"' leaves the page usable and still closes on Escape, in a browser without 'closedby' as well. Set 'persistent' for a drawer that has to be answered: Escape, a press outside, and a swipe leave it open, and the close control and 'close()' still close it. 'closedby="none"' keeps it open on all three as well, and 'closedby="closerequest"' keeps it open on a press outside. **A touch or a pen swipes it away**, toward the edge it came from, resolved against the writing direction. A swipe past halfway, or a quick one, closes it through the same request as every other way out. 'snap-points' lists the fractions of the panel a reader can leave on screen, such as '0.5 1' for a sheet that rests half open: it opens at the smallest, and a swipe settles at the nearest. While a swipe moves the panel, the distance is written on it as '--drawer-swipe-x' and '--drawer-swipe-y'. 'swipe="false"' turns swiping off. 'snap' is the snap point the panel rests at, and ':state(snapped)' is on the host while that is less than the whole panel. 'snapTo()' moves it to another. **Focus moving to a control past the window's edge opens the panel to its largest snap point**, so a reader moving through a half open sheet with 'Tab' never lands on a control they cannot see. Set 'dismissible' to draw a close control in the corner, labeled by 'dismiss-label', as 'Dialog' draws one. The panel's name is 'label' when you set it. Otherwise it is the heading in the 'header' slot, or the elements an 'aria-labelledby' on the host names, and 'fallback-label' where nothing names it. A development build warns when a drawer opens with nothing but 'fallback-label' to name it. The panel is described by the words at the start of its body, as 'Dialog' is: the elements in the default slot before the first one that is or holds a control. An 'aria-describedby' on the host replaces it. **Keyboard.** Opening moves focus to the first control in the panel. | Key | What it does | |---|---| | Tab, Shift+Tab | In a modal drawer, moves through the controls in the panel, from the last round to the first and from the first round to the last. In a drawer that is not modal, moves on to the page. | | Escape | Asks to close the drawer. A 'helix-before-close' listener can refuse, and 'persistent' or 'closedby="none"' keeps it open. | | Enter, Space | On the close control, closes the drawer. | Content stays mounted when the drawer is closed, so it is in the server markup and can animate. A closed '<dialog>' is already out of the tab order and the accessibility tree, so the drawer does not write 'inert'. The 'role', 'aria-modal', and the scrim also come from the '<dialog>' element. 'drawer-root.ssr.spec.ts' checks that the panel has no hand-written 'inert' or 'role'. Open the drawer declaratively with the platform's invoker attributes: '''html <helix-headless-button commandfor="nav" command="--toggle">Menu</helix-headless-button> <helix-headless-drawer id="nav">…</helix-headless-drawer> ''' */
|
|
19241
|
+
/** Uses 'MixinControllerOpen', so 'open', 'defaultOpen', and the 'helix-before-open' and 'helix-before-close' events work the same way as on an accordion item. The drawer is modal by default, which means four things: - focus is trapped inside: 'Tab' from the last control goes to the first, and 'Shift+Tab' from the first to the last, as in 'Dialog' - Escape and a press outside close it - the page behind is covered - the page behind does not scroll A drawer with 'modal="false"' leaves the page usable and still closes on Escape, in a browser without 'closedby' as well. Set 'persistent' for a drawer that has to be answered: Escape, a press outside, and a swipe leave it open, and the close control and 'close()' still close it. 'closedby="none"' keeps it open on all three as well, and 'closedby="closerequest"' keeps it open on a press outside. **A touch or a pen swipes it away**, toward the edge it came from, resolved against the writing direction. A swipe past halfway, or a quick one, closes it through the same request as every other way out. 'snap-points' lists the fractions of the panel a reader can leave on screen, such as '0.5 1' for a sheet that rests half open: it opens at the smallest, and a swipe settles at the nearest. While a swipe moves the panel, the distance is written on it as '--drawer-swipe-x' and '--drawer-swipe-y'. 'swipe="false"' turns swiping off. 'snap' is the snap point the panel rests at, and ':state(snapped)' is on the host while that is less than the whole panel. 'snapTo()' moves it to another. **Focus moving to a control past the window's edge opens the panel to its largest snap point**, so a reader moving through a half open sheet with 'Tab' never lands on a control they cannot see. Set 'dismissible' to draw a close control in the corner, labeled by 'dismiss-label', as 'Dialog' draws one. The panel's name is 'label' when you set it. Otherwise it is the heading in the 'header' slot, or the elements an 'aria-labelledby' on the host names, and 'fallback-label' where nothing names it. A development build warns when a drawer opens with nothing but 'fallback-label' to name it. The panel is described by the words at the start of its body, as 'Dialog' is: the elements in the default slot before the first one that is or holds a control. An 'aria-describedby' on the host replaces it. **Keyboard.** Opening moves focus to the first control in the panel. | Key | What it does | |---|---| | Tab, Shift+Tab | In a modal drawer, moves through the controls in the panel, from the last round to the first and from the first round to the last. In a drawer that is not modal, moves on to the page. | | Escape | Asks to close the drawer. A 'helix-before-close' listener can refuse, and 'persistent' or 'closedby="none"' keeps it open. | | Enter, Space | On the close control, closes the drawer. | Content stays mounted when the drawer is closed, so it is in the server markup and can animate. A closed '<dialog>' is already out of the tab order and the accessibility tree, so the drawer does not write 'inert'. The 'role', 'aria-modal', and the scrim also come from the '<dialog>' element. 'drawer-root.ssr.spec.ts' checks that the panel has no hand-written 'inert' or 'role'. Open the drawer declaratively with the platform's invoker attributes: '''html <helix-headless-button commandfor="nav" command="--toggle">Menu</helix-headless-button> <helix-headless-drawer id="nav">…</helix-headless-drawer> ''' From its first press, a button that opens the drawer this way says whether the drawer is open: a Helix button through 'expanded', and any other element with 'aria-expanded'. */
|
|
19108
19242
|
"helix-headless-drawer": DefineCustomElement<
|
|
19109
19243
|
HelixHeadlessDrawer,
|
|
19110
19244
|
HelixHeadlessDrawerVueProps,
|
|
@@ -19134,7 +19268,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19134
19268
|
HelixHeadlessFileInputVueProps,
|
|
19135
19269
|
HelixHeadlessFileInputVueEvents
|
|
19136
19270
|
>;
|
|
19137
|
-
/** Shows one filter declared by a 'FilterField': the field, the operator, and the values, with a control to remove the filter. The operator is shown only when it is not the field's default: ''' Disposition refunded, chargeback default operator, hidden Disposition is not refunded chosen operator, shown Created after 1 Aug a scalar field has no default ''' Omit 'operator-label' for the field's default operator and pass it for every other operator. The code that builds the chip has the field, and the field defines its default. The chip shows a filter and does not apply it. Dismissing fires 'helix-dismiss' as a request, as on 'Tag' and 'Announcement'. The chip is your element in your list, so you remove it, which keeps your model and the document in step. Call 'preventDefault()' on 'helix-dismiss' to cancel the dismissal, which is also how you take control of the interaction for one press. 'requestChange' documents the pattern. **Keyboard.** The remove button is a tab stop of its own, and Enter or Space on it asks to remove the filter. In a 'FilterInput', Backspace in the empty field asks to remove the last chip, the arrow keys move between the field and the chips, and Delete or Backspace on a chip asks to remove it. The remove button is named 'dismiss-label' followed by the chip's words, such as "Remove filter Status is not open", so a row of chips says which filter each button removes. Write '{label}' in 'dismiss-label' to put the words elsewhere. To let the user change the operator, slot a menu trigger into 'operator'. With the text fallback, the operator is a label. The chip does not interpret operators: their meaning belongs to your domain, as 'FilterOperator' explains. */
|
|
19271
|
+
/** Shows one filter declared by a 'FilterField': the field, the operator, and the values, with a control to remove the filter. The operator is shown only when it is not the field's default: ''' Disposition refunded, chargeback default operator, hidden Disposition is not refunded chosen operator, shown Created after 1 Aug a scalar field has no default ''' Omit 'operator-label' for the field's default operator and pass it for every other operator. The code that builds the chip has the field, and the field defines its default. The chip shows a filter and does not apply it. Dismissing fires 'helix-dismiss' as a request, as on 'Tag' and 'Announcement'. The chip is your element in your list, so you remove it, which keeps your model and the document in step. Call 'preventDefault()' on 'helix-dismiss' to cancel the dismissal, which is also how you take control of the interaction for one press. 'requestChange' documents the pattern. **Keyboard.** The remove button is a tab stop of its own, and Enter or Space on it asks to remove the filter. In a 'FilterInput', the field's text is the one tab stop: Backspace in the empty field asks to remove the last chip, the arrow keys move between the field and the chips, and Delete or Backspace on a chip asks to remove it. The remove button is named 'dismiss-label' followed by the chip's words, such as "Remove filter Status is not open", so a row of chips says which filter each button removes. Write '{label}' in 'dismiss-label' to put the words elsewhere. To let the user change the operator, slot a menu trigger into 'operator'. With the text fallback, the operator is a label. The chip does not interpret operators: their meaning belongs to your domain, as 'FilterOperator' explains. */
|
|
19138
19272
|
"helix-headless-filter-chip": DefineCustomElement<
|
|
19139
19273
|
HelixHeadlessFilterChip,
|
|
19140
19274
|
HelixHeadlessFilterChipVueProps,
|
|
@@ -19158,13 +19292,13 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19158
19292
|
HelixHeadlessFilterOperatorVueProps,
|
|
19159
19293
|
HelixHeadlessFilterOperatorVueEvents
|
|
19160
19294
|
>;
|
|
19161
|
-
/** Tokens are your own elements, slotted in. A filter can be a facet with a prefix, a saved query, or a range, and these belong to your model, so the element does not render tokens from a list of strings. Removing a token is a request the element fires, and you apply it. Combobox works the other way: its tokens show a selection it owns, drawn from the options it was given. 'value' is the typed text. Every keystroke fires 'input' with the text on the element, so a table can narrow as the user types. Backspace in an empty field fires 'helix-dismiss' on the last token, the same event its remove control fires, so one handler covers the pointer and the keyboard. **What a form receives.** The text under 'name', and then one more entry under 'name' for each token, in the order the tokens stand: | Token | Entry | |---|---| | Any element with a 'value' attribute | The value as written: 'saved:mine' | | 'FilterChip' with 'name' and values | 'status:open,pending' | | The same, with 'operator="none"' (what a typed '-status:' makes) | '-status:open,pending' | | The same, with any other 'operator' except 'any' | 'created[after]:2024' | | A token with neither | Nothing | The values are the chip's text outside its 'field' and 'operator' slots, with the spaces around each comma removed. A server splits an entry at its first colon, reads a leading '-' as the negation, and reads a word in brackets before the colon as the comparison. **Keyboard.** Focus stays in the text. The text names the highlighted suggestion as its 'aria-activedescendant'. | Key | What it does | |---|---| | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. | | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. | | Home, End | Highlights the first or the last suggestion while the panel is open. | | Escape | Closes the panel and stops there, so a dialog around the field stays open. | | Backspace | In an empty field, asks the last token to go. | | Left | With the caret at the start of the text, moves to the last token's remove button. Right on a right-to-left page. | | Left, Right on a token | Move between the tokens, and past the last back to the text. | | Delete, Backspace on a token | Asks the token to go. | **Typed filters.** The field parses only the fields you declare. Write 'FilterField' elements, usually inside the 'FilterMenu' slotted into 'start', so the picker and the text share one set. On Enter, the field reads the text against them. 'disposition:refunded,settled' and '-disposition:refunded' fire 'helix-facet' exactly as ticking those values in the picker would, and the parsed text is removed. Everything else stays, so 'refund tuesday disposition:settled' is a filter and a search at once. Helix defines the punctuation and you define every word. 'grammar.ts' has the full rule, so read it before you rely on it. A field with no 'FilterField' in it parses nothing. A field whose values cannot be listed, such as 'assignee:ada', goes directly inside this element, outside the menu. It is not assigned to a slot, so nothing draws it and the menu has no page for it, and the grammar still reads it. **Suggestions.** Slot options into 'suggestions' and the field shows them, moves through them with the arrow keys, and presses one on Enter. The option fires its own 'helix-select', and you decide what choosing it means. Keys before a colon and values after it use the same panel with different contents. 'filter-suggestions' narrows the panel to the options whose words hold the term at the caret, after its colon, ignoring case and accents, and hides the rest. 'readFilterText' is exported so you can narrow it yourself against partly typed text. While the panel is open, a reader hears how many suggestions it offers. The panel opens when it has options and closes when it has none, and a choice does not close it, so after picking a key you see its values next. Use 'selectionStart' and 'setSelectionRange' to write a completion back and put the caret after it, or the next parse reads the wrong term. **State.** Three things have three different owners: - 'value' is the text. The user types, the element applies it, and 'input' reports it. Setting 'value' seeds or corrects the text, and the next keystroke overwrites it, even in React. To control the value, cancel 'helix-before-change' and write the value you want, as with every field in this library. 'default-value' seeds the field. - 'open' is the suggestions panel. Cancel 'helix-before-open' or 'helix-before-close' to control it, and use 'default-open' to seed it. - Tokens are your elements in a slot and hold no state. A token goes when you remove it from your markup after 'helix-dismiss'. A 'FilterChip' naming a declared field works differently, because the picker holds what is ticked and removing the chip alone would leave its value ticked in the hidden menu. Its dismissal is treated as the field being filtered by nothing, so it fires 'helix-facet' like every other change, and the chip goes when the filter goes. */
|
|
19295
|
+
/** Tokens are your own elements, slotted in. A filter can be a facet with a prefix, a saved query, or a range, and these belong to your model, so the element does not render tokens from a list of strings. Removing a token is a request the element fires, and you apply it. Combobox works the other way: its tokens show a selection it owns, drawn from the options it was given. 'value' is the typed text. Every keystroke fires 'input' with the text on the element, so a table can narrow as the user types. Backspace in an empty field fires 'helix-dismiss' on the last token, the same event its remove control fires, so one handler covers the pointer and the keyboard. **What a form receives.** The text under 'name', and then one more entry under 'name' for each token, in the order the tokens stand: | Token | Entry | |---|---| | Any element with a 'value' attribute | The value as written: 'saved:mine' | | 'FilterChip' with 'name' and values | 'status:open,pending' | | The same, with 'operator="none"' (what a typed '-status:' makes) | '-status:open,pending' | | The same, with any other 'operator' except 'any' | 'created[after]:2024' | | A token with neither | Nothing | The values are the chip's text outside its 'field' and 'operator' slots, with the spaces around each comma removed. A server splits an entry at its first colon, reads a leading '-' as the negation, and reads a word in brackets before the colon as the comparison. **Keyboard.** Focus stays in the text, which is the field's one tab stop. The text names the highlighted suggestion as its 'aria-activedescendant', and the arrow keys reach the tokens. | Key | What it does | |---|---| | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. | | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. | | Home, End | Highlights the first or the last suggestion while the panel is open. | | Escape | Closes the panel and stops there, so a dialog around the field stays open. | | Backspace | In an empty field, asks the last token to go. | | Left | With the caret at the start of the text, moves to the last token's remove button. Right on a right-to-left page. | | Left, Right on a token | Move between the tokens, and past the last back to the text. | | Delete, Backspace on a token | Asks the token to go. | **Typed filters.** The field parses only the fields you declare. Write 'FilterField' elements, usually inside the 'FilterMenu' slotted into 'start', so the picker and the text share one set. On Enter, the field reads the text against them. 'disposition:refunded,settled' and '-disposition:refunded' fire 'helix-facet' exactly as ticking those values in the picker would, and the parsed text is removed. Everything else stays, so 'refund tuesday disposition:settled' is a filter and a search at once. Helix defines the punctuation and you define every word. 'grammar.ts' has the full rule, so read it before you rely on it. A field with no 'FilterField' in it parses nothing. A field whose values cannot be listed, such as 'assignee:ada', goes directly inside this element, outside the menu. It is not assigned to a slot, so nothing draws it and the menu has no page for it, and the grammar still reads it. **Suggestions.** Slot options into 'suggestions' and the field shows them, moves through them with the arrow keys, and presses one on Enter. The option fires its own 'helix-select', and you decide what choosing it means. Keys before a colon and values after it use the same panel with different contents. 'filter-suggestions' narrows the panel to the options whose words hold the term at the caret, after its colon, ignoring case and accents, and hides the rest. 'readFilterText' is exported so you can narrow it yourself against partly typed text. While the panel is open, a reader hears how many suggestions it offers. The panel opens when it has options and closes when it has none, and a choice does not close it, so after picking a key you see its values next. Use 'selectionStart' and 'setSelectionRange' to write a completion back and put the caret after it, or the next parse reads the wrong term. **State.** Three things have three different owners: - 'value' is the text. The user types, the element applies it, and 'input' reports it. Setting 'value' seeds or corrects the text, and the next keystroke overwrites it, even in React. To control the value, cancel 'helix-before-change' and write the value you want, as with every field in this library. 'default-value' seeds the field. - 'open' is the suggestions panel. Cancel 'helix-before-open' or 'helix-before-close' to control it, and use 'default-open' to seed it. - Tokens are your elements in a slot and hold no state. A token goes when you remove it from your markup after 'helix-dismiss'. A 'FilterChip' naming a declared field works differently, because the picker holds what is ticked and removing the chip alone would leave its value ticked in the hidden menu. Its dismissal is treated as the field being filtered by nothing, so it fires 'helix-facet' like every other change, and the chip goes when the filter goes. Set 'chips' and the field adds, updates, and removes those chips itself, from every 'helix-facet' you do not cancel. */
|
|
19162
19296
|
"helix-headless-filter-input": DefineCustomElement<
|
|
19163
19297
|
HelixHeadlessFilterInput,
|
|
19164
19298
|
HelixHeadlessFilterInputVueProps,
|
|
19165
19299
|
HelixHeadlessFilterInputVueEvents
|
|
19166
19300
|
>;
|
|
19167
|
-
/** Formats a date with 'Intl' where it is shown, so you do not write the same 'Intl' call and options in your own code. **'elapsed' shows compact relative time for a feed**, such as "42m", "3h", or "1d". After six days it shows a date. In en-US, 'Intl.NumberFormat' narrow renders both 'minute' and 'month' as 'm', so a compact "3m" could mean three minutes or three months. 'elapsedTime' in 'helix/core' does the measurement. **'relative' shows the same reading in words**, such as "3 hours ago" at 'long', "3 hr. ago" at 'short' and "3h ago" at 'narrow', the styles 'sl-relative-time' offers. 'numeric="always"' says "1 day ago" where the default says "yesterday". **'date-style' and 'time-style' take each locale's own pattern**, such as "Tuesday, August 4, 2026" at 'full', and stand in for the separate fields, which 'Intl' refuses beside them. 'hour-cycle' sets a twelve or twenty-four hour clock either way. **The text refreshes on one timer shared by the page.** Each element schedules an update for when its current reading expires, and an element showing a date schedules none, so a long feed left open costs almost nothing. 'frozen' draws the reading once and leaves it. **'fields' draws each field of a date as a part of its own**, such as 'day', 'month' and 'year', so a stylesheet can set the year in a lighter ink or the weekday in capitals with '::part()'. The text between the fields is the locale's own and has no part. An 'elapsed' or 'relative' reading is one phrase, with no parts inside it. **The output is always '<time datetime>'**, so copy and paste and scripts parsing the page get the exact instant, whatever the visible text says. A screen reader reads the text, so an 'elapsed' reading is named in full, such as "3 hours ago", and carries the whole date as its title. **A date with no time, such as '2026-08-04', is that day everywhere.** It is formatted in UTC unless 'time-zone' says otherwise, as Date Input and Date Picker format their dates, so a reader west of UTC sees August 4 and not August 3. **A date is written in a calendar Date Picker draws**: the locale's own where its months are the Gregorian months, as 'th-TH' writes 2569 for 2026, and 'gregory' where they are not, as for 'fa-IR'. 'calendar' picks any of them, 'persian' and 'hebrew' included. */
|
|
19301
|
+
/** Formats a date with 'Intl' where it is shown, so you do not write the same 'Intl' call and options in your own code. **'elapsed' shows compact relative time for a feed**, such as "42m", "3h", or "1d". After six days it shows a date. In en-US, 'Intl.NumberFormat' narrow renders both 'minute' and 'month' as 'm', so a compact "3m" could mean three minutes or three months. 'elapsedTime' in 'helix/core' does the measurement. **'relative' shows the same reading in words**, such as "3 hours ago" at 'long', "3 hr. ago" at 'short' and "3h ago" at 'narrow', the styles 'sl-relative-time' offers. 'numeric="always"' says "1 day ago" where the default says "yesterday". Both readings round the count, as 'sl-relative-time' does: 100 seconds ago is "2 minutes ago", and 59.6 minutes is "1 hour". **'date-style' and 'time-style' take each locale's own pattern**, such as "Tuesday, August 4, 2026" at 'full', and stand in for the separate fields, which 'Intl' refuses beside them. 'hour-cycle' sets a twelve or twenty-four hour clock either way. **The text refreshes on one timer shared by the page.** Each element schedules an update for when its current reading expires, and an element showing a date schedules none, so a long feed left open costs almost nothing. 'frozen' draws the reading once and leaves it. **'fields' draws each field of a date as a part of its own**, such as 'day', 'month' and 'year', so a stylesheet can set the year in a lighter ink or the weekday in capitals with '::part()'. The text between the fields is the locale's own and has no part. An 'elapsed' or 'relative' reading is one phrase, with no parts inside it. **The output is always '<time datetime>'**, so copy and paste and scripts parsing the page get the exact instant, whatever the visible text says. A screen reader reads the text, so an 'elapsed' reading is named in full, such as "3 hours ago", and carries the whole date as its title. **A date with no time, such as '2026-08-04', is that day everywhere.** It is formatted in UTC unless 'time-zone' says otherwise, as Date Input and Date Picker format their dates, so a reader west of UTC sees August 4 and not August 3. **A date is written in a calendar Date Picker draws**: the locale's own where its months are the Gregorian months, as 'th-TH' writes 2569 for 2026, and 'gregory' where they are not, as for 'fa-IR'. 'calendar' picks any of them, 'persian' and 'hebrew' included. */
|
|
19168
19302
|
"helix-headless-format-date": DefineCustomElement<
|
|
19169
19303
|
HelixHeadlessFormatDate,
|
|
19170
19304
|
HelixHeadlessFormatDateVueProps,
|
|
@@ -19338,7 +19472,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19338
19472
|
HelixHeadlessMenuItemVueProps,
|
|
19339
19473
|
HelixHeadlessMenuItemVueEvents
|
|
19340
19474
|
>;
|
|
19341
|
-
/** The trigger is slotted and stays your own element, as with the tooltip. The menu renders its surface in the top layer with the popover API, so an ancestor with 'overflow: hidden' does not clip it and it needs no 'z-index'. Slot a 'helix-button' or 'helix-icon-button' as the trigger, and the menu tells it that it opens a menu and whether the menu is open, inside its own shadow root. On a plain element, such as a '<button>', the menu writes 'aria-haspopup="menu"' and 'aria-expanded', from a frame after its own first render, so a server's markup is never changed while a framework hydrates it. It never writes 'aria-expanded' where you wrote it yourself. Submenus drill down by default. A submenu replaces the panel's content, and a back row returns to the previous page. One panel stays inside a narrow window, and works on touch screens, which have no hover. **'submenus="flyout"' opens each submenu in a panel of its own beside its row**, as React Aria's 'SubmenuTrigger' and Radix's 'Sub' do. Resting the pointer on the row opens it, and a pointer crossing toward the open panel over the rows between keeps it open, as Radix's grace area does. Right Arrow opens a row's submenu on its first row, and Left Arrow or Escape closes it and returns focus to the row, the two arrows swapping on a right-to-left page. The row says 'aria-expanded', and the panel is a 'menu' named by the row. The root holds which page is open, because only one page shows at a time. It sets this on items as a property, never as an attribute. An attribute written onto your element after it upgrades causes a hydration mismatch. Group rows under a heading with 'Menu.Section', which is a 'group' named by its heading. Between runs of rows, a '<helix-divider>' is a separator a screen reader announces. Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first row, and Up Arrow on its last. In the menu, Up and Down Arrow move between rows, Home and End go to the first and the last, a typed letter moves to the next row whose name starts with it, Enter and Space choose (Space on a choice row changes it and leaves the menu open), Right Arrow opens a row's submenu and Left Arrow goes back, the two swapping on a right-to-left page. Left Arrow on the top page does nothing. Escape closes the menu and returns focus to the trigger. Tab closes it and moves on. While it is open, the surface carries the trigger's width as '--floating-anchor-inline-size' and the room left below it as '--floating-available-block-size', as Radix's dropdown menu publishes its trigger's width, for a menu as wide as its trigger: 'helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }'. With 'context', the trigger is an area and the menu is its context menu: a right-click, a long press, Shift+F10 or the menu key over the area opens it at the pointer, or at the area's corner from the keyboard, as Radix's context menu does. A press on the area does not open it, and closing it returns focus to where it was. A touch or a pen held still on the area opens it too, on every browser, since iOS sends no 'contextmenu' for one. **A trigger with its own action.** With 'open-on="long-press"', a press on the trigger is the trigger's own, and a press held for half a second opens the menu, as React Aria's 'trigger="longPress"' does. Alt+Down or Alt+Up opens it from the keyboard, and the trigger is described by 'long-press-label', which says so. **A filter field.** With 'filterable', the menu opens with focus in a field above its rows, and typing narrows the rows of the page the keys move in, as React Aria's 'Autocomplete' around a 'Menu' does. A row is kept where its words hold the filter, in any case, or where 'filterMatch' says so. Each page starts unfiltered, and the filter is cleared as the menu closes. Where typing keeps no row, the menu shows 'no-results-text'. Focus stays in the field: Up and Down Arrow move the highlight through the rows that are left, Enter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow on a submenu goes back, and Escape clears the filter and then closes the menu. Home, End and the other keys move the caret and type. The field names the highlighted row with 'aria-activedescendant', and the rows are a 'menu' after the field. Cancel 'helix-filter' to keep every row showing and narrow the rows yourself, such as by replacing them with rows from a server. */
|
|
19475
|
+
/** The trigger is slotted and stays your own element, as with the tooltip. The menu renders its surface in the top layer with the popover API, so an ancestor with 'overflow: hidden' does not clip it and it needs no 'z-index'. Slot a 'helix-button' or 'helix-icon-button' as the trigger, and the menu tells it that it opens a menu and whether the menu is open, inside its own shadow root. On a plain element, such as a '<button>', the menu writes 'aria-haspopup="menu"' and 'aria-expanded', from a frame after its own first render, so a server's markup is never changed while a framework hydrates it. It never writes 'aria-expanded' where you wrote it yourself. Submenus drill down by default. A submenu replaces the panel's content, and a back row returns to the previous page. One panel stays inside a narrow window, and works on touch screens, which have no hover. Focus follows a mouse resting on a row in either mode, and a drilled page is a 'menu' named by the row that opened it. **'submenus="flyout"' opens each submenu in a panel of its own beside its row**, as React Aria's 'SubmenuTrigger' and Radix's 'Sub' do. Resting the pointer on the row opens it, and a pointer crossing toward the open panel over the rows between keeps it open, as Radix's grace area does. Right Arrow opens a row's submenu on its first row, and Left Arrow or Escape closes it and returns focus to the row, the two arrows swapping on a right-to-left page. The row says 'aria-expanded', and the panel is a 'menu' named by the row. The root holds which page is open, because only one page shows at a time. It sets this on items as a property, never as an attribute. An attribute written onto your element after it upgrades causes a hydration mismatch. Group rows under a heading with 'Menu.Section', which is a 'group' named by its heading. Between runs of rows, a '<helix-divider>' is a separator a screen reader announces. Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first row, and Up Arrow on its last. In the menu, Up and Down Arrow move between rows, Home and End go to the first and the last, a typed letter moves to the next row whose name starts with it, Enter and Space choose (Space on a choice row changes it and leaves the menu open), Right Arrow opens a row's submenu and Left Arrow goes back, the two swapping on a right-to-left page. Left Arrow on the top page does nothing. Escape closes the menu and returns focus to the trigger. Tab closes it and moves on. While it is open, the surface carries the trigger's width as '--floating-anchor-inline-size' and the room left below it as '--floating-available-block-size', as Radix's dropdown menu publishes its trigger's width, for a menu as wide as its trigger: 'helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }'. **The choices in one place.** 'checkedValues' holds the values of the rows that are checked, anywhere in the menu, and setting it checks exactly those rows, as React Aria's 'selectedKeys' does. 'change' is sent on the menu when a reader's choice changes it. With 'context', the trigger is an area and the menu is its context menu: a right-click, a long press, Shift+F10 or the menu key over the area opens it at the pointer, or at the area's corner from the keyboard, as Radix's context menu does. A press on the area does not open it, and closing it returns focus to where it was. A touch or a pen held still on the area opens it too, on every browser, since iOS sends no 'contextmenu' for one. **A trigger with its own action.** With 'open-on="long-press"', a press on the trigger is the trigger's own, and a press held for half a second opens the menu, as React Aria's 'trigger="longPress"' does. Alt+Down or Alt+Up opens it from the keyboard, and the trigger is described by 'long-press-label', which says so. **A filter field.** With 'filterable', the menu opens with focus in a field above its rows, and typing narrows the rows of the page the keys move in, as React Aria's 'Autocomplete' around a 'Menu' does. A row is kept where its words hold the filter, in any case, or where 'filterMatch' says so. Each page starts unfiltered, and the filter is cleared as the menu closes. Where typing keeps no row, the menu shows 'no-results-text'. Focus stays in the field: Up and Down Arrow move the highlight through the rows that are left, Enter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow on a submenu goes back, and Escape clears the filter and then closes the menu. A screen reader hears how many rows the filter keeps ('results-label'). Home, End and the other keys move the caret and type. The field names the highlighted row with 'aria-activedescendant', and the rows are a 'menu' after the field. Cancel 'helix-filter' to keep every row showing and narrow the rows yourself, such as by replacing them with rows from a server. */
|
|
19342
19476
|
"helix-headless-menu": DefineCustomElement<
|
|
19343
19477
|
HelixHeadlessMenu,
|
|
19344
19478
|
HelixHeadlessMenuVueProps,
|
|
@@ -19440,7 +19574,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19440
19574
|
HelixHeadlessPinInputVueProps,
|
|
19441
19575
|
HelixHeadlessPinInputVueEvents
|
|
19442
19576
|
>;
|
|
19443
|
-
/** Popover is the general overlay that the specific ones build on. 'Menu' holds commands, 'Select' holds options, and 'Tooltip' holds a description. Popover holds any content you put in it, so it has no keyboard handling of its own. The trigger is slotted and stays your own element. A Helix trigger is told whether the popover is open inside its own shadow root. On a plain element, such as a '<button>', the popover writes 'aria-expanded', from a frame after its own first render, or from the first press where that comes sooner. It never writes it where you wrote 'aria-expanded' yourself, and writes nothing else onto your markup. The panel is in the top layer through the popover API, so it needs no 'z-index', and an ancestor with 'overflow: hidden', 'transform', 'filter', or 'contain' does not clip or move it. It opens on click and from a command. 'command="--show"' and the related commands work as they do on 'Dialog' and 'Drawer', so a button anywhere on the page can open the popover with no script. **Opening moves focus into the panel**, to the first control in it, or to the panel itself where it holds none, and closing from inside gives it back to the trigger. It closes on Escape, on a press outside it, and when focus moves out of the trigger and the panel to somewhere else on the page. 'modal' keeps 'Tab' inside the panel while it is open and says so with 'aria-modal', for a panel that has to be answered before the page goes on. The rest of the page is hidden from screen readers with 'aria-hidden' while it is open, so the virtual cursor stays in the panel too. Without it the popover does not trap focus. The panel's name is 'label' when you set it. Otherwise it is the first heading in the panel, or the elements an 'aria-labelledby' on the host names. A development build warns when a popover opens with nothing but 'fallback-label' to name it. **Keyboard.** Opening moves focus to the first control in the panel, or to the panel where it holds none. | Key | What it does | |---|---| | Enter, Space | On the trigger, opens the panel, or closes it while it is open. | | Escape | Closes the panel and puts focus back on the trigger. | | Tab, Shift+Tab | Moves through the controls in the panel. Leaving the panel and the trigger closes it. With 'modal', moves from the last control round to the first and from the first round to the last. | 'arrow' draws a point on the panel's edge facing the trigger. The side the panel landed on is on the host as ':state(placed-top)' and its kin, and the trigger's width is on the panel as '--floating-anchor-inline-size', for a panel as wide as its trigger: '''css helix-popover::part(popover) { min-inline-size: var(--floating-anchor-inline-size); } ''' */
|
|
19577
|
+
/** Popover is the general overlay that the specific ones build on. 'Menu' holds commands, 'Select' holds options, and 'Tooltip' holds a description. Popover holds any content you put in it, so it has no keyboard handling of its own. The trigger is slotted and stays your own element. A Helix trigger is told whether the popover is open inside its own shadow root. On a plain element, such as a '<button>', the popover writes 'aria-expanded', from a frame after its own first render, or from the first press where that comes sooner. It never writes it where you wrote 'aria-expanded' yourself, and writes nothing else onto your markup. The panel is in the top layer through the popover API, so it needs no 'z-index', and an ancestor with 'overflow: hidden', 'transform', 'filter', or 'contain' does not clip or move it. It opens on click and from a command. 'command="--show"' and the related commands work as they do on 'Dialog' and 'Drawer', so a button anywhere on the page can open the popover with no script. From its first press, a button that opens it this way says whether the popover is open: a Helix button through 'expanded', and any other element with 'aria-expanded'. **Opening moves focus into the panel**, to the first control in it, or to the panel itself where it holds none, and closing from inside gives it back to the trigger. It closes on Escape, on a press outside it, and when focus moves out of the trigger and the panel to somewhere else on the page. 'modal' keeps 'Tab' inside the panel while it is open and says so with 'aria-modal', for a panel that has to be answered before the page goes on. The rest of the page is hidden from screen readers with 'aria-hidden' while it is open, so the virtual cursor stays in the panel too, and the page does not scroll behind it. Without it the popover does not trap focus. A press outside closes the panel and leaves focus where the press put it. Where it put focus nowhere, as a press on text or on the page's background does, focus goes back to the trigger. The panel's name is 'label' when you set it. Otherwise it is the first heading in the panel, or the elements an 'aria-labelledby' on the host names. A development build warns when a popover opens with nothing but 'fallback-label' to name it. **Keyboard.** Opening moves focus to the first control in the panel, or to the panel where it holds none. | Key | What it does | |---|---| | Enter, Space | On the trigger, opens the panel, or closes it while it is open. | | Escape | Closes the panel and puts focus back on the trigger. | | Tab, Shift+Tab | Moves through the controls in the panel. Leaving the panel and the trigger closes it. With 'modal', moves from the last control round to the first and from the first round to the last. | The panel opens against the trigger, or against the element 'anchor' names, such as a field beside the button that opens it. 'offset' moves it away from that element, 'cross-offset' slides it along the side it is on, 'container-padding' keeps it that far from the window's edges, and 'flip="false"' keeps it on its side where the other side has more room. 'arrow' draws a point on the panel's edge facing the trigger. The side the panel landed on is on the host as ':state(placed-top)' and its kin, its alignment along that side as ':state(aligned-start)' or ':state(aligned-end)', and the trigger's width is on the panel as '--floating-anchor-inline-size', for a panel as wide as its trigger: '''css helix-popover::part(popover) { min-inline-size: var(--floating-anchor-inline-size); } ''' */
|
|
19444
19578
|
"helix-headless-popover": DefineCustomElement<
|
|
19445
19579
|
HelixHeadlessPopover,
|
|
19446
19580
|
HelixHeadlessPopoverVueProps,
|
|
@@ -19494,7 +19628,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19494
19628
|
HelixHeadlessScrollAreaVueProps,
|
|
19495
19629
|
HelixHeadlessScrollAreaVueEvents
|
|
19496
19630
|
>;
|
|
19497
|
-
/** A trigger that opens a 'Listbox'. The list is the same element you can use on its own, with the same keyboard behavior, filtering, and multi-select rules. Select adds a trigger that shows what is chosen, a floating surface, and a place for focus to return to when the list closes. Your options stay in your light DOM and are slotted through into the listbox, so the listbox looks through slots to find them. For a list too long to draw whole, set 'items' instead: the list draws only the options in sight, as Listbox's 'items' does, and the trigger, its keys and the form read the whole set. 'Select' owns the value, passes it down to the listbox, and takes changes back, so the value lives in one place. With 'multiple', the value is the chosen values joined with commas, and the form receives one entry for each. An option's value may hold a comma, and it is read as one value. Set 'valueContent' to draw the trigger's content from the chosen options, and several chosen options are written as a list in the reader's language. **Keyboard.** On the closed trigger: | Key | What it does | |---|---| | Down, Enter, Space | Opens the list on the chosen option, or the first. | | Up | Opens the list on the chosen option, or the last. | | Home, End | Opens the list on the first or the last option. | | Left, Right | Chooses the option before or after the chosen one without opening, as React Aria's Select does
|
|
19631
|
+
/** A trigger that opens a 'Listbox'. The list is the same element you can use on its own, with the same keyboard behavior, filtering, and multi-select rules. Select adds a trigger that shows what is chosen, a floating surface, and a place for focus to return to when the list closes. Your options stay in your light DOM and are slotted through into the listbox, so the listbox looks through slots to find them. For a list too long to draw whole, set 'items' instead: the list draws only the options in sight, as Listbox's 'items' does, and the trigger, its keys and the form read the whole set. 'Select' owns the value, passes it down to the listbox, and takes changes back, so the value lives in one place. With 'multiple', the value is the chosen values joined with commas, and the form receives one entry for each. An option's value may hold a comma, and it is read as one value. Set 'valueContent' to draw the trigger's content from the chosen options, and several chosen options are written as a list in the reader's language. **Keyboard.** On the closed trigger: | Key | What it does | |---|---| | Down, Enter, Space | Opens the list on the chosen option, or the first. | | Up | Opens the list on the chosen option, or the last. | | Home, End | Opens the list on the first or the last option. | | Left, Right | Chooses the option before or after the chosen one without opening, as React Aria's Select does. On a right-to-left page Left chooses the one after. | | A letter or a word | Chooses the option whose words start with what you typed, as a native '<select>' does. With 'multiple', opens the list on it. | In the open list, which is a 'Listbox': | Key | What it does | |---|---| | Down, Up, Home, End, Page Down, Page Up | Moves the highlight. | | A letter or a word | Moves the highlight to the next option whose words start with what you typed. | | Enter, Space | Chooses the highlighted option and closes the list. With 'multiple', toggles it and leaves the list open. | | Escape | Closes the list and puts focus back on the trigger. | | Tab | Closes the list and moves on. | A choice made on the closed trigger is said aloud on Apple devices, where VoiceOver does not read the trigger's new name. **ARIA.** The trigger is a 'button' with 'aria-haspopup="listbox"' and 'aria-expanded', named by the label and then the chosen words, as a native '<select>' is. The list is the listbox 'Listbox' describes, named by the label, or by 'list-label' where there is none. Set 'autocomplete' to let a browser's autofill choose, as a native '<select>' with the same attribute would. */
|
|
19498
19632
|
"helix-headless-select": DefineCustomElement<
|
|
19499
19633
|
HelixHeadlessSelect,
|
|
19500
19634
|
HelixHeadlessSelectVueProps,
|
|
@@ -19560,7 +19694,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19560
19694
|
HelixHeadlessStatVueProps,
|
|
19561
19695
|
HelixHeadlessStatVueEvents
|
|
19562
19696
|
>;
|
|
19563
|
-
/** 'active' sets where the user is, and 'complete' stays on each step. Returning to stage one of three leaves stages one and two finished, so the root sets 'current' on the steps and never changes 'complete'. 'active' is optional. Without it, each step keeps its own 'current', so the sequence is correct in the server's markup, where the root cannot count its slotted children. 'linear' keeps a reader from passing a stage they have not finished, as Ark UI's linear steps do: a stage ahead is out of reach, and its button disabled, until every stage before it is 'complete' or 'optional'. Going back is always allowed. 'next()' and 'previous()' move one stage either way, under the same rules, for your own buttons. 'reset()' goes back to the first stage and clears every stage's 'complete', as Ark UI's 'resetStep' does. 'completion="passed"' marks a stage 'complete' once a reader moves past it, as Ark UI counts a stage before the current one as completed. Going back leaves it complete. In a 'linear' sequence the next stage is then in reach from the current one, and 'validate' decides whether the reader may go. To check a stage before a reader moves on from it, set 'validate' to a function that answers whether the stage is valid, as Ark UI's 'isStepValid' does. Moving forward asks it about the stage the reader is on, and where it answers 'false' the reader stays and the stage is ':state(invalid)' until it answers 'true'. An 'optional' stage is not asked. 'helix-before-activate' is still sent for every move, for a check of your own. 'progress' is how far through the sequence is, from 0 to 100: the share of its stages that are 'complete'. The 'progress' part carries it as a 'progressbar' and as '--steps-progress', and is hidden until a stylesheet gives it a 'display', so a bar of your own costs nothing until you draw it. A screen reader hears it as 'progress-label' says, "33% complete" unless set, as Ark UI's steps write it. The sequence is ':state(complete)' once every stage is. The sequence is a list named by 'label', and each step a list item. The current stage's button says 'aria-current="step"', and a finished stage's button is described by its 'complete-label'. **Keyboard.** Each stage's name is a button and its own tab stop, and Enter or Space goes to the stage. Set 'arrows' and the
|
|
19697
|
+
/** 'active' sets where the user is, and 'complete' stays on each step. Returning to stage one of three leaves stages one and two finished, so the root sets 'current' on the steps and never changes 'complete'. 'active' is optional. Without it, each step keeps its own 'current', so the sequence is correct in the server's markup, where the root cannot count its slotted children. 'active' names a step by its 'value'. A step with no 'value' is named by its place, counted from 1, so a sequence written without values moves as one written with them, and 'helix-activate' says '1', '2' and so on. Give every step a value or none, because a value of '2' and the second place are one name. 'linear' keeps a reader from passing a stage they have not finished, as Ark UI's linear steps do: a stage ahead is out of reach, and its button disabled, until every stage before it is 'complete' or 'optional'. Going back is always allowed. 'next()' and 'previous()' move one stage either way, under the same rules, for your own buttons. 'reset()' goes back to the first stage and clears every stage's 'complete', as Ark UI's 'resetStep' does. A button anywhere on the page calls them with no script, as Ark UI's previous and next triggers do: give it 'commandfor' with the sequence's 'id', and 'command="--previous"', '"--next"' or '"--reset"'. 'completion="passed"' marks a stage 'complete' once a reader moves past it, as Ark UI counts a stage before the current one as completed. Going back leaves it complete. In a 'linear' sequence the next stage is then in reach from the current one, and 'validate' decides whether the reader may go. To check a stage before a reader moves on from it, set 'validate' to a function that answers whether the stage is valid, as Ark UI's 'isStepValid' does. Moving forward asks it about the stage the reader is on, and where it answers 'false' the reader stays and the stage is ':state(invalid)' until it answers 'true'. An 'optional' stage is not asked. 'helix-before-activate' is still sent for every move, for a check of your own. 'progress' is how far through the sequence is, from 0 to 100: the share of its stages that are 'complete'. The 'progress' part carries it as a 'progressbar' and as '--steps-progress', and is hidden until a stylesheet gives it a 'display', so a bar of your own costs nothing until you draw it. A screen reader hears it as 'progress-label' says, "33% complete" unless set, as Ark UI's steps write it. The sequence is ':state(complete)' once every stage is. The sequence is a list named by 'label', and each step a list item. The current stage's button says 'aria-current="step"', and a finished stage's button is described by its 'complete-label'. **Keyboard.** Each stage's name is a button and its own tab stop, and Enter or Space goes to the stage. Set 'arrows' and the names are one tab stop, the current stage's, and the arrow keys move focus between them: Left and Right along a row, Up and Down a column, Home and End to the first and the last. The stop follows focus, so Tab leaves the sequence and Shift+Tab comes back to the name the reader left. The arrows pass over a disabled stage and one a linear sequence holds out of reach, and they move focus without going to the stage. */
|
|
19564
19698
|
"helix-headless-steps": DefineCustomElement<
|
|
19565
19699
|
HelixHeadlessSteps,
|
|
19566
19700
|
HelixHeadlessStepsVueProps,
|
|
@@ -19746,7 +19880,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19746
19880
|
HelixHeadlessVideoPlaylistMenuVueProps,
|
|
19747
19881
|
HelixHeadlessVideoPlaylistMenuVueEvents
|
|
19748
19882
|
>;
|
|
19749
|
-
/** **You slot the player**, so it keeps your appearance, extra controls, captions, and poster treatment. 'Sandbox' takes its preview and 'Menu' its trigger the same way. **Entries are markup.** React skips properties it would set imperatively during hydration, so an array property on a custom element is missing on the first paint of a server-rendered page. 'using-the-elements.mdx' has the measurement. Markup also makes each entry a real button with its name inside. **The playlist does not play media.** It sets 'src' on the player and tracks which entry is current. The current entry moves when: - an entry is pressed, - the player dispatches 'helix-next' or 'helix-previous', or - the player reaches the end. On 'ended' the playlist advances and the next clip starts playing, because the user already pressed play once. 'no-advance' turns that off, and the playlist stays on the entry that ended. 'repeat' decides what happens at the end: 'one' plays the same entry again, and 'all' goes from the last entry back to the first. Without it, the playlist stops on the last entry and sends 'helix-end'. 'shuffle' plays the entries in a random order, starting from the one that is current, and 'previous' retraces that order. **'helix-before-activate' says why the playlist is moving**, in 'detail.cause': 'press' for an entry or a menu choice, 'next' and 'previous' for the player's controls and the methods, 'ended' at the end of a clip, and 'removed' when the current entry leaves the playlist. Cancel an 'ended' move to show your own "Up next" countdown, then call 'next()'. **Removing the current entry moves the playlist on**, to the entry after it, or to the one before it when it was the last. A clip that was playing keeps playing in the entry that takes its place. **The player is named by the current entry**, and the device's own media controls show the entry as the title. A player you gave a 'label' keeps your name, and only the title follows the entry. **Keyboard.** The entries take one stop in the tab order: the entry you last focused, or the current entry before you have focused one. Enter or Space plays it. The arrow keys move focus to the entry before or after, and Home and End to the first and the last, passing over disabled entries. The current entry carries 'aria-current'. While focus is on the player, the player's own keys work, and 'Video' lists them, and Shift with N or P plays the next or the previous entry. The player's previous and next controls move through the entries in the same order the playlist does. **Moving entries.** 'reorderable' lets a reader change the order of the queue: - Alt with Up or Down moves the focused entry a place, and Alt with Home or End moves it to either end, as the APG's rearrangeable listbox does. Focus stays on it. - A pointer drags an entry, with a drop indicator, and the page scrolls near an edge. A press that does not travel still plays the entry. - A drop sends 'helix-before-reorder', which you can refuse, and then 'helix-reorder', whose 'keys' hold every entry's 'value' in the new order. **You move the entries**: the playlist moves no element of yours, and the next entry is the one after the current entry in the order you leave. - Each move is said in the live region, in words you can change: 'moved-label', 'dropped-label', 'canceled-label', and 'picked-up-label'. **What a screen reader hears.** A list named by 'label', with a button for each entry. When the playlist moves to another entry, by a press, by the player's controls, or at the end of a clip, a live region says 'playing-label', "Now playing" and the entry's name. */
|
|
19883
|
+
/** **You slot the player**, so it keeps your appearance, extra controls, captions, and poster treatment. 'Sandbox' takes its preview and 'Menu' its trigger the same way. **The player is a 'Video' or a plain '<video>'.** Either takes 'src' and 'poster' from the entry, is named by it, plays on, and answers Shift with N or P while focused. A plain '<video>' has no previous and next controls that send 'helix-previous' or 'helix-next', so its moves are the entries, the menu, and your own buttons calling 'previous()' and 'next()'. **Entries are markup.** React skips properties it would set imperatively during hydration, so an array property on a custom element is missing on the first paint of a server-rendered page. 'using-the-elements.mdx' has the measurement. Markup also makes each entry a real button with its name inside. **The playlist does not play media.** It sets 'src' on the player and tracks which entry is current. The current entry moves when: - an entry is pressed, - the player dispatches 'helix-next' or 'helix-previous', or - the player reaches the end. On 'ended' the playlist advances and the next clip starts playing, because the user already pressed play once. 'no-advance' turns that off, and the playlist stays on the entry that ended. 'repeat' decides what happens at the end: 'one' plays the same entry again, and 'all' goes from the last entry back to the first. Without it, the playlist stops on the last entry and sends 'helix-end'. 'shuffle' plays the entries in a random order, starting from the one that is current, and 'previous' retraces that order. **'helix-before-activate' says why the playlist is moving**, in 'detail.cause': 'press' for an entry or a menu choice, 'next' and 'previous' for the player's controls and the methods, 'ended' at the end of a clip, and 'removed' when the current entry leaves the playlist. Cancel an 'ended' move to show your own "Up next" countdown, then call 'next()'. **Removing the current entry moves the playlist on**, to the entry after it, or to the one before it when it was the last. A clip that was playing keeps playing in the entry that takes its place. **The player is named by the current entry**, and the device's own media controls show the entry as the title. A player you gave a 'label' keeps your name, and only the title follows the entry. A plain '<video>' is named through 'aria-label', unless you wrote one. **Keyboard.** The entries take one stop in the tab order: the entry you last focused, or the current entry before you have focused one. Enter or Space plays it. The arrow keys move focus to the entry before or after, and Home and End to the first and the last, passing over disabled entries. The current entry carries 'aria-current'. While focus is on the player, the player's own keys work, and 'Video' lists them, and Shift with N or P plays the next or the previous entry. The player's previous and next controls move through the entries in the same order the playlist does. **Moving entries.** 'reorderable' lets a reader change the order of the queue: - Alt with Up or Down moves the focused entry a place, and Alt with Home or End moves it to either end, as the APG's rearrangeable listbox does. Focus stays on it. - A pointer drags an entry, with a drop indicator, and the page scrolls near an edge. A press that does not travel still plays the entry. - A drop sends 'helix-before-reorder', which you can refuse, and then 'helix-reorder', whose 'keys' hold every entry's 'value' in the new order. **You move the entries**: the playlist moves no element of yours, and the next entry is the one after the current entry in the order you leave. - Each move is said in the live region, in words you can change: 'moved-label', 'dropped-label', 'canceled-label', and 'picked-up-label'. **What a screen reader hears.** A list named by 'label', with a button for each entry. When the playlist moves to another entry, by a press, by the player's controls, or at the end of a clip, a live region says 'playing-label', "Now playing" and the entry's name. */
|
|
19750
19884
|
"helix-headless-video-playlist": DefineCustomElement<
|
|
19751
19885
|
HelixHeadlessVideoPlaylist,
|
|
19752
19886
|
HelixHeadlessVideoPlaylistVueProps,
|
|
@@ -19758,7 +19892,7 @@ export interface WcToolkitVueGlobalComponents {
|
|
|
19758
19892
|
HelixHeadlessVideoVueProps,
|
|
19759
19893
|
HelixHeadlessVideoVueEvents
|
|
19760
19894
|
>;
|
|
19761
|
-
/** The items arrive as data, in one of two ways: - 'items' takes an array. A framework sets it as a property, and React hydration keeps it. - 'for' names a '<script type="application/json">' that holds an array, which a server sends as markup. Each item is drawn into a row in one of two ways: - 'renderItem' is a function from an item and its index to the row's content: a Lit template, a string, or a DOM node. - A '<template>' child defines one row. 'data-field="name"' fills an element with the item's 'name' as text, and 'data-field-href="url"' writes the item's 'url' into 'href', the same for any attribute. A field may be a path of keys, such as 'author.name'. Rows are your markup in the light DOM, so your stylesheet styles them. **A grid.** 'columns' lays the items out that many to a line, as a grid of equal columns, and windows the set a line at a time, as React Aria's grid layout does. Each item draws one element, a cell of the grid, and 'estimate' is the height of a line. 'min-column-width' lays out as many columns as fit the box instead, as React Aria's grid layout does with its smallest item size, and follows the box as it resizes. 'gap' spaces the rows, and the columns of a grid, by a number of pixels the list counts in each row's place. **Across.** 'orientation="horizontal"' lays the items out along a line and scrolls it sideways, as a strip of cards does, windowed the same way: 'estimate' is then an item's width, and the box needs an inline size. **Sections.** 'section-field' names the field of each item that says which section it is in, and the list draws a header before each section's items, as React Aria's list box sections do. Each section is an element with the 'group' role, named by its header, which is its first child and carries 'data-header', so your stylesheet styles it, such as with 'position: sticky'. A section starts wherever the field changes, so give the items in order. The window counts the headers with the items, and a section the window starts inside is drawn with its header. 'renderSection' draws a header of your own. **Keyboard.** The list is one tab stop. | Key | What it does | |---|---| | Down, Up | Moves to the next or the previous item, or in a grid to the item in the same column on the next or the previous line. | | Right, Left | In a grid, moves to the next or the previous item along the line, the other way round on a right-to-left page. In a list that runs across, moves to the next or the previous item the same way, and Down and Up are left to the row. | | Home, End | Moves to the first or the last item. | | Page Down, Page Up | Moves by the number of items, or of lines in a grid, on screen. | | A letter or a word | Moves to the next item whose text starts with what you typed. | | Escape | Lets go of every chosen item, in a list with 'selection-mode'. | | Tab | Moves into the focused row's own links and buttons, then out of the list. | An item that is not drawn is scrolled into view and focused, so a keyboard reaches the whole set. When the row holding the tab stop scrolls away, the stop moves to the first row on screen. Typing matches each item's 'text-field', which is the first 'data-field' of the row template by default, or the item itself when it is a string or a number. Each row says its place in the whole set with 'aria-posinset' and 'aria-setsize', so a screen reader says "4,000 of 10,000". The row holding focus stays drawn when it scrolls out. **Selecting.** 'selection-mode' makes the list a list box a reader chooses from: 'single' selects one item and 'multiple' any number. Space or a press selects an item, Shift with Space, an arrow, Home, End or a press takes in the items from the last one chosen, and Control or Command with A selects them all, in 'multiple'. Escape lets go of every chosen item, and keeps the key from the dialog or menu around the list while there was something to let go of. 'value' holds the chosen items' keys, separated by commas, in the order of the set: 'key-field' names each item's key, and a string or a number item is its own key. A change asks with 'helix-before-change' and tells with 'change'. Each row is an 'option' marked 'aria-selected', so a row's own links and buttons are not reached there: keep those to a list without 'selection-mode'. 'selection-behavior="replace"' selects the item pressed alone, as a file list does, and the arrow keys carry the selection with them. Control or Command with a press or with Space adds or takes out one item, and with an arrow moves without selecting. **Disabled items.** 'disabled-keys' names items by their keys, separated by commas. Their rows carry 'aria-disabled', the keys and typing pass over them, and a press, Space, or Control with A does not select them. **Loading more.** 'helix-range-change' fires as the items on screen change, and 'range' holds them. 'helix-load-more' fires once a reader is within one screen of the end, once for each length of the set: add to 'items' and it can fire again. While you fetch, set 'loading': the list is busy, and a row after the last item says "Loading more" ('loading-label', or your own content in the 'loading' slot). 'scrollToIndex' takes a reader to an item. **An empty list.** Set 'empty-label', or put your own content in the 'empty' slot, for a row shown when there are no items and none are loading, such as "No messages yet" and a link to write one. Without either, an empty list shows nothing, since a list whose items have not arrived yet has not said it has none. The list takes the 'empty' state while it has read its items and holds none, and the 'loading' state while 'loading' is set, so your stylesheet can change the box around it for either. A list with no name is reported once in a development build. Name it with 'label' or 'aria-label'. **Row height.** Rows are placed by 'estimate' until they are drawn. Then the list reads the drawn rows' height once and places every row by it, so a wrong estimate still reaches the last item. Set 'measured' for rows of different heights. Once the list draws rows of different heights, such as rows that wrap on a narrow screen, it places each row by its own height whether 'measured' is set or not. The list follows its source. A new 'items' array, an edit to the script's text, or a script replaced under the same id draws the new rows. A row that stays in view keeps its element as the list scrolls. The viewport scrolls on this tier. It carries 'data-scroller', and 'core' ships '[data-scroller] { overflow: auto }' into every shadow root, so 'scrollTop' works with no stylesheet. You still need to set a block size. */
|
|
19895
|
+
/** The items arrive as data, in one of two ways: - 'items' takes an array. A framework sets it as a property, and React hydration keeps it. - 'for' names a '<script type="application/json">' that holds an array, which a server sends as markup. Each item is drawn into a row in one of two ways: - 'renderItem' is a function from an item and its index to the row's content: a Lit template, a string, or a DOM node. - A '<template>' child defines one row. 'data-field="name"' fills an element with the item's 'name' as text, and 'data-field-href="url"' writes the item's 'url' into 'href', the same for any attribute. A field may be a path of keys, such as 'author.name'. Rows are your markup in the light DOM, so your stylesheet styles them. **A grid.** 'columns' lays the items out that many to a line, as a grid of equal columns, and windows the set a line at a time, as React Aria's grid layout does. Each item draws one element, a cell of the grid, and 'estimate' is the height of a line. 'min-column-width' lays out as many columns as fit the box instead, as React Aria's grid layout does with its smallest item size, and follows the box as it resizes. 'gap' spaces the rows, and the columns of a grid, by a number of pixels the list counts in each row's place. **Across.** 'orientation="horizontal"' lays the items out along a line and scrolls it sideways, as a strip of cards does, windowed the same way: 'estimate' is then an item's width, and the box needs an inline size. **Sections.** 'section-field' names the field of each item that says which section it is in, and the list draws a header before each section's items, as React Aria's list box sections do. Each section is an element with the 'group' role, named by its header, which is its first child and carries 'data-header', so your stylesheet styles it, such as with 'position: sticky'. A section starts wherever the field changes, so give the items in order. The window counts the headers with the items, and a section the window starts inside is drawn with its header. 'renderSection' draws a header of your own. **Keyboard.** The list is one tab stop. | Key | What it does | |---|---| | Down, Up | Moves to the next or the previous item, or in a grid to the item in the same column on the next or the previous line. | | Right, Left | In a grid, moves to the next or the previous item along the line, the other way round on a right-to-left page. In a list that runs across, moves to the next or the previous item the same way, and Down and Up are left to the row. | | Home, End | Moves to the first or the last item. | | Page Down, Page Up | Moves by the number of items, or of lines in a grid, on screen. | | A letter or a word | Moves to the next item whose text starts with what you typed. | | Escape | Lets go of every chosen item, in a list with 'selection-mode'. | | Tab | Moves into the focused row's own links and buttons, then out of the list. | An item that is not drawn is scrolled into view and focused, so a keyboard reaches the whole set. When the row holding the tab stop scrolls away, the stop moves to the first row on screen. Typing matches each item's 'text-field', which is the first 'data-field' of the row template by default, or the item itself when it is a string or a number. Each row says its place in the whole set with 'aria-posinset' and 'aria-setsize', so a screen reader says "4,000 of 10,000". The row holding focus stays drawn when it scrolls out. **Selecting.** 'selection-mode' makes the list a list box a reader chooses from: 'single' selects one item and 'multiple' any number. Space or a press selects an item, Shift with Space, an arrow, Home, End or a press takes in the items from the last one chosen, and Control or Command with A selects them all, in 'multiple'. Escape lets go of every chosen item, and keeps the key from the dialog or menu around the list while there was something to let go of. 'value' holds the chosen items' keys, separated by commas, in the order of the set: 'key-field' names each item's key, and a string or a number item is its own key. A change asks with 'helix-before-change' and tells with 'change'. Each row is an 'option' marked 'aria-selected', so a row's own links and buttons are not reached there: keep those to a list without 'selection-mode'. 'selection-behavior="replace"' selects the item pressed alone, as a file list does, and the arrow keys carry the selection with them. Control or Command with a press or with Space adds or takes out one item, and with an arrow moves without selecting. **Disabled items.** 'disabled-keys' names items by their keys, separated by commas. Their rows carry 'aria-disabled', the keys and typing pass over them, and a press, Space, or Control with A does not select them. **Rows a stylesheet can tell apart.** A chosen row carries 'data-selected', a disabled one 'data-disabled', as React Aria's rows do, and the row the keys are on, which holds the tab stop, 'data-active', whether or not the list has focus. **Loading more.** 'helix-range-change' fires as the items on screen change, and 'range' holds them. 'helix-load-more' fires once a reader is within one screen of the end, once for each length of the set: add to 'items' and it can fire again. While you fetch, set 'loading': the list is busy, and a row after the last item says "Loading more" ('loading-label', or your own content in the 'loading' slot). 'scrollToIndex' takes a reader to an item. **An empty list.** Set 'empty-label', or put your own content in the 'empty' slot, for a row shown when there are no items and none are loading, such as "No messages yet" and a link to write one. Without either, an empty list shows nothing, since a list whose items have not arrived yet has not said it has none. The list takes the 'empty' state while it has read its items and holds none, and the 'loading' state while 'loading' is set, so your stylesheet can change the box around it for either. A list with no name is reported once in a development build. Name it with 'label' or 'aria-label'. **Row height.** Rows are placed by 'estimate' until they are drawn. Then the list reads the drawn rows' height once and places every row by it, so a wrong estimate still reaches the last item. Set 'measured' for rows of different heights. Once the list draws rows of different heights, such as rows that wrap on a narrow screen, it places each row by its own height whether 'measured' is set or not. The list follows its source. A new 'items' array, an edit to the script's text, or a script replaced under the same id draws the new rows. A row that stays in view keeps its element as the list scrolls. The viewport scrolls on this tier. It carries 'data-scroller', and 'core' ships '[data-scroller] { overflow: auto }' into every shadow root, so 'scrollTop' works with no stylesheet. You still need to set a block size. */
|
|
19762
19896
|
"helix-headless-virtual-list": DefineCustomElement<
|
|
19763
19897
|
HelixHeadlessVirtualList,
|
|
19764
19898
|
HelixHeadlessVirtualListVueProps,
|