@fusion.dev/helix-headless 0.170.0 → 0.171.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.
Files changed (39) hide show
  1. package/custom-elements.json +610 -93
  2. package/dist/chat/composer/chat-composer.d.ts +2 -1
  3. package/dist/chat/composer/chat-composer.js +7 -1
  4. package/dist/chat/root/chat-root.d.ts +36 -6
  5. package/dist/chat/root/chat-root.js +53 -5
  6. package/dist/code-block/root/code-block-root.d.ts +20 -2
  7. package/dist/code-block/root/code-block-root.js +29 -8
  8. package/dist/color-picker/root/color-picker-root.d.ts +50 -7
  9. package/dist/color-picker/root/color-picker-root.js +62 -1
  10. package/dist/combobox/root/combobox-root.d.ts +16 -6
  11. package/dist/combobox/root/combobox-root.js +9 -2
  12. package/dist/command/root/command-root.d.ts +16 -1
  13. package/dist/command/root/command-root.js +8 -0
  14. package/dist/filter-input/chip/filter-chip.d.ts +13 -3
  15. package/dist/filter-input/chip/filter-chip.js +5 -0
  16. package/dist/filter-input/menu/filter-menu.js +0 -1
  17. package/dist/filter-input/root/filter-input-root.d.ts +71 -4
  18. package/dist/filter-input/root/filter-input-root.js +87 -2
  19. package/dist/format-date/root/format-date-root.d.ts +3 -1
  20. package/dist/input/root/input-root.d.ts +6 -0
  21. package/dist/input/root/input-root.js +13 -0
  22. package/dist/listbox/root/listbox-root.d.ts +6 -0
  23. package/dist/listbox/root/listbox-root.js +6 -1
  24. package/dist/number-input/root/number-input-root.d.ts +16 -6
  25. package/dist/number-input/root/number-input-root.js +15 -4
  26. package/dist/select/root/select-root.js +2 -0
  27. package/dist/steps/root/steps-root.d.ts +32 -8
  28. package/dist/steps/root/steps-root.js +70 -9
  29. package/dist/steps/step/step.d.ts +9 -1
  30. package/dist/steps/step/step.js +5 -0
  31. package/dist/video-playlist/root/video-playlist-root.d.ts +19 -1
  32. package/dist/video-playlist/root/video-playlist-root.js +14 -3
  33. package/dist/virtual-list/root/virtual-list-root.d.ts +8 -0
  34. package/dist/virtual-list/root/virtual-list-root.js +7 -2
  35. package/lint.json +1 -1
  36. package/package.json +5 -5
  37. package/types/jsx.d.ts +490 -116
  38. package/types/vue.d.ts +108 -25
  39. package/types/words.d.ts +12 -2
