@fusion.dev/helix-headless 0.171.0 → 0.173.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 (67) hide show
  1. package/custom-elements.json +1350 -124
  2. package/dist/button-group/root/button-group-root.d.ts +30 -0
  3. package/dist/button-group/root/button-group-root.js +50 -4
  4. package/dist/canvas/root/canvas-root.d.ts +7 -0
  5. package/dist/canvas/root/canvas-root.js +7 -0
  6. package/dist/chat/composer/chat-composer.d.ts +28 -1
  7. package/dist/chat/composer/chat-composer.js +22 -3
  8. package/dist/chat/root/chat-root.d.ts +38 -2
  9. package/dist/chat/root/chat-root.js +38 -1
  10. package/dist/color-input/root/color-input-root.d.ts +15 -1
  11. package/dist/color-input/root/color-input-root.js +19 -1
  12. package/dist/color-picker/root/color-picker-root.d.ts +5 -1
  13. package/dist/color-picker/root/color-picker-root.js +1 -1
  14. package/dist/copy-button/root/copy-button-root.d.ts +43 -3
  15. package/dist/copy-button/root/copy-button-root.js +49 -3
  16. package/dist/data-table/root/data-table-root.d.ts +5 -1
  17. package/dist/data-table/root/data-table-root.js +1 -0
  18. package/dist/dialog/root/dialog-root.js +1 -0
  19. package/dist/drawer/root/drawer-root.d.ts +4 -0
  20. package/dist/drawer/root/drawer-root.js +1 -0
  21. package/dist/element-events.generated.js +3 -0
  22. package/dist/graph/root/graph-root.d.ts +22 -0
  23. package/dist/graph/root/graph-root.js +21 -5
  24. package/dist/lightbox/root/lightbox-root.js +1 -0
  25. package/dist/list/root/list-root.d.ts +6 -1
  26. package/dist/list/root/list-root.js +3 -2
  27. package/dist/listbox/root/listbox-root.d.ts +2 -1
  28. package/dist/listbox/root/listbox-root.js +3 -2
  29. package/dist/menu/item/menu-item.d.ts +2 -0
  30. package/dist/menu/item/menu-item.js +2 -0
  31. package/dist/menu/root/menu-root.d.ts +73 -12
  32. package/dist/menu/root/menu-root.js +103 -7
  33. package/dist/outline/root/outline-root.d.ts +57 -0
  34. package/dist/outline/root/outline-root.js +98 -29
  35. package/dist/popover/root/popover-root.d.ts +59 -6
  36. package/dist/popover/root/popover-root.js +51 -3
  37. package/dist/select/root/select-root.d.ts +2 -2
  38. package/dist/select/root/select-root.js +2 -2
  39. package/dist/speed-dial/root/speed-dial-root.d.ts +14 -0
  40. package/dist/speed-dial/root/speed-dial-root.js +34 -2
  41. package/dist/splitter/root/splitter-root.d.ts +25 -2
  42. package/dist/splitter/root/splitter-root.js +19 -4
  43. package/dist/tag/group/tag-group.d.ts +8 -1
  44. package/dist/tag/group/tag-group.js +8 -0
  45. package/dist/tag/root/tag-root.d.ts +12 -0
  46. package/dist/tag/root/tag-root.js +12 -0
  47. package/dist/textarea/root/textarea-root.d.ts +8 -0
  48. package/dist/textarea/root/textarea-root.js +16 -0
  49. package/dist/time-picker/root/time-picker-root.d.ts +14 -0
  50. package/dist/time-picker/root/time-picker-root.js +8 -1
  51. package/dist/timeline/item/timeline-item.d.ts +5 -1
  52. package/dist/timeline/item/timeline-item.js +9 -0
  53. package/dist/timeline/root/timeline-root.d.ts +23 -0
  54. package/dist/timeline/root/timeline-root.js +17 -3
  55. package/dist/tooltip/root/tooltip-root.d.ts +10 -0
  56. package/dist/tooltip/root/tooltip-root.js +14 -2
  57. package/dist/virtual-list/reorder/index.d.ts +1 -0
  58. package/dist/virtual-list/reorder/index.js +4 -0
  59. package/dist/virtual-list/reorder/virtual-list-reorder.d.ts +86 -0
  60. package/dist/virtual-list/reorder/virtual-list-reorder.js +193 -0
  61. package/dist/virtual-list/root/virtual-list-root.d.ts +49 -11
  62. package/dist/virtual-list/root/virtual-list-root.js +10 -1
  63. package/lint.json +1 -1
  64. package/package.json +5 -5
  65. package/types/jsx.d.ts +880 -48
  66. package/types/vue.d.ts +174 -19
  67. package/types/words.d.ts +22 -0
