@fusion.dev/helix-headless 0.175.0 → 0.176.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-headless",
3
3
  "description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
4
- "version": "0.175.0",
4
+ "version": "0.176.0",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -49,13 +49,13 @@
49
49
  },
50
50
  "bugs": "https://github.com/project-fusion/fusion/issues",
51
51
  "dependencies": {
52
- "@fusion.dev/helix-core": "0.175.0",
53
- "@fusion.dev/helix-icons": "0.175.0",
52
+ "@fusion.dev/helix-core": "0.176.0",
53
+ "@fusion.dev/helix-icons": "0.176.0",
54
54
  "uqr": "^0.1.3"
55
55
  },
56
56
  "devDependencies": {
57
- "@fusion.dev/helix-cem": "0.175.0",
58
- "@fusion.dev/helix-testing": "0.175.0",
57
+ "@fusion.dev/helix-cem": "0.176.0",
58
+ "@fusion.dev/helix-testing": "0.176.0",
59
59
  "@fusion.dev/scripts": "0.0.0-dev",
60
60
  "@happy-dom/global-registrator": "^20.14.5",
61
61
  "@lit-labs/ssr": "^4.1.0",
package/types/jsx.d.ts CHANGED
@@ -16290,12 +16290,10 @@ disagreeing with its own name for every reader who meant the left. */
16290
16290
  /** The name of the icon in the Helix set.
16291
16291
 
16292
16292
  **A lookup, and the reason both this and `icon` exist.** A name is a string,
16293
- so it is what markup can carry, and resolving one means an index of the
16294
- whole set that no bundler can shake: 15 kB for a consumer who renders one
16295
- mark. An attribute is the only thing an HTML author can write, and that is
16296
- worth the index; a consumer who would rather not pay it imports the
16297
- element from `icon/root` and registers the glyphs it names, or hands over
16298
- the value instead.
16293
+ so it is what markup can carry, and resolving one means an index that no
16294
+ bundler can shake. The family's entry indexes a small set, `icon/all`
16295
+ indexes the whole set at 15 kB, and `icon/root` indexes nothing, for a
16296
+ page that registers the glyphs it names or hands over the value instead.
16299
16297
 
16300
16298
  A name written `prefix:name` asks the library registered under that
16301
16299
  prefix. */
@@ -16339,12 +16337,10 @@ disagreeing with its own name for every reader who meant the left. */
16339
16337
  /** The name of the icon in the Helix set.
16340
16338
 
16341
16339
  **A lookup, and the reason both this and `icon` exist.** A name is a string,
16342
- so it is what markup can carry, and resolving one means an index of the
16343
- whole set that no bundler can shake: 15 kB for a consumer who renders one
16344
- mark. An attribute is the only thing an HTML author can write, and that is
16345
- worth the index; a consumer who would rather not pay it imports the
16346
- element from `icon/root` and registers the glyphs it names, or hands over
16347
- the value instead.
16340
+ so it is what markup can carry, and resolving one means an index that no
16341
+ bundler can shake. The family's entry indexes a small set, `icon/all`
16342
+ indexes the whole set at 15 kB, and `icon/root` indexes nothing, for a
16343
+ page that registers the glyphs it names or hands over the value instead.
16348
16344
 
16349
16345
  A name written `prefix:name` asks the library registered under that
16350
16346
  prefix. */
@@ -47191,6 +47187,10 @@ export type CustomElements = {
47191
47187
  * `Notification` does for a read. Call `preventDefault()` on `helix-facet` to
47192
47188
  * cancel the change.
47193
47189
  *
47190
+ * Imported from its own entry, `@fusion.dev/helix-headless/filter-input/menu`, which registers
47191
+ * it with the `Menu` it draws its pages with. The family's entry leaves it out,
47192
+ * so a field without a picker does not carry `Menu`.
47193
+ *
47194
47194
  * ## Attributes & Properties
47195
47195
  *
47196
47196
  * Component attributes and properties that can be applied to the element or by using JavaScript.
@@ -47445,7 +47445,7 @@ export type CustomElements = {
47445
47445
  * | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |
47446
47446
  * | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |
47447
47447
  * | Home, End | Highlights the first or the last suggestion while the panel is open. |
47448
- * | Escape | Closes the panel and stops there, so a dialog around the field stays open. |
47448
+ * | Escape | Closes the panel and stops there, so a dialog around the field stays open. With the panel closed, empties the text. In an empty field, does nothing, so the page hears it. |
47449
47449
  * | Backspace | In an empty field, asks the last token to go. |
47450
47450
  * | 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. |
47451
47451
  * | Left, Right on a token | Move between the tokens, and past the last back to the text. |
@@ -47454,7 +47454,8 @@ export type CustomElements = {
47454
47454
  * **Typed filters.** The field parses only the fields you declare. Write
47455
47455
  * `FilterField` elements, usually inside the `FilterMenu` slotted into `start`,
47456
47456
  * so the picker and the text share one set. On Enter, the field reads the text
47457
- * against them. `disposition:refunded,settled` and `-disposition:refunded` fire
47457
+ * against them, and a paste is read the same way as soon as it lands.
47458
+ * `disposition:refunded,settled` and `-disposition:refunded` fire
47458
47459
  * `helix-facet` exactly as ticking those values in the picker would, and the
47459
47460
  * parsed text is removed. Everything else stays, so `refund tuesday
47460
47461
  * disposition:settled` is a filter and a search at once. Helix defines the
@@ -47467,6 +47468,12 @@ export type CustomElements = {
47467
47468
  * nothing draws it and the menu has no page for it, and the grammar still reads
47468
47469
  * it.
47469
47470
  *
47471
+ * **The picker has an entry of its own.** `FilterMenu` draws its pages with
47472
+ * `Menu`, which a field without a picker does not need, so this family's entry
47473
+ * leaves it out. A page that writes one imports
47474
+ * `@fusion.dev/helix/filter-input/menu` as well, and a picker written without it
47475
+ * is reported once the page has loaded, with the entry to add.
47476
+ *
47470
47477
  * **Suggestions.** Slot options into `suggestions` and the field shows them,
47471
47478
  * moves through them with the arrow keys, and presses one on Enter. The option
47472
47479
  * fires its own `helix-select`, and you decide what choosing it means. Keys
@@ -48987,8 +48994,11 @@ export type CustomElements = {
48987
48994
  * a dark background. Shapes that set their own `fill` or `stroke` are
48988
48995
  * unaffected.
48989
48996
  *
48990
- * **A name is looked up in a registry.** The family's entry registers the
48991
- * whole set, so any name in it draws. The element's own entry,
48997
+ * **A name is looked up in a registry.** The family's entry registers a small
48998
+ * set: the four carets, `arrow-left`, `arrow-right`, `check`, `x`, `plus`,
48999
+ * `minus`, `magnifying-glass`, `info` and `warning`. `icon/all` registers the
49000
+ * whole set, so any name in it draws, and a name that resolves to nothing
49001
+ * says to import it. The element's own entry,
48992
49002
  * `@fusion.dev/helix-headless/icon/root`, registers none: a page that imports
48993
49003
  * it and calls `registerIcons` with the glyphs it names ships those and no
48994
49004
  * others. `registerIconLibrary` resolves names under a prefix of your own,
@@ -49033,12 +49043,10 @@ export type CustomElements = {
49033
49043
  * - `name`: The name of the icon in the Helix set.
49034
49044
  *
49035
49045
  * **A lookup, and the reason both this and `icon` exist.** A name is a string,
49036
- * so it is what markup can carry, and resolving one means an index of the
49037
- * whole set that no bundler can shake: 15 kB for a consumer who renders one
49038
- * mark. An attribute is the only thing an HTML author can write, and that is
49039
- * worth the index; a consumer who would rather not pay it imports the
49040
- * element from `icon/root` and registers the glyphs it names, or hands over
49041
- * the value instead.
49046
+ * so it is what markup can carry, and resolving one means an index that no
49047
+ * bundler can shake. The family's entry indexes a small set, `icon/all`
49048
+ * indexes the whole set at 15 kB, and `icon/root` indexes nothing, for a
49049
+ * page that registers the glyphs it names or hands over the value instead.
49042
49050
  *
49043
49051
  * A name written `prefix:name` asks the library registered under that
49044
49052
  * prefix.
@@ -76618,6 +76626,10 @@ export type CustomElementsSolidJs = {
76618
76626
  * `Notification` does for a read. Call `preventDefault()` on `helix-facet` to
76619
76627
  * cancel the change.
76620
76628
  *
76629
+ * Imported from its own entry, `@fusion.dev/helix-headless/filter-input/menu`, which registers
76630
+ * it with the `Menu` it draws its pages with. The family's entry leaves it out,
76631
+ * so a field without a picker does not carry `Menu`.
76632
+ *
76621
76633
  * ## Attributes & Properties
76622
76634
  *
76623
76635
  * Component attributes and properties that can be applied to the element or by using JavaScript.
@@ -76874,7 +76886,7 @@ export type CustomElementsSolidJs = {
76874
76886
  * | Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |
76875
76887
  * | Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |
76876
76888
  * | Home, End | Highlights the first or the last suggestion while the panel is open. |
76877
- * | Escape | Closes the panel and stops there, so a dialog around the field stays open. |
76889
+ * | Escape | Closes the panel and stops there, so a dialog around the field stays open. With the panel closed, empties the text. In an empty field, does nothing, so the page hears it. |
76878
76890
  * | Backspace | In an empty field, asks the last token to go. |
76879
76891
  * | 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. |
76880
76892
  * | Left, Right on a token | Move between the tokens, and past the last back to the text. |
@@ -76883,7 +76895,8 @@ export type CustomElementsSolidJs = {
76883
76895
  * **Typed filters.** The field parses only the fields you declare. Write
76884
76896
  * `FilterField` elements, usually inside the `FilterMenu` slotted into `start`,
76885
76897
  * so the picker and the text share one set. On Enter, the field reads the text
76886
- * against them. `disposition:refunded,settled` and `-disposition:refunded` fire
76898
+ * against them, and a paste is read the same way as soon as it lands.
76899
+ * `disposition:refunded,settled` and `-disposition:refunded` fire
76887
76900
  * `helix-facet` exactly as ticking those values in the picker would, and the
76888
76901
  * parsed text is removed. Everything else stays, so `refund tuesday
76889
76902
  * disposition:settled` is a filter and a search at once. Helix defines the
@@ -76896,6 +76909,12 @@ export type CustomElementsSolidJs = {
76896
76909
  * nothing draws it and the menu has no page for it, and the grammar still reads
76897
76910
  * it.
76898
76911
  *
76912
+ * **The picker has an entry of its own.** `FilterMenu` draws its pages with
76913
+ * `Menu`, which a field without a picker does not need, so this family's entry
76914
+ * leaves it out. A page that writes one imports
76915
+ * `@fusion.dev/helix/filter-input/menu` as well, and a picker written without it
76916
+ * is reported once the page has loaded, with the entry to add.
76917
+ *
76899
76918
  * **Suggestions.** Slot options into `suggestions` and the field shows them,
76900
76919
  * moves through them with the arrow keys, and presses one on Enter. The option
76901
76920
  * fires its own `helix-select`, and you decide what choosing it means. Keys
@@ -78425,8 +78444,11 @@ export type CustomElementsSolidJs = {
78425
78444
  * a dark background. Shapes that set their own `fill` or `stroke` are
78426
78445
  * unaffected.
78427
78446
  *
78428
- * **A name is looked up in a registry.** The family's entry registers the
78429
- * whole set, so any name in it draws. The element's own entry,
78447
+ * **A name is looked up in a registry.** The family's entry registers a small
78448
+ * set: the four carets, `arrow-left`, `arrow-right`, `check`, `x`, `plus`,
78449
+ * `minus`, `magnifying-glass`, `info` and `warning`. `icon/all` registers the
78450
+ * whole set, so any name in it draws, and a name that resolves to nothing
78451
+ * says to import it. The element's own entry,
78430
78452
  * `@fusion.dev/helix-headless/icon/root`, registers none: a page that imports
78431
78453
  * it and calls `registerIcons` with the glyphs it names ships those and no
78432
78454
  * others. `registerIconLibrary` resolves names under a prefix of your own,
@@ -78471,12 +78493,10 @@ export type CustomElementsSolidJs = {
78471
78493
  * - `name`: The name of the icon in the Helix set.
78472
78494
  *
78473
78495
  * **A lookup, and the reason both this and `icon` exist.** A name is a string,
78474
- * so it is what markup can carry, and resolving one means an index of the
78475
- * whole set that no bundler can shake: 15 kB for a consumer who renders one
78476
- * mark. An attribute is the only thing an HTML author can write, and that is
78477
- * worth the index; a consumer who would rather not pay it imports the
78478
- * element from `icon/root` and registers the glyphs it names, or hands over
78479
- * the value instead.
78496
+ * so it is what markup can carry, and resolving one means an index that no
78497
+ * bundler can shake. The family's entry indexes a small set, `icon/all`
78498
+ * indexes the whole set at 15 kB, and `icon/root` indexes nothing, for a
78499
+ * page that registers the glyphs it names or hands over the value instead.
78480
78500
  *
78481
78501
  * A name written `prefix:name` asks the library registered under that
78482
78502
  * prefix.
package/types/vue.d.ts CHANGED
@@ -8332,12 +8332,10 @@ disagreeing with its own name for every reader who meant the left. */
8332
8332
  /** The name of the icon in the Helix set.
8333
8333
 
8334
8334
  **A lookup, and the reason both this and `icon` exist.** A name is a string,
8335
- so it is what markup can carry, and resolving one means an index of the
8336
- whole set that no bundler can shake: 15 kB for a consumer who renders one
8337
- mark. An attribute is the only thing an HTML author can write, and that is
8338
- worth the index; a consumer who would rather not pay it imports the
8339
- element from `icon/root` and registers the glyphs it names, or hands over
8340
- the value instead.
8335
+ so it is what markup can carry, and resolving one means an index that no
8336
+ bundler can shake. The family's entry indexes a small set, `icon/all`
8337
+ indexes the whole set at 15 kB, and `icon/root` indexes nothing, for a
8338
+ page that registers the glyphs it names or hands over the value instead.
8341
8339
 
8342
8340
  A name written `prefix:name` asks the library registered under that
8343
8341
  prefix. */
@@ -19385,7 +19383,7 @@ export interface WcToolkitVueGlobalComponents {
19385
19383
  HelixHeadlessFilterFieldVueProps,
19386
19384
  HelixHeadlessFilterFieldVueEvents
19387
19385
  >;
19388
- /** Reads the 'FilterField' declarations inside it and renders a two-level menu: the fields, and under each field its operators and values. The menu does not interpret what a field means. '''html <helix-headless-filter-menu label="Filter"> <helix-headless-filter-field name="disposition" label="Disposition"> <helix-headless-option value="refunded">Refunded</helix-headless-option> </helix-headless-filter-field> </helix-headless-filter-menu> ''' That field declares no operators, so it offers 'is any of' and 'is none of', the two the typed grammar supports. The menu and the typed text offer the same filters because both read 'FilterField.vocabulary'. Declare other operators on the field when you need them. Ticking a value applies the filter immediately. There is no Apply button. Each tick fires 'helix-facet' with the field's whole set of values, so results narrow as the user works. Unticking the last value fires an empty set, which is your cue to remove the chip. The operator is chosen in the menu. 'helix-facet' carries an empty 'operatorLabel' when the operator is the field's default, which is the value a chip's 'operator-label' expects, so the operator segment appears only for a non-default choice. The menu decides this because it is the only element that reads both the field and its operators. An operator's 'arity' sets what appears under it: - 'arity="none"', such as 'is empty' or 'is set', offers no values and clears any that were ticked. The operator is the whole filter. - 'arity="one"' offers the values as a single choice. Pressing another value replaces the choice, and pressing the chosen value clears it. 'helix-facet' includes 'arity', so you can tell an empty filter from no filter. The menu applies nothing. The chips are your markup and the rows are your data, so the menu fires the event and leaves the change to you, as 'Notification' does for a read. Call 'preventDefault()' on 'helix-facet' to cancel the change. */
19386
+ /** Reads the 'FilterField' declarations inside it and renders a two-level menu: the fields, and under each field its operators and values. The menu does not interpret what a field means. '''html <helix-headless-filter-menu label="Filter"> <helix-headless-filter-field name="disposition" label="Disposition"> <helix-headless-option value="refunded">Refunded</helix-headless-option> </helix-headless-filter-field> </helix-headless-filter-menu> ''' That field declares no operators, so it offers 'is any of' and 'is none of', the two the typed grammar supports. The menu and the typed text offer the same filters because both read 'FilterField.vocabulary'. Declare other operators on the field when you need them. Ticking a value applies the filter immediately. There is no Apply button. Each tick fires 'helix-facet' with the field's whole set of values, so results narrow as the user works. Unticking the last value fires an empty set, which is your cue to remove the chip. The operator is chosen in the menu. 'helix-facet' carries an empty 'operatorLabel' when the operator is the field's default, which is the value a chip's 'operator-label' expects, so the operator segment appears only for a non-default choice. The menu decides this because it is the only element that reads both the field and its operators. An operator's 'arity' sets what appears under it: - 'arity="none"', such as 'is empty' or 'is set', offers no values and clears any that were ticked. The operator is the whole filter. - 'arity="one"' offers the values as a single choice. Pressing another value replaces the choice, and pressing the chosen value clears it. 'helix-facet' includes 'arity', so you can tell an empty filter from no filter. The menu applies nothing. The chips are your markup and the rows are your data, so the menu fires the event and leaves the change to you, as 'Notification' does for a read. Call 'preventDefault()' on 'helix-facet' to cancel the change. Imported from its own entry, '@fusion.dev/helix-headless/filter-input/menu', which registers it with the 'Menu' it draws its pages with. The family's entry leaves it out, so a field without a picker does not carry 'Menu'. */
19389
19387
  "helix-headless-filter-menu": DefineCustomElement<
19390
19388
  HelixHeadlessFilterMenu,
19391
19389
  HelixHeadlessFilterMenuVueProps,
@@ -19397,7 +19395,7 @@ export interface WcToolkitVueGlobalComponents {
19397
19395
  HelixHeadlessFilterOperatorVueProps,
19398
19396
  HelixHeadlessFilterOperatorVueEvents
19399
19397
  >;
19400
- /** 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. */
19398
+ /** 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. With the panel closed, empties the text. In an empty field, does nothing, so the page hears it. | | 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, and a paste is read the same way as soon as it lands. '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. **The picker has an entry of its own.** 'FilterMenu' draws its pages with 'Menu', which a field without a picker does not need, so this family's entry leaves it out. A page that writes one imports '@fusion.dev/helix/filter-input/menu' as well, and a picker written without it is reported once the page has loaded, with the entry to add. **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. */
19401
19399
  "helix-headless-filter-input": DefineCustomElement<
19402
19400
  HelixHeadlessFilterInput,
19403
19401
  HelixHeadlessFilterInputVueProps,
@@ -19427,7 +19425,7 @@ export interface WcToolkitVueGlobalComponents {
19427
19425
  HelixHeadlessIconButtonVueProps,
19428
19426
  HelixHeadlessIconButtonVueEvents
19429
19427
  >;
19430
- /** The icons are Phosphor, drawn on a 256 box at stroke-width 16. Each glyph renders its full inner markup, because most icons are several elements, each with its own stroke and fill. The markup is generated at build time from SVG files in this repository and never comes from user input, so rendering it with 'unsafeSVG' is safe. The '<svg>' carries 'fill="currentColor"'. The generator keeps only the inner markup, and Phosphor sets its fill on the root tag that the generator discards. Without it, the 65 solid glyphs fall back to black and disappear on a dark background. Shapes that set their own 'fill' or 'stroke' are unaffected. **A name is looked up in a registry.** The family's entry registers the whole set, so any name in it draws. The element's own entry, '@fusion.dev/helix-headless/icon/root', registers none: a page that imports it and calls 'registerIcons' with the glyphs it names ships those and no others. 'registerIconLibrary' resolves names under a prefix of your own, such as 'lucide:camera', at once or later, and the element fires 'load' when a glyph that came later is drawn. A glyph registered after the element rendered is drawn then. **Or point 'src' at an SVG file**, such as 'src="/icons/rocket.svg"', and the element fetches it and draws its shapes in 'currentColor' where the file does not color them. A file is fetched once a page, however many icons name it, and 'load' fires when it is drawn. Scripts, event handlers and 'javascript:' links in the file are taken out before it is drawn. A server fetches nothing, so a served icon with a 'src' is drawn once the script runs. A name with no match, or a 'src' that is no SVG, renders nothing, and the element fires 'error', so a typo in a name can be heard. It waits until the page has loaded and painted first, so a library a later module registers is not taken for a typo. An icon is decorative by default and hidden from assistive technology. Set 'label' only when the icon is the only carrier of meaning, such as in a button with no text. An 'aria-label' on the element works too: the element is then an image with that name. **A decorative icon that is all a control holds is reported.** In a development build, a button or a link whose only content is an icon with no 'label', and which has no name of its own, warns 'missing-name' once, through the runtime channel every Helix warning uses. */
19428
+ /** The icons are Phosphor, drawn on a 256 box at stroke-width 16. Each glyph renders its full inner markup, because most icons are several elements, each with its own stroke and fill. The markup is generated at build time from SVG files in this repository and never comes from user input, so rendering it with 'unsafeSVG' is safe. The '<svg>' carries 'fill="currentColor"'. The generator keeps only the inner markup, and Phosphor sets its fill on the root tag that the generator discards. Without it, the 65 solid glyphs fall back to black and disappear on a dark background. Shapes that set their own 'fill' or 'stroke' are unaffected. **A name is looked up in a registry.** The family's entry registers a small set: the four carets, 'arrow-left', 'arrow-right', 'check', 'x', 'plus', 'minus', 'magnifying-glass', 'info' and 'warning'. 'icon/all' registers the whole set, so any name in it draws, and a name that resolves to nothing says to import it. The element's own entry, '@fusion.dev/helix-headless/icon/root', registers none: a page that imports it and calls 'registerIcons' with the glyphs it names ships those and no others. 'registerIconLibrary' resolves names under a prefix of your own, such as 'lucide:camera', at once or later, and the element fires 'load' when a glyph that came later is drawn. A glyph registered after the element rendered is drawn then. **Or point 'src' at an SVG file**, such as 'src="/icons/rocket.svg"', and the element fetches it and draws its shapes in 'currentColor' where the file does not color them. A file is fetched once a page, however many icons name it, and 'load' fires when it is drawn. Scripts, event handlers and 'javascript:' links in the file are taken out before it is drawn. A server fetches nothing, so a served icon with a 'src' is drawn once the script runs. A name with no match, or a 'src' that is no SVG, renders nothing, and the element fires 'error', so a typo in a name can be heard. It waits until the page has loaded and painted first, so a library a later module registers is not taken for a typo. An icon is decorative by default and hidden from assistive technology. Set 'label' only when the icon is the only carrier of meaning, such as in a button with no text. An 'aria-label' on the element works too: the element is then an image with that name. **A decorative icon that is all a control holds is reported.** In a development build, a button or a link whose only content is an icon with no 'label', and which has no name of its own, warns 'missing-name' once, through the runtime channel every Helix warning uses. */
19431
19429
  "helix-headless-icon": DefineCustomElement<
19432
19430
  HelixHeadlessIcon,
19433
19431
  HelixHeadlessIconVueProps,