@@ -23184,7 +23184,7 @@
23184
23184
  "declarations": [
23185
23185
  {
23186
23186
  "kind": "class",
23187
- "description": "The composer is a separate element so you can replace it. If you need\nattachments, slash commands, or a model picker, replace the composer and keep\nthe transcript.\n\nBy default, Enter sends and Shift+Enter starts a new line, the convention in\nmessaging apps. Document editors mostly use the opposite, so `submit-on`\ntakes `enter` or `button`. Use `button` for a long-form composer.\n\nThe composer clears only when no listener cancels the send, so the text is\nkept when you cancel a send that failed.\n\n**In a form, the draft is the composer's value**, submitted under `name`. A\nform reset puts back the `value` the markup declared, and a `<fieldset\ndisabled>` turns the composer off. Sending is still `helix-send`, and it\ndoes not submit the form.\n\n**`required`, `minlength` and `maxlength` are checked by the browser**, as\non a `<textarea>`, and the message is the browser's. `maxlength` stops the\nfield taking more. A draft that fails them does not send, and the composer\ntakes `:state(invalid)` and `aria-invalid` once the reader has tried to send\nit, the form was submitted, or the reader edited the field and left it.\nTabbing past an empty composer marks nothing.\n\n**`typing` says whether the user is writing**, and `helix-typing` is sent\neach time it changes: when they start, and when they send or stop for\n`typing-timeout` milliseconds. Pass it on to show \"is typing\" to the other\nside.",
23187
+ "description": "The composer is a separate element so you can replace it. If you need\nattachments, slash commands, or a model picker, replace the composer and keep\nthe transcript.\n\nBy default, Enter sends and Shift+Enter starts a new line, the convention in\nmessaging apps. Document editors mostly use the opposite, so `submit-on`\ntakes `enter` or `button`. Use `button` for a long-form composer.\n\nThe composer clears only when no listener cancels the send, so the text is\nkept when you cancel a send that failed.\n\n**In a form, the draft is the composer's value**, submitted under `name`. A\nform reset puts back the `value` the markup declared, and a `<fieldset\ndisabled>` turns the composer off. Sending is still `helix-send`, and it\ndoes not submit the form.\n\n**`required`, `minlength` and `maxlength` are checked by the browser**, as\non a `<textarea>`, and the message is the browser's. `maxlength` stops the\nfield taking more. A draft that fails them does not send, and the composer\ntakes `:state(invalid)` and `aria-invalid` once the reader has tried to send\nit, the form was submitted, or the reader edited the field and left it.\nSending an empty required composer counts as trying. Tabbing past an empty\ncomposer marks nothing.\n\n**`typing` says whether the user is writing**, and `helix-typing` is sent\neach time it changes: when they start, and when they send or stop for\n`typing-timeout` milliseconds. Pass it on to show \"is typing\" to the other\nside.",
23188
23188
  "name": "HelixHeadlessChatComposer",
23189
23189
  "cssParts": [
23190
23190
  {
@@ -25471,7 +25471,7 @@
25471
25471
  "declarations": [
25472
25472
  {
25473
25473
  "kind": "class",
25474
- "description": "Chat has no positioning, no backdrop, and no trigger, so you can put it in\nany container, such as a page, a sidebar, a modal, or a floating panel.\n\nThe transcript stays pinned to the bottom, including while a streamed answer\ngrows, until the user scrolls more than `threshold` away from it.\n\nWith `history` set to `more`, reaching the top fires `helix-history`. Set\n`loading` while you fetch, then prepend the older turns. The turn the user\nwas reading stays in place on screen.\n\nThe log is `aria-live=\"off\"`. A separate status region announces each new\nturn once, when it has finished arriving. It skips the user's own turns\nunless they failed to send, turns loaded as history, and the turns already\nthere when the transcript opened. A turn is said with its author first, such\nas \"Ada: It ships today\" (`arrival-label`), where its author can be named.\n\nPass the turns as children or as `turns` data. Do not use both. Children\nrender from the server and suit most conversations. `turns` draws a long\ntranscript one window at a time, so the log needs a block size of its own.\n\n**A conversation is built from three elements.** The chat holds the\ntranscript, a `Chat.Message` stands for each turn, and a `Chat.Composer` sits\nin the `composer` slot. When the user sends, `helix-send` reaches the chat:\nadd their turn with `author=\"me\"` and `state=\"sending\"`, then set `state` to\n`sent` or `failed` when your server answers. Add the reply as a turn with\n`state=\"streaming\"`, write its text as it arrives, and set `state` to `sent`\nwhen it is complete. While the user types, the composer sends\n`helix-typing`, which you can pass on to the other side. When the other side\ntypes, set `typing` to their name: the status band draws three dots and\n\"Ada is typing\" (`typing-label`), which a screen reader hears, and clearing\nit takes them away. Anything slotted into `status` is drawn first.\n\n**Keyboard.** The transcript moves between turns the way a feed does. Each\nturn says its place, such as \"3 of 40\", windowed or not.\n\n| Key | What it does |\n|---|---|\n| 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. |\n| Control with End | Moves focus to the composer. |\n| Control with Home | Moves focus to the first control above the transcript, or to the transcript. |\n\nWhile you are scrolled away from the newest turn, the `resume` region shows\na button that takes you back, named by `resume-label`, \"Jump to latest\".\nSlot your own control into `resume` to replace it.\n\nA screen reader names each turn by its author and its time, such as \"You, 2\nminutes ago\". Set `me-label` and `message-label` to say it in your language,\nand give each turn by `them` an `author-label`. A turn with neither an author\nlabel nor a time is named by `turn-label`, \"Message\".\n\nA turn from `turns` is drawn in the chat's shadow root, so style it through\nthe forwarded `message-*` parts. A turn by `me` also gets each part with\n`-mine` added, and the turn's state adds `message-meta-failed`,\n`message-content-sending`, and `message-content-streaming`. To style each\nparticipant differently, give `author-styles` the declarations for each\nauthor, such as `{\"ada\": \"--chat-message-background-color: …\"}`: the message\ndrawn for each of their turns takes them as its `style`, so the message's\ncustom properties change for that author alone. Turns passed as children are\nstyled by their `author`, such as `helix-chat-message[author=\"ada\"]`.",
25474
+ "description": "Chat has no positioning, no backdrop, and no trigger, so you can put it in\nany container, such as a page, a sidebar, a modal, or a floating panel.\n\nThe transcript stays pinned to the bottom, including while a streamed answer\ngrows, until the user scrolls more than `threshold` away from it.\n\nWith `history` set to `more`, reaching the top fires `helix-history`. Set\n`loading` while you fetch, then prepend the older turns. The turn the user\nwas reading stays in place on screen.\n\nThe log is `aria-live=\"off\"`. A separate status region announces each new\nturn once, when it has finished arriving. It skips the user's own turns\nunless they failed to send, turns loaded as history, and the turns already\nthere when the transcript opened. A turn is said with its author first, such\nas \"Ada: It ships today\" (`arrival-label`), where its author can be named.\n\nPass the turns as children or as `turns` data. Do not use both: a chat given\nboth draws every turn from `turns` and then the children, and says so once\nin the console. Children render from the server and suit most\nconversations. `turns` draws a long\ntranscript one window at a time, so the log needs a block size of its own.\n\n**A conversation is built from three elements.** The chat holds the\ntranscript, a `Chat.Message` stands for each turn, and a `Chat.Composer` sits\nin the `composer` slot. When the user sends, `helix-send` reaches the chat:\nadd their turn with `author=\"me\"` and `state=\"sending\"`, then set `state` to\n`sent` or `failed` when your server answers. Add the reply as a turn with\n`state=\"streaming\"`, write its text as it arrives, and set `state` to `sent`\nwhen it is complete. While the user types, the composer sends\n`helix-typing`, which you can pass on to the other side. When the other side\ntypes, set `typing` to their name: the status band draws three dots and\n\"Ada is typing\" (`typing-label`), which a screen reader hears, and clearing\nit takes them away. Anything slotted into `status` is drawn first.\n\n**Keyboard.** The transcript moves between turns the way a feed does. Each\nturn says its place, such as \"3 of 40\", windowed or not. The transcript is\na tab stop while it holds a turn, and the turn a reader moved to is one\ntoo. Moving to an older turn unpins a transcript that scrolls and scrolls\nthe turn into view, and moving to the newest pins it again.\n\n| Key | What it does |\n|---|---|\n| 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. |\n| Control with End | Moves focus to the composer. |\n| Control with Home | Moves focus to the first control above the transcript, or to the transcript. |\n\nWhile you are scrolled away from the newest turn, the `resume` region shows\na button that takes you back, named by `resume-label`, \"Jump to latest\".\nSlot your own control into `resume` to replace it.\n\nA screen reader names each turn by its author and its time, such as \"You, 2\nminutes ago\". Set `me-label` and `message-label` to say it in your language,\nand give each turn by `them` an `author-label`. A turn with neither an author\nlabel nor a time is named by `turn-label`, \"Message\".\n\nA turn from `turns` is drawn in the chat's shadow root, so style it through\nthe forwarded `message-*` parts. A turn by `me` also gets each part with\n`-mine` added, and the turn's state adds `message-meta-failed`,\n`message-content-sending`, and `message-content-streaming`. To style each\nparticipant differently, give `author-styles` the declarations for each\nauthor, such as `{\"ada\": \"--chat-message-background-color: …\"}`: the message\ndrawn for each of their turns takes them as its `style`, so the message's\ncustom properties change for that author alone. Turns passed as children are\nstyled by their `author`, such as `helix-chat-message[author=\"ada\"]`.",
25475
25475
  "name": "HelixHeadlessChat",
25476
25476
  "cssParts": [
25477
25477
  {
@@ -26112,7 +26112,7 @@
26112
26112
  "text": "void"
26113
26113
  }
26114
26114
  },
26115
- "description": "Makes the log a tab stop while it scrolls, and takes the stop away when it\ndoes not.\n\n**A reader on a keyboard scrolls the history from the log itself.**\nChromium and Firefox make a box that scrolls focusable on their own, and\nSafari does not, so there the arrow keys could not reach a long history.\nA log that fits is no stop at all, so Tab goes straight to the composer."
26115
+ "description": "Makes the log a tab stop while it holds a turn or scrolls, and takes the\nstop away from an empty log.\n\n**A reader on a keyboard scrolls the history from the log itself.**\nChromium and Firefox make a box that scrolls focusable on their own, and\nSafari does not, so there the arrow keys could not reach a long history.\n\n**And it is where the turns are entered.** Page Down from the log goes to\nthe turn at the top of the view. A log that fits was no stop at all, so a\nconversation whose turns held no control had no way into them by keyboard."
26116
26116
  },
26117
26117
  {
26118
26118
  "kind": "field",
@@ -26366,6 +26366,27 @@
26366
26366
  "readonly": true,
26367
26367
  "description": "A press anywhere in the way back takes the reader back.\n\nThe control is slotted so the consumer picks the words, which on its own\nleaves a button this element positions, lifts, shows and hides doing nothing\nuntil somebody wires it. The region exists for exactly one purpose, so a\npress inside it has exactly one meaning and this element is entitled to act\non it. `resume()` stays public for the other callers: a keyboard shortcut,\nor a consumer's own control somewhere else on the page."
26368
26368
  },
26369
+ {
26370
+ "kind": "field",
26371
+ "name": "warnedMixed",
26372
+ "type": {
26373
+ "text": "boolean"
26374
+ },
26375
+ "privacy": "private",
26376
+ "default": "false",
26377
+ "description": "Whether the chat has said it was given turns both ways."
26378
+ },
26379
+ {
26380
+ "kind": "method",
26381
+ "name": "warnMixed",
26382
+ "privacy": "private",
26383
+ "return": {
26384
+ "type": {
26385
+ "text": "void"
26386
+ }
26387
+ },
26388
+ "description": "Says once that turns arrived both as children and as `turns`."
26389
+ },
26369
26390
  {
26370
26391
  "kind": "method",
26371
26392
  "name": "follow",
@@ -26445,6 +26466,25 @@
26445
26466
  ],
26446
26467
  "description": "Moves focus to turn `at`, drawing it first where the transcript is\nwindowed and it is not drawn.\n\n**A turn takes focus only once a reader moves to it**, so the `tabindex`\nit needs is written then, long after any server's markup has hydrated,\nand never on a turn nobody moved to."
26447
26468
  },
26469
+ {
26470
+ "kind": "method",
26471
+ "name": "showTurn",
26472
+ "privacy": "private",
26473
+ "return": {
26474
+ "type": {
26475
+ "text": "Promise<void>"
26476
+ }
26477
+ },
26478
+ "parameters": [
26479
+ {
26480
+ "name": "at",
26481
+ "type": {
26482
+ "text": "number"
26483
+ }
26484
+ }
26485
+ ],
26486
+ "description": "Draws turn `at` where it is windowed and not drawn, and visits it."
26487
+ },
26448
26488
  {
26449
26489
  "kind": "field",
26450
26490
  "name": "stop",
@@ -26473,6 +26513,34 @@
26473
26513
  ],
26474
26514
  "description": "Focuses a turn, making it the transcript's one stop a reader moved to.\n\n**`0`, and never `-1`.** Chromium leaves the whole of a shadow host at a\nnegative `tabindex` out of the Tab order, its own controls and what is\nslotted into it alike, so a turn at `-1` lost its links and its Try again\nonce a reader had paged through it. The stop moves with the reader, and a\n`tabindex` you wrote on a turn is left as it is."
26475
26515
  },
26516
+ {
26517
+ "kind": "field",
26518
+ "name": "placed",
26519
+ "type": {
26520
+ "text": "number | undefined"
26521
+ },
26522
+ "privacy": "private",
26523
+ "description": "Where this element last scrolled the transcript to show a turn, until the scroll that follows."
26524
+ },
26525
+ {
26526
+ "kind": "method",
26527
+ "name": "reveal",
26528
+ "privacy": "private",
26529
+ "return": {
26530
+ "type": {
26531
+ "text": "void"
26532
+ }
26533
+ },
26534
+ "parameters": [
26535
+ {
26536
+ "name": "turn",
26537
+ "type": {
26538
+ "text": "HTMLElement"
26539
+ }
26540
+ }
26541
+ ],
26542
+ "description": "Scrolls the transcript, and nothing around it, until `turn` is in view,\nand notes the turn at the top as the reader's place. A pinned transcript\nis left at the bottom, which is where whoever holds the pin wants it.\n\nThe edge nearest the turn moves the least, and a turn taller than the\ntranscript is shown from its start."
26543
+ },
26476
26544
  {
26477
26545
  "kind": "method",
26478
26546
  "name": "firstControlIn",
@@ -27315,6 +27383,32 @@
27315
27383
  }
27316
27384
  }
27317
27385
  ],
27386
+ "cssStates": [
27387
+ {
27388
+ "description": "The conversation has no turns.",
27389
+ "name": "empty"
27390
+ },
27391
+ {
27392
+ "description": "Older turns are loading: `history` is `loading`.",
27393
+ "name": "loading"
27394
+ },
27395
+ {
27396
+ "description": "The transcript follows its newest turn.",
27397
+ "name": "pinned"
27398
+ },
27399
+ {
27400
+ "description": "`typing` names someone on the other side.",
27401
+ "name": "typing"
27402
+ },
27403
+ {
27404
+ "description": "Set one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.",
27405
+ "name": "settled",
27406
+ "inheritedFrom": {
27407
+ "name": "HelixElement",
27408
+ "module": "src/helix-element/helix-element.ts"
27409
+ }
27410
+ }
27411
+ ],
27318
27412
  "mixins": [
27319
27413
  {
27320
27414
  "name": "MixinCollection",
@@ -27359,16 +27453,6 @@
27359
27453
  },
27360
27454
  "tagName": "helix-headless-chat",
27361
27455
  "customElement": true,
27362
- "cssStates": [
27363
- {
27364
- "description": "Set one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.",
27365
- "name": "settled",
27366
- "inheritedFrom": {
27367
- "name": "HelixElement",
27368
- "module": "src/helix-element/helix-element.ts"
27369
- }
27370
- }
27371
- ],
27372
27456
  "modulePath": "src/chat/root/chat-root.ts",
27373
27457
  "definitionPath": "src/chat/root/chat-root.ts"
27374
27458
  }
@@ -31404,7 +31488,7 @@
31404
31488
  "declarations": [
31405
31489
  {
31406
31490
  "kind": "class",
31407
- "description": "Renders a `<pre><code>` pair: `pre` keeps the whitespace, and `code` marks it\nas code. Long lines scroll inside the block and do not wrap, because a line\nbreak can be significant in code.\n\nA copy button is on by default. Set `no-copy` to remove it. The button copies\nthe slotted text, so there is no second copy of the code to keep in sync.\n\nFor a fragment of code inside a sentence, use `Code`.\n\nSet `line-numbers` to number the lines in a gutter beside the code, hidden\nfrom the accessibility tree and left out of a copy. Set `mark-lines` to\nmark lines a reader should look at, such as `2, 4-6`: the block draws a\nband behind each run, placed where the lines are laid out, so it follows a\nhighlighter's markup and lines that wrap. Set `wrap` to wrap long lines\nrather than scroll them; a gutter then numbers each line where it starts.\nSet `wrappable` for a button in the header that turns `wrap` on and off,\npressed while the lines wrap.\n\nThe header holds the name, the `actions` slot, and the copy button. Slot a\ncontrol into `actions`, such as a button that sets `wrap` or one that opens\nthe code in an editor, and the block draws a header for it even with no\nname. `copy-icon` and `copied-icon` replace the copy button's two icons. Set `highlight` to a\nfunction that turns the code into highlighted markup, such as one wrapping\nShiki or Prism, and the block draws what it returns; it is handed the\nblock's `language`, so one function serves every block. The code stays in\nthe slot, so the copy button and the page's own text are the code as\nwritten.\n\nSet `expandable` on a block whose height is capped, such as by\n`--code-block-max-block-size`, and a button under it shows every line and\nthen fewer again, as a docs site's long example does. The button is drawn\nonly while the cap hides something, says whether the block is expanded with\n`aria-expanded`, names the block it opens with `aria-controls`, and the block\ncarries `:state(expanded)` while it is.\n\nSet `diff` to show a change. Put a unified diff, the output of `git diff` or\n`diff -u`, in the same slot, and the block draws the lines it added and\nremoved. The block never computes a diff itself. Line numbers come from the\nhunk headers and are hidden from the accessibility tree. Changed lines are\n`<ins>` and `<del>` with the `+` and `-` kept as text, so the change does not\ndepend on color. Where a removed line is paired with the added line that\nreplaced it, the words each does not share with the other are the `changed`\npart, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name,\nand its copy button copies the new version of the file. `variant=\"split\"`\nshows the old version beside the new, each removal opposite its replacement.\n`context-lines` folds each long run of unchanged lines, keeping that many\nbeside each change, behind a button that shows them and hides them again,\nas a code host draws a diff written with more context than a reader needs.\n\n**A block that scrolls is a tab stop.** While its lines run past its width or\nits cap, the scroller is a region named for the block, such as \"Code,\napp.ts\", that Tab reaches, so a keyboard scrolls it with the arrow keys in\nevery browser. Chromium and Firefox make a scrolling box focusable on their\nown, and Safari does not. A block that fits is no stop at all.\n\n**The code the block draws is marked untranslated**, `translate=\"no\"` on\nits `<pre>`, so a page translator leaves highlighted lines and a diff as\nwritten. Code in the slot takes its translation mode from the element, which\nwrites nothing onto itself, so set `translate=\"no\"` on the element to keep a\ntranslator off plain code too.\n\nOn the server, the slot renders as ordinary code, so a diff first appears as\nthe patch text in a `<pre>`. The client makes the same first render, which\nkeeps hydration clean, and draws the diff once it can read the content. Diff\nmode is experimental. The rest of the family is stable.\n\n**Several blocks are files**, one shown at a time under a row of tabs, as\nSandbox shows its source panes. Put Code Blocks in the default slot of a\nCode Block, and each is a file named on its tab by its `label` or, without\none, its `language`. `file` holds the name of the file shown. The tabs are a\ntab list: the arrow keys move to a tab and show its file, the two swapping\non a right-to-left page, and Home and End go to the first and the last.\nChoosing one sends `helix-before-change` with the file's name, which you can\ncancel, and `change` once `file` holds it. The files not shown carry\n`hidden`, and the one shown draws no name of its own, its tab naming it. One\nblock draws no tabs. A server cannot see the blocks inside, so the client\ndraws the tabs once it upgrades.",
31491
+ "description": "Renders a `<pre><code>` pair: `pre` keeps the whitespace, and `code` marks it\nas code. Long lines scroll inside the block and do not wrap, because a line\nbreak can be significant in code.\n\nA copy button is on by default. Set `no-copy` to remove it. The button copies\nthe slotted text, so there is no second copy of the code to keep in sync.\n\nFor a fragment of code inside a sentence, use `Code`.\n\nSet `line-numbers` to number the lines in a gutter beside the code, hidden\nfrom the accessibility tree and left out of a copy. Set `mark-lines` to\nmark lines a reader should look at, such as `2, 4-6`: the block draws a\nband behind each run, placed where the lines are laid out, so it follows a\nhighlighter's markup and lines that wrap. `added-lines` and\n`removed-lines` mark lines the same way as inserted and deleted, as\nExpressive Code's `ins` and `del` do, in code that is not a diff. The bands\nare drawn and hidden from screen readers, so say in the text around the\nblock what a marked line means. Set `wrap` to wrap long lines\nrather than scroll them; a gutter then numbers each line where it starts.\nSet `wrappable` for a button in the header that turns `wrap` on and off,\npressed while the lines wrap.\n\nThe header holds the name, the `actions` slot, and the copy button. Slot a\ncontrol into `actions`, such as a button that sets `wrap` or one that opens\nthe code in an editor, and the block draws a header for it even with no\nname. `copy-icon` and `copied-icon` replace the copy button's two icons. Set `highlight` to a\nfunction that turns the code into highlighted markup, such as one wrapping\nShiki or Prism, and the block draws what it returns; it is handed the\nblock's `language`, so one function serves every block. The code stays in\nthe slot, so the copy button and the page's own text are the code as\nwritten.\n\nSet `expandable` on a block whose height is capped, such as by\n`--code-block-max-block-size`, and a button under it shows every line and\nthen fewer again, as a docs site's long example does. The button is drawn\nonly while the cap hides something, says whether the block is expanded with\n`aria-expanded`, names the block it opens with `aria-controls`, and the block\ncarries `:state(expanded)` while it is.\n\nSet `diff` to show a change. Put a unified diff, the output of `git diff` or\n`diff -u`, in the same slot, and the block draws the lines it added and\nremoved. The block never computes a diff itself. Line numbers come from the\nhunk headers and are hidden from the accessibility tree. Changed lines are\n`<ins>` and `<del>` with the `+` and `-` kept as text, so the change does not\ndepend on color. Where a removed line is paired with the added line that\nreplaced it, the words each does not share with the other are the `changed`\npart, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name,\nand its copy button copies the new version of the file. `variant=\"split\"`\nshows the old version beside the new, each removal opposite its replacement.\n`context-lines` folds each long run of unchanged lines, keeping that many\nbeside each change, behind a button that shows them and hides them again,\nas a code host draws a diff written with more context than a reader needs.\n\n**A block that scrolls is a tab stop.** While its lines run past its width or\nits cap, the scroller is a region named for the block, such as \"Code,\napp.ts\", that Tab reaches, so a keyboard scrolls it with the arrow keys in\nevery browser. Chromium and Firefox make a scrolling box focusable on their\nown, and Safari does not. A block that fits is no stop at all.\n\n**The code the block draws is marked untranslated**, `translate=\"no\"` on\nits `<pre>`, so a page translator leaves highlighted lines and a diff as\nwritten. Code in the slot takes its translation mode from the element, which\nwrites nothing onto itself, so set `translate=\"no\"` on the element to keep a\ntranslator off plain code too.\n\nOn the server, the slot renders as ordinary code, so a diff first appears as\nthe patch text in a `<pre>`. The client makes the same first render, which\nkeeps hydration clean, and draws the diff once it can read the content. Diff\nmode is experimental. The rest of the family is stable.\n\n**Several blocks are files**, one shown at a time under a row of tabs, as\nSandbox shows its source panes. Put Code Blocks in the default slot of a\nCode Block, and each is a file named on its tab by its `label` or, without\none, its `language`. `file` holds the name of the file shown. The tabs are a\ntab list: the arrow keys move to a tab and show its file, the two swapping\non a right-to-left page, and Home and End go to the first and the last.\nChoosing one sends `helix-before-change` with the file's name, which you can\ncancel, and `change` once `file` holds it. The files not shown carry\n`hidden`, and the one shown draws no name of its own, its tab naming it. One\nblock draws no tabs. A server cannot see the blocks inside, so the client\ndraws the tabs once it upgrades.",
31408
31492
  "name": "HelixHeadlessCodeBlock",
31409
31493
  "cssProperties": [
31410
31494
  {
@@ -31558,9 +31642,17 @@
31558
31642
  "name": "label"
31559
31643
  },
31560
31644
  {
31561
- "description": "The band behind a run of lines `mark-lines` names. The block writes where the run is laid out into `--code-block-mark-start`, `--code-block-mark-size`, and `--code-block-mark-inline-size` on it. Hidden from the accessibility tree.",
31645
+ "description": "The band behind a run of lines `mark-lines`, `added-lines` or `removed-lines` names. The block writes where the run is laid out into `--code-block-mark-start`, `--code-block-mark-size`, and `--code-block-mark-inline-size` on it. Hidden from the accessibility tree.",
31562
31646
  "name": "mark"
31563
31647
  },
31648
+ {
31649
+ "description": "The band behind a run of lines `added-lines` names. Applied with `mark`.",
31650
+ "name": "mark-added"
31651
+ },
31652
+ {
31653
+ "description": "The band behind a run of lines `removed-lines` names. Applied with `mark`.",
31654
+ "name": "mark-removed"
31655
+ },
31564
31656
  {
31565
31657
  "description": "In a diff, the `+`, `-`, or space that starts a line.",
31566
31658
  "name": "marker"
@@ -31610,6 +31702,14 @@
31610
31702
  {
31611
31703
  "description": "The copy button's icon before a copy. Defaults to a clipboard.",
31612
31704
  "name": "copy-icon"
31705
+ },
31706
+ {
31707
+ "description": "An icon on the button that shows every line of a capped block, before its words.",
31708
+ "name": "expand-icon"
31709
+ },
31710
+ {
31711
+ "description": "The block's name in the header, such as a file icon beside the file name. Replaces `label` and `language` there, and draws the header.",
31712
+ "name": "label"
31613
31713
  }
31614
31714
  ],
31615
31715
  "members": [
@@ -31623,6 +31723,16 @@
31623
31723
  "default": "'helix-code-block'",
31624
31724
  "description": "The key this family's words are registered under, its styled tag:\n`registerWords('de', { 'helix-code-block': { copyLabel: 'Code kopieren' } })`."
31625
31725
  },
31726
+ {
31727
+ "kind": "field",
31728
+ "name": "addedLines",
31729
+ "type": {
31730
+ "text": "string"
31731
+ },
31732
+ "default": "''",
31733
+ "description": "The lines to mark as inserted, as numbers and ranges counted from 1, such\nas `3-4`. Drawn as `mark-lines` is, in the added color. Not for a diff.",
31734
+ "attribute": "added-lines"
31735
+ },
31626
31736
  {
31627
31737
  "kind": "field",
31628
31738
  "name": "codeLabel",
@@ -31839,6 +31949,16 @@
31839
31949
  "attribute": "no-copy",
31840
31950
  "reflects": true
31841
31951
  },
31952
+ {
31953
+ "kind": "field",
31954
+ "name": "removedLines",
31955
+ "type": {
31956
+ "text": "string"
31957
+ },
31958
+ "default": "''",
31959
+ "description": "The lines to mark as deleted, as numbers and ranges counted from 1. Drawn\nas `mark-lines` is, in the removed color. Not for a diff.",
31960
+ "attribute": "removed-lines"
31961
+ },
31842
31962
  {
31843
31963
  "kind": "field",
31844
31964
  "name": "showUnchangedLabel",
@@ -32254,6 +32374,10 @@
32254
32374
  {
32255
32375
  "name": "drawn",
32256
32376
  "default": "name"
32377
+ },
32378
+ {
32379
+ "name": "own",
32380
+ "default": "false"
32257
32381
  }
32258
32382
  ],
32259
32383
  "description": "The name with the copy button beside it, or nothing when there is no name.\n\n**The button is in the header wherever there is one**, because beside the\ncode it stands over the block and the block has to make room for it. A\ndiff cannot: its washes run to the edge, so the button stood on the hunk\nline and the line under it. In the header it is over nothing.\n\n**No name draws no header**, unless the page put a control in `actions`\nor asked for the wrap button. A bar holding the copy button alone turned a\n`Usage` section of one-line imports into a run of empty strips. The button\nthen stands beside the code, in room the block keeps for it."
@@ -32870,6 +32994,15 @@
32870
32994
  }
32871
32995
  ],
32872
32996
  "attributes": [
32997
+ {
32998
+ "name": "added-lines",
32999
+ "type": {
33000
+ "text": "string"
33001
+ },
33002
+ "default": "''",
33003
+ "description": "The lines to mark as inserted, as numbers and ranges counted from 1, such\nas `3-4`. Drawn as `mark-lines` is, in the added color. Not for a diff.",
33004
+ "fieldName": "addedLines"
33005
+ },
32873
33006
  {
32874
33007
  "name": "code-label",
32875
33008
  "type": {
@@ -33030,6 +33163,15 @@
33030
33163
  "description": "Whether to leave the copy button off.\n\nNegative, which is not a style choice. A boolean attribute is true whenever\nit is *present*, so a `copyable` defaulting to true could never be turned\noff from markup: `copyable=\"false\"` is the string \"false\", which is\npresent, which is true. Measured, and it is why this is named the other way\nround. The platform already writes booleans like this for the same reason,\n`novalidate` and `nomodule` and `noreferrer` among them.\n\n**Reflected, because the gutter is a stylesheet rule.** A sheet reserves\nthe copy button's width with `:host(:not([no-copy]))`, so the attribute is\nwhat decides whether the block pays for a control. Unreflected, setting it\nfrom script takes the button away (`render` reads the property) and leaves\nthe 40px it stood in reserved.\n\nA false boolean reflects as the attribute's absence, so this costs no\n`no-copy=\"\"` on hosts that never asked for one, and the rule about a\nreflected property taking no default is satisfied by the default being\n`false`.",
33031
33164
  "fieldName": "noCopy"
33032
33165
  },
33166
+ {
33167
+ "name": "removed-lines",
33168
+ "type": {
33169
+ "text": "string"
33170
+ },
33171
+ "default": "''",
33172
+ "description": "The lines to mark as deleted, as numbers and ranges counted from 1. Drawn\nas `mark-lines` is, in the removed color. Not for a diff.",
33173
+ "fieldName": "removedLines"
33174
+ },
33033
33175
  {
33034
33176
  "name": "show-unchanged-label",
33035
33177
  "type": {
@@ -36524,7 +36666,7 @@
36524
36666
  "name": "eyedropper-text"
36525
36667
  },
36526
36668
  {
36527
- "description": "The message under the picker, while `feedback` is set.",
36669
+ "description": "The message under the picker: `feedback`, or what is wrong with the answer once the picker is marked invalid.",
36528
36670
  "name": "feedback"
36529
36671
  },
36530
36672
  {
@@ -36938,7 +37080,7 @@
36938
37080
  "text": "boolean"
36939
37081
  },
36940
37082
  "default": "false",
36941
- "description": "Requires a color before the form can submit.\n\n**A color is exactly as requirable as a date**, which is the comparison\nthat settles it: this element extends `HelixFormElement`, carries `name`\nand reports its value, so a consumer writing `<helix-headless-color-picker\nname=\"brand\" required>` inside a form has every reason to expect the form\nto refuse an empty one. Its two siblings in the same composition position,\nDate Picker and Time Picker, both check it.\n\nWritten out rather than taken from `MixinField`, for the reason those two\nrecord: the mixin brings a label, a hint and a feedback region, and this is\na panel composed *into* a field that already has all three, so taking it\nwould give one control two of each. What is left is the validity call and\nthe anchor the browser points its bubble at.\n\n**Text that is not a color is bad input**, so a form does not submit\n`#00` from a half-typed value. The picker draws no message of its own, so\nreporting it as each keystroke arrives shows nothing until the form asks;\nColor Input shows its own message against the field the reader typed\ninto.",
37083
+ "description": "Requires a color before the form can submit.\n\n**A color is exactly as requirable as a date**, which is the comparison\nthat settles it: this element extends `HelixFormElement`, carries `name`\nand reports its value, so a consumer writing `<helix-headless-color-picker\nname=\"brand\" required>` inside a form has every reason to expect the form\nto refuse an empty one. Its two siblings in the same composition position,\nDate Picker and Time Picker, both check it.\n\nWritten out rather than taken from `MixinField`, for the reason those two\nrecord: the mixin brings a label, a hint and a feedback region, and this is\na panel composed *into* a field that already has all three, so taking it\nwould give one control two of each. What is left is the validity call and\nthe anchor the browser points its bubble at.\n\n**Text that is not a color is bad input**, so a form does not submit\n`#00` from a half-typed value. The picker marks it, and says\n`badInputMessage` under itself, once the reader leaves the value field or\npresses Enter, and a missing color once the reader has committed one or a\nform has refused the picker. Color Input shows its own message against the\nfield the reader typed into.",
36942
37084
  "attribute": "required",
36943
37085
  "reflects": true
36944
37086
  },
@@ -37111,6 +37253,82 @@
37111
37253
  "description": "The ids a control in the picker is described by: the help, then the message.",
37112
37254
  "readonly": true
37113
37255
  },
37256
+ {
37257
+ "kind": "field",
37258
+ "name": "typing",
37259
+ "type": {
37260
+ "text": "boolean"
37261
+ },
37262
+ "privacy": "private",
37263
+ "default": "false",
37264
+ "description": "Whether the reader is typing into the value field, between the first\nkeystroke and the `change` that ends it.\n\nHalf-typed text is rarely a color: `#00ff00` passes through `#0` and\n`#00ff0` on the way. So text that is not a color is refused once the\nreader leaves the field or presses Enter, and not on every keystroke."
37265
+ },
37266
+ {
37267
+ "kind": "field",
37268
+ "name": "draft",
37269
+ "type": {
37270
+ "text": "string | undefined"
37271
+ },
37272
+ "privacy": "private",
37273
+ "default": "undefined",
37274
+ "description": "Text in the value field that is not a color, or undefined while the field\nholds the value.\n\n**Kept in the field and out of the value**, as a native number field keeps\n\"12e\": the text stays where the reader can correct it, the value stays the\nlast color, and the picker reports `badInput` until the text is a color or\nthe value moves. Measured before this: typed \"nonsense\" became the value,\nso a form read `brand=nonsense` and the square had no color to show."
37275
+ },
37276
+ {
37277
+ "kind": "field",
37278
+ "name": "failure",
37279
+ "type": {
37280
+ "text": "'missing' | 'refused' | undefined"
37281
+ },
37282
+ "privacy": "protected",
37283
+ "description": "A required picker with no color is missing, and text that is not a color\nis refused, once the reader has finished typing it. See\n`MixinPickerFeedback.marked`.\n\nMeasured before this: typed \"nonsense\" and a required picker its form\nrefused both failed `checkValidity()` while `:state(invalid)` stayed off,\nthe value field had no `aria-invalid`, and nothing was said.",
37284
+ "readonly": true,
37285
+ "inheritedFrom": {
37286
+ "name": "MixinPickerFeedback",
37287
+ "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
37288
+ }
37289
+ },
37290
+ {
37291
+ "kind": "field",
37292
+ "name": "said",
37293
+ "type": {
37294
+ "text": "string"
37295
+ },
37296
+ "privacy": "private",
37297
+ "description": "The line under the picker: `feedback`, or, where the picker is marked by\nits own validation, what is wrong.",
37298
+ "readonly": true
37299
+ },
37300
+ {
37301
+ "kind": "method",
37302
+ "name": "formResetCallback",
37303
+ "return": {
37304
+ "type": {
37305
+ "text": "void"
37306
+ }
37307
+ },
37308
+ "description": "A reset ends any typing and takes back text that was not a color, so the\nfield shows the color the reset put back.",
37309
+ "inheritedFrom": {
37310
+ "name": "HelixFormElement",
37311
+ "module": "src/helix-form-element/helix-form-element.ts"
37312
+ },
37313
+ "type": {
37314
+ "text": "formResetCallback() => void"
37315
+ }
37316
+ },
37317
+ {
37318
+ "kind": "method",
37319
+ "name": "renderPickerFeedback",
37320
+ "privacy": "protected",
37321
+ "return": {
37322
+ "type": {
37323
+ "text": "TemplateResult | typeof nothing"
37324
+ }
37325
+ },
37326
+ "description": "The line `said` holds, or nothing while it is empty.",
37327
+ "inheritedFrom": {
37328
+ "name": "MixinPickerFeedback",
37329
+ "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
37330
+ }
37331
+ },
37114
37332
  {
37115
37333
  "kind": "field",
37116
37334
  "name": "dragging",
@@ -37635,52 +37853,6 @@
37635
37853
  "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
37636
37854
  }
37637
37855
  },
37638
- {
37639
- "kind": "field",
37640
- "name": "failure",
37641
- "type": {
37642
- "text": "'missing' | 'refused' | undefined"
37643
- },
37644
- "privacy": "protected",
37645
- "description": "What the picker's own validation finds: `missing`, `refused`, or\nnothing, which is what a picker that does not answer it reports.",
37646
- "readonly": true,
37647
- "inheritedFrom": {
37648
- "name": "MixinPickerFeedback",
37649
- "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
37650
- }
37651
- },
37652
- {
37653
- "kind": "method",
37654
- "name": "formResetCallback",
37655
- "return": {
37656
- "type": {
37657
- "text": "void"
37658
- }
37659
- },
37660
- "description": "Returns the control to its `defaultValue`, or to its `value` attribute\nwhere there is no `default-value`.\n\nBoth halves are dropped, the consumer's and the control's, because a\nreset means the form is as it was served. Clearing only the internal one\nwould leave a control that had been written to stuck at that value.",
37661
- "inheritedFrom": {
37662
- "name": "HelixFormElement",
37663
- "module": "src/helix-form-element/helix-form-element.ts"
37664
- },
37665
- "type": {
37666
- "text": "formResetCallback() => void"
37667
- }
37668
- },
37669
- {
37670
- "kind": "method",
37671
- "name": "renderPickerFeedback",
37672
- "privacy": "protected",
37673
- "return": {
37674
- "type": {
37675
- "text": "TemplateResult | typeof nothing"
37676
- }
37677
- },
37678
- "description": "The `feedback` line, or nothing while there is none.",
37679
- "inheritedFrom": {
37680
- "name": "MixinPickerFeedback",
37681
- "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
37682
- }
37683
- },
37684
37856
  {
37685
37857
  "kind": "field",
37686
37858
  "name": "defaultValue",
@@ -38861,7 +39033,7 @@
38861
39033
  "text": "boolean"
38862
39034
  },
38863
39035
  "default": "false",
38864
- "description": "Requires a color before the form can submit.\n\n**A color is exactly as requirable as a date**, which is the comparison\nthat settles it: this element extends `HelixFormElement`, carries `name`\nand reports its value, so a consumer writing `<helix-headless-color-picker\nname=\"brand\" required>` inside a form has every reason to expect the form\nto refuse an empty one. Its two siblings in the same composition position,\nDate Picker and Time Picker, both check it.\n\nWritten out rather than taken from `MixinField`, for the reason those two\nrecord: the mixin brings a label, a hint and a feedback region, and this is\na panel composed *into* a field that already has all three, so taking it\nwould give one control two of each. What is left is the validity call and\nthe anchor the browser points its bubble at.\n\n**Text that is not a color is bad input**, so a form does not submit\n`#00` from a half-typed value. The picker draws no message of its own, so\nreporting it as each keystroke arrives shows nothing until the form asks;\nColor Input shows its own message against the field the reader typed\ninto.",
39036
+ "description": "Requires a color before the form can submit.\n\n**A color is exactly as requirable as a date**, which is the comparison\nthat settles it: this element extends `HelixFormElement`, carries `name`\nand reports its value, so a consumer writing `<helix-headless-color-picker\nname=\"brand\" required>` inside a form has every reason to expect the form\nto refuse an empty one. Its two siblings in the same composition position,\nDate Picker and Time Picker, both check it.\n\nWritten out rather than taken from `MixinField`, for the reason those two\nrecord: the mixin brings a label, a hint and a feedback region, and this is\na panel composed *into* a field that already has all three, so taking it\nwould give one control two of each. What is left is the validity call and\nthe anchor the browser points its bubble at.\n\n**Text that is not a color is bad input**, so a form does not submit\n`#00` from a half-typed value. The picker marks it, and says\n`badInputMessage` under itself, once the reader leaves the value field or\npresses Enter, and a missing color once the reader has committed one or a\nform has refused the picker. Color Input shows its own message against the\nfield the reader typed into.",
38865
39037
  "fieldName": "required"
38866
39038
  },
38867
39039
  {
@@ -39566,7 +39738,7 @@
39566
39738
  "text": "boolean"
39567
39739
  },
39568
39740
  "default": "false",
39569
- "description": "Whether more than one option can be chosen.\n\nThe list already does the work: `value` comes apart on commas, a press\ntoggles rather than replaces, and the arrows move without choosing. What\nthis adds is the tags, and keeping the panel open between picks.\n\nA comma is therefore not available inside an option's value, which is the\nlistbox's contract and not this element's to change.\n\n**The list is told, and the field is not.** `aria-multiselectable` belongs\nto `listbox`, `grid`, `tree` and `tablist`, and `combobox` dropped it in\nARIA 1.2; the list sets it on itself through `ElementInternals`, where a\nreader on the field hears it through `aria-controls`. This element wrote it\nonto its own `role=\"combobox\"` input as well, which an audit reports as a\nproperty the role does not support and no spec here ever asserted: the one\nthat covers this says in as many words that telling the list is what this\nelement is responsible for.",
39741
+ "description": "Whether more than one option can be chosen.\n\nThe list already does the work: `value` is the chosen values joined with\ncommas, a press toggles rather than replaces, and the arrows move without\nchoosing. What this adds is the tags, and keeping the panel open between\npicks.\n\nAn option's value may hold a comma, and it is read as one value, as\n`Select` and `Listbox` read it. So may an answer the reader created.\n\n**The list is told, and the field is not.** `aria-multiselectable` belongs\nto `listbox`, `grid`, `tree` and `tablist`, and `combobox` dropped it in\nARIA 1.2; the list sets it on itself through `ElementInternals`, where a\nreader on the field hears it through `aria-controls`. This element wrote it\nonto its own `role=\"combobox\"` input as well, which an audit reports as a\nproperty the role does not support and no spec here ever asserted: the one\nthat covers this says in as many words that telling the list is what this\nelement is responsible for.",
39570
39742
  "attribute": "multiple"
39571
39743
  },