@@ -10544,7 +10544,7 @@
10544
10544
  "declarations": [
10545
10545
  {
10546
10546
  "kind": "class",
10547
- "description": "Sets `role=\"group\"` on the host through internals, and `label` names the\ngroup. Without a name, a screen reader announces the buttons as separate\ncontrols, and a development build warns once with the kind `missing-name`.\n\nThe group does not manage focus, so each button keeps its own tab stop. For\none tab stop with arrow keys between a mix of controls, the APG toolbar\npattern, use Toolbar.\n\nButtons are slotted, so they stay your own elements and keep their own\nappearance and size.\n\n**Buttons that stay pressed.** With `selection-mode`, each button with a\n`value` is a toggle button: a press presses or releases it. `multiple` lets\nany number be pressed, and each button says so with `aria-pressed`. `single`\nkeeps one pressed at a time: the group is a `radiogroup` and each button a\n`radio` that says so with `aria-checked`, as React Aria's toggle button\ngroup is. A press on the pressed one releases it, unless\n`disallow-empty-selection` keeps one pressed. `value` is the pressed values,\ncomma separated. A press sends a cancelable `helix-before-change` with the\nvalue it would leave, then `change`. A pressed Helix button has\n`:state(pressed)` on its own element.\n\nThe pressed state is written on the control inside each button's shadow\nroot, so the markup you rendered is never changed and a framework hydrating\nit sees what its server sent. That is also why only Helix buttons are\ntoggles: a native `<button>` or a button without a `value` stays a plain\naction button in the group, and a native one without its own\n`aria-pressed` warns once, with the runtime kind `untold-toggle`. The inner\ncontrol also carries\n`--button-group-pressed`, `1` or `0`, for a `::part(button)` rule of yours.\n\nUse Toggle Group instead for a choice that belongs in a form, or one where\nthe arrow keys choose as they move: it is a `radiogroup` of options with a\nform value, `required` and validation. A Button Group in a selection mode is\na set of actions that stay on, such as bold and italic, or a view that a\npress switches, and it submits nothing.\n\n**Keyboard.** In a selection mode the group is one tab stop: the button\nfocus was last on, then the first pressed one, then the first one.\n\n| Key | What it does |\n|---|---|\n| Right, Down | Moves to the next button, from the last back to the first. |\n| Left, Up | Moves to the button before, from the first round to the last. |\n| Home, End | Moves to the first or the last button. |\n| Space, Enter | Presses or releases the focused button. |\n\nLeft and Right swap on a right-to-left page, and a disabled button is\npassed over. Under `multiple` the group is a `toolbar`, with\n`aria-orientation` under `orientation=\"vertical\"`. Inside a toolbar it stays\na named `group`, and the toolbar's own arrow keys walk its buttons, so a\nreader meets one toolbar. Under `single` it is a `radiogroup` either way.",
10547
+ "description": "Sets `role=\"group\"` on the host through internals, and `label` names the\ngroup. Without a name, a screen reader announces the buttons as separate\ncontrols, and a development build warns once with the kind `missing-name`.\n\nThe group does not manage focus, so each button keeps its own tab stop. For\none tab stop with arrow keys between a mix of controls, the APG toolbar\npattern, use Toolbar.\n\nButtons are slotted, so they stay your own elements and keep their own\nappearance and size.\n\n**Buttons that stay pressed.** With `selection-mode`, each button with a\n`value` is a toggle button: a press presses or releases it. `multiple` lets\nany number be pressed, and each button says so with `aria-pressed`. `single`\nkeeps one pressed at a time: the group is a `radiogroup` and each button a\n`radio` that says so with `aria-checked`, as React Aria's toggle button\ngroup is. A press on the pressed one releases it, unless\n`disallow-empty-selection` keeps one pressed. `value` is the pressed values,\ncomma separated. A press sends a cancelable `helix-before-change` with the\nvalue it would leave, then `change`. A pressed Helix button has\n`:state(pressed)` on its own element.\n\nThe pressed state is written on the control inside each button's shadow\nroot, so the markup you rendered is never changed and a framework hydrating\nit sees what its server sent. That is also why only Helix buttons are\ntoggles: a native `<button>` or a button without a `value` stays a plain\naction button in the group, and a native one without its own\n`aria-pressed` warns once, with the runtime kind `untold-toggle`. The inner\ncontrol also carries\n`--button-group-pressed`, `1` or `0`, for a `::part(button)` rule of yours.\n\nUse Toggle Group instead for a choice that belongs in a form, or one where\nthe arrow keys choose as they move: it is a `radiogroup` of options with a\nform value, `required` and validation. A Button Group in a selection mode is\na set of actions that stay on, such as bold and italic, or a view that a\npress switches, and it submits nothing.\n\n**Keyboard.** In a selection mode the group is one tab stop: the button\nfocus was last on, then the first pressed one, then the first one.\n\n| Key | What it does |\n|---|---|\n| Right, Down | Moves to the next button, from the last back to the first. |\n| Left, Up | Moves to the button before, from the first round to the last. |\n| Home, End | Moves to the first or the last button. |\n| Space, Enter | Presses or releases the focused button. |\n\nLeft and Right swap on a right-to-left page, and a disabled button is\npassed over. Under `multiple` the group is a `toolbar`, with\n`aria-orientation` under `orientation=\"vertical\"`. Inside a toolbar it stays\na named `group`, and the toolbar's own arrow keys walk its buttons, so a\nreader meets one toolbar. Under `single` it is a `radiogroup` either way.\n\n**Disabled.** `disabled` on the group disables every button in it, Helix\nand native alike, and says so on the group with `aria-disabled`, as React\nAria's `isDisabled` does. A button disabled on its own stays disabled when\nthe group is enabled again, and a button that leaves the group gets back\nwhat it said for itself.",
10548
10548
  "name": "HelixHeadlessButtonGroup",
10549
10549
  "cssProperties": [
10550
10550
  {
@@ -10559,6 +10559,17 @@
10559
10559
  }
10560
10560
  ],
10561
10561
  "members": [
10562
+ {
10563
+ "kind": "field",
10564
+ "name": "disabled",
10565
+ "type": {
10566
+ "text": "boolean"
10567
+ },
10568
+ "default": "false",
10569
+ "description": "Disables every button in the group, and says so on the group with\n`aria-disabled`. Reflected, so a stylesheet can select on it.",
10570
+ "attribute": "disabled",
10571
+ "reflects": true
10572
+ },
10562
10573
  {
10563
10574
  "kind": "field",
10564
10575
  "name": "disallowEmptySelection",
@@ -10609,6 +10620,14 @@
10609
10620
  "description": "The values of the pressed buttons, comma separated, in a selection mode.\nA button's own `value` names it, so a value holds no comma.\n\nThe attribute is the seed, and a press changes the property, which does\nnot reflect, as a native control's `value` does not.",
10610
10621
  "attribute": "value"
10611
10622
  },
10623
+ {
10624
+ "kind": "field",
10625
+ "name": "values",
10626
+ "type": {
10627
+ "text": "string[]"
10628
+ },
10629
+ "description": "The pressed values as a list, in a selection mode, and an empty list\notherwise. Written, it presses exactly those buttons."
10630
+ },
10612
10631
  {
10613
10632
  "kind": "field",
10614
10633
  "name": "buttons",
@@ -10674,6 +10693,35 @@
10674
10693
  },
10675
10694
  "privacy": "private"
10676
10695
  },
10696
+ {
10697
+ "kind": "field",
10698
+ "name": "members",
10699
+ "type": {
10700
+ "text": "DisableableItem[]"
10701
+ },
10702
+ "privacy": "private",
10703
+ "description": "The children that can be disabled: Helix buttons and native ones alike. Empty on a server.",
10704
+ "readonly": true
10705
+ },
10706
+ {
10707
+ "kind": "field",
10708
+ "name": "held",
10709
+ "privacy": "private",
10710
+ "readonly": true,
10711
+ "default": "new Set<DisableableItem>()",
10712
+ "description": "The members this group has disabled, so one that leaves is given back its own answer."
10713
+ },
10714
+ {
10715
+ "kind": "method",
10716
+ "name": "cascade",
10717
+ "privacy": "private",
10718
+ "return": {
10719
+ "type": {
10720
+ "text": "void"
10721
+ }
10722
+ },
10723
+ "description": "Passes `disabled` down to the members, and gives a member that left\nwhat it said for itself.\n\nA member already disabled is not written to again: the watcher hears\nevery write to a native button's `disabled`, changed or not, and would\nanswer it with this."
10724
+ },
10677
10725
  {
10678
10726
  "kind": "method",
10679
10727
  "name": "sync",
@@ -11140,6 +11188,15 @@
11140
11188
  }
11141
11189
  ],
11142
11190
  "attributes": [
11191
+ {
11192
+ "name": "disabled",
11193
+ "type": {
11194
+ "text": "boolean"
11195
+ },
11196
+ "default": "false",
11197
+ "description": "Disables every button in the group, and says so on the group with\n`aria-disabled`. Reflected, so a stylesheet can select on it.",
11198
+ "fieldName": "disabled"
11199
+ },
11143
11200
  {
11144
11201
  "name": "disallow-empty-selection",
11145
11202
  "type": {
@@ -16090,6 +16147,10 @@
16090
16147
  "description": "Content above the board.",
16091
16148
  "name": "header"
16092
16149
  },
16150
+ {
16151
+ "description": "Content shown while `loading` is set, such as a progress bar while the document arrives.",
16152
+ "name": "loading"
16153
+ },
16093
16154
  {
16094
16155
  "description": "Replaces the glyph inside the pan down button.",
16095
16156
  "name": "pan-down-icon"
@@ -16331,6 +16392,17 @@
16331
16392
  "words": true
16332
16393
  }
16333
16394
  },
16395
+ {
16396
+ "kind": "field",
16397
+ "name": "loading",
16398
+ "type": {
16399
+ "text": "boolean"
16400
+ },
16401
+ "default": "false",
16402
+ "description": "Marks the board as busy while its document arrives: the board is\n`aria-busy`, and the `loading` slot is shown.",
16403
+ "attribute": "loading",
16404
+ "reflects": true
16405
+ },
16334
16406
  {
16335
16407
  "kind": "field",
16336
16408
  "name": "movedLabel",
@@ -20184,6 +20256,15 @@
20184
20256
  "description": "The text read with a card that has connections both ways. `{leadsTo}` is\n`leads-to-label` and `{comesFrom}` is `comes-from-label`, each filled in.",
20185
20257
  "fieldName": "linkedLabel"
20186
20258
  },
20259
+ {
20260
+ "name": "loading",
20261
+ "type": {
20262
+ "text": "boolean"
20263
+ },
20264
+ "default": "false",
20265
+ "description": "Marks the board as busy while its document arrives: the board is\n`aria-busy`, and the `loading` slot is shown.",
20266
+ "fieldName": "loading"
20267
+ },
20187
20268
  {
20188
20269
  "name": "moved-label",
20189
20270
  "type": {
@@ -20549,6 +20630,10 @@
20549
20630
  "description": "The user has been still for `idle-delay` milliseconds. The board's own controls stay; select on it to hide chrome of your own.",
20550
20631
  "name": "idle"
20551
20632
  },
20633
+ {
20634
+ "description": "While `loading` is set.",
20635
+ "name": "loading"
20636
+ },
20552
20637
  {
20553
20638
  "description": "While a press on the board, its cards or its connections is under way.",
20554
20639
  "name": "pressing"
@@ -23184,7 +23269,7 @@
23184
23269
  "declarations": [
23185
23270
  {
23186
23271
  "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.\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.",
23272
+ "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**`feedback` is a message of your own about the draft**, such as one your\nserver sent back. While it is set, the composer is invalid at once, does\nnot send or submit, shows the message under the field, and a screen reader\nhears it as it appears. Clear it to let the draft go.\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
23273
  "name": "HelixHeadlessChatComposer",
23189
23274
  "cssParts": [
23190
23275
  {
@@ -23195,6 +23280,10 @@
23195
23280
  "description": "The box around the `end` slot.",
23196
23281
  "name": "end"
23197
23282
  },
23283
+ {
23284
+ "description": "The `feedback` message, under the field while it is set.",
23285
+ "name": "feedback"
23286
+ },
23198
23287
  {
23199
23288
  "description": "The text field.",
23200
23289
  "name": "field"
@@ -23237,6 +23326,16 @@
23237
23326
  "default": "'helix-chat-composer'",
23238
23327
  "description": "The key this part's words are registered under, its styled tag:\n`registerWords('de', { 'helix-chat-composer': { sendLabel: 'Senden' } })`."
23239
23328
  },
23329
+ {
23330
+ "kind": "field",
23331
+ "name": "feedback",
23332
+ "type": {
23333
+ "text": "string"
23334
+ },
23335
+ "default": "''",
23336
+ "description": "A message about the draft, shown under the field. While set, the composer\nis invalid, does not send, and does not submit, as a field's `feedback`\ndoes, and the message is announced as it appears.",
23337
+ "attribute": "feedback"
23338
+ },
23240
23339
  {
23241
23340
  "kind": "field",
23242
23341
  "name": "label",
@@ -23361,6 +23460,16 @@
23361
23460
  "default": "false",
23362
23461
  "description": "Whether the reader has tried to send or submit the draft, or edited it and left."
23363
23462
  },
23463
+ {
23464
+ "kind": "field",
23465
+ "name": "edited",
23466
+ "type": {
23467
+ "text": "boolean"
23468
+ },
23469
+ "privacy": "private",
23470
+ "default": "false",
23471
+ "description": "Whether the reader has typed in the field since it last held a fresh\ndraft: since it rendered, since a send cleared it, or since a reset.\n\n**A send clears the field, and the field still sends `change` as it is\nleft**, because the platform compares the text with what it held when it\nwas focused. Measured in Chromium before this: a required composer sent\n\"hi\", cleared, and on Tab showed itself invalid over an empty draft\nnobody had written."
23472
+ },
23364
23473
  {
23365
23474
  "kind": "field",
23366
23475
  "name": "shownInvalid",
@@ -23454,6 +23563,13 @@
23454
23563
  "readonly": true,
23455
23564
  "description": "The reader has had a go at the draft, so whether it is wrong can be shown."
23456
23565
  },
23566
+ {
23567
+ "kind": "field",
23568
+ "name": "handleChange",
23569
+ "privacy": "private",
23570
+ "readonly": true,
23571
+ "description": "The field's `change`, which counts only after the reader typed in it."
23572
+ },
23457
23573
  {
23458
23574
  "kind": "method",
23459
23575
  "name": "formStateRestoreCallback",
@@ -24374,6 +24490,15 @@
24374
24490
  }
24375
24491
  ],
24376
24492
  "attributes": [
24493
+ {
24494
+ "name": "feedback",
24495
+ "type": {
24496
+ "text": "string"
24497
+ },
24498
+ "default": "''",
24499
+ "description": "A message about the draft, shown under the field. While set, the composer\nis invalid, does not send, and does not submit, as a field's `feedback`\ndoes, and the message is announced as it appears.",
24500
+ "fieldName": "feedback"
24501
+ },
24377
24502
  {
24378
24503
  "name": "label",
24379
24504
  "type": {
@@ -24491,7 +24616,7 @@
24491
24616
  ],
24492
24617
  "cssStates": [
24493
24618
  {
24494
- "description": "The draft fails `required`, `minlength`, `maxlength`, or a custom error, and the reader has tried to send or submit it, or edited the field and left it.",
24619
+ "description": "The draft fails `required`, `minlength`, `maxlength`, or a custom error, and the reader has tried to send or submit it, or edited the field and left it. Or `feedback` is set.",
24495
24620
  "name": "invalid"
24496
24621
  },
24497
24622
  {
@@ -25471,7 +25596,7 @@
25471
25596
  "declarations": [
25472
25597
  {
25473
25598
  "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: 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\"]`.",
25599
+ "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 transcript is a `log`, the role for content added in order where the\nnewest matters most, and it answers the APG feed's keys. The `feed` role\nreads its articles as a list from the top, with no newest end to stay\npinned to, so the log keeps the role a conversation has. While `loading` is\nset or older turns load, the log carries `aria-busy`, as the APG asks of a\nfeed.\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\nThe log scrolls on this tier. It carries `data-scroller`, and `core` ships\n`[data-scroller] { overflow: auto }` into every shadow root, so pinning,\nhistory and the window work with no stylesheet. You still need to give the\nlog a block size, such as `helix-headless-chat::part(log) { block-size:\n20rem }`.\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. When the turn\nholding focus is removed, focus moves to the turn that took its place, or to\nthe one before it where it was the last.\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
25600
  "name": "HelixHeadlessChat",
25476
25601
  "cssParts": [
25477
25602
  {
@@ -25515,7 +25640,7 @@
25515
25640
  "name": "loading"
25516
25641
  },
25517
25642
  {
25518
- "description": "The transcript, which scrolls.",
25643
+ "description": "The transcript, which scrolls. On this tier, it needs only a block size.",
25519
25644
  "name": "log"
25520
25645
  },
25521
25646
  {
@@ -26406,6 +26531,40 @@
26406
26531
  ],
26407
26532
  "description": "Keeps the window on the same turns when the set changes around them.\n\nTurns added before the first one are history, and the controller is told\nhow many so every measurement moves with its turn. A first turn that is gone\nmeans the set was trimmed or replaced, and a measurement that now names a\ndifferent turn is worse than the estimate."
26408
26533
  },
26534
+ {
26535
+ "kind": "field",
26536
+ "name": "held",
26537
+ "type": {
26538
+ "text": "{ at: number; id: unknown } | undefined"
26539
+ },
26540
+ "privacy": "private",
26541
+ "description": "The turn focus is in, by its place and its identity, once a reader is in one."
26542
+ },
26543
+ {
26544
+ "kind": "field",
26545
+ "name": "handleFocusIn",
26546
+ "privacy": "private",
26547
+ "readonly": true,
26548
+ "description": "Notes the turn focus went into, or that it went somewhere else."
26549
+ },
26550
+ {
26551
+ "kind": "field",
26552
+ "name": "handleFocusOut",
26553
+ "privacy": "private",
26554
+ "readonly": true,
26555
+ "description": "Forgets the turn once focus moves to something outside the transcript.\nA move to nothing is kept, since removing the turn that held focus is\none."
26556
+ },
26557
+ {
26558
+ "kind": "method",
26559
+ "name": "followRemoved",
26560
+ "privacy": "private",
26561
+ "return": {
26562
+ "type": {
26563
+ "text": "void"
26564
+ }
26565
+ },
26566
+ "description": "Moves focus to a neighbor where removing the turn that held it dropped\nfocus to the body: the turn that took its place, or the one before it\nwhere it was the last.\n\n**Focus went to the body**, and Page Down did nothing until the reader\ntabbed back into the transcript. List and Virtual List move focus to a\nneighbor the same way, as React Aria's GridList does. Focus anywhere but\nthe body is where you put it, and is left there."
26567
+ },
26409
26568
  {
26410
26569
  "kind": "method",
26411
26570
  "name": "tellTurns",
@@ -33745,7 +33904,7 @@
33745
33904
  "declarations": [
33746
33905
  {
33747
33906
  "kind": "class",
33748
- "description": "A text field with a button that opens `ColorPicker` in an overlay.\n`ColorPicker` provides the square, the ramps, the eyedropper, and the syntax\ntoggle, and you can also use it on its own, flat on the page. Color Input\nadds the field, the overlay, and the form value, the same arrangement Date\nInput has with `DatePicker`.\n\nYou can type or paste a color into the field without opening the picker.\nColor Input is a custom control, unlike `<input type=\"color\">`, so you can\nstyle the panel to match your interface.\n\nThe field reads every color syntax, including `#f00`, `#ff0000`,\n`rgb(255 0 0)`, `rgba(255,0,0,.5)`, `rgb(255 0 0 / 50%)`,\n`hsl(0 100% 50%)`, `oklch(62.8% 0.258 29.2)`, and `hsb(0, 100%, 100%)`. It\nwrites colors in the syntax that `format` names. The\nfield shows the value without reformatting it, because half-typed input does\nnot survive a round trip through a formatter. Date Input does the same with\ndates.\n\nTyping sends `input` on each keystroke and `change` when you leave the\nfield, as a text field does, so the message about a color it cannot read\nwaits until you are done. Dragging in the panel sends `input` as the color\nmoves and `change` when it settles.\n\nThe trigger and ArrowDown open the panel with focus in the square. Tab moves\nbetween the panel's controls without leaving it, and Escape closes it and\nreturns focus to the field.\n\nThe component sets `--color-input-swatch`, so do not set it yourself. It\nholds the resolved color, so the styled tier can paint the swatch without\nparsing the value.",
33907
+ "description": "A text field with a button that opens `ColorPicker` in an overlay.\n`ColorPicker` provides the square, the ramps, the eyedropper, and the syntax\ntoggle, and you can also use it on its own, flat on the page. Color Input\nadds the field, the overlay, and the form value, the same arrangement Date\nInput has with `DatePicker`.\n\nYou can type or paste a color into the field without opening the picker.\nColor Input is a custom control, unlike `<input type=\"color\">`, so you can\nstyle the panel to match your interface.\n\nThe field reads every color syntax, including `#f00`, `#ff0000`,\n`rgb(255 0 0)`, `rgba(255,0,0,.5)`, `rgb(255 0 0 / 50%)`,\n`hsl(0 100% 50%)`, `oklch(62.8% 0.258 29.2)`, and `hsb(0, 100%, 100%)`. It\nwrites colors in the syntax that `format` names. The\nfield shows the value without reformatting it, because half-typed input does\nnot survive a round trip through a formatter. Date Input does the same with\ndates.\n\nTyping sends `input` on each keystroke and `change` when you leave the\nfield, as a text field does, so the message about a color it cannot read\nwaits until you are done. Dragging in the panel sends `input` as the color\nmoves and `change` when it settles.\n\nThe trigger and ArrowDown open the panel with focus in the square. Tab moves\nbetween the panel's controls without leaving it, and Escape closes it and\nreturns focus to the control that opened it: the trigger after a press, and\nthe field after ArrowDown.\n\nThe component sets `--color-input-swatch`, so do not set it yourself. It\nholds the resolved color, so the styled tier can paint the swatch without\nparsing the value.",
33749
33908
  "name": "HelixHeadlessColorInput",
33750
33909
  "cssProperties": [
33751
33910
  {
@@ -34345,6 +34504,38 @@
34345
34504
  "module": "src/mixins/mixin-picker-field/mixin-picker-field.ts"
34346
34505
  }
34347
34506
  },
34507
+ {
34508
+ "kind": "field",
34509
+ "name": "pressedOpen",
34510
+ "type": {
34511
+ "text": "boolean"
34512
+ },
34513
+ "privacy": "private",
34514
+ "default": "false",
34515
+ "description": "Whether the trigger's press opened the panel that is open now."
34516
+ },
34517
+ {
34518
+ "kind": "field",
34519
+ "name": "handlePress",
34520
+ "privacy": "private",
34521
+ "readonly": true,
34522
+ "description": "The trigger's press, which notes that it opened the panel, so Escape hands\nfocus back to the trigger."
34523
+ },
34524
+ {
34525
+ "kind": "method",
34526
+ "name": "returnFocus",
34527
+ "privacy": "protected",
34528
+ "return": {
34529
+ "type": {
34530
+ "text": "void"
34531
+ }
34532
+ },
34533
+ "description": "Hands focus back to the control that opened the panel: the trigger after\nits press, which is the APG date picker dialog's rule, and the text after\nArrowDown from it.",
34534
+ "inheritedFrom": {
34535
+ "name": "MixinPickerField",
34536
+ "module": "src/mixins/mixin-picker-field/mixin-picker-field.ts"
34537
+ }
34538
+ },
34348
34539
  {
34349
34540
  "kind": "method",
34350
34541
  "name": "renderPicker",
@@ -34593,21 +34784,6 @@
34593
34784
  "module": "src/mixins/mixin-picker-field/mixin-picker-field.ts"
34594
34785
  }
34595
34786
  },
34596
- {
34597
- "kind": "method",
34598
- "name": "returnFocus",
34599
- "privacy": "protected",
34600
- "return": {
34601
- "type": {
34602
- "text": "void"
34603
- }
34604
- },
34605
- "description": "Puts the caret back in the field without the field reopening the panel.\n\nThe anchor rather than the text, which is the trigger where there is no\ntext: Color Input's swatch dropped focus to the body on Escape.",
34606
- "inheritedFrom": {
34607
- "name": "MixinPickerField",
34608
- "module": "src/mixins/mixin-picker-field/mixin-picker-field.ts"
34609
- }
34610
- },
34611
34787
  {
34612
34788
  "kind": "method",
34613
34789
  "name": "focus",
@@ -37323,7 +37499,7 @@
37323
37499
  "text": "TemplateResult | typeof nothing"
37324
37500
  }
37325
37501
  },
37326
- "description": "The line `said` holds, or nothing while it is empty.",
37502
+ "description": "The line `said` holds, or nothing while it is empty. `role=\"alert\"`, as\nevery field's feedback line has, so the message is announced when it\nappears.",
37327
37503
  "inheritedFrom": {
37328
37504
  "name": "MixinPickerFeedback",
37329
37505
  "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
@@ -44146,7 +44322,7 @@
44146
44322
  "declarations": [
44147
44323
  {
44148
44324
  "kind": "class",
44149
- "description": "Copies text to the clipboard and confirms the copy. The platform gives no\nfeedback for a clipboard write, so without a confirmation a press that copies\nlooks the same as one that fails.\n\nThe confirmation and the event wait for the write to finish. The browser can\nrefuse a clipboard write, for example on an insecure origin, in a document\nthat is not focused, or after a gesture that does not qualify. A refused\nwrite, or nothing to copy, names the button with `error-label` for the same\nmoment a copy shows `copied-label`, draws a cross, and sends\n`helix-copy-error`.\n\n`from` copies from another element on the page: its text, an attribute\nwritten `id[attribute]`, or a property written `id.property`, read at the\npress. It takes the place of `value`.\n\nIt replaces Button's render and its press, so it never submits a form or\nsends a command: `type`, `command`, `commandfor` and the `form*` overrides\nhave no effect, and the `start` and `end` slots and the `text` part are not\nrendered. An `aria-label` on the element names it before a copy, in place of\n`label`.\n\n**Keyboard.** Enter and Space copy, as they press a native button.\n\nThe button is named `label`, or the host's `aria-label`, and its name\nchanges to `copied-label` or `error-label` for the moment after a press. The\nsame words are said in a live region, so a screen reader hears the result,\nand the tooltip shows them.",
44325
+ "description": "Copies text to the clipboard and confirms the copy. The platform gives no\nfeedback for a clipboard write, so without a confirmation a press that copies\nlooks the same as one that fails.\n\nThe confirmation and the event wait for the write to finish. The browser can\nrefuse a clipboard write, for example on an insecure origin, in a document\nthat is not focused, or after a gesture that does not qualify. A refused\nwrite, or nothing to copy, names the button with `error-label` for the same\nmoment a copy shows `copied-label`, draws a cross, and sends\n`helix-copy-error`.\n\n`from` copies from another element on the page: its text, an attribute\nwritten `id[attribute]`, or a property written `id.property`, read at the\npress. It takes the place of `value`.\n\nIt replaces Button's render and its press, so it never submits a form or\nsends a command: `type`, `command`, `commandfor` and the `form*` overrides\nhave no effect, and the `start` and `end` slots and the `text` part are not\nrendered. An `aria-label` on the element names it before a copy, in place of\n`label`.\n\n**Keyboard.** Enter and Space copy, as they press a native button.\n\nThe button is named `label`, or the host's `aria-label`, and its name\nchanges to `copied-label` or `error-label` for the moment after a press. The\nsame words are said in a live region, so a screen reader hears the result,\nand the tooltip shows them. The tooltip does not also describe the button,\nsince its words are the button's name.\n\n**The tooltip.** It shows the name on hover and focus and the result after a\npress. `tooltip=\"copy\"` shows it only for the result, and `tooltip=\"none\"`\ndraws none, as Web Awesome's copy button offers. `tooltip-placement` is the\nside it prefers, and it moves to another side where that one does not fit.\n\n**Words on the button.** `show-label` draws the name beside the icon, and\nthe result in its place after a press. The button is as wide as the longest\nof the three, so a press does not resize it.",
44150
44326
  "name": "HelixHeadlessCopyButton",
44151
44327
  "cssParts": [
44152
44328
  {
@@ -44177,6 +44353,14 @@
44177
44353
  "module": "src/button/root/button-root.ts"
44178
44354
  }
44179
44355
  },
44356
+ {
44357
+ "description": "The words beside the icon, under `show-label`. It holds all three, `label`, `copied-label` and `error-label`, with all but the current one hidden.",
44358
+ "name": "text",
44359
+ "inheritedFrom": {
44360
+ "name": "HelixHeadlessButton",
44361
+ "module": "src/button/root/button-root.ts"
44362
+ }
44363
+ },
44180
44364
  {
44181
44365
  "description": "The tooltip bubble, forwarded from the tooltip inside the button.",
44182
44366
  "name": "tooltip"
@@ -44314,6 +44498,36 @@
44314
44498
  "module": "src/button/root/button-root.ts"
44315
44499
  }
44316
44500
  },
44501
+ {
44502
+ "kind": "field",
44503
+ "name": "showLabel",
44504
+ "type": {
44505
+ "text": "boolean"
44506
+ },
44507
+ "default": "false",
44508
+ "description": "Draws the name as words beside the icon, and the result in their place\nafter a press. The button stays as wide as the longest of them.",
44509
+ "attribute": "show-label",
44510
+ "reflects": true
44511
+ },
44512
+ {
44513
+ "kind": "field",
44514
+ "name": "tooltip",
44515
+ "type": {
44516
+ "text": "'copy' | 'full' | 'none' | undefined"
44517
+ },
44518
+ "description": "When the tooltip shows: `full` on hover and focus and after a press,\n`copy` only after a press, to show the result, and `none` never, for a\nbutton whose result shows another way, such as under `show-label`.\n\nUnset is `full`, and the attribute stays absent until you write it.",
44519
+ "attribute": "tooltip"
44520
+ },
44521
+ {
44522
+ "kind": "field",
44523
+ "name": "tooltipPlacement",
44524
+ "type": {
44525
+ "text": "'bottom' | 'bottom-end' | 'bottom-start' | 'left' | 'left-end' | 'left-start' | 'right' | 'right-end' | 'right-start' | 'top' | 'top-end' | 'top-start'"
44526
+ },
44527
+ "default": "'top'",
44528
+ "description": "The side the tooltip prefers. It moves to another side where this one\ndoes not fit.",
44529
+ "attribute": "tooltip-placement"
44530
+ },
44317
44531
  {
44318
44532
  "kind": "field",
44319
44533
  "name": "value",
@@ -44338,6 +44552,16 @@
44338
44552
  "description": "The words for the state it is in, used twice on purpose.\n\nThe tooltip is the visible confirmation and the accessible name is the\nspoken one, and they have to be the same words. A tooltip that changes to\nCopied while the accessible name stays Copy tells a sighted reader it\nworked and leaves a screen reader user pressing a button that never\nacknowledges anything. Changing the name of the focused element is what\nmakes the announcement happen at all.",
44339
44553
  "readonly": true
44340
44554
  },
44555
+ {
44556
+ "kind": "field",
44557
+ "name": "showedResult",
44558
+ "type": {
44559
+ "text": "boolean"
44560
+ },
44561
+ "privacy": "private",
44562
+ "default": "false",
44563
+ "description": "Whether the last render showed a result, so `tooltip=\"copy\"` opens and closes on the change."
44564
+ },
44341
44565
  {
44342
44566
  "kind": "field",
44343
44567
  "name": "clipboard",
@@ -44433,6 +44657,17 @@
44433
44657
  },
44434
44658
  "description": "The mark for a press that put nothing on the clipboard, behind a seam of its own."
44435
44659
  },
44660
+ {
44661
+ "kind": "method",
44662
+ "name": "renderText",
44663
+ "privacy": "protected",
44664
+ "return": {
44665
+ "type": {
44666
+ "text": "TemplateResult | typeof nothing"
44667
+ }
44668
+ },
44669
+ "description": "The words beside the icon, under `show-label`, behind a seam of its own.\n\nAll three are drawn and only the current one shows, so the button is as\nwide as the longest of them and a press does not resize it. Hidden from a\nscreen reader, which hears the same words as the button's name."
44670
+ },
44436
44671
  {
44437
44672
  "kind": "method",
44438
44673
  "name": "renderTooltip",
@@ -45682,6 +45917,32 @@
45682
45917
  "module": "src/button/root/button-root.ts"
45683
45918
  }
45684
45919
  },
45920
+ {
45921
+ "name": "show-label",
45922
+ "type": {
45923
+ "text": "boolean"
45924
+ },
45925
+ "default": "false",
45926
+ "description": "Draws the name as words beside the icon, and the result in their place\nafter a press. The button stays as wide as the longest of them.",
45927
+ "fieldName": "showLabel"
45928
+ },
45929
+ {
45930
+ "name": "tooltip",
45931
+ "type": {
45932
+ "text": "'copy' | 'full' | 'none' | undefined"
45933
+ },
45934
+ "description": "When the tooltip shows: `full` on hover and focus and after a press,\n`copy` only after a press, to show the result, and `none` never, for a\nbutton whose result shows another way, such as under `show-label`.\n\nUnset is `full`, and the attribute stays absent until you write it.",
45935
+ "fieldName": "tooltip"
45936
+ },
45937
+ {
45938
+ "name": "tooltip-placement",
45939
+ "type": {
45940
+ "text": "'bottom' | 'bottom-end' | 'bottom-start' | 'left' | 'left-end' | 'left-start' | 'right' | 'right-end' | 'right-start' | 'top' | 'top-end' | 'top-start'"
45941
+ },
45942
+ "default": "'top'",
45943
+ "description": "The side the tooltip prefers. It moves to another side where this one\ndoes not fit.",
45944
+ "fieldName": "tooltipPlacement"
45945
+ },
45685
45946
  {
45686
45947
  "name": "value",
45687
45948
  "type": {
@@ -46213,7 +46474,7 @@
46213
46474
  "name": "select-selected"
46214
46475
  },
46215
46476
  {
46216
- "description": "The grid.",
46477
+ "description": "The grid. While `windowed`, the box that scrolls, which needs only a block size on this tier.",
46217
46478
  "name": "table"
46218
46479
  },
46219
46480
  {
@@ -46855,7 +47116,7 @@
46855
47116
  "text": "boolean"
46856
47117
  },
46857
47118
  "default": "false",
46858
- "description": "Draws only the rows in view, with empty space in place of the rest.\n\n**Not a `mode`.** `mode` says where the rows come from and who filtered\nthem; this says how many of the ones we hold get drawn. They are\nindependent: a consumer fetching five thousand rows a chunk at a time wants\n`mode=\"server\"` and this at once, and folding this into `mode` would be an\nAPI that forbids that combination for no reason.\n\n**Composes with `paginated` rather than excluding it.** A window over a\npage is coherent -- the page is the slice of the result, the window is the\npart of that slice on screen -- and the arithmetic is the same either way,\nso there is nothing to forbid. Together they suit a table paging at a\nthousand rows, where the page is a reasonable fetch and a poor render.\n\nOff by default. Windowing costs a scroll listener, a measurement per row\ndrawn, and a `block-size` on the scrolling box, and a table of twenty rows\nshould pay none of them.",
47119
+ "description": "Draws only the rows in view, with empty space in place of the rest.\n\n**Not a `mode`.** `mode` says where the rows come from and who filtered\nthem; this says how many of the ones we hold get drawn. They are\nindependent: a consumer fetching five thousand rows a chunk at a time wants\n`mode=\"server\"` and this at once, and folding this into `mode` would be an\nAPI that forbids that combination for no reason.\n\n**Composes with `paginated` rather than excluding it.** A window over a\npage is coherent -- the page is the slice of the result, the window is the\npart of that slice on screen -- and the arithmetic is the same either way,\nso there is nothing to forbid. Together they suit a table paging at a\nthousand rows, where the page is a reasonable fetch and a poor render.\n\nOff by default. Windowing costs a scroll listener, a measurement per row\ndrawn, and a `block-size` on the scrolling box, and a table of twenty rows\nshould pay none of them.\n\nWhile windowed, the `table` part scrolls on this tier: it carries\n`data-scroller`, and `core` ships `[data-scroller] { overflow: auto }` into\nevery shadow root. You still need to give it a block size.",
46859
47120
  "attribute": "windowed",
46860
47121
  "reflects": true
46861
47122
  },
@@ -49868,7 +50129,7 @@
49868
50129
  "text": "boolean"
49869
50130
  },
49870
50131
  "default": "false",
49871
- "description": "Draws only the rows in view, with empty space in place of the rest.\n\n**Not a `mode`.** `mode` says where the rows come from and who filtered\nthem; this says how many of the ones we hold get drawn. They are\nindependent: a consumer fetching five thousand rows a chunk at a time wants\n`mode=\"server\"` and this at once, and folding this into `mode` would be an\nAPI that forbids that combination for no reason.\n\n**Composes with `paginated` rather than excluding it.** A window over a\npage is coherent -- the page is the slice of the result, the window is the\npart of that slice on screen -- and the arithmetic is the same either way,\nso there is nothing to forbid. Together they suit a table paging at a\nthousand rows, where the page is a reasonable fetch and a poor render.\n\nOff by default. Windowing costs a scroll listener, a measurement per row\ndrawn, and a `block-size` on the scrolling box, and a table of twenty rows\nshould pay none of them.",
50132
+ "description": "Draws only the rows in view, with empty space in place of the rest.\n\n**Not a `mode`.** `mode` says where the rows come from and who filtered\nthem; this says how many of the ones we hold get drawn. They are\nindependent: a consumer fetching five thousand rows a chunk at a time wants\n`mode=\"server\"` and this at once, and folding this into `mode` would be an\nAPI that forbids that combination for no reason.\n\n**Composes with `paginated` rather than excluding it.** A window over a\npage is coherent -- the page is the slice of the result, the window is the\npart of that slice on screen -- and the arithmetic is the same either way,\nso there is nothing to forbid. Together they suit a table paging at a\nthousand rows, where the page is a reasonable fetch and a poor render.\n\nOff by default. Windowing costs a scroll listener, a measurement per row\ndrawn, and a `block-size` on the scrolling box, and a table of twenty rows\nshould pay none of them.\n\nWhile windowed, the `table` part scrolls on this tier: it carries\n`data-scroller`, and `core` ships `[data-scroller] { overflow: auto }` into\nevery shadow root. You still need to give it a block size.",
49872
50133
  "fieldName": "windowed"
49873
50134
  },
49874
50135
  {
@@ -56048,7 +56309,7 @@
56048
56309
  "text": "TemplateResult | typeof nothing"
56049
56310
  }
56050
56311
  },
56051
- "description": "The `feedback` line, or nothing while there is none.",
56312
+ "description": "The `feedback` line, or nothing while there is none.\n\n`role=\"alert\"`, as a field's feedback line has, so the message is\nannounced when it appears and the label and hint are not read with it.",
56052
56313
  "inheritedFrom": {
56053
56314
  "name": "MixinPickerFeedback",
56054
56315
  "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
@@ -58723,7 +58984,7 @@
58723
58984
  "name": "commands",
58724
58985
  "privacy": "protected",
58725
58986
  "readonly": true,
58726
- "default": "new CommandController(this, { commands: { '--close': () => this.close(), '--show': () => this.show(), '--toggle': () => this.toggleOpen(), }, })"
58987
+ "default": "new CommandController(this, { commands: { '--close': () => this.close(), '--show': () => this.show(), '--toggle': () => this.toggleOpen(), }, expanded: () => this.open, })"
58727
58988
  },
58728
58989
  {
58729
58990
  "kind": "field",
@@ -61459,7 +61720,7 @@
61459
61720
  "declarations": [
61460
61721
  {
61461
61722
  "kind": "class",
61462
- "description": "Uses `MixinControllerOpen`, so `open`, `defaultOpen`, and the\n`helix-before-open` and `helix-before-close` events work the same way as on\nan accordion item.\n\nThe drawer is modal by default, which means four things:\n\n- focus is trapped inside: `Tab` from the last control goes to the first,\n and `Shift+Tab` from the first to the last, as in `Dialog`\n- Escape and a press outside close it\n- the page behind is covered\n- the page behind does not scroll\n\nA drawer with `modal=\"false\"` leaves the page usable and still closes on\nEscape, in a browser without `closedby` as well.\n\nSet `persistent` for a drawer that has to be answered: Escape, a press\noutside, and a swipe leave it open, and the close control and `close()`\nstill close it. `closedby=\"none\"` keeps it open on all three as well, and\n`closedby=\"closerequest\"` keeps it open on a press outside.\n\n**A touch or a pen swipes it away**, toward the edge it came from, resolved\nagainst the writing direction. A swipe past halfway, or a quick one, closes\nit through the same request as every other way out. `snap-points` lists the\nfractions of the panel a reader can leave on screen, such as `0.5 1` for a\nsheet that rests half open: it opens at the smallest, and a swipe settles at\nthe nearest. While a swipe moves the panel, the distance is written on it as\n`--drawer-swipe-x` and `--drawer-swipe-y`. `swipe=\"false\"` turns swiping off.\n\n`snap` is the snap point the panel rests at, and `:state(snapped)` is on the\nhost while that is less than the whole panel. `snapTo()` moves it to\nanother. **Focus moving to a control past the\nwindow's edge opens the panel to its largest snap point**, so a reader\nmoving through a half open sheet with `Tab` never lands on a control they\ncannot see.\n\nSet `dismissible` to draw a close control in the corner, labeled by\n`dismiss-label`, as `Dialog` draws one.\n\nThe panel's name is `label` when you set it. Otherwise it is the heading in\nthe `header` slot, or the elements an `aria-labelledby` on the host names,\nand `fallback-label` where nothing names it. A development build warns\nwhen a drawer opens with nothing but `fallback-label` to name it.\n\nThe panel is described by the words at the start of its body, as `Dialog`\nis: the elements in the default slot before the first one that is or holds\na control. An `aria-describedby` on the host replaces it.\n\n**Keyboard.** Opening moves focus to the first control in the panel.\n\n| Key | What it does |\n|---|---|\n| Tab, Shift+Tab | In a modal drawer, moves through the controls in the panel, from the last round to the first and from the first round to the last. In a drawer that is not modal, moves on to the page. |\n| Escape | Asks to close the drawer. A `helix-before-close` listener can refuse, and `persistent` or `closedby=\"none\"` keeps it open. |\n| Enter, Space | On the close control, closes the drawer. |\n\nContent stays mounted when the drawer is closed, so it is in the server\nmarkup and can animate. A closed `<dialog>` is already out of the tab order\nand the accessibility tree, so the drawer does not write `inert`. The `role`,\n`aria-modal`, and the scrim also come from the `<dialog>` element.\n`drawer-root.ssr.spec.ts` checks that the panel has no hand-written `inert`\nor `role`.\n\nOpen the drawer declaratively with the platform's invoker attributes:\n\n```html\n<helix-headless-button commandfor=\"nav\" command=\"--toggle\">Menu</helix-headless-button>\n<helix-headless-drawer id=\"nav\">…</helix-headless-drawer>\n```",
61723
+ "description": "Uses `MixinControllerOpen`, so `open`, `defaultOpen`, and the\n`helix-before-open` and `helix-before-close` events work the same way as on\nan accordion item.\n\nThe drawer is modal by default, which means four things:\n\n- focus is trapped inside: `Tab` from the last control goes to the first,\n and `Shift+Tab` from the first to the last, as in `Dialog`\n- Escape and a press outside close it\n- the page behind is covered\n- the page behind does not scroll\n\nA drawer with `modal=\"false\"` leaves the page usable and still closes on\nEscape, in a browser without `closedby` as well.\n\nSet `persistent` for a drawer that has to be answered: Escape, a press\noutside, and a swipe leave it open, and the close control and `close()`\nstill close it. `closedby=\"none\"` keeps it open on all three as well, and\n`closedby=\"closerequest\"` keeps it open on a press outside.\n\n**A touch or a pen swipes it away**, toward the edge it came from, resolved\nagainst the writing direction. A swipe past halfway, or a quick one, closes\nit through the same request as every other way out. `snap-points` lists the\nfractions of the panel a reader can leave on screen, such as `0.5 1` for a\nsheet that rests half open: it opens at the smallest, and a swipe settles at\nthe nearest. While a swipe moves the panel, the distance is written on it as\n`--drawer-swipe-x` and `--drawer-swipe-y`. `swipe=\"false\"` turns swiping off.\n\n`snap` is the snap point the panel rests at, and `:state(snapped)` is on the\nhost while that is less than the whole panel. `snapTo()` moves it to\nanother. **Focus moving to a control past the\nwindow's edge opens the panel to its largest snap point**, so a reader\nmoving through a half open sheet with `Tab` never lands on a control they\ncannot see.\n\nSet `dismissible` to draw a close control in the corner, labeled by\n`dismiss-label`, as `Dialog` draws one.\n\nThe panel's name is `label` when you set it. Otherwise it is the heading in\nthe `header` slot, or the elements an `aria-labelledby` on the host names,\nand `fallback-label` where nothing names it. A development build warns\nwhen a drawer opens with nothing but `fallback-label` to name it.\n\nThe panel is described by the words at the start of its body, as `Dialog`\nis: the elements in the default slot before the first one that is or holds\na control. An `aria-describedby` on the host replaces it.\n\n**Keyboard.** Opening moves focus to the first control in the panel.\n\n| Key | What it does |\n|---|---|\n| Tab, Shift+Tab | In a modal drawer, moves through the controls in the panel, from the last round to the first and from the first round to the last. In a drawer that is not modal, moves on to the page. |\n| Escape | Asks to close the drawer. A `helix-before-close` listener can refuse, and `persistent` or `closedby=\"none\"` keeps it open. |\n| Enter, Space | On the close control, closes the drawer. |\n\nContent stays mounted when the drawer is closed, so it is in the server\nmarkup and can animate. A closed `<dialog>` is already out of the tab order\nand the accessibility tree, so the drawer does not write `inert`. The `role`,\n`aria-modal`, and the scrim also come from the `<dialog>` element.\n`drawer-root.ssr.spec.ts` checks that the panel has no hand-written `inert`\nor `role`.\n\nOpen the drawer declaratively with the platform's invoker attributes:\n\n```html\n<helix-headless-button commandfor=\"nav\" command=\"--toggle\">Menu</helix-headless-button>\n<helix-headless-drawer id=\"nav\">…</helix-headless-drawer>\n```\n\nFrom its first press, a button that opens the drawer this way says whether\nthe drawer is open: a Helix button through `expanded`, and any other\nelement with `aria-expanded`.",
61463
61724
  "name": "HelixHeadlessDrawer",
61464
61725
  "cssProperties": [
61465
61726
  {
@@ -61531,7 +61792,7 @@
61531
61792
  "name": "commands",
61532
61793
  "privacy": "protected",
61533
61794
  "readonly": true,
61534
- "default": "new CommandController(this, { commands: { '--close': () => this.requestOpen(false), '--show': () => this.requestOpen(true), '--toggle': () => this.toggleOpen(), }, })"
61795
+ "default": "new CommandController(this, { commands: { '--close': () => this.requestOpen(false), '--show': () => this.requestOpen(true), '--toggle': () => this.toggleOpen(), }, expanded: () => this.open, })"
61535
61796
  },
61536
61797
  {
61537
61798
  "kind": "field",
@@ -74836,6 +75097,10 @@
74836
75097
  "description": "What screen readers hear: how many notes there are when a search or the legend changes it, and which way the drawing went after a key or a control moved it.",
74837
75098
  "name": "live"
74838
75099
  },
75100
+ {
75101
+ "description": "The box in place of the list while `loading` is set and it holds no notes, holding the `loading` slot.",
75102
+ "name": "loading"
75103
+ },
74839
75104
  {
74840
75105
  "description": "One note in the list.",
74841
75106
  "name": "note"
@@ -74938,6 +75203,10 @@
74938
75203
  "description": "Content above the graph.",
74939
75204
  "name": "header"
74940
75205
  },
75206
+ {
75207
+ "description": "What the panel shows while `loading` is set and the list holds no notes. Defaults to `loading-label`.",
75208
+ "name": "loading"
75209
+ },
74941
75210
  {
74942
75211
  "description": "Replaces the glyph inside the pan down button.",
74943
75212
  "name": "pan-down-icon"
@@ -75150,6 +75419,30 @@
75150
75419
  "words": true
75151
75420
  }
75152
75421
  },
75422
+ {
75423
+ "kind": "field",
75424
+ "name": "loading",
75425
+ "type": {
75426
+ "text": "boolean"
75427
+ },
75428
+ "default": "false",
75429
+ "description": "Marks the graph as busy while its notes arrive: the list is `aria-busy`,\nand the panel says so where it holds no notes yet.",
75430
+ "attribute": "loading",
75431
+ "reflects": true
75432
+ },
75433
+ {
75434
+ "kind": "field",
75435
+ "name": "loadingLabel",
75436
+ "type": {
75437
+ "text": "string"
75438
+ },
75439
+ "default": "'Loading notes'",
75440
+ "description": "What the panel says while `loading` is set and the list holds no notes.",
75441
+ "attribute": "loading-label",
75442
+ "helix": {
75443
+ "words": true
75444
+ }
75445
+ },
75153
75446
  {
75154
75447
  "kind": "field",
75155
75448
  "name": "movedDownLabel",
@@ -75222,6 +75515,14 @@
75222
75515
  "attribute": "no-panel",
75223
75516
  "reflects": true
75224
75517
  },
75518
+ {
75519
+ "kind": "field",
75520
+ "name": "noteContent",
75521
+ "type": {
75522
+ "text": "((node: GraphNode) => unknown) | undefined | undefined"
75523
+ },
75524
+ "description": "What each note's row in the list shows in place of its name: a function\ngiven the note that returns text, an element or a Lit template.\n\nFor an icon by its kind, or a date under its name, as React Aria's\n`ListBoxItem` takes children. The row is still named by the note's name,\nwhich typeahead and the search find it by, and described by how it stands\nto the selected note. Return the name with your content where it should\nstill show. A property only, there being no way to write a function in\nmarkup."
75525
+ },
75225
75526
  {
75226
75527
  "kind": "field",
75227
75528
  "name": "notesLabel",
@@ -77242,6 +77543,24 @@
77242
77543
  "description": "How a note that links to the selected one is described, with `{note}`.",
77243
77544
  "fieldName": "linksToLabel"
77244
77545
  },
77546
+ {
77547
+ "name": "loading",
77548
+ "type": {
77549
+ "text": "boolean"
77550
+ },
77551
+ "default": "false",
77552
+ "description": "Marks the graph as busy while its notes arrive: the list is `aria-busy`,\nand the panel says so where it holds no notes yet.",
77553
+ "fieldName": "loading"
77554
+ },
77555
+ {
77556
+ "name": "loading-label",
77557
+ "type": {
77558
+ "text": "string"
77559
+ },
77560
+ "default": "'Loading notes'",
77561
+ "description": "What the panel says while `loading` is set and the list holds no notes.",
77562
+ "fieldName": "loadingLabel"
77563
+ },
77245
77564
  {
77246
77565
  "name": "moved-down-label",
77247
77566
  "type": {
@@ -77560,6 +77879,10 @@
77560
77879
  "description": "The user has been still long enough for the header and footer to fade.",
77561
77880
  "name": "idle"
77562
77881
  },
77882
+ {
77883
+ "description": "While `loading` is set.",
77884
+ "name": "loading"
77885
+ },
77563
77886
  {
77564
77887
  "description": "The drawing shows the selected note's local graph, with `depth`.",
77565
77888
  "name": "local"
@@ -88862,7 +89185,7 @@
88862
89185
  "name": "commands",
88863
89186
  "privacy": "protected",
88864
89187
  "readonly": true,
88865
- "default": "new CommandController(this, { commands: { '--close': () => this.close(), '--fullscreen': () => this.toggleFullscreen(), '--next': () => this.next(), '--previous': () => this.previous(), '--show': () => this.show(), '--toggle': () => this.toggleOpen(), }, })"
89188
+ "default": "new CommandController(this, { commands: { '--close': () => this.close(), '--fullscreen': () => this.toggleFullscreen(), '--next': () => this.next(), '--previous': () => this.previous(), '--show': () => this.show(), '--toggle': () => this.toggleOpen(), }, expanded: () => this.open, })"
88866
89189
  },
88867
89190
  {
88868
89191
  "kind": "field",
@@ -93379,7 +93702,7 @@
93379
93702
  "text": "string"
93380
93703
  },
93381
93704
  "default": "''",
93382
- "description": "The selected rows' values, separated by commas with no spaces, such as `a,c`, in a list that selects.\n\nSet it to start with rows selected. A row's value is its `value`, or its\nwords where it has none.",
93705
+ "description": "The selected rows' values, separated by commas with no spaces, such as `a,c`, in a list that selects.\n\nA press or a key writes it in row order, as Data Table does, whatever\norder the rows were chosen in. Set it to start with rows selected. A row's value is its `value`, or its\nwords where it has none.",
93383
93706
  "attribute": "value"
93384
93707
  },
93385
93708
  {
@@ -93655,7 +93978,7 @@
93655
93978
  }
93656
93979
  }
93657
93980
  ],
93658
- "description": "Selects what a press or a key leaves, asking first. `helix-before-change`\ncarries the `value` it would leave, and `change` follows once it has moved."
93981
+ "description": "Selects what a press or a key leaves, asking first. `helix-before-change`\ncarries the `value` it would leave, and `change` follows once it has moved.\n\nIn row order, as Data Table and Table write theirs, whatever order the\nrows were chosen in: a press on the fourth row and then the first is\n`a,d`."
93659
93982
  },
93660
93983
  {
93661
93984
  "kind": "method",
@@ -94505,7 +94828,7 @@
94505
94828
  "text": "string"
94506
94829
  },
94507
94830
  "default": "''",
94508
- "description": "The selected rows' values, separated by commas with no spaces, such as `a,c`, in a list that selects.\n\nSet it to start with rows selected. A row's value is its `value`, or its\nwords where it has none.",
94831
+ "description": "The selected rows' values, separated by commas with no spaces, such as `a,c`, in a list that selects.\n\nA press or a key writes it in row order, as Data Table does, whatever\norder the rows were chosen in. Set it to start with rows selected. A row's value is its `value`, or its\nwords where it has none.",
94509
94832
  "fieldName": "value"
94510
94833
  }
94511
94834
  ],
@@ -95410,7 +95733,7 @@
95410
95733
  }
95411
95734
  }
95412
95735
  ],
95413
- "description": "Says how many options a filter left, in the live region.\n\n**A reader typing into a filter cannot see the list narrow**, and React\nAria and Web Awesome both say the count as it changes. Only \"No matches\"\nwas said here, so a query that left forty options and one that left one\nsounded the same. Said when the filter changes and the count with it, so\na keystroke that leaves the same options says nothing new. An empty filter\nsays nothing, being the list as it was given; no matches is `empty-text`,\nwhich the region says in place of this."
95736
+ "description": "Says how many options a filter left, in the live region.\n\n**A reader typing into a filter cannot see the list narrow**, and React\nAria and Web Awesome both say the count as it changes. Only \"No matches\"\nwas said here, so a query that left forty options and one that left one\nsounded the same. Said when the filter changes and the count with it, so\na keystroke that leaves the same options says nothing new. An empty filter\nsays nothing, being the list as it was given; no matches is `empty-text`,\nwhich the region says in place of this. A load that ends says the count\ntoo, whatever the filter."
95414
95737
  },
95415
95738
  {
95416
95739
  "kind": "method",
@@ -109951,6 +110274,14 @@
109951
110274
  "description": "The row is checked.",
109952
110275
  "name": "checked"
109953
110276
  },
110277
+ {
110278
+ "description": "The row is disabled.",
110279
+ "name": "disabled"
110280
+ },
110281
+ {
110282
+ "description": "Under `submenus=\"flyout\"`, the row's submenu is open beside it.",
110283
+ "name": "expanded"
110284
+ },
109954
110285
  {
109955
110286
  "description": "In a menu with `filterable`, the arrow keys or the pointer reached the row while focus stays in the filter field.",
109956
110287
  "name": "highlighted"
@@ -110023,7 +110354,7 @@
110023
110354
  "declarations": [
110024
110355
  {
110025
110356
  "kind": "class",
110026
- "description": "The trigger is slotted and stays your own element, as with the tooltip. The\nmenu renders its surface in the top layer with the popover API, so an\nancestor with `overflow: hidden` does not clip it and it needs no `z-index`.\n\nSlot a `helix-button` or `helix-icon-button` as the trigger, and the menu\ntells it that it opens a menu and whether the menu is open, inside its own\nshadow root. On a plain element, such as a `<button>`, the menu writes\n`aria-haspopup=\"menu\"` and `aria-expanded`, from a frame after its own first\nrender, so a server's markup is never changed while a framework hydrates it.\nIt never writes `aria-expanded` where you wrote it yourself.\n\nSubmenus drill down by default. A submenu replaces the panel's content, and a\nback row returns to the previous page. One panel stays inside a narrow\nwindow, and works on touch screens, which have no hover.\n\n**`submenus=\"flyout\"` opens each submenu in a panel of its own beside its\nrow**, as React Aria's `SubmenuTrigger` and Radix's `Sub` do. Resting the\npointer on the row opens it, and a pointer crossing toward the open panel\nover the rows between keeps it open, as Radix's grace area does. Right Arrow\nopens a row's submenu on its first row, and Left Arrow or Escape closes it\nand returns focus to the row, the two arrows swapping on a right-to-left\npage. The row says `aria-expanded`, and the panel is a `menu` named by the\nrow.\n\nThe root holds which page is open, because only one page shows at a time. It\nsets this on items as a property, never as an attribute. An attribute written\nonto your element after it upgrades causes a hydration mismatch.\n\nGroup rows under a heading with `Menu.Section`, which is a `group` named by\nits heading. Between runs of rows, a `<helix-divider>` is a separator a\nscreen reader announces.\n\nKeys: Enter, Space or Down Arrow on the trigger opens the menu on its first\nrow, and Up Arrow on its last. In the menu, Up and Down Arrow move between\nrows, Home and End go to the first and the last, a typed letter moves to\nthe next row whose name starts with it, Enter and Space choose (Space on a\nchoice row changes it and leaves the menu open), Right Arrow\nopens a row's submenu and Left Arrow goes back, the two swapping on a\nright-to-left page. Left Arrow on the top page does nothing. Escape closes\nthe menu and returns focus to the trigger. Tab closes it and moves on.\n\nWhile it is open, the surface carries the trigger's width as\n`--floating-anchor-inline-size` and the room left below it as\n`--floating-available-block-size`, as Radix's dropdown menu publishes its\ntrigger's width, for a menu as wide as its trigger:\n`helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }`.\n\nWith `context`, the trigger is an area and the menu is its context menu: a\nright-click, a long press, Shift+F10 or the menu key over the area opens it\nat the pointer, or at the area's corner from the keyboard, as Radix's context\nmenu does. A press on the area does not open it, and closing it returns focus\nto where it was. A touch or a pen held still on the area opens it too, on\nevery browser, since iOS sends no `contextmenu` for one.\n\n**A trigger with its own action.** With `open-on=\"long-press\"`, a press on\nthe trigger is the trigger's own, and a press held for half a second opens\nthe menu, as React Aria's `trigger=\"longPress\"` does. Alt+Down or Alt+Up\nopens it from the keyboard, and the trigger is described by\n`long-press-label`, which says so.\n\n**A filter field.** With `filterable`, the menu opens with focus in a field\nabove its rows, and typing narrows the rows of the page the keys move in,\nas React Aria's `Autocomplete` around a `Menu` does. A row is kept where its\nwords hold the filter, in any case, or where `filterMatch` says so. Each\npage starts unfiltered, and the filter is cleared as the menu closes. Where\ntyping keeps no row, the menu shows `no-results-text`. Focus stays in the\nfield: Up and Down Arrow move the highlight through the rows that are left,\nEnter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow\non a submenu goes back, and Escape clears the filter and then closes the\nmenu. Home, End and the other keys move the caret and type. The field names\nthe highlighted row with `aria-activedescendant`, and the rows are a `menu`\nafter the field. Cancel `helix-filter` to keep every row\nshowing and narrow the rows yourself, such as by replacing them with rows\nfrom a server.",
110357
+ "description": "The trigger is slotted and stays your own element, as with the tooltip. The\nmenu renders its surface in the top layer with the popover API, so an\nancestor with `overflow: hidden` does not clip it and it needs no `z-index`.\n\nSlot a `helix-button` or `helix-icon-button` as the trigger, and the menu\ntells it that it opens a menu and whether the menu is open, inside its own\nshadow root. On a plain element, such as a `<button>`, the menu writes\n`aria-haspopup=\"menu\"` and `aria-expanded`, from a frame after its own first\nrender, so a server's markup is never changed while a framework hydrates it.\nIt never writes `aria-expanded` where you wrote it yourself.\n\nSubmenus drill down by default. A submenu replaces the panel's content, and a\nback row returns to the previous page. One panel stays inside a narrow\nwindow, and works on touch screens, which have no hover. Focus follows a\nmouse resting on a row in either mode, and a drilled page is a `menu` named\nby the row that opened it.\n\n**`submenus=\"flyout\"` opens each submenu in a panel of its own beside its\nrow**, as React Aria's `SubmenuTrigger` and Radix's `Sub` do. Resting the\npointer on the row opens it, and a pointer crossing toward the open panel\nover the rows between keeps it open, as Radix's grace area does. Right Arrow\nopens a row's submenu on its first row, and Left Arrow or Escape closes it\nand returns focus to the row, the two arrows swapping on a right-to-left\npage. The row says `aria-expanded`, and the panel is a `menu` named by the\nrow.\n\nThe root holds which page is open, because only one page shows at a time. It\nsets this on items as a property, never as an attribute. An attribute written\nonto your element after it upgrades causes a hydration mismatch.\n\nGroup rows under a heading with `Menu.Section`, which is a `group` named by\nits heading. Between runs of rows, a `<helix-divider>` is a separator a\nscreen reader announces.\n\nKeys: Enter, Space or Down Arrow on the trigger opens the menu on its first\nrow, and Up Arrow on its last. In the menu, Up and Down Arrow move between\nrows, Home and End go to the first and the last, a typed letter moves to\nthe next row whose name starts with it, Enter and Space choose (Space on a\nchoice row changes it and leaves the menu open), Right Arrow\nopens a row's submenu and Left Arrow goes back, the two swapping on a\nright-to-left page. Left Arrow on the top page does nothing. Escape closes\nthe menu and returns focus to the trigger. Tab closes it and moves on.\n\nWhile it is open, the surface carries the trigger's width as\n`--floating-anchor-inline-size` and the room left below it as\n`--floating-available-block-size`, as Radix's dropdown menu publishes its\ntrigger's width, for a menu as wide as its trigger:\n`helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }`.\n\n**The choices in one place.** `checkedValues` holds the values of the rows\nthat are checked, anywhere in the menu, and setting it checks exactly\nthose rows, as React Aria's `selectedKeys` does. `change` is sent on the\nmenu when a reader's choice changes it.\n\nWith `context`, the trigger is an area and the menu is its context menu: a\nright-click, a long press, Shift+F10 or the menu key over the area opens it\nat the pointer, or at the area's corner from the keyboard, as Radix's context\nmenu does. A press on the area does not open it, and closing it returns focus\nto where it was. A touch or a pen held still on the area opens it too, on\nevery browser, since iOS sends no `contextmenu` for one.\n\n**A trigger with its own action.** With `open-on=\"long-press\"`, a press on\nthe trigger is the trigger's own, and a press held for half a second opens\nthe menu, as React Aria's `trigger=\"longPress\"` does. Alt+Down or Alt+Up\nopens it from the keyboard, and the trigger is described by\n`long-press-label`, which says so.\n\n**A filter field.** With `filterable`, the menu opens with focus in a field\nabove its rows, and typing narrows the rows of the page the keys move in,\nas React Aria's `Autocomplete` around a `Menu` does. A row is kept where its\nwords hold the filter, in any case, or where `filterMatch` says so. Each\npage starts unfiltered, and the filter is cleared as the menu closes. Where\ntyping keeps no row, the menu shows `no-results-text`. Focus stays in the\nfield: Up and Down Arrow move the highlight through the rows that are left,\nEnter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow\non a submenu goes back, and Escape clears the filter and then closes the\nmenu. A screen reader hears how many rows the filter keeps\n(`results-label`). Home, End and the other keys move the caret and type. The field names\nthe highlighted row with `aria-activedescendant`, and the rows are a `menu`\nafter the field. Cancel `helix-filter` to keep every row\nshowing and narrow the rows yourself, such as by replacing them with rows\nfrom a server.",
110027
110358
  "name": "HelixHeadlessMenu",
110028
110359
  "cssProperties": [
110029
110360
  {
@@ -110078,6 +110409,14 @@
110078
110409
  "description": "The items.",
110079
110410
  "name": ""
110080
110411
  },
110412
+ {
110413
+ "description": "What the menu shows when it has no items, for content richer than `empty-text`.",
110414
+ "name": "empty"
110415
+ },
110416
+ {
110417
+ "description": "What the menu shows while its items load, for content richer than `loading-text`.",
110418
+ "name": "loading"
110419
+ },
110081
110420
  {
110082
110421
  "description": "What the menu shows when the filter keeps no rows, for content richer than `no-results-text`.",
110083
110422
  "name": "no-results"
@@ -110102,6 +110441,20 @@
110102
110441
  "module": "src/mixins/mixin-collection/mixin-collection.ts"
110103
110442
  }
110104
110443
  },
110444
+ {
110445
+ "kind": "field",
110446
+ "name": "statusSlots",
110447
+ "type": {
110448
+ "text": "boolean"
110449
+ },
110450
+ "privacy": "protected",
110451
+ "default": "true",
110452
+ "description": "Whether the status line is an `empty` or `loading` slot, with\n`empty-text` or `loading-text` as its fallback.\n\n**Off unless a family turns it on**, because a slot is published API:\neach family that renders one documents it in its own manifest. The live\nregion keeps saying the text either way, because a slotted picture has no\nwords to say.",
110453
+ "inheritedFrom": {
110454
+ "name": "MixinCollection",
110455
+ "module": "src/mixins/mixin-collection/mixin-collection.ts"
110456
+ }
110457
+ },
110105
110458
  {
110106
110459
  "kind": "field",
110107
110460
  "name": "backLabel",
@@ -110320,6 +110673,16 @@
110320
110673
  "description": "Space between the trigger and the surface, in pixels.",
110321
110674
  "attribute": "offset"
110322
110675
  },
110676
+ {
110677
+ "kind": "field",
110678
+ "name": "openOn",
110679
+ "type": {
110680
+ "text": "'click' | 'long-press'"
110681
+ },
110682
+ "default": "'click'",
110683
+ "description": "What opens the menu from its trigger. `long-press` leaves a press to the\ntrigger's own action and opens the menu on a press held for half a second,\nor on Alt+Down or Alt+Up.",
110684
+ "attribute": "open-on"
110685
+ },
110323
110686
  {
110324
110687
  "kind": "field",
110325
110688
  "name": "pressHeld",
@@ -110347,16 +110710,6 @@
110347
110710
  "privacy": "private",
110348
110711
  "description": "Where a held press on a context menu's area is, to open the menu there."
110349
110712
  },
110350
- {
110351
- "kind": "field",
110352
- "name": "openOn",
110353
- "type": {
110354
- "text": "'click' | 'long-press'"
110355
- },
110356
- "default": "'click'",
110357
- "description": "What opens the menu from its trigger. `long-press` leaves a press to the\ntrigger's own action and opens the menu on a press held for half a second,\nor on Alt+Down or Alt+Up.",
110358
- "attribute": "open-on"
110359
- },
110360
110713
  {
110361
110714
  "kind": "field",
110362
110715
  "name": "placement",
@@ -110367,6 +110720,19 @@
110367
110720
  "description": "The side the menu opens on, when there is room.\n\nIt moves if that side does not fit.",
110368
110721
  "attribute": "placement"
110369
110722
  },
110723
+ {
110724
+ "kind": "field",
110725
+ "name": "resultsLabel",
110726
+ "type": {
110727
+ "text": "string"
110728
+ },
110729
+ "default": "'{count, plural, one {# result} other {# results}}'",
110730
+ "description": "What a screen reader hears when the filter narrows the rows. `{count}` is\nhow many rows are left, written in the locale, and each language writes\nthe forms it has, as Listbox's `results-label` does.",
110731
+ "attribute": "results-label",
110732
+ "helix": {
110733
+ "words": true
110734
+ }
110735
+ },
110370
110736
  {
110371
110737
  "kind": "field",
110372
110738
  "name": "submenus",
@@ -110393,6 +110759,13 @@
110393
110759
  "default": "new KeyboardNavigationController(this, { /* None while closed: the rows are hidden, and a key on the trigger is this element's to answer. Down and Up there open the menu. */ items: () => (this.open ? this.items : []), reserved: () => ['ArrowLeft', 'ArrowRight'], selects: () => false, typeahead: typeaheadBy((item) => slottedWords(item as HelixHeadlessMenuItem, [''])), })",
110394
110760
  "description": "Moving between rows, which is not this element's own business any more.\n\n`selects` false, because arriving at Delete must not delete: moving and\nchoosing are one act in a radio group and two acts here, which is the\ndistinction the controller was already drawing for `Tabs`.\n\nThe origin is the selection, and `focus` is the wrong reading however right\nit looks: that origin also carries a rule a menu must not follow, that a\npress which did not come from the set moves nothing. That rule is there for\na tab panel, which is a tab stop beside the tabs; a menu's panel holds the\nrows and nothing else, and Down on a menu that has just opened is how a\nreader gets to the first row at all.\n\nThe horizontal pair is reserved rather than released. Right opens a\nsubmenu and left comes back, which are the platform's own bindings for a\nmenu that drills, so those keys are spoken for here rather than unhandled."
110395
110761
  },
110762
+ {
110763
+ "kind": "field",
110764
+ "name": "phases",
110765
+ "privacy": "protected",
110766
+ "readonly": true,
110767
+ "default": "new OpenPhaseController(this, { mark: { entering: (on) => this.toggleState('entering', on), exiting: (on) => this.toggleState('exiting', on), }, open: () => this.open, surface: () => this.partNamed('surface'), })"
110768
+ },
110396
110769
  {
110397
110770
  "kind": "field",
110398
110771
  "name": "aria",
@@ -110616,6 +110989,22 @@
110616
110989
  ],
110617
110990
  "description": "Moves the reader to a row: focus, or with `filterable` the highlight,\nwhich the field names with `aria-activedescendant`. An element reference,\nbecause the field is in this shadow root and the row in the tree around\nit, the one direction a reference crosses."
110618
110991
  },
110992
+ {
110993
+ "kind": "field",
110994
+ "name": "rowWatch",
110995
+ "type": {
110996
+ "text": "MutationObserver | undefined"
110997
+ },
110998
+ "privacy": "private",
110999
+ "description": "Watches for rows taken away while the menu is open."
111000
+ },
111001
+ {
111002
+ "kind": "field",
111003
+ "name": "followRemoved",
111004
+ "privacy": "private",
111005
+ "readonly": true,
111006
+ "description": "Moves the reader to a neighbor when the page takes away the row they were\non: the row that took its place, or the one before it where it was the\nlast. A menu with no rows left closes and gives focus to its trigger.\n\n**Focus went to the body**, and the menu then ignored every key, its\nlistener being on the host: measured in Chromium, removing the focused\nrow and pressing ArrowUp did nothing. List and Virtual List move focus to\na neighbor the same way, as React Aria's collections do. With `filterable`,\nfocus stays in the field and the highlight moves. Focus a reader put\nanywhere but the body is left there."
111007
+ },
110619
111008
  {
110620
111009
  "kind": "method",
110621
111010
  "name": "show",
@@ -110717,6 +111106,44 @@
110717
111106
  },
110718
111107
  "description": "Returns to the page above, or closes when there is none."
110719
111108
  },
111109
+ {
111110
+ "kind": "field",
111111
+ "name": "choiceRows",
111112
+ "type": {
111113
+ "text": "HelixHeadlessMenuItem[]"
111114
+ },
111115
+ "privacy": "private",
111116
+ "description": "The choice rows anywhere in the menu, in document order.",
111117
+ "readonly": true
111118
+ },
111119
+ {
111120
+ "kind": "field",
111121
+ "name": "checkedValues",
111122
+ "type": {
111123
+ "text": "string[]"
111124
+ },
111125
+ "description": "The values of the choice rows that are checked, anywhere in the menu, in\ndocument order.\n\nSet it to check exactly those rows and uncheck every other choice row, as\nReact Aria's `selectedKeys` controls a menu's selection from one place.\nEach row keeps its own `checked` too, which this reads and writes. `change`\nis sent on the menu when a reader's choice changes it."
111126
+ },
111127
+ {
111128
+ "kind": "field",
111129
+ "name": "toldChecked",
111130
+ "type": {
111131
+ "text": "string | undefined"
111132
+ },
111133
+ "privacy": "private",
111134
+ "description": "The checked values `change` last said, joined, so a choice that moved nothing says nothing."
111135
+ },
111136
+ {
111137
+ "kind": "method",
111138
+ "name": "tellChecked",
111139
+ "privacy": "private",
111140
+ "return": {
111141
+ "type": {
111142
+ "text": "void"
111143
+ }
111144
+ },
111145
+ "description": "Sends `change` when a reader's choice has changed which rows are checked."
111146
+ },
110720
111147
  {
110721
111148
  "kind": "field",
110722
111149
  "name": "handleSelect",
@@ -110913,7 +111340,7 @@
110913
111340
  "name": "handleHover",
110914
111341
  "privacy": "private",
110915
111342
  "readonly": true,
110916
- "description": "A mouse resting on a row, under `flyout`: focus follows it, and after a\nmoment the row's submenu opens, or the submenus below the row's own page\nclose. Not while the pointer is crossing toward an open submenu."
111343
+ "description": "A mouse resting on a row: focus follows it, and under `flyout`, after a\nmoment, the row's submenu opens, or the submenus below the row's own page\nclose. Not while the pointer is crossing toward an open submenu.\n\n**In every mode**, as the APG's menus, React Aria's and Radix's have it.\nUnder `drill` the pointer did not move focus, so the row under the\npointer and the row the keys moved from were two rows, measured in\nChromium: hovering Delete left focus on Cut."
110917
111344
  },
110918
111345
  {
110919
111346
  "kind": "field",
@@ -110941,6 +111368,16 @@
110941
111368
  ],
110942
111369
  "description": "Whether the pointer is inside the grace area, while it holds."
110943
111370
  },
111371
+ {
111372
+ "kind": "field",
111373
+ "name": "namedByPage",
111374
+ "type": {
111375
+ "text": "boolean"
111376
+ },
111377
+ "privacy": "private",
111378
+ "default": "false",
111379
+ "description": "Whether the surface is named by a submenu's page, which `nameSurface` undoes at the top."
111380
+ },
110944
111381
  {
110945
111382
  "kind": "method",
110946
111383
  "name": "nameSurface",
@@ -110950,7 +111387,7 @@
110950
111387
  "text": "void"
110951
111388
  }
110952
111389
  },
110953
- "description": "Names the surface by its trigger, where nothing else names it.\n\nBy element reference, which is the one direction that crosses: the surface\nis in this shadow root and the trigger is in the tree around it. A host\n`aria-labelledby` is carried down by `aria`, and a host `aria-label` or\n`label` is a name of its own, so each of them clears this reference."
111390
+ "description": "Names the surface by its trigger, where nothing else names it, and a\nsubmenu's page by its title.\n\nBy element reference, which is the one direction that crosses: the surface\nis in this shadow root and the trigger is in the tree around it. A host\n`aria-labelledby` is carried down by `aria`, and a host `aria-label` or\n`label` is a name of its own, so each of them clears this reference."
110954
111391
  },
110955
111392
  {
110956
111393
  "kind": "method",
@@ -111182,20 +111619,6 @@
111182
111619
  "module": "src/mixins/mixin-collection/mixin-collection.ts"
111183
111620
  }
111184
111621
  },
111185
- {
111186
- "kind": "field",
111187
- "name": "statusSlots",
111188
- "type": {
111189
- "text": "boolean"
111190
- },
111191
- "privacy": "protected",
111192
- "default": "false",
111193
- "description": "Whether the status line is an `empty` or `loading` slot, with\n`empty-text` or `loading-text` as its fallback.\n\n**Off unless a family turns it on**, because a slot is published API:\neach family that renders one documents it in its own manifest. The live\nregion keeps saying the text either way, because a slotted picture has no\nwords to say.",
111194
- "inheritedFrom": {
111195
- "name": "MixinCollection",
111196
- "module": "src/mixins/mixin-collection/mixin-collection.ts"
111197
- }
111198
- },
111199
111622
  {
111200
111623
  "kind": "field",
111201
111624
  "name": "defaultOpen",
@@ -111657,6 +112080,14 @@
111657
112080
  }
111658
112081
  ],