39572
39744
  {
@@ -39852,9 +40024,17 @@
39852
40024
  "text": "string[]"
39853
40025
  },
39854
40026
  "privacy": "private",
39855
- "description": "The values chosen, in the order they were chosen.",
40027
+ "description": "The values chosen, in the order they were chosen, read against the\noptions' values and the answers created here, so a value that holds a\ncomma is one value. See `chosenValues`.\n\nMeasured before this: choosing `Paris, France` drew two tags, \"Paris\" and\n\"France\", and the form received two entries.",
39856
40028
  "readonly": true
39857
40029
  },
40030
+ {
40031
+ "kind": "field",
40032
+ "name": "created",
40033
+ "privacy": "private",
40034
+ "readonly": true,
40035
+ "default": "new Set<string>()",
40036
+ "description": "The answers created here, which no option holds, kept so their commas read as theirs."
40037
+ },
39858
40038
  {
39859
40039
  "kind": "field",
39860
40040
  "name": "chosen",
@@ -42167,7 +42347,7 @@
42167
42347
  "text": "boolean"
42168
42348
  },
42169
42349
  "default": "false",
42170
- "description": "Whether more than one option can be chosen.\n\nThe list already does the work: `value` comes apart on commas, a press\ntoggles rather than replaces, and the arrows move without choosing. What\nthis adds is the tags, and keeping the panel open between picks.\n\nA comma is therefore not available inside an option's value, which is the\nlistbox's contract and not this element's to change.\n\n**The list is told, and the field is not.** `aria-multiselectable` belongs\nto `listbox`, `grid`, `tree` and `tablist`, and `combobox` dropped it in\nARIA 1.2; the list sets it on itself through `ElementInternals`, where a\nreader on the field hears it through `aria-controls`. This element wrote it\nonto its own `role=\"combobox\"` input as well, which an audit reports as a\nproperty the role does not support and no spec here ever asserted: the one\nthat covers this says in as many words that telling the list is what this\nelement is responsible for.",
42350
+ "description": "Whether more than one option can be chosen.\n\nThe list already does the work: `value` is the chosen values joined with\ncommas, a press toggles rather than replaces, and the arrows move without\nchoosing. What this adds is the tags, and keeping the panel open between\npicks.\n\nAn option's value may hold a comma, and it is read as one value, as\n`Select` and `Listbox` read it. So may an answer the reader created.\n\n**The list is told, and the field is not.** `aria-multiselectable` belongs\nto `listbox`, `grid`, `tree` and `tablist`, and `combobox` dropped it in\nARIA 1.2; the list sets it on itself through `ElementInternals`, where a\nreader on the field hears it through `aria-controls`. This element wrote it\nonto its own `role=\"combobox\"` input as well, which an audit reports as a\nproperty the role does not support and no spec here ever asserted: the one\nthat covers this says in as many words that telling the list is what this\nelement is responsible for.",
42171
42351
  "fieldName": "multiple"