111659
112082
  "events": [
112083
+ {
112084
+ "type": {
112085
+ "text": "Event"
112086
+ },
112087
+ "description": "A reader's choice checked or unchecked rows. Read `checkedValues` for the rows that are checked now.",
112088
+ "name": "change",
112089
+ "reactProp": "onchange"
112090
+ },
111660
112091
  {
111661
112092
  "type": {
111662
112093
  "text": "HelixBeforeCloseEvent"
@@ -111811,6 +112242,15 @@
111811
112242
  "description": "The side the menu opens on, when there is room.\n\nIt moves if that side does not fit.",
111812
112243
  "fieldName": "placement"
111813
112244
  },
112245
+ {
112246
+ "name": "results-label",
112247
+ "type": {
112248
+ "text": "string"
112249
+ },
112250
+ "default": "'{count, plural, one {# result} other {# results}}'",
112251
+ "description": "What a screen reader hears when the filter narrows the rows. `{count}` is\nhow many rows are left, written in the locale, and each language writes\nthe forms it has, as Listbox's `results-label` does.",
112252
+ "fieldName": "resultsLabel"
112253
+ },
111814
112254
  {
111815
112255
  "name": "submenus",
111816
112256
  "type": {
@@ -111890,6 +112330,14 @@
111890
112330
  "description": "A submenu's page is showing, so content that is not a row can hide with the top page.",
111891
112331
  "name": "drilled"
111892
112332
  },
112333
+ {
112334
+ "description": "From the moment the panel shows until its entrance has finished.",
112335
+ "name": "entering"
112336
+ },
112337
+ {
112338
+ "description": "From the moment the panel hides until its exit has finished.",
112339
+ "name": "exiting"
112340
+ },
111893
112341
  {
111894
112342
  "description": "A row on the current page has a checkbox or a link, so every row keeps the trailing column.",
111895
112343
  "name": "mark"
@@ -123653,7 +124101,7 @@
123653
124101
  "declarations": [
123654
124102
  {
123655
124103
  "kind": "class",
123656
- "description": "Outline is a table of contents for a document. `Navigation` does the same job\nfor a site.\n\nThe links are your own anchors. A router renders its own `<a>` and cannot\nrender one inside the outline's shadow root, and the hrefs are fragments on\nthe same page.\n\nWrite the anchors flat, with `data-level` for their depth, or nested in\nlists, `<ul><li><a>`. A screen reader hears the levels either way: the\noutline puts a flat run into lists inside list items of its own, nested by\n`data-level`, and leaves the links where they are. A link without\n`data-level` is at the top level.\n\nA heading slotted into `heading` names the navigation, in place of `label`.\n\nIn a contents rail with a scrollbar of its own, `follow` keeps the link of\nthe section in view showing as the reader scrolls the page.\n\n**Keyboard.** The links are your anchors, in the tab order as you wrote\nthem, so the outline adds no keys of its own: Tab moves through the links\nand Enter follows one. Following a link moves focus to its section, so the\nnext Tab goes on from the heading, also with `behavior` set.\n\n**What a screen reader hears.** A navigation landmark named by `label`, \"On\nthis page\", or by the slotted heading. The links are lists, nested by level,\nso a reader hears how many links a level holds and where each one is. The\nlink to the section in view carries `aria-current=\"location\"`, read as\n\"current location\", and it moves as the page scrolls without announcing,\nwhich would interrupt the reading it follows.\n\nThe current section is decided by the headings' positions. An\n`IntersectionObserver` with a band near the top fails both ways: when\nheadings are far apart, none is in the band and no section is marked, and\nwhen they are close together, several are in the band at once.",
124104
+ "description": "Outline is a table of contents for a document. `Navigation` does the same job\nfor a site.\n\nThe links are your own anchors. A router renders its own `<a>` and cannot\nrender one inside the outline's shadow root, and the hrefs are fragments on\nthe same page.\n\nWrite the anchors flat, with `data-level` for their depth, or nested in\nlists, `<ul><li><a>`. A screen reader hears the levels either way: the\noutline puts a flat run into lists inside list items of its own, nested by\n`data-level`, and leaves the links where they are. A link without\n`data-level` is at the top level.\n\nA heading slotted into `heading` names the navigation, in place of `label`.\n\nIn a contents rail with a scrollbar of its own, `follow` keeps the link of\nthe section in view showing as the reader scrolls the page.\n\n**Keyboard.** The links are your anchors, in the tab order as you wrote\nthem, so the outline adds no keys of its own: Tab moves through the links\nand Enter follows one. Following a link moves focus to its section, so the\nnext Tab goes on from the heading, also with `behavior` set.\n\n**What a screen reader hears.** A navigation landmark named by `label`, \"On\nthis page\", or by the slotted heading. The links are lists, nested by level,\nso a reader hears how many links a level holds and where each one is. The\nlink to the section in view carries `aria-current=\"location\"`, read as\n\"current location\", and it moves as the page scrolls without announcing,\nwhich would interrupt the reading it follows.\n\nThe current section is decided by the headings' positions. An\n`IntersectionObserver` with a band near the top fails both ways: when\nheadings are far apart, none is in the band and no section is marked, and\nwhen they are close together, several are in the band at once.\n\n**Several sections at once.** `marks=\"visible\"` marks the link of every\nsection with part of it on screen, from the reading line to the bottom of\nwhat the sections scroll in, as Zag's table of contents marks its active\nids. The mark then runs from the first of those links to the last, and\n`marked` lists their ids in page order.\n\n**Going to a section from code.** `scrollToSection(id)` scrolls to the\nsection as a press on its link does, with `behavior`, and marks its link at\nonce.\n\n**Styling a link by its state.** Each link the outline finds carries\n`data-depth`, its depth in the outline from `1`, nested lists and\n`data-level` alike, and `aria-current=\"location\"` while its section is\nmarked, so `a[aria-current]` and `a[data-depth=\"2\"]` are the hooks for a\nrule of yours.",
123657
124105
  "name": "HelixHeadlessOutline",
123658
124106
  "cssParts": [
123659
124107
  {
@@ -123709,7 +124157,7 @@
123709
124157
  "name": "indicator",
123710
124158
  "privacy": "private",
123711
124159
  "readonly": true,
123712
- "default": "new IndicatorController(this, { active: () => this.links.find((link) => link.hasAttribute('aria-current')), indicator: () => this.partNamed('indicator'), surface: () => this.partNamed('nav'), })"
124160
+ "default": "new IndicatorController(this, { active: () => this.links.find((link) => link.hasAttribute('aria-current')), indicator: () => this.partNamed('indicator'), surface: () => this.partNamed('nav'), through: () => this.links.findLast((link) => link.hasAttribute('aria-current')), })"
123713
124161
  },
123714
124162
  {
123715
124163
  "kind": "field",
@@ -123744,6 +124192,16 @@
123744
124192
  "words": true
123745
124193
  }
123746
124194
  },
124195
+ {
124196
+ "kind": "field",
124197
+ "name": "marks",
124198
+ "type": {
124199
+ "text": "'reading' | 'visible'"
124200
+ },
124201
+ "default": "'reading'",
124202
+ "description": "Which links are marked. `reading` marks the one section being read, the\nlast whose heading has passed the reading line. `visible` marks every\nsection with part of it on screen, and the mark runs across their links.",
124203
+ "attribute": "marks"
124204
+ },
123747
124205
  {
123748
124206
  "kind": "field",
123749
124207
  "name": "offset",
@@ -123763,6 +124221,25 @@
123763
124221
  "description": "The id of the section in view, or empty before anything is measured.\n\nRead-only, and a getter rather than a property for that reason: it is\nderived from where the page is scrolled to, so a consumer setting it would\nbe overwritten by the next thing that crossed the reading line. Every other\nwritable property in this library that a component also writes is state a\nconsumer can own; this one cannot be, and saying so with the type is better\nthan saying it in a sentence nobody reads.",
123764
124222
  "readonly": true
123765
124223
  },
124224
+ {
124225
+ "kind": "field",
124226
+ "name": "marked",
124227
+ "type": {
124228
+ "text": "string[]"
124229
+ },
124230
+ "description": "The ids of the sections whose links are marked, in page order: the one\n`current` names, or under `marks=\"visible\"` every section on screen.\nRead-only, for the reason `current` gives.",
124231
+ "readonly": true
124232
+ },
124233
+ {
124234
+ "kind": "field",
124235
+ "name": "markedIds",
124236
+ "type": {
124237
+ "text": "string[]"
124238
+ },
124239
+ "privacy": "private",
124240
+ "default": "[]",
124241
+ "description": "What `marked` reports, which only `markTo` writes."
124242
+ },
123766
124243
  {
123767
124244
  "kind": "field",
123768
124245
  "name": "reading",
@@ -123841,6 +124318,37 @@
123841
124318
  },
123842
124319
  "description": "Works out which section is being read, and marks its link.\n\nPositional rather than a reading of what intersects, for the reason above.\nThe comparison is against `offset` and not zero, so the reading line is\nwherever the page says the top of the readable area is."
123843
124320
  },
124321
+ {
124322
+ "kind": "method",
124323
+ "name": "onScreen",
124324
+ "privacy": "private",
124325
+ "return": {
124326
+ "type": {
124327
+ "text": "{ link: HTMLAnchorElement; target: Element }[]"
124328
+ }
124329
+ },
124330
+ "parameters": [
124331
+ {
124332
+ "name": "sections",
124333
+ "type": {
124334
+ "text": "{ link: HTMLAnchorElement; target: Element }[]"
124335
+ }
124336
+ },
124337
+ {
124338
+ "name": "origin",
124339
+ "type": {
124340
+ "text": "number"
124341
+ }
124342
+ },
124343
+ {
124344
+ "name": "scroller",
124345
+ "type": {
124346
+ "text": "Element"
124347
+ }
124348
+ }
124349
+ ],
124350
+ "description": "The sections with part of them on screen, under `marks=\"visible\"`: each\nruns from its own target to the next one's, and the last to the end of the\npage."
124351
+ },
123844
124352
  {
123845
124353
  "kind": "method",
123846
124354
  "name": "markTo",
@@ -123852,9 +124360,9 @@
123852
124360
  },
123853
124361
  "parameters": [
123854
124362
  {
123855
- "name": "active",
124363
+ "name": "marked",
123856
124364
  "type": {
123857
- "text": "{ link: HTMLAnchorElement; target: Element } | undefined"
124365
+ "text": "{ link: HTMLAnchorElement; target: Element }[]"
123858
124366
  }
123859
124367
  }
123860
124368
  ],
@@ -123971,6 +124479,52 @@
123971
124479
  "readonly": true,
123972
124480
  "description": "Takes a link's click, but only where `auto` would not have done the job.\n\nLeft the platform's wherever it can be: a modified click is a new tab or a\ndownload and none of this applies, a click something else has already\nhandled is not ours, and `auto` is the whole point of `auto`."
123973
124481
  },
124482
+ {
124483
+ "kind": "method",
124484
+ "name": "scrollToSection",
124485
+ "return": {
124486
+ "type": {
124487
+ "text": "boolean"
124488
+ }
124489
+ },
124490
+ "parameters": [
124491
+ {
124492
+ "name": "id",
124493
+ "type": {
124494
+ "text": "string"
124495
+ }
124496
+ }
124497
+ ],
124498
+ "description": "Scrolls to the section with this id, as a press on its link does, with\n`behavior`, and marks its link at once. The address and focus stay where\nthey are. Returns whether the outline has a link to that section.",
124499
+ "type": {
124500
+ "text": "scrollToSection(id: string) => boolean"
124501
+ }
124502
+ },
124503
+ {
124504
+ "kind": "method",
124505
+ "name": "travel",
124506
+ "privacy": "private",
124507
+ "return": {
124508
+ "type": {
124509
+ "text": "boolean"
124510
+ }
124511
+ },
124512
+ "parameters": [
124513
+ {
124514
+ "name": "section",
124515
+ "type": {
124516
+ "text": "{ link: HTMLAnchorElement; target: Element }"
124517
+ }
124518
+ },
124519
+ {
124520
+ "name": "scroll",
124521
+ "type": {
124522
+ "text": "boolean"
124523
+ }
124524
+ }
124525
+ ],
124526
+ "description": "Marks the section a reader asked for, and holds the mark there until the\npage stops moving. Scrolls to it where `scroll` says this element does\nthe scrolling, and returns whether it did."
124527
+ },
123974
124528
  {
123975
124529
  "kind": "method",
123976
124530
  "name": "watch",
@@ -123989,6 +124543,17 @@
123989
124543
  "readonly": true,
123990
124544
  "description": "The set changed: watch it, and measure it.\n\nBoth, for the reason the tab strip records: the host renders before its\nlinks have anything to point at, so the first measurement finds nothing,\nand without a second one at `slotchange` the mark stays unplaced for the\nlife of the page."
123991
124545
  },
124546
+ {
124547
+ "kind": "method",
124548
+ "name": "writeDepths",
124549
+ "privacy": "private",
124550
+ "return": {
124551
+ "type": {
124552
+ "text": "void"
124553
+ }
124554
+ },
124555
+ "description": "Writes each link's depth in the outline, from 1, as `data-depth`: the\nlist items around it inside the outline, or for a flat run, its place in\nthe lists `data-level` makes of it.\n\nOn the consumer's links, as `aria-current` is, and only after the first\nrender, where a framework has hydrated them."
124556
+ },
123992
124557
  {
123993
124558
  "kind": "method",
123994
124559
  "name": "unland",
@@ -124425,6 +124990,15 @@
124425
124990
  "description": "The navigation's name, read by screen readers. A heading in the `heading`\nslot names it in place of this.",
124426
124991
  "fieldName": "label"
124427
124992
  },
124993
+ {
124994
+ "name": "marks",
124995
+ "type": {
124996
+ "text": "'reading' | 'visible'"
124997
+ },
124998
+ "default": "'reading'",
124999
+ "description": "Which links are marked. `reading` marks the one section being read, the\nlast whose heading has passed the reading line. `visible` marks every\nsection with part of it on screen, and the mark runs across their links.",
125000
+ "fieldName": "marks"
125001
+ },
124428
125002
  {
124429
125003
  "name": "offset",
124430
125004
  "type": {
@@ -129958,7 +130532,7 @@
129958
130532
  "declarations": [
129959
130533
  {
129960
130534
  "kind": "class",
129961
- "description": "Popover is the general overlay that the specific ones build on. `Menu` holds\ncommands, `Select` holds options, and `Tooltip` holds a description. Popover\nholds any content you put in it, so it has no keyboard handling of its own.\n\nThe trigger is slotted and stays your own element. A Helix trigger is told\nwhether the popover is open inside its own shadow root. On a plain element,\nsuch as a `<button>`, the popover writes `aria-expanded`, from a frame after\nits own first render, or from the first press where that comes sooner. It\nnever writes it where you wrote `aria-expanded` yourself, and writes nothing\nelse onto your markup.\n\nThe panel is in the top layer through the popover API, so it needs no\n`z-index`, and an ancestor with `overflow: hidden`, `transform`, `filter`, or\n`contain` does not clip or move it.\n\nIt opens on click and from a command. `command=\"--show\"` and the related\ncommands work as they do on `Dialog` and `Drawer`, so a button anywhere on\nthe page can open the popover with no script.\n\n**Opening moves focus into the panel**, to the first control in it, or to the\npanel itself where it holds none, and closing from inside gives it back to\nthe trigger. It closes on Escape, on a press outside it, and when focus moves\nout of the trigger and the panel to somewhere else on the page.\n\n`modal` keeps `Tab` inside the panel while it is open and says so with\n`aria-modal`, for a panel that has to be answered before the page goes on.\nThe rest of the page is hidden from screen readers with `aria-hidden` while\nit is open, so the virtual cursor stays in the panel too. Without it the\npopover does not trap focus.\n\nThe panel's name is `label` when you set it. Otherwise it is the first\nheading in the panel, or the elements an `aria-labelledby` on the host names.\nA development build warns when a popover opens with nothing but\n`fallback-label` to name it.\n\n**Keyboard.** Opening moves focus to the first control in the panel, or to\nthe panel where it holds none.\n\n| Key | What it does |\n|---|---|\n| Enter, Space | On the trigger, opens the panel, or closes it while it is open. |\n| Escape | Closes the panel and puts focus back on the trigger. |\n| Tab, Shift+Tab | Moves through the controls in the panel. Leaving the panel and the trigger closes it. With `modal`, moves from the last control round to the first and from the first round to the last. |\n\n`arrow` draws a point on the panel's edge facing the trigger. The side the\npanel landed on is on the host as `:state(placed-top)` and its kin, and the\ntrigger's width is on the panel as `--floating-anchor-inline-size`, for a\npanel as wide as its trigger:\n\n```css\nhelix-popover::part(popover) {\n min-inline-size: var(--floating-anchor-inline-size);\n}\n```",
130535
+ "description": "Popover is the general overlay that the specific ones build on. `Menu` holds\ncommands, `Select` holds options, and `Tooltip` holds a description. Popover\nholds any content you put in it, so it has no keyboard handling of its own.\n\nThe trigger is slotted and stays your own element. A Helix trigger is told\nwhether the popover is open inside its own shadow root. On a plain element,\nsuch as a `<button>`, the popover writes `aria-expanded`, from a frame after\nits own first render, or from the first press where that comes sooner. It\nnever writes it where you wrote `aria-expanded` yourself, and writes nothing\nelse onto your markup.\n\nThe panel is in the top layer through the popover API, so it needs no\n`z-index`, and an ancestor with `overflow: hidden`, `transform`, `filter`, or\n`contain` does not clip or move it.\n\nIt opens on click and from a command. `command=\"--show\"` and the related\ncommands work as they do on `Dialog` and `Drawer`, so a button anywhere on\nthe page can open the popover with no script. From its first press, a\nbutton that opens it this way says whether the popover is open: a Helix\nbutton through `expanded`, and any other element with `aria-expanded`.\n\n**Opening moves focus into the panel**, to the first control in it, or to the\npanel itself where it holds none, and closing from inside gives it back to\nthe trigger. It closes on Escape, on a press outside it, and when focus moves\nout of the trigger and the panel to somewhere else on the page.\n\n`modal` keeps `Tab` inside the panel while it is open and says so with\n`aria-modal`, for a panel that has to be answered before the page goes on.\nThe rest of the page is hidden from screen readers with `aria-hidden` while\nit is open, so the virtual cursor stays in the panel too, and the page does\nnot scroll behind it. Without it the popover does not trap focus.\n\nA press outside closes the panel and leaves focus where the press put it.\nWhere it put focus nowhere, as a press on text or on the page's background\ndoes, focus goes back to the trigger.\n\nThe panel's name is `label` when you set it. Otherwise it is the first\nheading in the panel, or the elements an `aria-labelledby` on the host names.\nA development build warns when a popover opens with nothing but\n`fallback-label` to name it.\n\n**Keyboard.** Opening moves focus to the first control in the panel, or to\nthe panel where it holds none.\n\n| Key | What it does |\n|---|---|\n| Enter, Space | On the trigger, opens the panel, or closes it while it is open. |\n| Escape | Closes the panel and puts focus back on the trigger. |\n| Tab, Shift+Tab | Moves through the controls in the panel. Leaving the panel and the trigger closes it. With `modal`, moves from the last control round to the first and from the first round to the last. |\n\nThe panel opens against the trigger, or against the element `anchor` names,\nsuch as a field beside the button that opens it. `offset` moves it away from\nthat element, `cross-offset` slides it along the side it is on,\n`container-padding` keeps it that far from the window's edges, and\n`flip=\"false\"` keeps it on its side where the other side has more room.\n\n`arrow` draws a point on the panel's edge facing the trigger. The side the\npanel landed on is on the host as `:state(placed-top)` and its kin, its\nalignment along that side as `:state(aligned-start)` or\n`:state(aligned-end)`, and the trigger's width is on the panel as\n`--floating-anchor-inline-size`, for a panel as wide as its trigger:\n\n```css\nhelix-popover::part(popover) {\n min-inline-size: var(--floating-anchor-inline-size);\n}\n```",
129962
130536
  "name": "HelixHeadlessPopover",
129963
130537
  "cssProperties": [
129964
130538
  {
@@ -130021,6 +130595,16 @@
130021
130595
  "default": "'helix-popover'",
130022
130596
  "description": "The key this family's words are registered under, its styled tag:\n`registerWords('de', { 'helix-popover': { fallbackLabel: 'Popup' } })`."
130023
130597
  },
130598
+ {
130599
+ "kind": "field",
130600
+ "name": "anchor",
130601
+ "type": {
130602
+ "text": "Element | string"
130603
+ },
130604
+ "default": "''",
130605
+ "description": "The element the panel opens against, where that is not the trigger: its\n`id` in the same document or shadow root, or the element itself. Left\nempty, the panel opens against the trigger, or against the button whose\ncommand opened it.",
130606
+ "attribute": "anchor"
130607
+ },
130024
130608
  {
130025
130609
  "kind": "field",
130026
130610
  "name": "arrow",
@@ -130031,6 +130615,25 @@
130031
130615
  "description": "Draws a point on the panel's edge facing the trigger.\n\nOff by default, which is the house style: a panel that opens from its\ntrigger already reads as belonging to it.",
130032
130616
  "attribute": "arrow"
130033
130617
  },
130618
+ {
130619
+ "kind": "field",
130620
+ "name": "containerPadding",
130621
+ "type": {
130622
+ "text": "number | undefined"
130623
+ },
130624
+ "description": "How close to the window's edges the panel may come, in pixels, when it\nslides, shrinks or moves to the other side to fit. Left unset, it slides\nand shrinks to 8 pixels from an edge and moves to the other side only\nonce it would cross one.",
130625
+ "attribute": "container-padding"
130626
+ },
130627
+ {
130628
+ "kind": "field",
130629
+ "name": "crossOffset",
130630
+ "type": {
130631
+ "text": "number"
130632
+ },
130633
+ "default": "0",
130634
+ "description": "How far to slide the panel along the side it is on, in pixels: to the\nright on the top or the bottom, and down on the left or the right.",
130635
+ "attribute": "cross-offset"
130636
+ },
130034
130637
  {
130035
130638
  "kind": "field",
130036
130639
  "name": "fallbackLabel",
@@ -130044,6 +130647,16 @@
130044
130647
  "words": true
130045
130648
  }
130046
130649
  },
130650
+ {
130651
+ "kind": "field",
130652
+ "name": "flip",
130653
+ "type": {
130654
+ "text": "boolean"
130655
+ },
130656
+ "default": "true",
130657
+ "description": "Whether the panel moves to the other side of the trigger when its own\nside has no room. On by default. Write `flip=\"false\"` to keep it on its\nside, where it shrinks to fit, as React Aria's `shouldFlip` turns off.",
130658
+ "attribute": "flip"
130659
+ },
130047
130660
  {
130048
130661
  "kind": "field",
130049
130662
  "name": "label",
@@ -130103,7 +130716,7 @@
130103
130716
  "name": "panel",
130104
130717
  "privacy": "private",
130105
130718
  "readonly": true,
130106
- "default": "new PopoverController(this, { anchor: () => this.trigger, arrow: () => this.partNamed('arrow'), /* The host *and* whatever invoked it, never the panel alone. An outside press is measured against this, and the host is not a box to rely on, a sheet being free to give it none, so a boundary of the panel alone would close on the very press that opened it. A `--toggle` button outside the host is part of the control by any reading a reader would give it: pressing it while the panel is open should close it once, not close it on `pointerdown` and reopen it on the `click` that follows. */ boundary: (): (HTMLElement | undefined)[] => [this, this.invoker], /* Measured to the point where there is one, as `Tooltip` measures it: the arrow is a square turned on its center, which reaches `n / sqrt(2)` past the edge it sits on. */ offset: () => this.offset + arrowReach(this.partNamed('arrow')), onDismiss: () => this.hide(), /* The side the panel landed on, for a sheet outside that draws by side, where no attribute can follow `::part()`. As `Tooltip` records it. */ onPlace: (placement) => { const side = sideOf(placement) this.toggleState('placed-bottom', side === 'bottom') this.toggleState('placed-left', side === 'left') this.toggleState('placed-right', side === 'right') this.toggleState('placed-top', side === 'top') this.side = side }, open: () => this.open, placement: () => this.placement, surface: () => this.partNamed('popover'), })"
130719
+ "default": "new PopoverController(this, { anchor: () => this.placedAgainst, arrow: () => this.partNamed('arrow'), /* The host *and* whatever invoked it, never the panel alone. An outside press is measured against this, and the host is not a box to rely on, a sheet being free to give it none, so a boundary of the panel alone would close on the very press that opened it. A `--toggle` button outside the host is part of the control by any reading a reader would give it: pressing it while the panel is open should close it once, not close it on `pointerdown` and reopen it on the `click` that follows. */ boundary: (): (HTMLElement | undefined)[] => [this, this.invoker], crossOffset: () => this.crossOffset, flip: () => this.flip, /* Measured to the point where there is one, as `Tooltip` measures it: the arrow is a square turned on its center, which reaches `n / sqrt(2)` past the edge it sits on. */ offset: () => this.offset + arrowReach(this.partNamed('arrow')), onDismiss: () => this.dismiss(), /* The side the panel landed on, for a sheet outside that draws by side, where no attribute can follow `::part()`. As `Tooltip` records it. */ onPlace: (placement) => { const side = sideOf(placement) this.toggleState('aligned-end', placement.endsWith('-end')) this.toggleState('aligned-start', placement.endsWith('-start')) this.toggleState('placed-bottom', side === 'bottom') this.toggleState('placed-left', side === 'left') this.toggleState('placed-right', side === 'right') this.toggleState('placed-top', side === 'top') this.side = side }, open: () => this.open, padding: () => this.containerPadding, placement: () => this.placement, surface: () => this.partNamed('popover'), })"
130107
130720
  },
130108
130721
  {
130109
130722
  "kind": "field",
@@ -130166,11 +130779,11 @@
130166
130779
  "name": "commands",
130167
130780
  "privacy": "protected",
130168
130781
  "readonly": true,
130169
- "default": "new CommandController(this, { commands: { '--close': () => this.hide(), '--show': (source: Element | null) => { this.invoker = source instanceof HTMLElement ? source : undefined this.show() }, '--toggle': (source: Element | null) => { this.invoker = source instanceof HTMLElement ? source : undefined if (this.open) { this.hide() } else { this.show() } }, }, })"
130782
+ "default": "new CommandController(this, { commands: { '--close': () => this.hide(), '--show': (source: Element | null) => { this.invoker = source instanceof HTMLElement ? source : undefined this.show() }, '--toggle': (source: Element | null) => { this.invoker = source instanceof HTMLElement ? source : undefined if (this.open) { this.hide() } else { this.show() } }, }, expanded: () => this.open, })"
130170
130783
  },
130171
130784
  {
130172
130785
  "kind": "field",
130173
- "name": "trigger",
130786
+ "name": "placedAgainst",
130174
130787
  "type": {
130175
130788
  "text": "HTMLElement"
130176
130789
  },
@@ -130178,6 +130791,27 @@
130178
130791
  "description": "The element the panel opens against.",
130179
130792
  "readonly": true
130180
130793
  },
130794
+ {
130795
+ "kind": "field",
130796
+ "name": "trigger",
130797
+ "type": {
130798
+ "text": "HTMLElement"
130799
+ },
130800
+ "privacy": "private",
130801
+ "description": "The element that opened the panel, which focus goes back to.",
130802
+ "readonly": true
130803
+ },
130804
+ {
130805
+ "kind": "method",
130806
+ "name": "dismiss",
130807
+ "privacy": "private",
130808
+ "return": {
130809
+ "type": {
130810
+ "text": "void"
130811
+ }
130812
+ },
130813
+ "description": "A press outside, or Escape, closing the panel.\n\n**Focus goes back to the trigger where the press put it nowhere.** The\npress is heard on `pointerdown`, and the browser moves focus a moment\nlater: onto what was pressed where that takes focus, and to the body where\nit does not. A popover dismissed by a press on text was left with focus on\nthe body, measured in Chromium, where React Aria's returns it to the\ntrigger. Read after the press, once the browser has moved it."
130814
+ },
130181
130815
  {
130182
130816
  "kind": "method",
130183
130817
  "name": "show",
@@ -130814,6 +131448,15 @@
130814
131448
  }
130815
131449
  ],
130816
131450
  "attributes": [
131451
+ {
131452
+ "name": "anchor",
131453
+ "type": {
131454
+ "text": "Element | string"
131455
+ },
131456
+ "default": "''",
131457
+ "description": "The element the panel opens against, where that is not the trigger: its\n`id` in the same document or shadow root, or the element itself. Left\nempty, the panel opens against the trigger, or against the button whose\ncommand opened it.",
131458
+ "fieldName": "anchor"
131459
+ },
130817
131460
  {
130818
131461
  "name": "arrow",
130819
131462
  "type": {
@@ -130823,6 +131466,23 @@
130823
131466
  "description": "Draws a point on the panel's edge facing the trigger.\n\nOff by default, which is the house style: a panel that opens from its\ntrigger already reads as belonging to it.",
130824
131467
  "fieldName": "arrow"
130825
131468
  },
131469
+ {
131470
+ "name": "container-padding",
131471
+ "type": {
131472
+ "text": "number | undefined"
131473
+ },
131474
+ "description": "How close to the window's edges the panel may come, in pixels, when it\nslides, shrinks or moves to the other side to fit. Left unset, it slides\nand shrinks to 8 pixels from an edge and moves to the other side only\nonce it would cross one.",
131475
+ "fieldName": "containerPadding"
131476
+ },
131477
+ {
131478
+ "name": "cross-offset",
131479
+ "type": {
131480
+ "text": "number"
131481
+ },
131482
+ "default": "0",
131483
+ "description": "How far to slide the panel along the side it is on, in pixels: to the\nright on the top or the bottom, and down on the left or the right.",
131484
+ "fieldName": "crossOffset"
131485
+ },
130826
131486
  {
130827
131487
  "name": "fallback-label",
130828
131488
  "type": {
@@ -130832,6 +131492,15 @@
130832
131492
  "description": "The panel's name where nothing else names it: no `label`, no heading in\nthe panel, and no `aria-labelledby` on the host.",
130833
131493
  "fieldName": "fallbackLabel"
130834
131494
  },
131495
+ {
131496
+ "name": "flip",
131497
+ "type": {
131498
+ "text": "boolean"
131499
+ },
131500
+ "default": "true",
131501
+ "description": "Whether the panel moves to the other side of the trigger when its own\nside has no room. On by default. Write `flip=\"false\"` to keep it on its\nside, where it shrinks to fit, as React Aria's `shouldFlip` turns off.",
131502
+ "fieldName": "flip"
131503
+ },
130835
131504
  {
130836
131505
  "name": "label",
130837
131506
  "type": {
@@ -130895,6 +131564,14 @@
130895
131564
  }
130896
131565
  ],
130897
131566
  "cssStates": [
131567
+ {
131568
+ "description": "While the panel is aligned to the end of the side it sits on.",
131569
+ "name": "aligned-end"
131570
+ },
131571
+ {
131572
+ "description": "While the panel is aligned to the start of the side it sits on.",
131573
+ "name": "aligned-start"
131574
+ },
130898
131575
  {
130899
131576
  "description": "From the moment the panel shows until its entrance has finished.",
130900
131577
  "name": "entering"
@@ -140865,7 +141542,7 @@
140865
141542
  "declarations": [
140866
141543
  {
140867
141544
  "kind": "class",
140868
- "description": "A trigger that opens a `Listbox`. The list is the same element you can use on\nits own, with the same keyboard behavior, filtering, and multi-select rules.\nSelect adds a trigger that shows what is chosen, a floating surface, and a\nplace for focus to return to when the list closes.\n\nYour options stay in your light DOM and are slotted through into the listbox,\nso the listbox looks through slots to find them. For a list too long to draw\nwhole, set `items` instead: the list draws only the options in sight, as\nListbox's `items` does, and the trigger, its keys and the form read the\nwhole set.\n\n`Select` owns the value, passes it down to the listbox, and takes changes\nback, so the value lives in one place. With `multiple`, the value is the\nchosen values joined with commas, and the form receives one entry for each.\nAn option's value may hold a comma, and it is read as one value.\n\nSet `valueContent` to draw the trigger's content from the chosen options,\nand several chosen options are written as a list in the reader's language.\n\n**Keyboard.** On the closed trigger:\n\n| Key | What it does |\n|---|---|\n| Down, Enter, Space | Opens the list on the chosen option, or the first. |\n| Up | Opens the list on the chosen option, or the last. |\n| Home, End | Opens the list on the first or the last option. |\n| Left, Right | Chooses the option before or after the chosen one without opening, as React Aria's Select does, in either direction of text. |\n| A letter or a word | Chooses the option whose words start with what you typed, as a native `<select>` does. With `multiple`, opens the list on it. |\n\nIn the open list, which is a `Listbox`:\n\n| Key | What it does |\n|---|---|\n| Down, Up, Home, End, Page Down, Page Up | Moves the highlight. |\n| A letter or a word | Moves the highlight to the next option whose words start with what you typed. |\n| Enter, Space | Chooses the highlighted option and closes the list. With `multiple`, toggles it and leaves the list open. |\n| Escape | Closes the list and puts focus back on the trigger. |\n| Tab | Closes the list and moves on. |\n\nA choice made on the closed trigger is said aloud on Apple devices, where\nVoiceOver does not read the trigger's new name.\n\n**ARIA.** The trigger is a `button` with `aria-haspopup=\"listbox\"` and\n`aria-expanded`, named by the label and then the chosen words, as a native\n`<select>` is. The list is the listbox `Listbox` describes, named by the\nlabel, or by `list-label` where there is none.\n\nSet `autocomplete` to let a browser's autofill choose, as a native `<select>`\nwith the same attribute would.",
141545
+ "description": "A trigger that opens a `Listbox`. The list is the same element you can use on\nits own, with the same keyboard behavior, filtering, and multi-select rules.\nSelect adds a trigger that shows what is chosen, a floating surface, and a\nplace for focus to return to when the list closes.\n\nYour options stay in your light DOM and are slotted through into the listbox,\nso the listbox looks through slots to find them. For a list too long to draw\nwhole, set `items` instead: the list draws only the options in sight, as\nListbox's `items` does, and the trigger, its keys and the form read the\nwhole set.\n\n`Select` owns the value, passes it down to the listbox, and takes changes\nback, so the value lives in one place. With `multiple`, the value is the\nchosen values joined with commas, and the form receives one entry for each.\nAn option's value may hold a comma, and it is read as one value.\n\nSet `valueContent` to draw the trigger's content from the chosen options,\nand several chosen options are written as a list in the reader's language.\n\n**Keyboard.** On the closed trigger:\n\n| Key | What it does |\n|---|---|\n| Down, Enter, Space | Opens the list on the chosen option, or the first. |\n| Up | Opens the list on the chosen option, or the last. |\n| Home, End | Opens the list on the first or the last option. |\n| Left, Right | Chooses the option before or after the chosen one without opening, as React Aria's Select does. On a right-to-left page Left chooses the one after. |\n| A letter or a word | Chooses the option whose words start with what you typed, as a native `<select>` does. With `multiple`, opens the list on it. |\n\nIn the open list, which is a `Listbox`:\n\n| Key | What it does |\n|---|---|\n| Down, Up, Home, End, Page Down, Page Up | Moves the highlight. |\n| A letter or a word | Moves the highlight to the next option whose words start with what you typed. |\n| Enter, Space | Chooses the highlighted option and closes the list. With `multiple`, toggles it and leaves the list open. |\n| Escape | Closes the list and puts focus back on the trigger. |\n| Tab | Closes the list and moves on. |\n\nA choice made on the closed trigger is said aloud on Apple devices, where\nVoiceOver does not read the trigger's new name.\n\n**ARIA.** The trigger is a `button` with `aria-haspopup=\"listbox\"` and\n`aria-expanded`, named by the label and then the chosen words, as a native\n`<select>` is. The list is the listbox `Listbox` describes, named by the\nlabel, or by `list-label` where there is none.\n\nSet `autocomplete` to let a browser's autofill choose, as a native `<select>`\nwith the same attribute would.",
140869
141546
  "name": "HelixHeadlessSelect",
140870
141547
  "cssProperties": [
140871
141548
  {
@@ -141398,7 +142075,7 @@
141398
142075
  "name": "handleTriggerKeydown",
141399
142076
  "privacy": "private",
141400
142077
  "readonly": true,
141401
- "description": "The keys of the closed trigger.\n\nLetters choose without opening, the way a native `<select>` and React\nAria's Select do, so a reader who knows the answer types it. A Space in the\nmiddle of those letters is one of them. With `multiple`, a letter opens the\nlist on the match instead, because adding to a set is a choice the reader\nmakes in the list. ArrowLeft and ArrowRight choose the option before and\nafter the chosen one."
142078
+ "description": "The keys of the closed trigger.\n\nLetters choose without opening, the way a native `<select>` and React\nAria's Select do, so a reader who knows the answer types it. A Space in the\nmiddle of those letters is one of them. With `multiple`, a letter opens the\nlist on the match instead, because adding to a set is a choice the reader\nmakes in the list. ArrowLeft and ArrowRight choose the option before and\nafter the chosen one, the other way round on a right-to-left page."
141402
142079
  },
141403
142080
  {
141404
142081
  "kind": "method",
@@ -149624,7 +150301,44 @@
149624
150301
  "text": "void"
149625
150302
  }
149626
150303
  },
149627
- "description": "Tells a slotted trigger what it is doing, since it cannot know.\n\nThe fallback button is rendered by this element and says so in its own\ntemplate. A trigger the consumer slotted is their markup, and the state it\nneeds to announce is state only this element holds: without this, the\narrangement this component recommends, an icon button slotted as the\ntrigger, is a control that opens a menu and never says it has one. A\nconsumer who has to mirror `open` back onto their own trigger is a consumer\nwho will forget, and the failure is silent to everyone who can see the\nscreen.\n\n**Never `setAttribute`.** Writing `aria-expanded` onto the consumer's\nelement is a hydration mismatch React reports and does not patch up,\nmeasured against React 19.2.8. `tellDisclosure` carries the argument and the\nmeasurement: the state travels as a property, into the trigger's own shadow\nroot, where React neither looks nor compares.\n\n`aria-haspopup` goes with it rather than being written separately. An\nattribute the consumer's server never sent is a mismatch whether or not it\nmoves afterwards, measured in both load orders, and a trigger that says it\nis expanded is already saying it has something to expand."
150304
+ "description": "Tells a slotted trigger what it is doing, since it cannot know.\n\nThe fallback button is rendered by this element and says so in its own\ntemplate. A trigger the consumer slotted is their markup, and the state it\nneeds to announce is state only this element holds: without this, the\narrangement this component recommends, an icon button slotted as the\ntrigger, is a control that opens a menu and never says it has one. A\nconsumer who has to mirror `open` back onto their own trigger is a consumer\nwho will forget, and the failure is silent to everyone who can see the\nscreen.\n\n**Never `setAttribute`.** Writing `aria-expanded` onto the consumer's\nelement is a hydration mismatch React reports and does not patch up,\nmeasured against React 19.2.8. `tellDisclosure` carries the argument and the\nmeasurement: the state travels as a property, into the trigger's own shadow\nroot, where React neither looks nor compares.\n\n`aria-haspopup` goes with it rather than being written separately. An\nattribute the consumer's server never sent is a mismatch whether or not it\nmoves afterwards, measured in both load orders, and a trigger that says it\nis expanded is already saying it has something to expand.\n\n**A plain trigger once a reader has reached it.** A `<button>` of yours has\nno shadow root, so it takes `aria-haspopup=\"menu\"` and `aria-expanded` as\nattributes, written only once focus or a pointer has reached it. That is\nafter hydration, which is the only time React compares them. A trigger\nthat carries either attribute itself is yours to keep up to date."
150305
+ },
150306
+ {
150307
+ "kind": "field",
150308
+ "name": "toldPlain",
150309
+ "type": {
150310
+ "text": "Element | undefined"
150311
+ },
150312
+ "privacy": "private",
150313
+ "description": "The plain trigger this dial has written its state on, so it can be taken back."
150314
+ },
150315
+ {
150316
+ "kind": "field",
150317
+ "name": "reached",
150318
+ "type": {
150319
+ "text": "boolean"
150320
+ },
150321
+ "privacy": "private",
150322
+ "default": "false",
150323
+ "description": "Whether a reader has reached the trigger, by focus or a pointer, which is after hydration."
150324
+ },
150325
+ {
150326
+ "kind": "method",
150327
+ "name": "untellPlain",
150328
+ "privacy": "private",
150329
+ "return": {
150330
+ "type": {
150331
+ "text": "void"
150332
+ }
150333
+ },
150334
+ "description": "Takes the state off a plain trigger that is no longer this dial's."
150335
+ },
150336
+ {
150337
+ "kind": "field",
150338
+ "name": "handleReach",
150339
+ "privacy": "private",
150340
+ "readonly": true,
150341
+ "description": "A reader reaching the trigger, which lets a plain one be told its state."
149628
150342
  },
149629
150343
  {
149630
150344
  "kind": "field",
@@ -150334,7 +151048,7 @@
150334
151048
  "declarations": [
150335
151049
  {
150336
151050
  "kind": "class",
150337
- "description": "A splitter has one axis. Nest splitters to get two axes and three-pane or\nfour-pane layouts.\n\nWhen a splitter is slotted into a pane of another at a right angle, a corner\nhandle appears where the dividers cross. It shows the `move` cursor, responds\nto both arrow axes, and a drag moves both dividers at once. The corner is\nadded at `firstUpdated` and is not in the server markup. Before it appears,\nboth dividers work on their own.\n\nThe divider has `role=\"separator\"` and `aria-valuenow`, with\n`aria-valuetext` saying the start pane's share as a percentage in the\nnearest `lang`, or in the reader's locale where no `lang` is set, and `aria-controls` names the start pane. Drag it with a pointer or move it with the arrow keys,\npress `Home` or `End` to move it to its bounds, and press `Enter` to collapse\nthe start pane and open it again. A drag in progress is tracked as a state, so both dividers a\ncorner moves stay lit for as long as they move.\n\nBy default, `min` and `max` let the divider reach either edge, so you can\ndrag a pane fully closed. Set them to limit the range.\n\nA pane can be collapsed, which is a separate state from a divider at the\nedge. `collapsed` names the shut pane, `start` or `end`, and the pane opens\nback to the position where the collapsing gesture began. A drag records that position\non press, and every other way of collapsing records it in `settle`.\n`collapsed-size` keeps a sliver of the pane visible, such as a tab strip.\nCollapsing overrides `min` and `max`.\n\nSet `primary` to the pane that keeps its size when the splitter's own size\nchanges, such as a sidebar beside a window being resized. The other pane\ntakes all of the change, as Web Awesome's split panel does. Without it,\nboth panes keep their share.\n\n**Three or more panes along one axis are splitters nested on that axis**, a\nsplitter in the `end` pane of another for three columns. The nested one\nkeeps the pane on its far side the size it was while the outer divider\nmoves, so a divider resizes only the two panes beside it, as Zag's splitter\ndoes with any number of panels. Where the whole row is resized, every pane\nkeeps its share, unless `primary` says otherwise.\n\n**Keyboard.** The divider is one tab stop.\n\n| Key | What it does |\n|---|---|\n| Left, Right | Moves a side-by-side divider by `step`. On a right-to-left page, Left moves it toward the end. |\n| Up, Down | Moves a stacked divider by `step`. |\n| Home, End | Moves the divider to its bounds. |\n| Enter | Collapses the start pane, and opens it again. |\n| F6 | Moves focus from one pane to the first control in the other, and from the divider to the start pane. |",
151051
+ "description": "A splitter has one axis. Nest splitters to get two axes and three-pane or\nfour-pane layouts.\n\nWhen a splitter is slotted into a pane of another at a right angle, a corner\nhandle appears where the dividers cross. It shows the `move` cursor, responds\nto both arrow axes, and a drag moves both dividers at once. The corner is\nadded at `firstUpdated` and is not in the server markup. Before it appears,\nboth dividers work on their own.\n\nThe divider has `role=\"separator\"` and `aria-valuenow`, with\n`aria-valuetext` saying the start pane's share as a percentage in the\nnearest `lang`, or in the reader's locale where no `lang` is set, and `aria-controls` names the start pane. Drag it with a pointer or move it with the arrow keys,\npress `Home` or `End` to move it to its bounds, and press `Enter` to collapse\nthe start pane and open it again. A drag in progress is tracked as a state, so both dividers a\ncorner moves stay lit for as long as they move.\n\nBy default, `min` and `max` let the divider reach either edge, so you can\ndrag a pane fully closed. Set them to limit the range.\n\nA pane can be collapsed, which is a separate state from a divider at the\nedge. `collapsed` names the shut pane, `start` or `end`, and the pane opens\nback to the position where the collapsing gesture began. A drag records that position\non press, and every other way of collapsing records it in `settle`.\n`collapsed-size` keeps a sliver of the pane visible, such as a tab strip.\nCollapsing overrides `min` and `max`. `collapsible` says which panes can be\ncollapsed at all, as Zag's panels each say.\n\n`min` is the least the start pane keeps and `end-min` the least the end pane\nkeeps, each a percentage or a CSS length such as `16rem`.\n\nSet `primary` to the pane that keeps its size when the splitter's own size\nchanges, such as a sidebar beside a window being resized. The other pane\ntakes all of the change, as Web Awesome's split panel does. Without it,\nboth panes keep their share.\n\n**Three or more panes along one axis are splitters nested on that axis**, a\nsplitter in the `end` pane of another for three columns. The nested one\nkeeps the pane on its far side the size it was while the outer divider\nmoves, so a divider resizes only the two panes beside it, as Zag's splitter\ndoes with any number of panels. Where the whole row is resized, every pane\nkeeps its share, unless `primary` says otherwise.\n\n**Keyboard.** The divider is one tab stop.\n\n| Key | What it does |\n|---|---|\n| Left, Right | Moves a side-by-side divider by `step`. On a right-to-left page, Left moves it toward the end. |\n| Up, Down | Moves a stacked divider by `step`. |\n| Home, End | Moves the divider to its bounds. |\n| Enter | Collapses the start pane, or the end pane where `collapsible=\"end\"`, and opens it again. |\n| F6 | Moves focus from one pane to the first control in the other, and from the divider to the start pane. |",
150338
151052
  "name": "HelixHeadlessSplitter",
150339
151053
  "cssProperties": [
150340
151054
  {
@@ -150421,6 +151135,15 @@
150421
151135
  "description": "How much of a shut pane is still shown, as a percentage.\n\nZero by default, which is a pane fully gone. A tab strip or a title bar\nthat should survive its own collapse says how much of itself to keep, and\nonly whoever put it there knows that, which is the same reason `min` is a\nconsumer's to set.",
150422
151136
  "attribute": "collapsed-size"
150423
151137
  },
151138
+ {
151139
+ "kind": "field",
151140
+ "name": "collapsible",
151141
+ "type": {
151142
+ "text": "'both' | 'end' | 'none' | 'start' | undefined"
151143
+ },
151144
+ "description": "Which panes can be collapsed, as Zag's panels each take `collapsible`:\n`start`, `end`, `both`, or `none`. A pane that cannot be collapsed stops\nat the edge without shutting. `Enter` collapses the end pane where only\nthe end pane can be collapsed, and the start pane otherwise.\n\nUnset is `both`, and the attribute stays absent until you write it.",
151145
+ "attribute": "collapsible"
151146
+ },
150424
151147
  {
150425
151148
  "kind": "field",
150426
151149
  "name": "cornerLabel",
@@ -150466,6 +151189,16 @@
150466
151189
  "description": "Where the divider starts, when `position` is not set.",
150467
151190
  "attribute": "default-position"
150468
151191
  },
151192
+ {
151193
+ "kind": "field",
151194
+ "name": "endMin",
151195
+ "type": {
151196
+ "text": "number | string"
151197
+ },
151198
+ "default": "0",
151199
+ "description": "The least the end pane keeps, in the units `min` takes: a percentage, or\na CSS length such as `16rem` resolved against the splitter's box. The\ndivider stops that far from the end, whatever `max` allows, so `min` and\n`end-min` hold a minimum for each pane, as Zag's panels each take\n`minSize`.",
151200
+ "attribute": "end-min"
151201
+ },
150469
151202
  {
150470
151203
  "kind": "field",
150471
151204
  "name": "label",
@@ -150891,6 +151624,25 @@
150891
151624
  ],
150892
151625
  "description": "The collapse a settled position amounts to, if any, so a pane dragged shut\nand a pane shut by a consumer's button are the same state.\n\nNo separate threshold. Landing on the collapsed size *is* the gesture, and\n`clamp` puts every overshoot exactly on the bound, so the default of zero\nlatches on any drag that runs off the end."
150893
151626
  },
151627
+ {
151628
+ "kind": "method",
151629
+ "name": "canCollapse",
151630
+ "privacy": "private",
151631
+ "return": {
151632
+ "type": {
151633
+ "text": "boolean"
151634
+ }
151635
+ },
151636
+ "parameters": [
151637
+ {
151638
+ "name": "pane",
151639
+ "type": {
151640
+ "text": "'end' | 'start'"
151641
+ }
151642
+ }
151643
+ ],
151644
+ "description": "Whether `collapsible` lets this pane be collapsed."
151645
+ },
150894
151646
  {
150895
151647
  "kind": "method",
150896
151648
  "name": "clamp",
@@ -151581,6 +152333,14 @@
151581
152333
  "description": "How much of a shut pane is still shown, as a percentage.\n\nZero by default, which is a pane fully gone. A tab strip or a title bar\nthat should survive its own collapse says how much of itself to keep, and\nonly whoever put it there knows that, which is the same reason `min` is a\nconsumer's to set.",
151582
152334
  "fieldName": "collapsedSize"
151583
152335
  },
152336
+ {
152337
+ "name": "collapsible",
152338
+ "type": {
152339
+ "text": "'both' | 'end' | 'none' | 'start' | undefined"
152340
+ },
152341
+ "description": "Which panes can be collapsed, as Zag's panels each take `collapsible`:\n`start`, `end`, `both`, or `none`. A pane that cannot be collapsed stops\nat the edge without shutting. `Enter` collapses the end pane where only\nthe end pane can be collapsed, and the start pane otherwise.\n\nUnset is `both`, and the attribute stays absent until you write it.",
152342
+ "fieldName": "collapsible"
152343
+ },
151584
152344
  {
151585
152345
  "name": "corner-label",
151586
152346
  "type": {
@@ -151616,6 +152376,15 @@
151616
152376
  "description": "Where the divider starts, when `position` is not set.",
151617
152377
  "fieldName": "defaultPosition"
151618
152378
  },
152379
+ {
152380
+ "name": "end-min",
152381
+ "type": {
152382
+ "text": "number | string"
152383
+ },
152384
+ "default": "0",
152385
+ "description": "The least the end pane keeps, in the units `min` takes: a percentage, or\na CSS length such as `16rem` resolved against the splitter's box. The\ndivider stops that far from the end, whatever `max` allows, so `min` and\n`end-min` hold a minimum for each pane, as Zag's panels each take\n`minSize`.",
152386
+ "fieldName": "endMin"
152387
+ },
151619
152388
  {
151620
152389
  "name": "label",
151621
152390
  "type": {
@@ -163974,7 +164743,7 @@
163974
164743
  "declarations": [
163975
164744
  {
163976
164745
  "kind": "class",
163977
- "description": "A part of `Tag` that holds tags as one control: a grid of rows, one tab stop\nfor the whole set. The arrow keys move between tags, Home and End go to the\nfirst and the last, and a typed letter goes to the next tag starting with\nit. Delete or Backspace removes the focused tag where it is `dismissible`,\nby sending its `helix-dismiss`: remove it from your list in the handler, and\nfocus moves to the next tag, or the previous one after the last.\n\n`selection-mode` lets a reader select tags, with Space, Enter or a press:\n`single` selects one at a time and `multiple` any number. In `multiple`,\nShift with an arrow, Home or End selects the range from the tag last\npressed to the tag focus moves to, Shift with a press or Space selects the\nrange to that tag, and Control or Command with A selects every tag that is\nnot disabled. `selection-behavior=\"replace\"` selects the tag a reader\npresses or moves to alone, as a file list does, and Control or Command\nwith a press or Space adds or takes out one tag. `disallow-empty-selection`\nkeeps one tag selected once one is. `value` holds the\nselected tags' values, separated by commas, and a change asks with\n`helix-before-change` and tells with `change`. Enter on a tag with an\n`href` follows its link. A `disabled` tag is passed over. A selected tag\nthat is removed leaves `value`, which then sends `change`.\n\nName the set with `label`. Each tag is named by its words alone, without\nits remove button. `value` takes an array of values on the property as\nwell, as React sets `value={['Apple']}`; a press writes it back as a\nstring.\n\n**Removing the last tag keeps focus in the group.** With no tags left the\nset is a `group`, and focus moves to its `empty` part,\nwhich holds the `empty` slot: put words there such as \"No filters\" for a\nreader to hear. With nothing slotted it says `empty-label`, \"No tags\".\nWhere only disabled tags are left, the first of them holds the tab stop and\ntakes focus, so the reader stays in the set.",
164746
+ "description": "A part of `Tag` that holds tags as one control: a grid of rows, one tab stop\nfor the whole set. The arrow keys move between tags, Home and End go to the\nfirst and the last, and a typed letter goes to the next tag starting with\nit. Delete or Backspace removes the focused tag where it is `dismissible`,\nby sending its `helix-dismiss`: remove it from your list in the handler, and\nfocus moves to the next tag, or the previous one after the last.\n\n`selection-mode` lets a reader select tags, with Space, Enter or a press:\n`single` selects one at a time and `multiple` any number. In `multiple`,\nShift with an arrow, Home or End selects the range from the tag last\npressed to the tag focus moves to, Shift with a press or Space selects the\nrange to that tag, and Control or Command with A selects every tag that is\nnot disabled. `selection-behavior=\"replace\"` selects the tag a reader\npresses or moves to alone, as a file list does, and Control or Command\nwith a press or Space adds or takes out one tag. `disallow-empty-selection`\nkeeps one tag selected once one is, and Escape lets go of the selection\notherwise. `value` holds the\nselected tags' values, separated by commas, and a change asks with\n`helix-before-change` and tells with `change`. Enter on a tag with an\n`href` follows its link. A `disabled` tag is passed over. A selected tag\nthat is removed leaves `value`, which then sends `change`.\n\nName the set with `label`. Each tag is named by its words alone, without\nits remove button. `value` takes an array of values on the property as\nwell, as React sets `value={['Apple']}`; a press writes it back as a\nstring.\n\n**Removing the last tag keeps focus in the group.** With no tags left the\nset is a `group`, and focus moves to its `empty` part,\nwhich holds the `empty` slot: put words there such as \"No filters\" for a\nreader to hear. With nothing slotted it says `empty-label`, \"No tags\".\nWhere only disabled tags are left, the first of them holds the tab stop and\ntakes focus, so the reader stays in the set.\n\n**Typing new tags.** A field where people type tags and press Enter to add\neach one is Combobox with `multiple` and `allows-custom-value`, or\n`creatable` to ask first with `helix-create`. It draws each value as a tag,\nBackspace on the empty field removes the last one, and the arrow keys move\nbetween them.",
163978
164747
  "name": "HelixHeadlessTagGroup",
163979
164748
  "cssParts": [
163980
164749
  {
@@ -164887,7 +165656,7 @@
164887
165656
  "declarations": [
164888
165657
  {
164889
165658
  "kind": "class",
164890
- "description": "A label that people can optionally remove. `dismissible` is the difference\nfrom a badge: a badge shows a state that people cannot change, and a tag\nnames something they can remove.\n\nThe remove button sends `helix-dismiss`. The tag does not remove itself,\nbecause your code owns the list it is in, so remove it in your handler. A\nlistener can cancel `helix-dismiss`, and `dismiss()` then returns `false`.\nWhen the handler removes a tag whose remove button has focus, focus moves to\nthe next tag's remove button, or to the previous one's after the last tag.\n\nThe remove button is named for its tag, such as \"Remove Apple\", so a list of\nbuttons says which tag each one removes. Write `{label}` in `dismiss-label`\nto put the tag's words somewhere else, such as `dismiss-label=\"{label}\nentfernen\"`.\n\n`href` makes the label a link, and `disabled` takes the tag out of reach: its\nlink and its remove button stop answering.\n\n**In a `Tag.Group` a tag is a row of a grid.** The group gives it its role,\nits place in the one tab stop and, where the group selects, whether it is\nselected. Its remove button leaves the tab order there, Delete and Backspace\ndoing its job from the row.",
165659
+ "description": "A label that people can optionally remove. `dismissible` is the difference\nfrom a badge: a badge shows a state that people cannot change, and a tag\nnames something they can remove.\n\nThe remove button sends `helix-dismiss`. The tag does not remove itself,\nbecause your code owns the list it is in, so remove it in your handler. A\nlistener can cancel `helix-dismiss`, and `dismiss()` then returns `false`.\nWhen the handler removes a tag whose remove button has focus, focus moves to\nthe next tag's remove button, or to the previous one's after the last tag.\n\nThe remove button is named for its tag, such as \"Remove Apple\", so a list of\nbuttons says which tag each one removes. Write `{label}` in `dismiss-label`\nto put the tag's words somewhere else, such as `dismiss-label=\"{label}\nentfernen\"`.\n\n`href` makes the label a link, and `disabled` takes the tag out of reach: its\nlink and its remove button stop answering.\n\n**In a `Tag.Group` a tag is a row of a grid.** The group gives it its role,\nits place in the one tab stop and, where the group selects, whether it is\nselected. Its remove button leaves the tab order there, Delete and Backspace\ndoing its job from the row.\n\n**Styling a tag by what is happening to it.** `:state(selected)` while it is\nselected, `:state(focus-visible)` while its cell shows keyboard focus,\n`[disabled]` while it is out of reach, and the host's own `:hover` and\n`:active` under the pointer, as React Aria's `data-hovered` and\n`data-pressed` are.",
164891
165660
  "name": "HelixHeadlessTag",
164892
165661
  "cssParts": [
164893
165662
  {
@@ -165064,6 +165833,13 @@
165064
165833
  "description": "The remove button's name: `dismissLabel` with the tag's own words.\n\n**Named for its tag**, because a set of tags each named \"Remove\" is a list\nof buttons that says nothing about which tag each one takes away. The\nwords are the tag's slotted text, its category first, and `{label}` in\n`dismissLabel` says where they go. Without it they follow the verb, unless\nthe label already holds them, which is what a page naming each button by\nhand wrote.\n\nRead from the children, so empty on a server and while hydrating, where\nthe name is the verb alone until the update after.",
165065
165834
  "readonly": true
165066
165835
  },
165836
+ {
165837
+ "kind": "field",
165838
+ "name": "handleCellFocus",
165839
+ "privacy": "private",
165840
+ "readonly": true,
165841
+ "description": "Says whether the cell shows keyboard focus, as `:focus-visible` does, so a\nsheet outside can draw the ring on the tag by the host."
165842
+ },
165067
165843
  {
165068
165844
  "kind": "method",
165069
165845
  "name": "renderLabel",
@@ -165656,6 +166432,10 @@
165656
166432
  }
165657
166433
  ],
165658
166434
  "cssStates": [
166435
+ {
166436
+ "description": "The tag's cell has keyboard focus that the browser shows, in a `Tag.Group`.",
166437
+ "name": "focus-visible"
166438
+ },
165659
166439
  {
165660
166440
  "description": "The tag is selected in a `Tag.Group` that selects.",
165661
166441
  "name": "selected"
@@ -166139,6 +166919,61 @@
166139
166919
  "text": "setSelectionRange(start: number, end: number, direction?: SelectionDirection) => void"
166140
166920
  }
166141
166921
  },
166922
+ {
166923
+ "kind": "method",
166924
+ "name": "setRangeText",
166925
+ "return": {
166926
+ "type": {
166927
+ "text": "void"
166928
+ }
166929
+ },
166930
+ "parameters": [
166931
+ {
166932
+ "name": "replacement",
166933
+ "type": {
166934
+ "text": "string"
166935
+ }
166936
+ },
166937
+ {
166938
+ "name": "start",
166939
+ "optional": true,
166940
+ "type": {
166941
+ "text": "number"
166942
+ }
166943
+ },
166944
+ {
166945
+ "name": "end",
166946
+ "optional": true,
166947
+ "type": {
166948
+ "text": "number"
166949
+ }
166950
+ },
166951
+ {
166952
+ "name": "selectMode",
166953
+ "optional": true,
166954
+ "type": {
166955
+ "text": "SelectionMode"
166956
+ }
166957
+ }
166958
+ ],
166959
+ "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.",
166960
+ "type": {
166961
+ "text": "setRangeText(replacement: string, start?: number, end?: number, selectMode?: SelectionMode) => void"
166962
+ }
166963
+ },
166964
+ {
166965
+ "kind": "method",
166966
+ "name": "select",
166967
+ "return": {
166968
+ "type": {
166969
+ "text": "void"
166970
+ }
166971
+ },
166972
+ "description": "Selects everything in the field.",
166973
+ "type": {
166974
+ "text": "select() => void"
166975
+ }
166976
+ },
166142
166977
  {
166143
166978
  "kind": "field",
166144
166979
  "name": "textLength",
@@ -172946,6 +173781,14 @@
172946
173781
  "words": true
172947
173782
  }
172948
173783
  },
173784
+ {
173785
+ "kind": "field",
173786
+ "name": "timeContent",
173787
+ "type": {
173788
+ "text": "((time: string, written: string) => unknown) | undefined | undefined"
173789
+ },
173790
+ "description": "What each time in the list shows: a function given the time as `HH:mm`,\nor `HH:mm:ss` with `seconds`, and the time as the row writes it, that\nreturns text, an element or a Lit template.\n\nFor the seats left at a time, or a caption under it, as React Aria's\n`ListBoxItem` takes children. Content with `slot=\"start\"`, `slot=\"end\"`\nor `slot=\"description\"` goes to that slot of the row, and a description\nis read after the time. The row is still named by the written time, and\ntypeahead still finds it by that. Return the written time with your\ncontent where it should still show. A property only, there being no way\nto write a function in markup. The wheels draw their own figures."
173791
+ },
172949
173792
  {
172950
173793
  "kind": "field",
172951
173794
  "name": "unavailableMessage",
@@ -173360,7 +174203,7 @@
173360
174203
  "text": "TemplateResult | typeof nothing"
173361
174204
  }
173362
174205
  },
173363
- "description": "The `feedback` line, or nothing while there is none.",
174206
+ "description": "The `feedback` line, or nothing while there is none.\n\n`role=\"alert\"`, as a field's feedback line has, so the message is\nannounced when it appears and the label and hint are not read with it.",
173364
174207
  "inheritedFrom": {
173365
174208
  "name": "MixinPickerFeedback",
173366
174209
  "module": "src/mixins/mixin-picker-feedback/mixin-picker-feedback.ts"
@@ -175245,7 +176088,7 @@
175245
176088
  "declarations": [
175246
176089
  {
175247
176090
  "kind": "class",
175248
- "description": "Given `datetime`, the label you write is wrapped in a `<time>` element, so a\nmachine-readable value such as \"2026-08-19\" travels with a label such as\n\"yesterday\". Without `datetime`, the label is a `<span>`.\n\n**`relative` writes the time for you** as how long ago it was, such as \"3\nhours ago\", from `datetime`, where the `time` slot is empty. The words move\non as they go stale, \"3 hours ago\" becoming \"4 hours ago\", with one wakeup\nshared by every reading on the page, as `FormatDate` keeps its own. They are\nin the language of the page, or of the nearest `lang`.\n\nEach entry draws the connector line that arrives at it and hides it when it\nis the first entry, using `:host(:first-child)`. This needs no index, no\ncounting parent, and no script. `Steps` and `Breadcrumbs` work the same way.\n\n`tone` sets the kind of event and is the only thing that colors the mark. It\nuses the same values as `Announcement`. **A screen reader hears the tone as\na word**, from `tone-labels`: the mark is an image named \"Error\",\n\"Information\", \"Success\" or \"Warning\", so the color is not the only place\nthe meaning is. `neutral` and `primary` say nothing unless you name them.\n\n**`pending` marks an event that has not happened yet**, such as one that is\nscheduled. The mark is the open circle, and a screen reader hears\n`pending-label`, \"Scheduled\", with the tone's word.",
176091
+ "description": "Given `datetime`, the label you write is wrapped in a `<time>` element, so a\nmachine-readable value such as \"2026-08-19\" travels with a label such as\n\"yesterday\". Without `datetime`, the label is a `<span>`.\n\n**`relative` writes the time for you** as how long ago it was, such as \"3\nhours ago\", from `datetime`, where the `time` slot is empty. The words move\non as they go stale, \"3 hours ago\" becoming \"4 hours ago\", with one wakeup\nshared by every reading on the page, as `FormatDate` keeps its own. They are\nin the language of the page, or of the nearest `lang`. The whole date and\ntime is the reading's `title`, so a pointer resting on \"3 hours ago\" shows\nwhen it was, and a screen reader reads it as the description.\n\nEach entry draws the connector line that arrives at it and hides it when it\nis the first entry, using `:host(:first-child)`. This needs no index, no\ncounting parent, and no script. `Steps` and `Breadcrumbs` work the same way.\n\n`tone` sets the kind of event and is the only thing that colors the mark. It\nuses the same values as `Announcement`. **A screen reader hears the tone as\na word**, from `tone-labels`: the mark is an image named \"Error\",\n\"Information\", \"Success\" or \"Warning\", so the color is not the only place\nthe meaning is. `neutral` and `primary` say nothing unless you name them.\n\n**`pending` marks an event that has not happened yet**, such as one that is\nscheduled. The mark is the open circle, and a screen reader hears\n`pending-label`, \"Scheduled\", with the tone's word.",
175249
176092
  "name": "HelixHeadlessTimelineItem",
175250
176093
  "cssParts": [
175251
176094
  {
@@ -175333,6 +176176,16 @@
175333
176176
  "default": "''",
175334
176177
  "description": "What the `time` slot shows where nothing is slotted: the reading under\n`relative`, read against the clock before each render, and nothing\notherwise."
175335
176178
  },
176179
+ {
176180
+ "kind": "field",
176181
+ "name": "whole",
176182
+ "type": {
176183
+ "text": "string"
176184
+ },
176185
+ "privacy": "private",
176186
+ "default": "''",
176187
+ "description": "The whole date and time `datetime` names, the reading's title under `relative`."
176188
+ },
175336
176189
  {
175337
176190
  "kind": "field",
175338
176191
  "name": "moment",
@@ -175907,15 +176760,35 @@
175907
176760
  "declarations": [
175908
176761
  {
175909
176762
  "kind": "class",
175910
- "description": "A timeline is a record of events that happened or are scheduled. Each entry\ncarries a time, and no entry is current or complete. For a process you move\nthrough, with a current stage and `active` and `complete` states, use\n`Steps`.\n\nEach entry draws the connector line that arrives at it and hides it when it\nis first, using `:host(:first-child)`. This resolves at layout with no\nscript, so the server markup is correct before anything runs.\n\nThe host has `role=\"list\"`, because the entries are your elements in the\nlight DOM. `Steps` does the same.\n\n**Group entries by date with `Timeline.Group`**, which puts a heading such as\n\"Today\" over its entries. The group is an entry of the timeline, and its\nentries are a list of their own named by the heading.\n\n**The reading order is the order you write the entries in**, in every layout\nthe styled tier draws: down the page, either side of a line down the middle,\nor across the page. Inside each entry the time is read before what happened.\nWrite the entries in the order the events happened, oldest or newest first,\nand the layout only moves where they are drawn.",
176763
+ "description": "A timeline is a record of events that happened or are scheduled. Each entry\ncarries a time, and no entry is current or complete. For a process you move\nthrough, with a current stage and `active` and `complete` states, use\n`Steps`.\n\nEach entry draws the connector line that arrives at it and hides it when it\nis first, using `:host(:first-child)`. This resolves at layout with no\nscript, so the server markup is correct before anything runs.\n\nThe host has `role=\"list\"`, because the entries are your elements in the\nlight DOM. `Steps` does the same.\n\n**Group entries by date with `Timeline.Group`**, which puts a heading such as\n\"Today\" over its entries. The group is an entry of the timeline, and its\nentries are a list of their own named by the heading.\n\n**The reading order is the order you write the entries in**, in every layout\nthe styled tier draws: down the page, either side of a line down the middle,\nor across the page. Inside each entry the time is read before what happened.\nWrite the entries in the order the events happened, oldest or newest first,\nand the layout only moves where they are drawn.\n\n**A feed that loads more entries sets `loading` while it fetches.** The\ntimeline is busy, and an entry after the last says \"Loading more\"\n(`loading-label`, or your own content in the `loading` slot). Put a button\nthat asks for more after the timeline, and move focus to the first new\nentry when they arrive.",
175911
176764
  "name": "HelixHeadlessTimeline",
176765
+ "cssParts": [
176766
+ {
176767
+ "description": "The entry after the last while `loading` is set.",
176768
+ "name": "loading"
176769
+ }
176770
+ ],
175912
176771
  "slots": [
175913
176772
  {
175914
176773
  "description": "The entries, and any groups of them.",
175915
176774
  "name": ""
176775
+ },
176776
+ {
176777
+ "description": "Content for the entry after the last while `loading` is set. Falls back to `loading-label`.",
176778
+ "name": "loading"
175916
176779
  }
175917
176780
  ],
175918
176781
  "members": [
176782
+ {
176783
+ "kind": "field",
176784
+ "name": "words",
176785
+ "type": {
176786
+ "text": "string"
176787
+ },
176788
+ "static": true,
176789
+ "default": "'helix-timeline'",
176790
+ "description": "The key this family's words are registered under, its styled tag:\n`registerWords('de', { 'helix-timeline': { loadingLabel: 'Wird geladen' } })`."
176791
+ },
175919
176792
  {
175920
176793
  "kind": "field",
175921
176794
  "name": "label",
@@ -175926,6 +176799,30 @@
175926
176799
  "description": "Accessible name for the timeline, for people who reach it out of context.",
175927
176800
  "attribute": "label"
175928
176801
  },
176802
+ {
176803
+ "kind": "field",
176804
+ "name": "loading",
176805
+ "type": {
176806
+ "text": "boolean"
176807
+ },
176808
+ "default": "false",
176809
+ "description": "Marks the timeline as busy fetching more entries, and draws an entry\nafter the last that says so.",
176810
+ "attribute": "loading",
176811
+ "reflects": true
176812
+ },
176813
+ {
176814
+ "kind": "field",
176815
+ "name": "loadingLabel",
176816
+ "type": {
176817
+ "text": "string"
176818
+ },
176819
+ "default": "'Loading more'",
176820
+ "description": "The text of the entry drawn while `loading` is set, where the `loading` slot is empty.",
176821
+ "attribute": "loading-label",
176822
+ "helix": {
176823
+ "words": true
176824
+ }
176825
+ },
175929
176826
  {
175930
176827
  "kind": "field",
175931
176828
  "name": "tier",
@@ -176275,6 +177172,38 @@
176275
177172
  "default": "''",
176276
177173
  "description": "Accessible name for the timeline, for people who reach it out of context.",
176277
177174
  "fieldName": "label"
177175
+ },
177176
+ {
177177
+ "name": "loading",
177178
+ "type": {
177179
+ "text": "boolean"
177180
+ },
177181
+ "default": "false",
177182
+ "description": "Marks the timeline as busy fetching more entries, and draws an entry\nafter the last that says so.",
177183
+ "fieldName": "loading"
177184
+ },
177185
+ {
177186
+ "name": "loading-label",
177187
+ "type": {
177188
+ "text": "string"
177189
+ },
177190
+ "default": "'Loading more'",
177191
+ "description": "The text of the entry drawn while `loading` is set, where the `loading` slot is empty.",
177192
+ "fieldName": "loadingLabel"
177193
+ }
177194
+ ],
177195
+ "cssStates": [
177196
+ {
177197
+ "description": "While `loading` is set.",
177198
+ "name": "loading"
177199
+ },
177200
+ {
177201
+ "description": "Set one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.",
177202
+ "name": "settled",
177203
+ "inheritedFrom": {
177204
+ "name": "HelixElement",
177205
+ "module": "src/helix-element/helix-element.ts"
177206
+ }
176278
177207
  }
176279
177208
  ],
176280
177209
  "superclass": {
@@ -176307,16 +177236,6 @@
176307
177236
  },
176308
177237
  "tagName": "helix-headless-timeline",
176309
177238
  "customElement": true,
176310
- "cssStates": [
176311
- {
176312
- "description": "Set one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.",
176313
- "name": "settled",
176314
- "inheritedFrom": {
176315
- "name": "HelixElement",
176316
- "module": "src/helix-element/helix-element.ts"
176317
- }
176318
- }
176319
- ],
176320
177239
  "modulePath": "src/timeline/root/timeline-root.ts",
176321
177240
  "definitionPath": "src/timeline/root/timeline-root.ts"
176322
177241
  }
@@ -181625,7 +182544,7 @@
181625
182544
  "declarations": [
181626
182545
  {
181627
182546
  "kind": "class",
181628
- "description": "The trigger stays your own element. The bubble renders in the\ntop layer through the popover API, so an ancestor with `overflow: hidden`\ndoes not clip it and no `z-index` is needed. `FloatingController` positions\nit and flips it to another side when the preferred side does not fit.\n\n**Place the tooltip beside its trigger, name the trigger with `for`, and\nname the tooltip in the trigger's `aria-describedby`.** The description is\nthen in your own markup, so it is in the server's HTML and in the\naccessibility tree at rest, in every browser, before anyone points at the\ntrigger or focuses it:\n\n```html\n<helix-headless-button aria-describedby=\"save-tip\" id=\"save\">Save</helix-headless-button>\n<helix-headless-tooltip content=\"Save your work\" for=\"save\" id=\"save-tip\"></helix-headless-tooltip>\n```\n\nWithout the attribute, the tooltip links itself through an element reference\non the control that takes focus, and it never writes into your markup before\nyou act, so hydration stays intact. A trigger that is a Helix component is\ndescribed at once, inside its own shadow root. A plain element in your\nmarkup is described when you first point at it or focus it, so a screen\nreader in reading mode meets it with no description until then. Where the\nbrowser has no element references, nothing links the two, and the tooltip\nwarns once on first open. The tooltip can also wrap its trigger, which\ndescribes a Helix component and leaves a plain element undescribed. In the\n`for` form the tooltip itself is out of the accessibility tree while its\nbubble is down, so you meet its words once, as the trigger's description.\n\nThe tooltip shows on hover and on focus. It hides on pointer leave, on blur,\non Escape, and when the trigger is activated. The pointer can move from the\ntrigger onto the bubble and the bubble stays, unless you set\n`hoverable=\"false\"`. `delay` is how long the pointer rests before it shows,\nand `delay-out` how long it stays once the pointer leaves.\n\nOnce one tooltip is showing, moving to another trigger shows its tooltip\nwith no `delay`, and the first one hides. The same holds for `skip-delay`\nmilliseconds after a tooltip hides, 300 unless you set it. `show-on=\"focus\"`\nshows the tooltip on keyboard focus only, for a hint a pointer does not need.",
182547
+ "description": "The trigger stays your own element. The bubble renders in the\ntop layer through the popover API, so an ancestor with `overflow: hidden`\ndoes not clip it and no `z-index` is needed. `FloatingController` positions\nit and flips it to another side when the preferred side does not fit.\n\n**Place the tooltip beside its trigger, name the trigger with `for`, and\nname the tooltip in the trigger's `aria-describedby`.** The description is\nthen in your own markup, so it is in the server's HTML and in the\naccessibility tree at rest, in every browser, before anyone points at the\ntrigger or focuses it:\n\n```html\n<helix-headless-button aria-describedby=\"save-tip\" id=\"save\">Save</helix-headless-button>\n<helix-headless-tooltip content=\"Save your work\" for=\"save\" id=\"save-tip\"></helix-headless-tooltip>\n```\n\nWithout the attribute, the tooltip links itself through an element reference\non the control that takes focus, and it never writes into your markup before\nyou act, so hydration stays intact. A trigger that is a Helix component is\ndescribed at once, inside its own shadow root. A plain element in your\nmarkup is described when you first point at it or focus it, so a screen\nreader in reading mode meets it with no description until then. Where the\nbrowser has no element references, nothing links the two, and the tooltip\nwarns once on first open. The tooltip can also wrap its trigger, which\ndescribes a Helix component and leaves a plain element undescribed. In the\n`for` form the tooltip itself is out of the accessibility tree while its\nbubble is down, so you meet its words once, as the trigger's description.\nA trigger whose name is already the tooltip's words, such as an icon button\nnamed Settings under a tooltip reading Settings, is not described by them\nagain.\n\nThe tooltip shows on hover and on focus. It hides on pointer leave, on blur,\non Escape, and when the trigger is activated. The pointer can move from the\ntrigger onto the bubble and the bubble stays, unless you set\n`hoverable=\"false\"`. `delay` is how long the pointer rests before it shows,\nand `delay-out` how long it stays once the pointer leaves.\n\nOnce one tooltip is showing, moving to another trigger shows its tooltip\nwith no `delay`, and the first one hides. The same holds for `skip-delay`\nmilliseconds after a tooltip hides, 300 unless you set it. `show-on=\"focus\"`\nshows the tooltip on keyboard focus only, for a hint a pointer does not need.",
181629
182548
  "name": "HelixHeadlessTooltip",
181630
182549
  "cssParts": [
181631
182550
  {
@@ -182059,6 +182978,16 @@
182059
182978
  ],
182060
182979
  "description": "Describes the control that takes the trigger's focus by this tooltip.\n\n`light` says a reader has just acted, which is what allows a write onto a\nplain element in the consumer's markup. See `linkDescription`."
182061
182980
  },
182981
+ {
182982
+ "kind": "field",
182983
+ "name": "describes",
182984
+ "type": {
182985
+ "text": "boolean"
182986
+ },
182987
+ "privacy": "private",
182988
+ "description": "Whether the bubble's words add anything to the trigger: they are not\nempty, and they are not the trigger's own name, such as an icon button\nnamed Settings under a tooltip reading Settings, which a screen reader\nread as \"Settings, Settings\".",
182989
+ "readonly": true
182990
+ },
182062
182991
  {
182063
182992
  "kind": "field",
182064
182993
  "name": "linkOnArrival",
@@ -195022,13 +195951,295 @@
195022
195951
  }
195023
195952
  ]
195024
195953
  },
195954
+ {
195955
+ "kind": "javascript-module",
195956
+ "path": "src/virtual-list/reorder/index.ts",
195957
+ "declarations": [],
195958
+ "exports": [
195959
+ {
195960
+ "kind": "js",
195961
+ "name": "reorderVirtualList",
195962
+ "declaration": {
195963
+ "name": "reorderVirtualList",
195964
+ "module": "./virtual-list-reorder.js"
195965
+ }
195966
+ },
195967
+ {
195968
+ "kind": "js",
195969
+ "name": "VirtualListReorderController",
195970
+ "declaration": {
195971
+ "name": "VirtualListReorderController",
195972
+ "module": "./virtual-list-reorder.js"
195973
+ }
195974
+ }
195975
+ ]
195976
+ },
195977
+ {
195978
+ "kind": "javascript-module",
195979
+ "path": "src/virtual-list/reorder/virtual-list-reorder.ts",
195980
+ "declarations": [
195981
+ {
195982
+ "kind": "class",
195983
+ "description": "Moves the items of a `reorderable` virtual list, by pointer and by keyboard,\nand says each move in a region screen readers announce.\n\n**Its own entry**, `@fusion.dev/helix-headless/virtual-list/reorder`, so a\nlist that never moves items carries none of this. Importing the entry gives\nevery virtual list one, and `reorderable` turns it on.\n\n- **Alt with Up or Down** moves the item the keys are on a place at once,\n and Alt with Home or End to either end, as the APG's rearrangeable\n listbox does. Across, Alt with Left or Right does, mirrored right to left.\n The keys stay on the item that moved.\n- **A pointer** drags a whole row, with no grip: a press that travels is a\n drag, and one that does not is still a press. The list scrolls near an\n edge.\n- **The page moves the items.** A drop sends `helix-before-reorder` and then\n `helix-reorder` with every key in the new order.\n\nA row being dragged carries `data-dragging`, and the row a drop would land\nbeside `data-drop-before` or `data-drop-after`. While a pointer drags a row,\na copy of it follows the pointer in the list's `drag-preview` part. The\nstyled tier's entry hands in the sheet that draws those, which the list\nadopts while it reorders.",
195984
+ "name": "VirtualListReorderController",
195985
+ "members": [
195986
+ {
195987
+ "kind": "field",
195988
+ "name": "host",
195989
+ "type": {
195990
+ "text": "HelixHeadlessVirtualList"
195991
+ },
195992
+ "privacy": "private",
195993
+ "readonly": true,
195994
+ "default": "host"
195995
+ },
195996
+ {
195997
+ "kind": "field",
195998
+ "name": "sheet",
195999
+ "type": {
196000
+ "text": "CSSResult | undefined"
196001
+ },
196002
+ "description": "The sheet the list adopts while it reorders, from the styled tier.",
196003
+ "default": "sheet"
196004
+ },
196005
+ {
196006
+ "kind": "field",
196007
+ "name": "marked",
196008
+ "privacy": "private",
196009
+ "default": "new Set<HTMLElement>()",
196010
+ "description": "The rows marked last, so a mark that moves is taken off where it was."
196011
+ },
196012
+ {
196013
+ "kind": "field",
196014
+ "name": "live",
196015
+ "type": {
196016
+ "text": "HTMLElement | undefined"
196017
+ },
196018
+ "privacy": "private",
196019
+ "description": "The region each move is said in, drawn while the list reorders."
196020
+ },
196021
+ {
196022
+ "kind": "field",
196023
+ "name": "reorder",
196024
+ "type": {
196025
+ "text": "ReorderController"
196026
+ },
196027
+ "privacy": "private",
196028
+ "readonly": true,
196029
+ "default": "new ReorderController(host, { get axis() { return host.orientation === 'horizontal' ? 'inline' : 'block' }, box: (key) => this.rowFor(key)?.getBoundingClientRect(), current: () => { const row = this.rows.find((one) => one.hasAttribute('data-active')) return row && !row.hasAttribute('data-disabled') ? this.keyOf(row) : undefined }, enabled: () => this.enabled, grip: (event) => { const row = this.rowOf(event) const key = row && !row.hasAttribute('data-disabled') ? this.keyOf(row) : undefined return row && key !== undefined ? { element: row, key } : undefined }, holds: false, keys: () => host.keys(), name: (key) => this.names.get(key) || key, preview: (key) => this.rowFor(key), say: (words) => { if (this.live) { this.live.textContent = words } }, scroller: () => host.renderRoot?.querySelector<HTMLElement>('[part=\"viewport\"]') ?? null, })"
196030
+ },
196031
+ {
196032
+ "kind": "field",
196033
+ "name": "enabled",
196034
+ "type": {
196035
+ "text": "boolean"
196036
+ },
196037
+ "privacy": "private",
196038
+ "description": "Whether the list moves its items now: one column, without sections.",
196039
+ "readonly": true
196040
+ },
196041
+ {
196042
+ "kind": "field",
196043
+ "name": "names",
196044
+ "privacy": "private",
196045
+ "default": "new Map<string, string>()",
196046
+ "description": "The words of each drawn row by its item's key, as they were when the list\nlast drew. A move is said after the page has moved the items and before\nthe rows are drawn again, so a row's own words then belong to another item."
196047
+ },
196048
+ {
196049
+ "kind": "method",
196050
+ "name": "hostUpdated",
196051
+ "return": {
196052
+ "type": {
196053
+ "text": "void"
196054
+ }
196055
+ }
196056
+ },
196057
+ {
196058
+ "kind": "method",
196059
+ "name": "hostConnected",
196060
+ "return": {
196061
+ "type": {
196062
+ "text": "void"
196063
+ }
196064
+ }
196065
+ },
196066
+ {
196067
+ "kind": "method",
196068
+ "name": "hostDisconnected",
196069
+ "return": {
196070
+ "type": {
196071
+ "text": "void"
196072
+ }
196073
+ }
196074
+ },
196075
+ {
196076
+ "kind": "field",
196077
+ "name": "rows",
196078
+ "type": {
196079
+ "text": "HTMLElement[]"
196080
+ },
196081
+ "privacy": "private",
196082
+ "description": "The rows the list draws now.",
196083
+ "readonly": true
196084
+ },
196085
+ {
196086
+ "kind": "method",
196087
+ "name": "keyOf",
196088
+ "privacy": "private",
196089
+ "return": {
196090
+ "type": {
196091
+ "text": "string | undefined"
196092
+ }
196093
+ },
196094
+ "parameters": [
196095
+ {
196096
+ "name": "row",
196097
+ "type": {
196098
+ "text": "HTMLElement"
196099
+ }
196100
+ }
196101
+ ],
196102
+ "description": "The key of the item a row draws."
196103
+ },
196104
+ {
196105
+ "kind": "method",
196106
+ "name": "rowFor",
196107
+ "privacy": "private",
196108
+ "return": {
196109
+ "type": {
196110
+ "text": "HTMLElement | undefined"
196111
+ }
196112
+ },
196113
+ "parameters": [
196114
+ {
196115
+ "name": "key",
196116
+ "type": {
196117
+ "text": "string"
196118
+ }
196119
+ }
196120
+ ],
196121
+ "description": "The row that draws the item with that key, where one is drawn."
196122
+ },
196123
+ {
196124
+ "kind": "method",
196125
+ "name": "rowOf",
196126
+ "privacy": "private",
196127
+ "return": {
196128
+ "type": {
196129
+ "text": "HTMLElement | undefined"
196130
+ }
196131
+ },
196132
+ "parameters": [
196133
+ {
196134
+ "name": "event",
196135
+ "type": {
196136
+ "text": "Event"
196137
+ }
196138
+ }
196139
+ ],
196140
+ "description": "The row an event passed through."
196141
+ },
196142
+ {
196143
+ "kind": "field",
196144
+ "name": "waiting",
196145
+ "type": {
196146
+ "text": "number | undefined"
196147
+ },
196148
+ "privacy": "private",
196149
+ "description": "The place an item moved by a key goes to, until the page has moved it."
196150
+ },
196151
+ {
196152
+ "kind": "field",
196153
+ "name": "handleReorder",
196154
+ "privacy": "private",
196155
+ "readonly": true,
196156
+ "description": "Keeps the keys on the item that moved. The page moves the items as it\nhears this, and the rows are drawn again in place, so the row that had\nfocus now draws another item. Focus goes to the item's new row once the\nlist has drawn it."
196157
+ },
196158
+ {
196159
+ "kind": "method",
196160
+ "name": "draw",
196161
+ "privacy": "private",
196162
+ "return": {
196163
+ "type": {
196164
+ "text": "void"
196165
+ }
196166
+ },
196167
+ "parameters": [
196168
+ {
196169
+ "name": "on",
196170
+ "type": {
196171
+ "text": "boolean"
196172
+ }
196173
+ }
196174
+ ],
196175
+ "description": "Draws the list's `drag-preview` part and its region for the words while it\nreorders, and takes them away after. The list's own template draws\nneither."
196176
+ },
196177
+ {
196178
+ "kind": "method",
196179
+ "name": "mark",
196180
+ "privacy": "private",
196181
+ "return": {
196182
+ "type": {
196183
+ "text": "void"
196184
+ }
196185
+ },
196186
+ "description": "Puts each row's mark in a move on it, and the styled tier's sheet on the list."
196187
+ }
196188
+ ],
196189
+ "helix": {}
196190
+ },
196191
+ {
196192
+ "kind": "function",
196193
+ "name": "reorderVirtualList",
196194
+ "return": {
196195
+ "type": {
196196
+ "text": "void"
196197
+ }
196198
+ },
196199
+ "parameters": [
196200
+ {
196201
+ "name": "element",
196202
+ "type": {
196203
+ "text": "typeof HelixHeadlessVirtualList"
196204
+ }
196205
+ },
196206
+ {
196207
+ "name": "sheet",
196208
+ "optional": true,
196209
+ "type": {
196210
+ "text": "CSSResult"
196211
+ }
196212
+ }
196213
+ ],
196214
+ "description": "Gives every virtual list of a class a `VirtualListReorderController`, and\nthe class the words it says, as properties that read and write their\nattributes: `movedLabel`, `canceledLabel`, `droppedLabel`, and\n`pickedUpLabel`.\n\nThe entries call it for their own tier's class: the headless entry for\n`HelixHeadlessVirtualList`, and the styled one for `HelixVirtualList`, with\nthe sheet that draws a move. **Lists already on the page are given one\ntoo**, so a page that imports the list and then this entry has its lists\nreorder."
196215
+ }
196216
+ ],
196217
+ "exports": [
196218
+ {
196219
+ "kind": "js",
196220
+ "name": "VirtualListReorderController",
196221
+ "declaration": {
196222
+ "name": "VirtualListReorderController",
196223
+ "module": "src/virtual-list/reorder/virtual-list-reorder.ts"
196224
+ }
196225
+ },
196226
+ {
196227
+ "kind": "js",
196228
+ "name": "reorderVirtualList",
196229
+ "declaration": {
196230
+ "name": "reorderVirtualList",
196231
+ "module": "src/virtual-list/reorder/virtual-list-reorder.ts"
196232
+ }
196233
+ }
196234
+ ]
196235
+ },
195025
196236
  {
195026
196237
  "kind": "javascript-module",
195027
196238
  "path": "src/virtual-list/root/virtual-list-root.ts",
195028
196239
  "declarations": [
195029
196240
  {
195030
196241
  "kind": "class",
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.",
196242
+ "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| Alt with Up or Down | In a `reorderable` list, moves the item a place. Alt with Home or End moves it to either end. |\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. The row a reader last focused keeps the tab stop and\nstays drawn when it scrolls away, so Tab and Shift+Tab come back to it, as\nReact Aria's collections do. In a list nobody has focused yet, the stop\nmoves 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**Moving items** is a separate import, `@fusion.dev/helix/virtual-list/reorder`,\nas React Aria's drag and drop is. With it imported, `reorderable` lets a\nreader move items in a list of one column without sections:\n\n- Alt with Up or Down moves the item the keys are on a place, and Alt with\n Home or End to either end, as the APG's rearrangeable listbox does.\n- A pointer drags a whole row. A press that does not travel is still a\n press. The list scrolls near an edge, and an item far down a long set is\n reached by dragging to the edge.\n- A drop sends `helix-before-reorder`, which you can refuse, and then\n `helix-reorder`, whose `keys` hold every item's key in the new order.\n **You move the items**: set `items` to them in that order. The keys stay\n on the item that moved.\n- Each move is said in a region screen readers announce. The row being\n dragged carries `data-dragging`, and the row a drop would land beside\n `data-drop-before` or `data-drop-after`.\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.",
195032
196243
  "name": "HelixHeadlessVirtualList",
195033
196244
  "cssParts": [
195034
196245
  {
@@ -195234,6 +196445,16 @@
195234
196445
  },
195235
196446
  "description": "Draws each section's header, given its name and its place among the\nsections, for a list given `section-field`. Set it as a property. Where\nit is unset, the header is the name as text."
195236
196447
  },
196448
+ {
196449
+ "kind": "field",
196450
+ "name": "reorderable",
196451
+ "type": {
196452
+ "text": "boolean"
196453
+ },
196454
+ "default": "false",
196455
+ "description": "Lets a reader move items, once `@fusion.dev/helix/virtual-list/reorder`\n(or `@fusion.dev/helix-headless/virtual-list/reorder`) is imported: Alt\nwith an arrow moves the row the keys are on, and a pointer drags a row.\nThe list moves no item itself: you move your `items` on `helix-reorder`.\nWithout that import it does nothing, so a list that never moves items\ncarries none of the code. A list of one column, without sections.",
196456
+ "attribute": "reorderable"
196457
+ },
195237
196458
  {
195238
196459
  "kind": "field",
195239
196460
  "name": "sectionField",
@@ -195815,17 +197036,6 @@
195815
197036
  ],
195816
197037
  "description": "The key of item `at` in `value`. See `keyField`."
195817
197038
  },
195818
- {
195819
- "kind": "method",
195820
- "name": "keys",
195821
- "privacy": "private",
195822
- "return": {
195823
- "type": {
195824
- "text": "string[]"
195825
- }
195826
- },
195827
- "description": "Every item's key, in the order of the set."
195828
- },
195829
197039
  {
195830
197040
  "kind": "field",
195831
197041
  "name": "chosen",
@@ -195908,25 +197118,6 @@
195908
197118
  "readonly": true,
195909
197119
  "description": "A press on a row selects it, in a list with `selection-mode`, except on a\ncontrol of its own. Shift takes in a range."
195910
197120
  },
195911
- {
195912
- "kind": "method",
195913
- "name": "focusIndex",
195914
- "privacy": "private",
195915
- "return": {
195916
- "type": {
195917
- "text": "Promise<void>"
195918
- }
195919
- },
195920
- "parameters": [
195921
- {
195922
- "name": "index",
195923
- "type": {
195924
- "text": "number"
195925
- }
195926
- }
195927
- ],
195928
- "description": "Focuses the row for item `index`, scrolling it into view and drawing it\nfirst when it is not drawn."
195929
- },
195930
197121
  {
195931
197122
  "kind": "field",
195932
197123
  "name": "handleFocusOut",
@@ -195961,6 +197152,16 @@
195961
197152
  "privacy": "private",
195962
197153
  "description": "The item a key is moving focus to, drawn until it has it."
195963
197154
  },
197155
+ {
197156
+ "kind": "field",
197157
+ "name": "visited",
197158
+ "type": {
197159
+ "text": "boolean"
197160
+ },
197161
+ "privacy": "private",
197162
+ "default": "false",
197163
+ "description": "Whether a reader has focused a row, after which their row keeps the tab stop."
197164
+ },
195964
197165
  {
195965
197166
  "kind": "method",
195966
197167
  "name": "keptIndex",
@@ -195970,7 +197171,7 @@
195970
197171
  "text": "number | undefined"
195971
197172
  }
195972
197173
  },
195973
- "description": "The item drawn outside the window to keep focus, or to take it, if there is one."
197174
+ "description": "The item drawn outside the window to keep focus, to take it, or to take\nit back: the row a reader last focused stays drawn after focus leaves the\nlist, so Shift+Tab returns to it."
195974
197175
  },
195975
197176
  {
195976
197177
  "kind": "method",
@@ -196093,7 +197294,7 @@
196093
197294
  "text": "void"
196094
197295
  }
196095
197296
  },
196096
- "description": "Puts the windowed rows into the light DOM, and takes the rest out.\n\n**A row that stays in the window keeps its element.** Clearing and\ncloning every row on every move replaced the node a reader had focused,\nso a link in a row lost focus to the body on any scroll, even with its row\nstill on screen. Rows are keyed by item: the ones leaving go, the ones\narriving are drawn in their place, and the ones staying are not moved.\n\n**The row holding focus is drawn outside the window too**, beside it on the\nside it belongs, and the spacer on that side gives up its room.\n\n**One row holds the tab stop**, the one the reader last focused while it is\ndrawn, and the first row on screen once it is not. Its own links and\nbuttons are in the tab order, and those of every other row wait."
197297
+ "description": "Puts the windowed rows into the light DOM, and takes the rest out.\n\n**A row that stays in the window keeps its element.** Clearing and\ncloning every row on every move replaced the node a reader had focused,\nso a link in a row lost focus to the body on any scroll, even with its row\nstill on screen. Rows are keyed by item: the ones leaving go, the ones\narriving are drawn in their place, and the ones staying are not moved.\n\n**The row holding focus is drawn outside the window too**, beside it on the\nside it belongs, and the spacer on that side gives up its room.\n\n**One row holds the tab stop**, the one the reader last focused, which\nstays drawn outside the window, and the first row on screen in a list\nnobody has focused yet. Its own links and buttons are in the tab order,\nand those of every other row wait."
196097
197298
  },
196098
197299
  {
196099
197300
  "kind": "field",
@@ -196525,6 +197726,14 @@
196525
197726
  "name": "helix-before-change",
196526
197727
  "reactProp": "onhelix-before-change"
196527
197728
  },
197729
+ {
197730
+ "type": {
197731
+ "text": "HelixBeforeReorderEvent"
197732
+ },
197733
+ "description": "Fired when an item is dropped at a new place, in a `reorderable` list with `@fusion.dev/helix/virtual-list/reorder` imported, with every key in the new order. Cancelable: cancel it to keep the item where it is.",
197734
+ "name": "helix-before-reorder",
197735
+ "reactProp": "onhelix-before-reorder"
197736
+ },
196528
197737
  {
196529
197738
  "type": {
196530
197739
  "text": "HelixLoadMoreEvent"
@@ -196540,6 +197749,14 @@
196540
197749
  "description": "Fired when the items on screen change, with the new `first` and `last`, which `range` also holds.",
196541
197750
  "name": "helix-range-change",
196542
197751
  "reactProp": "onhelix-range-change"
197752
+ },
197753
+ {
197754
+ "type": {
197755
+ "text": "HelixReorderEvent"
197756
+ },
197757
+ "description": "Fired after `helix-before-reorder` when nobody canceled it. Set `items` to the order in `keys`. Cancelable: cancel it to say the move did not happen.",
197758
+ "name": "helix-reorder",
197759
+ "reactProp": "onhelix-reorder"
196543
197760
  }
196544
197761
  ],
196545
197762
  "attributes": [
@@ -196660,6 +197877,15 @@
196660
197877
  "description": "Which way the list runs. `horizontal` lays the items out along a line\nand scrolls it sideways: Left and Right move between items, the other\nway round on a right-to-left page, and `estimate` is an item's width. A\ngrid always runs down.",
196661
197878
  "fieldName": "orientation"
196662
197879
  },
197880
+ {
197881
+ "name": "reorderable",
197882
+ "type": {
197883
+ "text": "boolean"
197884
+ },
197885
+ "default": "false",
197886
+ "description": "Lets a reader move items, once `@fusion.dev/helix/virtual-list/reorder`\n(or `@fusion.dev/helix-headless/virtual-list/reorder`) is imported: Alt\nwith an arrow moves the row the keys are on, and a pointer drags a row.\nThe list moves no item itself: you move your `items` on `helix-reorder`.\nWithout that import it does nothing, so a list that never moves items\ncarries none of the code. A list of one column, without sections.",
197887
+ "fieldName": "reorderable"
197888
+ },
196663
197889
  {
196664
197890
  "name": "section-field",
196665
197891
  "type": {
@@ -196950,6 +198176,6 @@
196950
198176
  ],
196951
198177
  "helix": {
196952
198178
  "package": "@fusion.dev/helix-headless",
196953
- "version": "0.171.0"
198179
+ "version": "0.173.0"
196954
198180
  }
196955
198181
  }