42172
42352
  },
42173
42353
  {
@@ -42597,7 +42777,7 @@
42597
42777
  "declarations": [
42598
42778
  {
42599
42779
  "kind": "class",
42600
- "description": "The list is a `Listbox`, which handles filtering, the empty state, the match\nhighlight, `aria-activedescendant`, scrolling an option into view, and moving\nbetween options with the keyboard. The palette adds a dialog and a hotkey\nthat opens it.\n\nThe palette keeps no value. It is not a form control and submits nothing.\nChoosing an option dispatches `helix-select` once. To remember the last\ncommand, store it yourself. An option with `href` is a link to a page, which\nthe browser follows once the palette has closed.\n\nThe hotkey listener is on the document, so the hotkey works from anywhere on\nthe page, including inside another control's text field, whether or not the\npalette is open. `mod` means Command on a Mac and Control elsewhere, so you\nwrite one binding.\n\nWith `inline`, the palette is drawn in the page with no dialog, as a search\nover a list that is always shown.\n\n**Pages.** A command can open a page of commands of its own, as a palette\noffers \"Change theme\" and then the themes. Give the option `opens` with a\nname, and slot the page's commands as `page:` and that name:\n\n```html\n<helix-command>\n <helix-option value=\"theme\" opens=\"theme\">Change theme</helix-option>\n <helix-option value=\"dark\" slot=\"page:theme\">Dark</helix-option>\n <helix-option value=\"light\" slot=\"page:theme\">Light</helix-option>\n</helix-command>\n```\n\nChoosing the opener says `helix-select` with its value, and canceling it\nkeeps the page that is shown. The list then shows the page, named by the\nopener's words, and a screen reader hears those words. Backspace in an empty\nfilter goes back, and a screen reader hears the name of the page it goes\nback to. `page` says which page is shown.\n\nThe filter is cleared when the palette closes, so each opening starts from\nthe full list. Combobox and Select do the same. As typing narrows the list, a\nscreen reader hears how many commands are left, such as \"3 commands\".\n\n**Keyboard.** Focus goes to the filter field as the palette opens, and the\nhighlight moves through the commands while you type.\n\n| Key | What it does |\n|---|---|\n| `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. |\n| Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. |\n| Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. |\n| Home, End, Left, Right | Move the caret in the filter field. |\n| 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. |\n| Command or Control with Enter | Takes the highlighted command's `alternate` destination, where it has one. |\n| Backspace | In an empty filter on a page, goes back to the page before. |\n| Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. |\n| Tab | Stays in the palette, which is modal. With `inline`, moves on through the page. |\n\n**ARIA.** The palette is a modal `dialog` named by `label`, or with\n`inline` no dialog at all. Inside it the filter field is a text field with\n`aria-autocomplete=\"list\"`, `aria-controls` on the list, and\n`aria-activedescendant` on the highlighted command, as the field of React\nAria's `Autocomplete` is. The commands are a `listbox` of `option`s. How many commands typing left, the empty text and\nthe loading text are said in a polite live region.",
42780
+ "description": "The list is a `Listbox`, which handles filtering, the empty state, the match\nhighlight, `aria-activedescendant`, scrolling an option into view, and moving\nbetween options with the keyboard. The palette adds a dialog and a hotkey\nthat opens it.\n\nThe palette keeps no value. It is not a form control and submits nothing.\nChoosing an option dispatches `helix-select` once. To remember the last\ncommand, store it yourself. An option with `href` is a link to a page, which\nthe browser follows once the palette has closed.\n\nThe hotkey listener is on the document, so the hotkey works from anywhere on\nthe page, including inside another control's text field, whether or not the\npalette is open. `mod` means Command on a Mac and Control elsewhere, so you\nwrite one binding.\n\nWith `inline`, the palette is drawn in the page with no dialog, as a search\nover a list that is always shown.\n\n**Pages.** A command can open a page of commands of its own, as a palette\noffers \"Change theme\" and then the themes. Give the option `opens` with a\nname, and slot the page's commands as `page:` and that name:\n\n```html\n<helix-command>\n <helix-option value=\"theme\" opens=\"theme\">Change theme</helix-option>\n <helix-option value=\"dark\" slot=\"page:theme\">Dark</helix-option>\n <helix-option value=\"light\" slot=\"page:theme\">Light</helix-option>\n</helix-command>\n```\n\nChoosing the opener says `helix-select` with its value, and canceling it\nkeeps the page that is shown. The list then shows the page, named by the\nopener's words, and a screen reader hears those words. Backspace in an empty\nfilter goes back, and a screen reader hears the name of the page it goes\nback to. `page` says which page is shown.\n\nThe filter is cleared when the palette closes, so each opening starts from\nthe full list. Combobox and Select do the same. As typing narrows the list, a\nscreen reader hears how many commands are left, such as \"3 commands\".\n\n**Keyboard.** Focus goes to the filter field as the palette opens, and the\nhighlight moves through the commands while you type.\n\n| Key | What it does |\n|---|---|\n| `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. |\n| Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. |\n| Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. |\n| Home, End | Move the caret in the filter field. With `home-end=\"list\"`, move the highlight to the first or the last command. |\n| Left, Right | Move the caret in the filter field. |\n| 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. |\n| Command or Control with Enter | Takes the highlighted command's `alternate` destination, where it has one. |\n| Backspace | In an empty filter on a page, goes back to the page before. |\n| Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. |\n| Tab | Stays in the palette, which is modal. With `inline`, moves on through the page. |\n\n**ARIA.** The palette is a modal `dialog` named by `label`, or with\n`inline` no dialog at all. Inside it the filter field is a text field with\n`aria-autocomplete=\"list\"`, `aria-controls` on the list, and\n`aria-activedescendant` on the highlighted command, as the field of React\nAria's `Autocomplete` is. The commands are a `listbox` of `option`s. How many commands typing left, the empty text and\nthe loading text are said in a polite live region.",
42601
42781
  "name": "HelixHeadlessCommand",
42602
42782
  "cssParts": [
42603
42783
  {
@@ -42761,6 +42941,15 @@
42761
42941
  },
42762
42942
  "description": "Whether a command is kept by the filter: a function given the command's\nwords and the filter, trimmed, that returns `true` to keep it showing, as\nReact Aria's `Autocomplete` takes `filter`. See Listbox's `filterMatch`.\n\nAbsent, a command is kept where its words hold the filter, in any case. A\nproperty only, there being no way to write a function in markup."
42763
42943
  },
42944
+ {
42945
+ "kind": "field",
42946
+ "name": "homeEnd",
42947
+ "type": {
42948
+ "text": "'list' | undefined"
42949
+ },
42950
+ "description": "Where Home and End go from the filter field.\n\nAbsent, they move the caret, as APG's combobox has them. `list` moves the\nhighlight to the first or the last command, as React Aria's Autocomplete\ndoes, and Shift with either still selects the text.",
42951
+ "attribute": "home-end"
42952
+ },
42764
42953
  {
42765
42954
  "kind": "field",
42766
42955
  "name": "hotkey",
@@ -42804,6 +42993,16 @@
42804
42993
  "words": true
42805
42994
  }
42806
42995
  },
42996
+ {
42997
+ "kind": "field",
42998
+ "name": "layout",
42999
+ "type": {
43000
+ "text": "'grid' | 'stack' | undefined"
43001
+ },
43002
+ "description": "How the commands are laid out, as Listbox's `layout`: `grid` draws them in\nrows and columns, for a palette of icons or emoji, and the arrow keys\nfollow the rows and the columns. Absent is one command under another.",
43003
+ "attribute": "layout",
43004
+ "reflects": true
43005
+ },
42807
43006
  {
42808
43007
  "kind": "field",
42809
43008
  "name": "loadError",
@@ -43629,6 +43828,14 @@
43629
43828
  "description": "How long typing rests before the commands are filtered, in milliseconds,\nso a palette filtered on a server sends one `helix-filter` for a word.\n`0` filters on every keystroke. See Listbox's `filter-delay`.",
43630
43829
  "fieldName": "filterDelay"
43631
43830
  },
43831
+ {
43832
+ "name": "home-end",
43833
+ "type": {
43834
+ "text": "'list' | undefined"
43835
+ },
43836
+ "description": "Where Home and End go from the filter field.\n\nAbsent, they move the caret, as APG's combobox has them. `list` moves the\nhighlight to the first or the last command, as React Aria's Autocomplete\ndoes, and Shift with either still selects the text.",
43837
+ "fieldName": "homeEnd"
43838
+ },
43632
43839
  {
43633
43840
  "name": "hotkey",
43634
43841
  "type": {
@@ -43656,6 +43863,14 @@
43656
43863
  "description": "Accessible name for the overlay, which has no visible heading.",
43657
43864
  "fieldName": "label"
43658
43865
  },
43866
+ {
43867
+ "name": "layout",
43868
+ "type": {
43869
+ "text": "'grid' | 'stack' | undefined"
43870
+ },
43871
+ "description": "How the commands are laid out, as Listbox's `layout`: `grid` draws them in\nrows and columns, for a palette of icons or emoji, and the arrow keys\nfollow the rows and the columns. Absent is one command under another.",
43872
+ "fieldName": "layout"
43873
+ },
43659
43874
  {
43660
43875
  "name": "load-error",
43661
43876
  "type": {
@@ -67414,7 +67629,7 @@
67414
67629
  "declarations": [
67415
67630
  {
67416
67631
  "kind": "class",
67417
- "description": "Shows one filter declared by a `FilterField`: the field, the operator, and\nthe values, with a control to remove the filter.\n\nThe operator is shown only when it is not the field's default:\n\n```\nDisposition refunded, chargeback default operator, hidden\nDisposition is not refunded chosen operator, shown\nCreated after 1 Aug a scalar field has no default\n```\n\nOmit `operator-label` for the field's default operator and pass it for every\nother operator. The code that builds the chip has the field, and the field\ndefines its default.\n\nThe chip shows a filter and does not apply it. Dismissing fires\n`helix-dismiss` as a request, as on `Tag` and `Announcement`. The chip is\nyour element in your list, so you remove it, which keeps your model and the\ndocument in step. Call `preventDefault()` on `helix-dismiss` to cancel the\ndismissal, which is also how you take control of the interaction for one\npress. `requestChange` documents the pattern.\n\n**Keyboard.** The remove button is a tab stop of its own, and Enter or Space\non it asks to remove the filter. In a `FilterInput`, Backspace in the empty\nfield asks to remove the last chip, the arrow keys move between the field\nand the chips, and Delete or Backspace on a chip asks to remove it.\n\nThe remove button is named `dismiss-label` followed by the chip's words,\nsuch as \"Remove filter Status is not open\", so a row of chips says which\nfilter each button removes. Write `{label}` in `dismiss-label` to put the\nwords elsewhere.\n\nTo let the user change the operator, slot a menu trigger into `operator`.\nWith the text fallback, the operator is a label. The chip does not interpret\noperators: their meaning belongs to your domain, as `FilterOperator`\nexplains.",
67632
+ "description": "Shows one filter declared by a `FilterField`: the field, the operator, and\nthe values, with a control to remove the filter.\n\nThe operator is shown only when it is not the field's default:\n\n```\nDisposition refunded, chargeback default operator, hidden\nDisposition is not refunded chosen operator, shown\nCreated after 1 Aug a scalar field has no default\n```\n\nOmit `operator-label` for the field's default operator and pass it for every\nother operator. The code that builds the chip has the field, and the field\ndefines its default.\n\nThe chip shows a filter and does not apply it. Dismissing fires\n`helix-dismiss` as a request, as on `Tag` and `Announcement`. The chip is\nyour element in your list, so you remove it, which keeps your model and the\ndocument in step. Call `preventDefault()` on `helix-dismiss` to cancel the\ndismissal, which is also how you take control of the interaction for one\npress. `requestChange` documents the pattern.\n\n**Keyboard.** The remove button is a tab stop of its own, and Enter or Space\non it asks to remove the filter. In a `FilterInput`, the field's text is the\none tab stop: Backspace in the empty field asks to remove the last chip, the\narrow keys move between the field and the chips, and Delete or Backspace on\na chip asks to remove it.\n\nThe remove button is named `dismiss-label` followed by the chip's words,\nsuch as \"Remove filter Status is not open\", so a row of chips says which\nfilter each button removes. Write `{label}` in `dismiss-label` to put the\nwords elsewhere.\n\nTo let the user change the operator, slot a menu trigger into `operator`.\nWith the text fallback, the operator is a label. The chip does not interpret\noperators: their meaning belongs to your domain, as `FilterOperator`\nexplains.",
67418
67633
  "name": "HelixHeadlessFilterChip",
67419
67634
  "cssParts": [
67420
67635
  {
@@ -67484,6 +67699,15 @@
67484
67699
  "module": "src/mixins/mixin-dismissible/mixin-dismissible.ts"
67485
67700
  }
67486
67701
  },
67702
+ {
67703
+ "kind": "field",
67704
+ "name": "dismissTabStop",
67705
+ "type": {
67706
+ "text": "boolean"
67707
+ },
67708
+ "default": "true",
67709
+ "description": "Whether the remove button is a tab stop of its own.\n\n`FilterInput` writes `false` on the chips in its `tags` slot: the field's\ntext is its one tab stop, and the arrow keys move from the text to the\nchips, as in a `multiple` Combobox. No attribute: it is coordination\nbetween elements, as `Tag.dismissTabStop` is."
67710
+ },
67487
67711
  {
67488
67712
  "kind": "field",
67489
67713
  "name": "label",
@@ -69952,7 +70176,7 @@
69952
70176
  "declarations": [
69953
70177
  {
69954
70178
  "kind": "class",
69955
- "description": "Tokens are your own elements, slotted in. A filter can be a facet with a\nprefix, a saved query, or a range, and these belong to your model, so the\nelement does not render tokens from a list of strings. Removing a token is a\nrequest the element fires, and you apply it. Combobox works the other way:\nits tokens show a selection it owns, drawn from the options it was given.\n\n`value` is the typed text. Every keystroke fires `input` with the text on the\nelement, so a table can narrow as the user types. Backspace in an empty field\nfires `helix-dismiss` on the last token, the same event its remove control\nfires, so one handler covers the pointer and the keyboard.\n\n**What a form receives.** The text under `name`, and then one more entry\nunder `name` for each token, in the order the tokens stand:\n\n| Token | Entry |\n|---|---|\n| Any element with a `value` attribute | The value as written: `saved:mine` |\n| `FilterChip` with `name` and values | `status:open,pending` |\n| The same, with `operator=\"none\"` (what a typed `-status:` makes) | `-status:open,pending` |\n| The same, with any other `operator` except `any` | `created[after]:2024` |\n| A token with neither | Nothing |\n\nThe values are the chip's text outside its `field` and `operator` slots,\nwith the spaces around each comma removed. A server splits an entry at its\nfirst colon, reads a leading `-` as the negation, and reads a word in\nbrackets before the colon as the comparison.\n\n**Keyboard.** Focus stays in the text. The text names the highlighted\nsuggestion as its `aria-activedescendant`.\n\n| Key | What it does |\n|---|---|\n| Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |\n| Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |\n| Home, End | Highlights the first or the last suggestion while the panel is open. |\n| Escape | Closes the panel and stops there, so a dialog around the field stays open. |\n| Backspace | In an empty field, asks the last token to go. |\n| 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. |\n| Left, Right on a token | Move between the tokens, and past the last back to the text. |\n| Delete, Backspace on a token | Asks the token to go. |\n\n**Typed filters.** The field parses only the fields you declare. Write\n`FilterField` elements, usually inside the `FilterMenu` slotted into `start`,\nso the picker and the text share one set. On Enter, the field reads the text\nagainst them. `disposition:refunded,settled` and `-disposition:refunded` fire\n`helix-facet` exactly as ticking those values in the picker would, and the\nparsed text is removed. Everything else stays, so `refund tuesday\ndisposition:settled` is a filter and a search at once. Helix defines the\npunctuation and you define every word. `grammar.ts` has the full rule, so\nread it before you rely on it. A field with no `FilterField` in it parses\nnothing.\n\nA field whose values cannot be listed, such as `assignee:ada`, goes directly\ninside this element, outside the menu. It is not assigned to a slot, so\nnothing draws it and the menu has no page for it, and the grammar still reads\nit.\n\n**Suggestions.** Slot options into `suggestions` and the field shows them,\nmoves through them with the arrow keys, and presses one on Enter. The option\nfires its own `helix-select`, and you decide what choosing it means. Keys\nbefore a colon and values after it use the same panel with different\ncontents. `filter-suggestions` narrows the panel to the options whose words\nhold the term at the caret, after its colon, ignoring case and accents, and\nhides the rest. `readFilterText` is exported so you can narrow it yourself\nagainst partly typed text. While the panel is open, a reader hears how many\nsuggestions it offers. The panel opens when it has options and closes when it has\nnone, and a choice does not close it, so after picking a key you see its\nvalues next. Use `selectionStart` and `setSelectionRange` to write a\ncompletion back and put the caret after it, or the next parse reads the wrong\nterm.\n\n**State.** Three things have three different owners:\n\n- `value` is the text. The user types, the element applies it, and `input`\n reports it. Setting `value` seeds or corrects the text, and the next\n keystroke overwrites it, even in React. To control the value, cancel\n `helix-before-change` and write the value you want, as with every field in\n this library. `default-value` seeds the field.\n- `open` is the suggestions panel. Cancel `helix-before-open` or\n `helix-before-close` to control it, and use `default-open` to seed it.\n- Tokens are your elements in a slot and hold no state. A token goes when you\n remove it from your markup after `helix-dismiss`. A `FilterChip` naming a\n declared field works differently, because the picker holds what is ticked\n and removing the chip alone would leave its value ticked in the hidden\n menu. Its dismissal is treated as the field being filtered by nothing, so\n it fires `helix-facet` like every other change, and the chip goes when the\n filter goes.",
70179
+ "description": "Tokens are your own elements, slotted in. A filter can be a facet with a\nprefix, a saved query, or a range, and these belong to your model, so the\nelement does not render tokens from a list of strings. Removing a token is a\nrequest the element fires, and you apply it. Combobox works the other way:\nits tokens show a selection it owns, drawn from the options it was given.\n\n`value` is the typed text. Every keystroke fires `input` with the text on the\nelement, so a table can narrow as the user types. Backspace in an empty field\nfires `helix-dismiss` on the last token, the same event its remove control\nfires, so one handler covers the pointer and the keyboard.\n\n**What a form receives.** The text under `name`, and then one more entry\nunder `name` for each token, in the order the tokens stand:\n\n| Token | Entry |\n|---|---|\n| Any element with a `value` attribute | The value as written: `saved:mine` |\n| `FilterChip` with `name` and values | `status:open,pending` |\n| The same, with `operator=\"none\"` (what a typed `-status:` makes) | `-status:open,pending` |\n| The same, with any other `operator` except `any` | `created[after]:2024` |\n| A token with neither | Nothing |\n\nThe values are the chip's text outside its `field` and `operator` slots,\nwith the spaces around each comma removed. A server splits an entry at its\nfirst colon, reads a leading `-` as the negation, and reads a word in\nbrackets before the colon as the comparison.\n\n**Keyboard.** Focus stays in the text, which is the field's one tab stop. The\ntext names the highlighted suggestion as its `aria-activedescendant`, and the\narrow keys reach the tokens.\n\n| Key | What it does |\n|---|---|\n| Enter | Presses the highlighted suggestion. With none highlighted, reads the typed filters into chips, or submits the form when there are none. |\n| Down, Up | Moves the highlight through the suggestions, wrapping, and opens the panel. |\n| Home, End | Highlights the first or the last suggestion while the panel is open. |\n| Escape | Closes the panel and stops there, so a dialog around the field stays open. |\n| Backspace | In an empty field, asks the last token to go. |\n| 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. |\n| Left, Right on a token | Move between the tokens, and past the last back to the text. |\n| Delete, Backspace on a token | Asks the token to go. |\n\n**Typed filters.** The field parses only the fields you declare. Write\n`FilterField` elements, usually inside the `FilterMenu` slotted into `start`,\nso the picker and the text share one set. On Enter, the field reads the text\nagainst them. `disposition:refunded,settled` and `-disposition:refunded` fire\n`helix-facet` exactly as ticking those values in the picker would, and the\nparsed text is removed. Everything else stays, so `refund tuesday\ndisposition:settled` is a filter and a search at once. Helix defines the\npunctuation and you define every word. `grammar.ts` has the full rule, so\nread it before you rely on it. A field with no `FilterField` in it parses\nnothing.\n\nA field whose values cannot be listed, such as `assignee:ada`, goes directly\ninside this element, outside the menu. It is not assigned to a slot, so\nnothing draws it and the menu has no page for it, and the grammar still reads\nit.\n\n**Suggestions.** Slot options into `suggestions` and the field shows them,\nmoves through them with the arrow keys, and presses one on Enter. The option\nfires its own `helix-select`, and you decide what choosing it means. Keys\nbefore a colon and values after it use the same panel with different\ncontents. `filter-suggestions` narrows the panel to the options whose words\nhold the term at the caret, after its colon, ignoring case and accents, and\nhides the rest. `readFilterText` is exported so you can narrow it yourself\nagainst partly typed text. While the panel is open, a reader hears how many\nsuggestions it offers. The panel opens when it has options and closes when it has\nnone, and a choice does not close it, so after picking a key you see its\nvalues next. Use `selectionStart` and `setSelectionRange` to write a\ncompletion back and put the caret after it, or the next parse reads the wrong\nterm.\n\n**State.** Three things have three different owners:\n\n- `value` is the text. The user types, the element applies it, and `input`\n reports it. Setting `value` seeds or corrects the text, and the next\n keystroke overwrites it, even in React. To control the value, cancel\n `helix-before-change` and write the value you want, as with every field in\n this library. `default-value` seeds the field.\n- `open` is the suggestions panel. Cancel `helix-before-open` or\n `helix-before-close` to control it, and use `default-open` to seed it.\n- Tokens are your elements in a slot and hold no state. A token goes when you\n remove it from your markup after `helix-dismiss`. A `FilterChip` naming a\n declared field works differently, because the picker holds what is ticked\n and removing the chip alone would leave its value ticked in the hidden\n menu. Its dismissal is treated as the field being filtered by nothing, so\n it fires `helix-facet` like every other change, and the chip goes when the\n filter goes. Set `chips` and the field adds, updates, and removes those\n chips itself, from every `helix-facet` you do not cancel.",
69956
70180
  "name": "HelixHeadlessFilterInput",
69957
70181
  "cssParts": [
69958
70182
  {
@@ -69963,6 +70187,10 @@
69963
70187
  "description": "The input itself.",
69964
70188
  "name": "control"
69965
70189
  },
70190
+ {
70191
+ "description": "Shown in the panel when `filter-suggestions` hides every suggestion.",
70192
+ "name": "empty"
70193
+ },
69966
70194
  {
69967
70195
  "description": "The error message under the field.",
69968
70196
  "name": "feedback"
@@ -69987,6 +70215,10 @@
69987
70215
  "description": "The live region that says how many suggestions the open panel offers. It is rendered from the first time the panel opens with suggestions.",
69988
70216
  "name": "live"
69989
70217
  },
70218
+ {
70219
+ "description": "Shown in the panel while the suggestions load.",
70220
+ "name": "loading"
70221
+ },
69990
70222
  {
69991
70223
  "description": "The count of tokens that did not fit. It is a `<button>` with `expandable` and a `<span>` without it.",
69992
70224
  "name": "rest"
@@ -70021,6 +70253,14 @@
70021
70253
  "description": "The label, for content richer than the `label` text.",
70022
70254
  "name": "label"
70023
70255
  },
70256
+ {
70257
+ "description": "What the panel shows while `loading` is set, for content richer than `loading-text`.",
70258
+ "name": "loading"
70259
+ },
70260
+ {
70261
+ "description": "What the panel shows when `filter-suggestions` hides every suggestion, for content richer than `no-results-text`.",
70262
+ "name": "no-results"
70263
+ },
70024
70264
  {
70025
70265
  "description": "Content before the text, such as a search icon.",
70026
70266
  "name": "start"
@@ -70071,6 +70311,16 @@
70071
70311
  "module": "src/mixins/mixin-controller-value/mixin-controller-value.ts"
70072
70312
  }
70073
70313
  },
70314
+ {
70315
+ "kind": "field",
70316
+ "name": "chips",
70317
+ "type": {
70318
+ "text": "boolean"
70319
+ },
70320
+ "default": "false",
70321
+ "description": "Whether the field keeps a `FilterChip` for each filter in its `tags` slot,\nfrom the `helix-facet` events it hears.\n\nOff, you build the chips, which is what you do when your own model holds\nthe filters. On, a filter typed, picked, or changed adds or updates the\nchip for its field, one with no values takes it away (unless its\ncomparison takes none, such as \"is empty\"), and removing the chip clears\nthe filter. A `helix-facet` you cancel changes no chip.\n\nThe chips are elements the field adds to its own children, so leave this\noff where a framework renders those children and would remove them.",
70322
+ "attribute": "chips"
70323
+ },
70074
70324
  {
70075
70325
  "kind": "field",
70076
70326
  "name": "clearable",
@@ -70104,6 +70354,40 @@
70104
70354
  "description": "Whether the panel narrows itself to the suggestions that hold the term\nbeing typed, as React Aria's Autocomplete filters. Off, the panel shows\nwhat you slot and you narrow it.",
70105
70355
  "attribute": "filter-suggestions"
70106
70356
  },
70357
+ {
70358
+ "kind": "field",
70359
+ "name": "loading",
70360
+ "type": {
70361
+ "text": "boolean"
70362
+ },
70363
+ "default": "false",
70364
+ "description": "Whether the suggestions are still loading, such as while a request for the\nvalues of a typed key is out.\n\nThe panel opens on `loading-text`, or the `loading` slot, while the field\nhas focus, and a screen reader hears it. Slot the options and clear this\nwhen they arrive.",
70365
+ "attribute": "loading",
70366
+ "reflects": true
70367
+ },
70368
+ {
70369
+ "kind": "field",
70370
+ "name": "loadingText",
70371
+ "type": {
70372
+ "text": "string"
70373
+ },
70374
+ "default": "'Loading'",
70375
+ "description": "Text the panel shows while the suggestions load.",
70376
+ "attribute": "loading-text",
70377
+ "helix": {
70378
+ "words": true
70379
+ }
70380
+ },
70381
+ {
70382
+ "kind": "field",
70383
+ "name": "noResultsText",
70384
+ "type": {
70385
+ "text": "string"
70386
+ },
70387
+ "default": "''",
70388
+ "description": "Text the panel shows when `filter-suggestions` hides every suggestion, such\nas \"No matching filters\".\n\nEmpty, or no `no-results` slot, and the panel closes instead, as it does\nwhen it has nothing to offer.",
70389
+ "attribute": "no-results-text"
70390
+ },
70107
70391
  {
70108
70392
  "kind": "field",
70109
70393
  "name": "placeholder",
@@ -70451,6 +70735,32 @@
70451
70735
  ],
70452
70736
  "description": "Says a field is now filtered by these values, through the picker where\nthere is one, and reports whether it stood.\n\nAnnounced by the menu rather than relayed by this element, so the ticks and\nthe event never come from two places. A consumer who wrote `FilterField`s\nwithout a picker gets it from here, which is the only case where nothing\nelse could have said it."
70453
70737
  },
70738
+ {
70739
+ "kind": "field",
70740
+ "name": "handleFacet",
70741
+ "privacy": "private",
70742
+ "readonly": true,
70743
+ "description": "Keeps the chip for a filter in step with it, under `chips`.\n\nAfter every listener has had its turn, so a consumer's `preventDefault()`\non the same event, on this element or above it, is read: `dispatchEvent`\nruns them all before the microtask does."
70744
+ },
70745
+ {
70746
+ "kind": "method",
70747
+ "name": "drawChip",
70748
+ "privacy": "private",
70749
+ "return": {
70750
+ "type": {
70751
+ "text": "void"
70752
+ }
70753
+ },
70754
+ "parameters": [
70755
+ {
70756
+ "name": "facet",
70757
+ "type": {
70758
+ "text": "FacetDetail"
70759
+ }
70760
+ }
70761
+ ],
70762
+ "description": "Adds, updates or removes the chip for one filter. See `chips`."
70763
+ },
70454
70764
  {
70455
70765
  "kind": "field",
70456
70766
  "name": "handleDismiss",
@@ -70523,6 +70833,16 @@
70523
70833
  },
70524
70834
  "description": "What is on offer, settled before the render that draws it.\n\n**Not left to `slotchange`, for the reason the token row is not.** That\nevent reports the assignment moving and nothing else, and it does not fire\nat all under the harness these are tested in, so a panel that learned only\nfrom it would be a panel that never opened. Reading the slot every update is\nwhat makes the answer true whenever anyone asks.\n\nState only. Opening is an announcement and belongs after the render, which\nis why `settleOpen` is not called from here."
70525
70835
  },
70836
+ {
70837
+ "kind": "field",
70838
+ "name": "unmatched",
70839
+ "type": {
70840
+ "text": "boolean"
70841
+ },
70842
+ "privacy": "private",
70843
+ "description": "Whether `filter-suggestions` has hidden every suggestion there is, where a\n`no-results-text` or a `no-results` slot says so. The panel stays open on\nit, and `:state(no-results)` is on the host.",
70844
+ "readonly": true
70845
+ },
70526
70846
  {
70527
70847
  "kind": "field",
70528
70848
  "name": "handleSuggestions",
@@ -70556,7 +70876,7 @@
70556
70876
  "name": "handleTokens",
70557
70877
  "privacy": "private",
70558
70878
  "readonly": true,
70559
- "description": "The row again, whenever what is in it changes."
70879
+ "description": "The row again, whenever what is in it changes.\n\n**And the text is the field's one tab stop.** Each token's remove button\nwas a stop of its own, so Tab through a field with five filters took six\npresses. A `Tag` or `FilterChip` takes `dismissTabStop` for this, as the\ntags of a `multiple` Combobox do, and the arrow keys still reach every one.\nA token not yet defined is told once it is."
70560
70880
  },
70561
70881
  {
70562
70882
  "kind": "method",
@@ -72396,6 +72716,15 @@
72396
72716
  }
72397
72717
  ],
72398
72718
  "attributes": [
72719
+ {
72720
+ "name": "chips",
72721
+ "type": {
72722
+ "text": "boolean"
72723
+ },
72724
+ "default": "false",
72725
+ "description": "Whether the field keeps a `FilterChip` for each filter in its `tags` slot,\nfrom the `helix-facet` events it hears.\n\nOff, you build the chips, which is what you do when your own model holds\nthe filters. On, a filter typed, picked, or changed adds or updates the\nchip for its field, one with no values takes it away (unless its\ncomparison takes none, such as \"is empty\"), and removing the chip clears\nthe filter. A `helix-facet` you cancel changes no chip.\n\nThe chips are elements the field adds to its own children, so leave this\noff where a framework renders those children and would remove them.",
72726
+ "fieldName": "chips"
72727
+ },
72399
72728
  {
72400
72729
  "name": "clearable",
72401
72730
  "type": {
@@ -72423,6 +72752,33 @@
72423
72752
  "description": "Whether the panel narrows itself to the suggestions that hold the term\nbeing typed, as React Aria's Autocomplete filters. Off, the panel shows\nwhat you slot and you narrow it.",
72424
72753
  "fieldName": "filterSuggestions"
72425
72754
  },
72755
+ {
72756
+ "name": "loading",
72757
+ "type": {
72758
+ "text": "boolean"
72759
+ },
72760
+ "default": "false",
72761
+ "description": "Whether the suggestions are still loading, such as while a request for the\nvalues of a typed key is out.\n\nThe panel opens on `loading-text`, or the `loading` slot, while the field\nhas focus, and a screen reader hears it. Slot the options and clear this\nwhen they arrive.",
72762
+ "fieldName": "loading"
72763
+ },
72764
+ {
72765
+ "name": "loading-text",
72766
+ "type": {
72767
+ "text": "string"
72768
+ },
72769
+ "default": "'Loading'",
72770
+ "description": "Text the panel shows while the suggestions load.",
72771
+ "fieldName": "loadingText"
72772
+ },
72773
+ {
72774
+ "name": "no-results-text",
72775
+ "type": {
72776
+ "text": "string"
72777
+ },
72778
+ "default": "''",
72779
+ "description": "Text the panel shows when `filter-suggestions` hides every suggestion, such\nas \"No matching filters\".\n\nEmpty, or no `no-results` slot, and the panel closes instead, as it does\nwhen it has nothing to offer.",
72780
+ "fieldName": "noResultsText"
72781
+ },
72426
72782
  {
72427
72783
  "name": "placeholder",
72428
72784
  "type": {
@@ -72673,6 +73029,14 @@
72673
73029
  "description": "The field has an error to show, from the browser's validation or from your `feedback`.",
72674
73030
  "name": "invalid"
72675
73031
  },
73032
+ {
73033
+ "description": "While `loading` is set.",
73034
+ "name": "loading"
73035
+ },
73036
+ {
73037
+ "description": "`filter-suggestions` hid every suggestion, and `no-results-text` or the `no-results` slot says so.",
73038
+ "name": "no-results"
73039
+ },
72676
73040
  {
72677
73041
  "description": "The suggestions are open.",
72678
73042
  "name": "open"
@@ -72990,7 +73354,7 @@
72990
73354
  "declarations": [
72991
73355
  {
72992
73356
  "kind": "class",
72993
- "description": "Formats a date with `Intl` where it is shown, so you do not write the same\n`Intl` call and options in your own code.\n\n**`elapsed` shows compact relative time for a feed**, such as \"42m\", \"3h\", or\n\"1d\". After six days it shows a date. In en-US, `Intl.NumberFormat` narrow\nrenders both `minute` and `month` as `m`, so a compact \"3m\" could mean three\nminutes or three months. `elapsedTime` in `helix/core` does the measurement.\n\n**`relative` shows the same reading in words**, such as \"3 hours ago\" at\n`long`, \"3 hr. ago\" at `short` and \"3h ago\" at `narrow`, the styles\n`sl-relative-time` offers. `numeric=\"always\"` says \"1 day ago\" where the\ndefault says \"yesterday\".\n\n**`date-style` and `time-style` take each locale's own pattern**, such as\n\"Tuesday, August 4, 2026\" at `full`, and stand in for the separate fields,\nwhich `Intl` refuses beside them. `hour-cycle` sets a twelve or twenty-four\nhour clock either way.\n\n**The text refreshes on one timer shared by the page.** Each element\nschedules an update for when its current reading expires, and an element\nshowing a date schedules none, so a long feed left open costs almost nothing.\n`frozen` draws the reading once and leaves it.\n\n**`fields` draws each field of a date as a part of its own**, such as\n`day`, `month` and `year`, so a stylesheet can set the year in a lighter ink\nor the weekday in capitals with `::part()`. The text between the fields is\nthe locale's own and has no part. An `elapsed` or `relative` reading is one\nphrase, with no parts inside it.\n\n**The output is always `<time datetime>`**, so copy and paste and scripts\nparsing the page get the exact instant, whatever the visible text says. A\nscreen reader reads the text, so an `elapsed` reading is named in full, such\nas \"3 hours ago\", and carries the whole date as its title.\n\n**A date with no time, such as `2026-08-04`, is that day everywhere.** It is\nformatted in UTC unless `time-zone` says otherwise, as Date Input and Date\nPicker format their dates, so a reader west of UTC sees August 4 and not\nAugust 3.\n\n**A date is written in a calendar Date Picker draws**: the locale's own\nwhere its months are the Gregorian months, as `th-TH` writes 2569 for 2026,\nand `gregory` where they are not, as for `fa-IR`. `calendar` picks any of\nthem, `persian` and `hebrew` included.",
73357
+ "description": "Formats a date with `Intl` where it is shown, so you do not write the same\n`Intl` call and options in your own code.\n\n**`elapsed` shows compact relative time for a feed**, such as \"42m\", \"3h\", or\n\"1d\". After six days it shows a date. In en-US, `Intl.NumberFormat` narrow\nrenders both `minute` and `month` as `m`, so a compact \"3m\" could mean three\nminutes or three months. `elapsedTime` in `helix/core` does the measurement.\n\n**`relative` shows the same reading in words**, such as \"3 hours ago\" at\n`long`, \"3 hr. ago\" at `short` and \"3h ago\" at `narrow`, the styles\n`sl-relative-time` offers. `numeric=\"always\"` says \"1 day ago\" where the\ndefault says \"yesterday\". Both readings round the count, as\n`sl-relative-time` does: 100 seconds ago is \"2 minutes ago\", and 59.6\nminutes is \"1 hour\".\n\n**`date-style` and `time-style` take each locale's own pattern**, such as\n\"Tuesday, August 4, 2026\" at `full`, and stand in for the separate fields,\nwhich `Intl` refuses beside them. `hour-cycle` sets a twelve or twenty-four\nhour clock either way.\n\n**The text refreshes on one timer shared by the page.** Each element\nschedules an update for when its current reading expires, and an element\nshowing a date schedules none, so a long feed left open costs almost nothing.\n`frozen` draws the reading once and leaves it.\n\n**`fields` draws each field of a date as a part of its own**, such as\n`day`, `month` and `year`, so a stylesheet can set the year in a lighter ink\nor the weekday in capitals with `::part()`. The text between the fields is\nthe locale's own and has no part. An `elapsed` or `relative` reading is one\nphrase, with no parts inside it.\n\n**The output is always `<time datetime>`**, so copy and paste and scripts\nparsing the page get the exact instant, whatever the visible text says. A\nscreen reader reads the text, so an `elapsed` reading is named in full, such\nas \"3 hours ago\", and carries the whole date as its title.\n\n**A date with no time, such as `2026-08-04`, is that day everywhere.** It is\nformatted in UTC unless `time-zone` says otherwise, as Date Input and Date\nPicker format their dates, so a reader west of UTC sees August 4 and not\nAugust 3.\n\n**A date is written in a calendar Date Picker draws**: the locale's own\nwhere its months are the Gregorian months, as `th-TH` writes 2569 for 2026,\nand `gregory` where they are not, as for `fa-IR`. `calendar` picks any of\nthem, `persian` and `hebrew` included.",
72994
73358
  "name": "HelixHeadlessFormatDate",
72995
73359
  "cssParts": [
72996
73360
  {
@@ -83862,6 +84226,48 @@
83862
84226
  },
83863
84227
  "description": "Where the selection starts, as an offset into the value."
83864
84228
  },
84229
+ {
84230
+ "kind": "method",
84231
+ "name": "setRangeText",
84232
+ "return": {
84233
+ "type": {
84234
+ "text": "void"
84235
+ }
84236
+ },
84237
+ "parameters": [
84238
+ {
84239
+ "name": "replacement",
84240
+ "type": {
84241
+ "text": "string"
84242
+ }
84243
+ },
84244
+ {
84245
+ "name": "start",
84246
+ "optional": true,
84247
+ "type": {
84248
+ "text": "number"
84249
+ }
84250
+ },
84251
+ {
84252
+ "name": "end",
84253
+ "optional": true,
84254
+ "type": {
84255
+ "text": "number"
84256
+ }
84257
+ },
84258
+ {
84259
+ "name": "selectMode",
84260
+ "optional": true,
84261
+ "type": {
84262
+ "text": "SelectionMode"
84263
+ }
84264
+ }
84265
+ ],
84266
+ "description": "Replaces a range of the text, as the native method does: the selection\nwhere `start` and `end` are left out, and `selectMode` says what is\nselected after. It sends no event, as the native method sends none.",
84267
+ "type": {
84268
+ "text": "setRangeText(replacement: string, start?: number, end?: number, selectMode?: SelectionMode) => void"
84269
+ }
84270
+ },
83865
84271
  {
83866
84272
  "kind": "method",
83867
84273
  "name": "setSelectionRange",
@@ -116935,7 +117341,7 @@
116935
117341
  "text": "string"
116936
117342
  },
116937
117343
  "default": "'Decrease'",
116938
- "description": "The name of the step down button, read by screen readers.",
117344
+ "description": "The name of the step down button, read by screen readers. The field's\nlabel follows it, so a reader hears \"Decrease Quantity\", as React Aria\nnames its steppers.",
116939
117345
  "attribute": "decrement-label",
116940
117346
  "helix": {
116941
117347
  "words": true
@@ -116957,7 +117363,7 @@
116957
117363
  "text": "string"
116958
117364
  },
116959
117365
  "default": "'Increase'",
116960
- "description": "The name of the step up button, read by screen readers.",
117366
+ "description": "The name of the step up button, read by screen readers. The field's\nlabel follows it, so a reader hears \"Increase Quantity\", as React Aria\nnames its steppers.",
116961
117367
  "attribute": "increment-label",
116962
117368
  "helix": {
116963
117369
  "words": true
@@ -117333,13 +117739,16 @@
117333
117739
  },
117334
117740
  "parameters": [
117335
117741
  {
117336
- "name": "large",
117337
- "default": "false"
117742
+ "name": "count",
117743
+ "default": "1",
117744
+ "type": {
117745
+ "text": "number | boolean"
117746
+ }
117338
117747
  }
117339
117748
  ],
117340
- "description": "Steps the value up, by `largeStep` steps when `large` is set.",
117749
+ "description": "Steps the value up by `step`, `count` times, as the native method and\n`Input.stepUp` do. `true` takes `largeStep` steps, as `PageUp` does.",
117341
117750
  "type": {
117342
- "text": "stepUp(large = false) => void"
117751
+ "text": "stepUp(count: number | boolean = 1) => void"
117343
117752
  }
117344
117753
  },
117345
117754
  {
@@ -117352,15 +117761,37 @@
117352
117761
  },
117353
117762
  "parameters": [
117354
117763
  {
117355
- "name": "large",
117356
- "default": "false"
117764
+ "name": "count",
117765
+ "default": "1",
117766
+ "type": {
117767
+ "text": "number | boolean"
117768
+ }
117357
117769
  }
117358
117770
  ],
117359
- "description": "Steps the value down, by `largeStep` steps when `large` is set.\n\nThe same path a press of the down arrow takes, so a consumer driving this\nfrom their own control gets the clamping and the announcement rather than\nhaving to repeat both.",
117771
+ "description": "Steps the value down by `step`, `count` times. `true` takes `largeStep`\nsteps, as `PageDown` does.\n\nThe same path a press of the down arrow takes, so a consumer driving this\nfrom their own control gets the clamping and the announcement rather than\nhaving to repeat both.",
117360
117772
  "type": {
117361
- "text": "stepDown(large = false) => void"
117773
+ "text": "stepDown(count: number | boolean = 1) => void"
117362
117774
  }
117363
117775
  },
117776
+ {
117777
+ "kind": "method",
117778
+ "name": "stepsOf",
117779
+ "privacy": "private",
117780
+ "return": {
117781
+ "type": {
117782
+ "text": "number"
117783
+ }
117784
+ },
117785
+ "parameters": [
117786
+ {
117787
+ "name": "count",
117788
+ "type": {
117789
+ "text": "number | boolean"
117790
+ }
117791
+ }
117792
+ ],
117793
+ "description": "How many steps a `stepUp` argument asks for: a count, or `largeStep` for `true`."
117794
+ },
117364
117795
  {
117365
117796
  "kind": "field",
117366
117797
  "name": "repeat",
@@ -118974,7 +119405,7 @@
118974
119405
  "text": "string"
118975
119406
  },
118976
119407
  "default": "'Decrease'",
118977
- "description": "The name of the step down button, read by screen readers.",
119408
+ "description": "The name of the step down button, read by screen readers. The field's\nlabel follows it, so a reader hears \"Decrease Quantity\", as React Aria\nnames its steppers.",
118978
119409
  "fieldName": "decrementLabel"
118979
119410
  },
118980
119411
  {
@@ -118991,7 +119422,7 @@
118991
119422
  "text": "string"
118992
119423
  },
118993
119424
  "default": "'Increase'",
118994
- "description": "The name of the step up button, read by screen readers.",
119425
+ "description": "The name of the step up button, read by screen readers. The field's\nlabel follows it, so a reader hears \"Increase Quantity\", as React Aria\nnames its steppers.",
118995
119426
  "fieldName": "incrementLabel"
118996
119427
  },
118997
119428
  {
@@ -152522,7 +152953,7 @@
152522
152953
  "declarations": [
152523
152954
  {
152524
152955
  "kind": "class",
152525
- "description": "`active` sets where the user is, and `complete` stays on each step. Returning\nto stage one of three leaves stages one and two finished, so the root sets\n`current` on the steps and never changes `complete`.\n\n`active` is optional. Without it, each step keeps its own `current`, so the\nsequence is correct in the server's markup, where the root cannot count its\nslotted children.\n\n`linear` keeps a reader from passing a stage they have not finished, as Ark\nUI's linear steps do: a stage ahead is out of reach, and its button disabled,\nuntil every stage before it is `complete` or `optional`. Going back is always\nallowed. `next()` and `previous()` move one stage either way, under the\nsame rules, for your own buttons. `reset()` goes back to the first stage and\nclears every stage's `complete`, as Ark UI's `resetStep` does.\n\n`completion=\"passed\"` marks a stage `complete` once a reader moves past it,\nas Ark UI counts a stage before the current one as completed. Going back\nleaves it complete. In a `linear` sequence the next stage is then in reach\nfrom the current one, and `validate` decides whether the reader may go.\n\nTo check a stage before a reader moves on from it, set `validate` to a\nfunction that answers whether the stage is valid, as Ark UI's `isStepValid`\ndoes. Moving forward asks it about the stage the reader is on, and where it\nanswers `false` the reader stays and the stage is `:state(invalid)` until it\nanswers `true`. An `optional` stage is not asked. `helix-before-activate`\nis still sent for every move, for a check of your own.\n\n`progress` is how far through the sequence is, from 0 to 100: the share of\nits stages that are `complete`. The `progress` part carries it as a\n`progressbar` and as `--steps-progress`, and is hidden until a stylesheet\ngives it a `display`, so a bar of your own costs nothing until you draw it.\nA screen reader hears it as `progress-label` says, \"33% complete\" unless\nset, as Ark UI's steps write it. The sequence is `:state(complete)` once\nevery stage is.\n\nThe sequence is a list named by `label`, and each step a list item. The\ncurrent stage's button says `aria-current=\"step\"`, and a finished stage's\nbutton is described by its `complete-label`.\n\n**Keyboard.** Each stage's name is a button and its own tab stop, and Enter\nor Space goes to the stage. Set `arrows` and the arrow keys move focus\nbetween the names as well, as Ark UI's steps do: Left and Right along a row,\nUp and Down a column, Home and End to the first and the last. The arrows\npass over a disabled stage and one a linear sequence holds out of reach,\nand they move focus without going to the stage.",
152956
+ "description": "`active` sets where the user is, and `complete` stays on each step. Returning\nto stage one of three leaves stages one and two finished, so the root sets\n`current` on the steps and never changes `complete`.\n\n`active` is optional. Without it, each step keeps its own `current`, so the\nsequence is correct in the server's markup, where the root cannot count its\nslotted children.\n\n`active` names a step by its `value`. A step with no `value` is named by its\nplace, counted from 1, so a sequence written without values moves as one\nwritten with them, and `helix-activate` says `1`, `2` and so on. Give every\nstep a value or none, because a value of `2` and the second place are one\nname.\n\n`linear` keeps a reader from passing a stage they have not finished, as Ark\nUI's linear steps do: a stage ahead is out of reach, and its button disabled,\nuntil every stage before it is `complete` or `optional`. Going back is always\nallowed. `next()` and `previous()` move one stage either way, under the\nsame rules, for your own buttons. `reset()` goes back to the first stage and\nclears every stage's `complete`, as Ark UI's `resetStep` does. A button\nanywhere on the page calls them with no script, as Ark UI's previous and\nnext triggers do: give it `commandfor` with the sequence's `id`, and\n`command=\"--previous\"`, `\"--next\"` or `\"--reset\"`.\n\n`completion=\"passed\"` marks a stage `complete` once a reader moves past it,\nas Ark UI counts a stage before the current one as completed. Going back\nleaves it complete. In a `linear` sequence the next stage is then in reach\nfrom the current one, and `validate` decides whether the reader may go.\n\nTo check a stage before a reader moves on from it, set `validate` to a\nfunction that answers whether the stage is valid, as Ark UI's `isStepValid`\ndoes. Moving forward asks it about the stage the reader is on, and where it\nanswers `false` the reader stays and the stage is `:state(invalid)` until it\nanswers `true`. An `optional` stage is not asked. `helix-before-activate`\nis still sent for every move, for a check of your own.\n\n`progress` is how far through the sequence is, from 0 to 100: the share of\nits stages that are `complete`. The `progress` part carries it as a\n`progressbar` and as `--steps-progress`, and is hidden until a stylesheet\ngives it a `display`, so a bar of your own costs nothing until you draw it.\nA screen reader hears it as `progress-label` says, \"33% complete\" unless\nset, as Ark UI's steps write it. The sequence is `:state(complete)` once\nevery stage is.\n\nThe sequence is a list named by `label`, and each step a list item. The\ncurrent stage's button says `aria-current=\"step\"`, and a finished stage's\nbutton is described by its `complete-label`.\n\n**Keyboard.** Each stage's name is a button and its own tab stop, and Enter\nor Space goes to the stage. Set `arrows` and the names are one tab stop, the\ncurrent stage's, and the arrow keys move focus between them: Left and Right\nalong a row, Up and Down a column, Home and End to the first and the last.\nThe stop follows focus, so Tab leaves the sequence and Shift+Tab comes back\nto the name the reader left. The arrows pass over a disabled stage and one a\nlinear sequence holds out of reach, and they move focus without going to the\nstage.",
152526
152957
  "name": "HelixHeadlessSteps",
152527
152958
  "cssProperties": [
152528
152959
  {
@@ -152560,7 +152991,7 @@
152560
152991
  "text": "boolean"
152561
152992
  },
152562
152993
  "default": "false",
152563
- "description": "Whether the arrow keys move focus between the stages' names, along the\nway the steps run. Off by default, so the arrows keep scrolling the page.",
152994
+ "description": "Whether the arrow keys move focus between the stages' names, along the\nway the steps run, and the names are one tab stop. Off by default, so the\narrows keep scrolling the page.",
152564
152995
  "attribute": "arrows"
152565
152996
  },
152566
152997
  {
@@ -152654,6 +153085,13 @@
152654
153085
  "readonly": true,
152655
153086
  "default": "new KeyboardNavigationController(this, { items: () => (this.arrows ? this.steps.map(navigable) : []), origin: 'focus', reserved: () => this.orientation === 'vertical' ? ['ArrowLeft', 'ArrowRight'] : ['ArrowDown', 'ArrowUp'], selects: () => false, wrap: false, })"
152656
153087
  },
153088
+ {
153089
+ "kind": "field",
153090
+ "name": "commands",
153091
+ "privacy": "protected",
153092
+ "readonly": true,
153093
+ "default": "new CommandController(this, { commands: { '--next': () => this.next(), '--previous': () => this.previous(), '--reset': () => this.reset(), }, })"
153094
+ },
152657
153095
  {
152658
153096
  "kind": "field",
152659
153097
  "name": "steps",
@@ -152674,6 +153112,25 @@
152674
153112
  "description": "The index of the stage the reader is on, or `-1`.\n\nRead from `active` once anything has set it, because a move writes\n`active` at once and each step's `current` only on the next update: two\ncalls to `next()` in one task then move two stages.",
152675
153113
  "readonly": true
152676
153114
  },
153115
+ {
153116
+ "kind": "method",
153117
+ "name": "named",
153118
+ "privacy": "private",
153119
+ "return": {
153120
+ "type": {
153121
+ "text": "HelixHeadlessStep | undefined"
153122
+ }
153123
+ },
153124
+ "parameters": [
153125
+ {
153126
+ "name": "steps",
153127
+ "type": {
153128
+ "text": "HelixHeadlessStep[]"
153129
+ }
153130
+ }
153131
+ ],
153132
+ "description": "The step `active` names, by `value` or by place, or the first enabled one."
153133
+ },
152677
153134
  {
152678
153135
  "kind": "method",
152679
153136
  "name": "requestActive",
@@ -152839,6 +153296,32 @@
152839
153296
  "privacy": "private",
152840
153297
  "readonly": true
152841
153298
  },
153299
+ {
153300
+ "kind": "field",
153301
+ "name": "holder",
153302
+ "type": {
153303
+ "text": "HelixHeadlessStep | undefined"
153304
+ },
153305
+ "privacy": "private",
153306
+ "description": "The step whose name holds the sequence's one tab stop under `arrows`, once focus has chosen it."
153307
+ },
153308
+ {
153309
+ "kind": "method",
153310
+ "name": "rove",
153311
+ "privacy": "private",
153312
+ "return": {
153313
+ "type": {
153314
+ "text": "void"
153315
+ }
153316
+ },
153317
+ "description": "Gives the one tab stop to a name, under `arrows`: the one focus last left,\nelse the current stage's, else the first a reader can go to. Without\n`arrows` every name is its own stop. Client only."
153318
+ },
153319
+ {
153320
+ "kind": "field",
153321
+ "name": "handleFocus",
153322
+ "privacy": "private",
153323
+ "readonly": true
153324
+ },
152842
153325
  {
152843
153326
  "kind": "field",
152844
153327
  "name": "handleSlotChange",
@@ -153321,7 +153804,7 @@
153321
153804
  "text": "boolean"
153322
153805
  },
153323
153806
  "default": "false",
153324
- "description": "Whether the arrow keys move focus between the stages' names, along the\nway the steps run. Off by default, so the arrows keep scrolling the page.",
153807
+ "description": "Whether the arrow keys move focus between the stages' names, along the\nway the steps run, and the names are one tab stop. Off by default, so the\narrows keep scrolling the page.",
153325
153808
  "fieldName": "arrows"
153326
153809
  },
153327
153810
  {
@@ -153636,7 +154119,7 @@
153636
154119
  "text": "string"
153637
154120
  },
153638
154121
  "default": "''",
153639
- "description": "The value the step sends in `helix-select`.",
154122
+ "description": "The value the step sends in `helix-select`, and what names the step in its\nsequence's `active`. Without one, the sequence names the step by its place,\ncounted from 1.",
153640
154123
  "attribute": "value"
153641
154124
  },
153642
154125
  {
@@ -154132,7 +154615,7 @@
154132
154615
  "text": "string"
154133
154616
  },
154134
154617
  "default": "''",
154135
- "description": "The value the step sends in `helix-select`.",
154618
+ "description": "The value the step sends in `helix-select`, and what names the step in its\nsequence's `active`. Without one, the sequence names the step by its place,\ncounted from 1.",
154136
154619
  "fieldName": "value"
154137
154620
  }
154138
154621
  ],
@@ -189733,7 +190216,7 @@
189733
190216
  "declarations": [
189734
190217
  {
189735
190218
  "kind": "class",
189736
- "description": "**You slot the player**, so it keeps your appearance, extra controls,\ncaptions, and poster treatment. `Sandbox` takes its preview and `Menu` its\ntrigger the same way.\n\n**Entries are markup.** React skips properties it would set imperatively\nduring hydration, so an array property on a custom element is missing on the\nfirst paint of a server-rendered page. `using-the-elements.mdx` has the\nmeasurement. Markup also makes each entry a real button with its name inside.\n\n**The playlist does not play media.** It sets `src` on the player and tracks\nwhich entry is current. The current entry moves when:\n\n- an entry is pressed,\n- the player dispatches `helix-next` or `helix-previous`, or\n- the player reaches the end.\n\nOn `ended` the playlist advances and the next clip starts playing, because\nthe user already pressed play once. `no-advance` turns that off, and the\nplaylist stays on the entry that ended. `repeat` decides what happens at the\nend: `one` plays the same entry again, and `all` goes from the last entry\nback to the first. Without it, the playlist stops on the last entry and\nsends `helix-end`. `shuffle` plays the entries in a random order, starting\nfrom the one that is current, and `previous` retraces that order.\n\n**`helix-before-activate` says why the playlist is moving**, in\n`detail.cause`: `press` for an entry or a menu choice, `next` and\n`previous` for the player's controls and the methods, `ended` at the end of\na clip, and `removed` when the current entry leaves the playlist. Cancel an\n`ended` move to show your own \"Up next\" countdown, then call `next()`.\n\n**Removing the current entry moves the playlist on**, to the entry after it,\nor to the one before it when it was the last. A clip that was playing keeps\nplaying in the entry that takes its place.\n\n**The player is named by the current entry**, and the device's own media\ncontrols show the entry as the title. A player you gave a `label` keeps\nyour name, and only the title follows the entry.\n\n**Keyboard.** The entries take one stop in the tab order: the entry you\nlast focused, or the current entry before you have focused one. Enter or\nSpace plays it. The arrow keys move focus to the entry before or after, and\nHome and End to the first and the last, passing over disabled entries. The\ncurrent entry carries `aria-current`. While focus is on the player, the\nplayer's own keys work, and `Video` lists them, and Shift with N or P plays\nthe next or the previous entry. The player's previous and next controls\nmove through the entries in the same order the playlist does.\n\n**Moving entries.** `reorderable` lets a reader change the order of the\nqueue:\n\n- Alt with Up or Down moves the focused entry a place, and Alt with Home or\n End moves it to either end, as the APG's rearrangeable listbox does.\n Focus stays on it.\n- A pointer drags an entry, with a drop indicator, and the page scrolls near\n an edge. A press that does not travel still plays the entry.\n- A drop sends `helix-before-reorder`, which you can refuse, and then\n `helix-reorder`, whose `keys` hold every entry's `value` in the new order.\n **You move the entries**: the playlist moves no element of yours, and the\n next entry is the one after the current entry in the order you leave.\n- Each move is said in the live region, in words you can change:\n `moved-label`, `dropped-label`, `canceled-label`, and `picked-up-label`.\n\n**What a screen reader hears.** A list named by `label`, with a button for\neach entry. When the playlist moves to another entry, by a press, by the\nplayer's controls, or at the end of a clip, a live region says\n`playing-label`, \"Now playing\" and the entry's name.",
190219
+ "description": "**You slot the player**, so it keeps your appearance, extra controls,\ncaptions, and poster treatment. `Sandbox` takes its preview and `Menu` its\ntrigger the same way.\n\n**The player is a `Video` or a plain `<video>`.** Either takes `src` and\n`poster` from the entry, is named by it, plays on, and answers Shift with N\nor P while focused. A plain `<video>` has no previous and next controls\nthat send `helix-previous` or `helix-next`, so its moves are the entries,\nthe menu, and your own buttons calling `previous()` and `next()`.\n\n**Entries are markup.** React skips properties it would set imperatively\nduring hydration, so an array property on a custom element is missing on the\nfirst paint of a server-rendered page. `using-the-elements.mdx` has the\nmeasurement. Markup also makes each entry a real button with its name inside.\n\n**The playlist does not play media.** It sets `src` on the player and tracks\nwhich entry is current. The current entry moves when:\n\n- an entry is pressed,\n- the player dispatches `helix-next` or `helix-previous`, or\n- the player reaches the end.\n\nOn `ended` the playlist advances and the next clip starts playing, because\nthe user already pressed play once. `no-advance` turns that off, and the\nplaylist stays on the entry that ended. `repeat` decides what happens at the\nend: `one` plays the same entry again, and `all` goes from the last entry\nback to the first. Without it, the playlist stops on the last entry and\nsends `helix-end`. `shuffle` plays the entries in a random order, starting\nfrom the one that is current, and `previous` retraces that order.\n\n**`helix-before-activate` says why the playlist is moving**, in\n`detail.cause`: `press` for an entry or a menu choice, `next` and\n`previous` for the player's controls and the methods, `ended` at the end of\na clip, and `removed` when the current entry leaves the playlist. Cancel an\n`ended` move to show your own \"Up next\" countdown, then call `next()`.\n\n**Removing the current entry moves the playlist on**, to the entry after it,\nor to the one before it when it was the last. A clip that was playing keeps\nplaying in the entry that takes its place.\n\n**The player is named by the current entry**, and the device's own media\ncontrols show the entry as the title. A player you gave a `label` keeps\nyour name, and only the title follows the entry. A plain `<video>` is\nnamed through `aria-label`, unless you wrote one.\n\n**Keyboard.** The entries take one stop in the tab order: the entry you\nlast focused, or the current entry before you have focused one. Enter or\nSpace plays it. The arrow keys move focus to the entry before or after, and\nHome and End to the first and the last, passing over disabled entries. The\ncurrent entry carries `aria-current`. While focus is on the player, the\nplayer's own keys work, and `Video` lists them, and Shift with N or P plays\nthe next or the previous entry. The player's previous and next controls\nmove through the entries in the same order the playlist does.\n\n**Moving entries.** `reorderable` lets a reader change the order of the\nqueue:\n\n- Alt with Up or Down moves the focused entry a place, and Alt with Home or\n End moves it to either end, as the APG's rearrangeable listbox does.\n Focus stays on it.\n- A pointer drags an entry, with a drop indicator, and the page scrolls near\n an edge. A press that does not travel still plays the entry.\n- A drop sends `helix-before-reorder`, which you can refuse, and then\n `helix-reorder`, whose `keys` hold every entry's `value` in the new order.\n **You move the entries**: the playlist moves no element of yours, and the\n next entry is the one after the current entry in the order you leave.\n- Each move is said in the live region, in words you can change:\n `moved-label`, `dropped-label`, `canceled-label`, and `picked-up-label`.\n\n**What a screen reader hears.** A list named by `label`, with a button for\neach entry. When the playlist moves to another entry, by a press, by the\nplayer's controls, or at the end of a clip, a live region says\n`playing-label`, \"Now playing\" and the entry's name.",
189737
190220
  "name": "HelixHeadlessVideoPlaylist",
189738
190221
  "cssParts": [
189739
190222
  {
@@ -190022,6 +190505,40 @@
190022
190505
  "privacy": "private",
190023
190506
  "description": "The entry that holds the list's tab stop: the one a reader last focused.\nBefore they focus one, the current entry holds it."
190024
190507
  },
190508
+ {
190509
+ "kind": "field",
190510
+ "name": "wroteName",
190511
+ "type": {
190512
+ "text": "string | undefined"
190513
+ },
190514
+ "privacy": "private",
190515
+ "description": "The name this playlist last wrote on a plain media player, to tell it from yours."
190516
+ },
190517
+ {
190518
+ "kind": "method",
190519
+ "name": "name",
190520
+ "privacy": "private",
190521
+ "return": {
190522
+ "type": {
190523
+ "text": "void"
190524
+ }
190525
+ },
190526
+ "parameters": [
190527
+ {
190528
+ "name": "player",
190529
+ "type": {
190530
+ "text": "Player"
190531
+ }
190532
+ },
190533
+ {
190534
+ "name": "text",
190535
+ "type": {
190536
+ "text": "string"
190537
+ }
190538
+ }
190539
+ ],
190540
+ "description": "Names the player by the entry.\n\nThe consumer's own name for the player stands. Only a player named by\nnobody takes the entry's words as its name: `label` on a player that has\none, and `aria-label` on a plain `<video>` or `<audio>`, which has none and\nwas heard as an unnamed video."
190541
+ },
190025
190542
  {
190026
190543
  "kind": "field",
190027
190544
  "name": "pointed",
@@ -194511,7 +195028,7 @@
194511
195028
  "declarations": [
194512
195029
  {
194513
195030
  "kind": "class",
194514
- "description": "The items arrive as data, in one of two ways:\n\n- `items` takes an array. A framework sets it as a property, and React\n hydration keeps it.\n- `for` names a `<script type=\"application/json\">` that holds an array, which\n a server sends as markup.\n\nEach item is drawn into a row in one of two ways:\n\n- `renderItem` is a function from an item and its index to the row's\n content: a Lit template, a string, or a DOM node.\n- A `<template>` child defines one row. `data-field=\"name\"` fills an element\n with the item's `name` as text, and `data-field-href=\"url\"` writes the\n item's `url` into `href`, the same for any attribute. A field may be a path\n of keys, such as `author.name`.\n\nRows are your markup in the light DOM, so your stylesheet styles them.\n\n**A grid.** `columns` lays the items out that many to a line, as a grid of\nequal columns, and windows the set a line at a time, as React Aria's grid\nlayout does. Each item draws one element, a cell of the grid, and\n`estimate` is the height of a line. `min-column-width` lays out as many\ncolumns as fit the box instead, as React Aria's grid layout does with its\nsmallest item size, and follows the box as it resizes. `gap` spaces the rows, and the columns\nof a grid, by a number of pixels the list counts in each row's place.\n\n**Across.** `orientation=\"horizontal\"` lays the items out along a line and\nscrolls it sideways, as a strip of cards does, windowed the same way:\n`estimate` is then an item's width, and the box needs an inline size.\n\n**Sections.** `section-field` names the field of each item that says which\nsection it is in, and the list draws a header before each section's items,\nas React Aria's list box sections do. Each section is an element with the\n`group` role, named by its header, which is its first child and carries\n`data-header`, so your stylesheet styles it, such as with `position:\nsticky`. A section starts wherever the field changes, so give the items in\norder. The window counts the headers with the items, and a section the\nwindow starts inside is drawn with its header. `renderSection` draws a\nheader of your own.\n\n**Keyboard.** The list is one tab stop.\n\n| Key | What it does |\n|---|---|\n| 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. |\n| 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. |\n| Home, End | Moves to the first or the last item. |\n| Page Down, Page Up | Moves by the number of items, or of lines in a grid, on screen. |\n| A letter or a word | Moves to the next item whose text starts with what you typed. |\n| Escape | Lets go of every chosen item, in a list with `selection-mode`. |\n| Tab | Moves into the focused row's own links and buttons, then out of the list. |\n\nAn item that is not drawn is scrolled into view and focused, so a keyboard\nreaches the whole set. When the row holding the tab stop scrolls away, the\nstop moves to the first row on screen. Typing matches each item's\n`text-field`, which is the first `data-field` of the row template by default,\nor the item itself when it is a string or a number.\n\nEach row says its place in the whole set with `aria-posinset` and\n`aria-setsize`, so a screen reader says \"4,000 of 10,000\". The row holding\nfocus stays drawn when it scrolls out.\n\n**Selecting.** `selection-mode` makes the list a list box a reader chooses\nfrom: `single` selects one item and `multiple` any number. Space or a press\nselects an item, Shift with Space, an arrow, Home, End or a press takes in\nthe items from the last one chosen, and Control or Command with A selects\nthem all, in `multiple`. Escape lets go of every chosen item, and keeps the\nkey from the dialog or menu around the list while there was something to\nlet go of. `value` holds the chosen items' keys, separated by commas, in\nthe order of the set: `key-field` names each item's key, and a string or a\nnumber item is its own key. A change asks with `helix-before-change` and\ntells with `change`. Each row is an `option` marked `aria-selected`, so a\nrow's own links and buttons are not reached there: keep those to a list\nwithout `selection-mode`.\n\n`selection-behavior=\"replace\"` selects the item pressed alone, as a file\nlist does, and the arrow keys carry the selection with them. Control or\nCommand with a press or with Space adds or takes out one item, and with an\narrow moves without selecting.\n\n**Disabled items.** `disabled-keys` names items by their keys, separated by\ncommas. Their rows carry `aria-disabled`, the keys and typing pass over\nthem, and a press, Space, or Control with A does not select them.\n\n**Loading more.** `helix-range-change` fires as the items on screen change,\nand `range` holds them. `helix-load-more` fires once a reader is within one\nscreen of the end, once for each length of the set: add to `items` and it can\nfire again. While you fetch, set `loading`: the list is busy, and a row after\nthe last item says \"Loading more\" (`loading-label`, or your own content in\nthe `loading` slot). `scrollToIndex` takes a reader to an item.\n\n**An empty list.** Set `empty-label`, or put your own content in the `empty`\nslot, for a row shown when there are no items and none are loading, such as\n\"No messages yet\" and a link to write one. Without either, an empty list\nshows nothing, since a list whose items have not arrived yet has not said\nit has none.\n\nThe list takes the `empty` state while it has read its items and holds none,\nand the `loading` state while `loading` is set, so your stylesheet can\nchange the box around it for either. A list with no name is reported once\nin a development build. Name it with `label` or `aria-label`.\n\n**Row height.** Rows are placed by `estimate` until they are drawn. Then the\nlist reads the drawn rows' height once and places every row by it, so a\nwrong estimate still reaches the last item. Set `measured` for rows of\ndifferent heights. Once the list draws rows of different heights, such as\nrows that wrap on a narrow screen, it places each row by its own height\nwhether `measured` is set or not.\n\nThe list follows its source. A new `items` array, an edit to the script's\ntext, or a script replaced under the same id draws the new rows. A row that\nstays in view keeps its element as the list scrolls.\n\nThe viewport scrolls on this tier. It carries `data-scroller`, and `core`\nships `[data-scroller] { overflow: auto }` into every shadow root, so\n`scrollTop` works with no stylesheet. You still need to set a block size.",
195031
+ "description": "The items arrive as data, in one of two ways:\n\n- `items` takes an array. A framework sets it as a property, and React\n hydration keeps it.\n- `for` names a `<script type=\"application/json\">` that holds an array, which\n a server sends as markup.\n\nEach item is drawn into a row in one of two ways:\n\n- `renderItem` is a function from an item and its index to the row's\n content: a Lit template, a string, or a DOM node.\n- A `<template>` child defines one row. `data-field=\"name\"` fills an element\n with the item's `name` as text, and `data-field-href=\"url\"` writes the\n item's `url` into `href`, the same for any attribute. A field may be a path\n of keys, such as `author.name`.\n\nRows are your markup in the light DOM, so your stylesheet styles them.\n\n**A grid.** `columns` lays the items out that many to a line, as a grid of\nequal columns, and windows the set a line at a time, as React Aria's grid\nlayout does. Each item draws one element, a cell of the grid, and\n`estimate` is the height of a line. `min-column-width` lays out as many\ncolumns as fit the box instead, as React Aria's grid layout does with its\nsmallest item size, and follows the box as it resizes. `gap` spaces the rows, and the columns\nof a grid, by a number of pixels the list counts in each row's place.\n\n**Across.** `orientation=\"horizontal\"` lays the items out along a line and\nscrolls it sideways, as a strip of cards does, windowed the same way:\n`estimate` is then an item's width, and the box needs an inline size.\n\n**Sections.** `section-field` names the field of each item that says which\nsection it is in, and the list draws a header before each section's items,\nas React Aria's list box sections do. Each section is an element with the\n`group` role, named by its header, which is its first child and carries\n`data-header`, so your stylesheet styles it, such as with `position:\nsticky`. A section starts wherever the field changes, so give the items in\norder. The window counts the headers with the items, and a section the\nwindow starts inside is drawn with its header. `renderSection` draws a\nheader of your own.\n\n**Keyboard.** The list is one tab stop.\n\n| Key | What it does |\n|---|---|\n| 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. |\n| 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. |\n| Home, End | Moves to the first or the last item. |\n| Page Down, Page Up | Moves by the number of items, or of lines in a grid, on screen. |\n| A letter or a word | Moves to the next item whose text starts with what you typed. |\n| Escape | Lets go of every chosen item, in a list with `selection-mode`. |\n| Tab | Moves into the focused row's own links and buttons, then out of the list. |\n\nAn item that is not drawn is scrolled into view and focused, so a keyboard\nreaches the whole set. When the row holding the tab stop scrolls away, the\nstop moves to the first row on screen. Typing matches each item's\n`text-field`, which is the first `data-field` of the row template by default,\nor the item itself when it is a string or a number.\n\nEach row says its place in the whole set with `aria-posinset` and\n`aria-setsize`, so a screen reader says \"4,000 of 10,000\". The row holding\nfocus stays drawn when it scrolls out.\n\n**Selecting.** `selection-mode` makes the list a list box a reader chooses\nfrom: `single` selects one item and `multiple` any number. Space or a press\nselects an item, Shift with Space, an arrow, Home, End or a press takes in\nthe items from the last one chosen, and Control or Command with A selects\nthem all, in `multiple`. Escape lets go of every chosen item, and keeps the\nkey from the dialog or menu around the list while there was something to\nlet go of. `value` holds the chosen items' keys, separated by commas, in\nthe order of the set: `key-field` names each item's key, and a string or a\nnumber item is its own key. A change asks with `helix-before-change` and\ntells with `change`. Each row is an `option` marked `aria-selected`, so a\nrow's own links and buttons are not reached there: keep those to a list\nwithout `selection-mode`.\n\n`selection-behavior=\"replace\"` selects the item pressed alone, as a file\nlist does, and the arrow keys carry the selection with them. Control or\nCommand with a press or with Space adds or takes out one item, and with an\narrow moves without selecting.\n\n**Disabled items.** `disabled-keys` names items by their keys, separated by\ncommas. Their rows carry `aria-disabled`, the keys and typing pass over\nthem, and a press, Space, or Control with A does not select them.\n\n**Rows a stylesheet can tell apart.** A chosen row carries `data-selected`,\na disabled one `data-disabled`, as React Aria's rows do, and the row the\nkeys are on, which holds the tab stop, `data-active`, whether or not the\nlist has focus.\n\n**Loading more.** `helix-range-change` fires as the items on screen change,\nand `range` holds them. `helix-load-more` fires once a reader is within one\nscreen of the end, once for each length of the set: add to `items` and it can\nfire again. While you fetch, set `loading`: the list is busy, and a row after\nthe last item says \"Loading more\" (`loading-label`, or your own content in\nthe `loading` slot). `scrollToIndex` takes a reader to an item.\n\n**An empty list.** Set `empty-label`, or put your own content in the `empty`\nslot, for a row shown when there are no items and none are loading, such as\n\"No messages yet\" and a link to write one. Without either, an empty list\nshows nothing, since a list whose items have not arrived yet has not said\nit has none.\n\nThe list takes the `empty` state while it has read its items and holds none,\nand the `loading` state while `loading` is set, so your stylesheet can\nchange the box around it for either. A list with no name is reported once\nin a development build. Name it with `label` or `aria-label`.\n\n**Row height.** Rows are placed by `estimate` until they are drawn. Then the\nlist reads the drawn rows' height once and places every row by it, so a\nwrong estimate still reaches the last item. Set `measured` for rows of\ndifferent heights. Once the list draws rows of different heights, such as\nrows that wrap on a narrow screen, it places each row by its own height\nwhether `measured` is set or not.\n\nThe list follows its source. A new `items` array, an edit to the script's\ntext, or a script replaced under the same id draws the new rows. A row that\nstays in view keeps its element as the list scrolls.\n\nThe viewport scrolls on this tier. It carries `data-scroller`, and `core`\nships `[data-scroller] { overflow: auto }` into every shadow root, so\n`scrollTop` works with no stylesheet. You still need to set a block size.",
194515
195032
  "name": "HelixHeadlessVirtualList",
194516
195033
  "cssParts": [
194517
195034
  {
@@ -195490,7 +196007,7 @@
195490
196007
  }
195491
196008
  }
195492
196009
  ],
195493
- "description": "Writes a row's role, and whether it is chosen in a list that selects:\n`option` with `aria-selected` there, and `listitem` otherwise, and\n`aria-disabled` on an item `disabled-keys` names. Every pass,\nsince a choice changes no row's content."
196010
+ "description": "Writes a row's role, and whether it is chosen in a list that selects:\n`option` with `aria-selected` there, and `listitem` otherwise, and\n`aria-disabled` on an item `disabled-keys` names. Every pass,\nsince a choice changes no row's content.\n\n`data-selected` and `data-disabled` say the same to a stylesheet, as\nReact Aria's rows do, so one rule reads the same in either kind of list."
195494
196011
  },
195495
196012
  {
195496
196013
  "kind": "method",
@@ -196433,6 +196950,6 @@
196433
196950
  ],
196434
196951
  "helix": {
196435
196952
  "package": "@fusion.dev/helix-headless",
196436
- "version": "0.170.0"
196953
+ "version": "0.171.0"
196437
196954
  }
196438
196955
  }