@fusion.dev/helix-headless 0.183.0 → 0.185.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/types/vue.d.ts CHANGED
@@ -40,6 +40,7 @@ import type {
40
40
  HelixHeadlessChat,
41
41
  HelixHeadlessCheckboxGroup,
42
42
  HelixHeadlessCheckbox,
43
+ registerHighlighter,
43
44
  HelixHeadlessCodeBlock,
44
45
  HelixHeadlessCode,
45
46
  HelixHeadlessColorInput,
@@ -3432,7 +3433,11 @@ whole of it, which Shiki writes, are taken off, so the lines sit level
3432
3433
  with the gutter's numbers and the block keeps one tab stop. The code stays
3433
3434
  in the slot, so the copy button copies it as written and a reader without
3434
3435
  the script still has it. Not called on a server, which has no code to
3435
- read, nor for a diff. */
3436
+ read, nor for a diff.
3437
+
3438
+ Absent, the block draws with the highlighter `registerHighlighter` gave
3439
+ every block, where an entry such as `@fusion.dev/helix-sandbox/code-block`
3440
+ registered one, and plain otherwise. */
3436
3441
  highlight?: (HelixHeadlessCodeBlock["highlight"]) | undefined;
3437
3442
  };
3438
3443
 
@@ -4884,6 +4889,16 @@ and the grid becomes a tree grid.
4884
4889
  Reflected, because the styled tier indents a tree grid's row headers by
4885
4890
  it. No default, so a table that sets none writes nothing onto its host. */
4886
4891
  childField?: (HelixHeadlessDataTable["childField"]) | undefined;
4892
+ /** The column tracks, as a grid track list such as `2fr 1fr max-content`,
4893
+ dealt out one track to a column in the order the columns are written. A
4894
+ column's own `width` wins in its place, and a column it does not reach
4895
+ takes the track a column with no `width` takes.
4896
+
4897
+ **The one track list a server can send.** A server rendering this element
4898
+ has no columns to read a `width` from, and neither has a stylesheet laying
4899
+ out the rows a page served before the table upgrades, so a table sized here
4900
+ lays those rows out at the widths it draws. */
4901
+ columns?: (HelixHeadlessDataTable["columns"]) | undefined;
4887
4902
  /** The keys of the rows open at the start, separated by commas. Used until
4888
4903
  `expanded` is set. */
4889
4904
  "default-expanded"?: (HelixHeadlessDataTable["defaultExpanded"]) | undefined;
@@ -11042,7 +11057,11 @@ Cleared as the menu closes and as a submenu opens or closes, so each page
11042
11057
  starts with every row showing. */
11043
11058
  filter?: (HelixHeadlessMenu["filter"]) | undefined;
11044
11059
  /** Whether the menu shows a field above its rows that narrows them as the
11045
- reader types, with focus staying in the field. */
11060
+ reader types, with focus staying in the field, once
11061
+ `@fusion.dev/helix/menu/filter` (or `@fusion.dev/helix-headless/menu/filter`)
11062
+ is imported. Without that import it does nothing, so a menu that never
11063
+ filters carries none of the filter's code, and a development build says
11064
+ which import is missing. */
11046
11065
  filterable?: (HelixHeadlessMenu["filterable"]) | undefined;
11047
11066
  /** The filter field's name and placeholder. */
11048
11067
  "filter-label"?: (HelixHeadlessMenu["filterLabel"]) | undefined;
@@ -15432,13 +15451,11 @@ and each column may say otherwise.
15432
15451
  **It is also the only track list a server can send.** The shim has no tree
15433
15452
  to walk, so a render there knows of no columns and this attribute is the
15434
15453
  whole answer: a table given one lays its grid out in the first paint, and a
15435
- table sized only by its columns is one track wide until it upgrades.
15454
+ table sized only by its columns takes, until it upgrades, a track for each
15455
+ column at the width a column with no `width` takes (`helix.css`).
15436
15456
 
15437
- **Data Table has none of this, and should not.** Its columns are its schema
15438
- rather than an option, so there is always a column to write a `width` on
15439
- and a list here would be a second way to say what that says. This table's
15440
- cells are markup, and a table written as rows of cells with no column
15441
- declared in it has nowhere else to be sized from. */
15457
+ Data Table takes the same list, for the same reason: a data table that
15458
+ serves its first page as rows is laid out by it before it upgrades. */
15442
15459
  columns?: (HelixHeadlessTable["columns"]) | undefined;
15443
15460
  /** The keys of the rows whose rows are shown at the start, separated by
15444
15461
  commas. Used until `expanded` is set. */
@@ -16294,6 +16311,12 @@ number, and both are carried as one comma-separated value, which is what a
16294
16311
  form submits. `TimePicker` carries the longer note on the interaction and
16295
16312
  on why a wheel cannot do either. */
16296
16313
  mode?: (HelixHeadlessTimeInput["mode"]) | undefined;
16314
+ /** The words on the list's button that chooses the current time, drawn with
16315
+ `show-now`. */
16316
+ "now-label"?: (HelixHeadlessTimeInput["nowLabel"]) | undefined;
16317
+ /** The words on the list's button that chooses the current time, drawn with
16318
+ `show-now`. */
16319
+ nowLabel?: (HelixHeadlessTimeInput["nowLabel"]) | undefined;
16297
16320
  /** Placeholder text shown before a time is entered. */
16298
16321
  placeholder?: (HelixHeadlessTimeInput["placeholder"]) | undefined;
16299
16322
  /** The message shown when a range holds more than two times.
@@ -16334,6 +16357,14 @@ removes rather than as "Remove" said once per time. */
16334
16357
  may give them, the field writes them, and the list's `step` counts seconds.
16335
16358
  See Time Picker's `seconds`. */
16336
16359
  seconds?: (HelixHeadlessTimeInput["seconds"]) | undefined;
16360
+ /** Draws a button under the times in the list that chooses the current time,
16361
+ moved to the nearest time on offer. See Time Picker's `show-now`. Its words
16362
+ are `now-label`. */
16363
+ "show-now"?: (HelixHeadlessTimeInput["showNow"]) | undefined;
16364
+ /** Draws a button under the times in the list that chooses the current time,
16365
+ moved to the nearest time on offer. See Time Picker's `show-now`. Its words
16366
+ are `now-label`. */
16367
+ showNow?: (HelixHeadlessTimeInput["showNow"]) | undefined;
16337
16368
  /** How far apart the offered times are, in minutes, or in seconds with
16338
16369
  `seconds`. */
16339
16370
  step?: (HelixHeadlessTimeInput["step"]) | undefined;
@@ -19444,7 +19475,7 @@ export interface WcToolkitVueGlobalComponents {
19444
19475
  HelixHeadlessCheckboxVueProps,
19445
19476
  HelixHeadlessCheckboxVueEvents
19446
19477
  >;
19447
- /** Renders a '<pre><code>' pair: 'pre' keeps the whitespace, and 'code' marks it as code. Long lines scroll inside the block and do not wrap, because a line break can be significant in code. A copy button is on by default. Set 'no-copy' to remove it. The button copies the slotted text, so there is no second copy of the code to keep in sync. For a fragment of code inside a sentence, use 'Code'. Set 'line-numbers' to number the lines in a gutter beside the code, hidden from the accessibility tree and left out of a copy. Set 'mark-lines' to mark lines a reader should look at, such as '2, 4-6': the block draws a band behind each run, placed where the lines are laid out, so it follows a highlighter's markup and lines that wrap. 'added-lines' and 'removed-lines' mark lines the same way as inserted and deleted, as Expressive Code's 'ins' and 'del' do, in code that is not a diff. The bands are drawn and hidden from screen readers, so say in the text around the block what a marked line means. Set 'wrap' to wrap long lines rather than scroll them; a gutter then numbers each line where it starts. Set 'wrappable' for a button in the header that turns 'wrap' on and off, pressed while the lines wrap. The header holds the name, the 'actions' slot, and the copy button. Slot a control into 'actions', such as a button that sets 'wrap' or one that opens the code in an editor, and the block draws a header for it even with no name. 'copy-icon' and 'copied-icon' replace the copy button's two icons. Set 'highlight' to a function that turns the code into highlighted markup, such as one wrapping Shiki or Prism, and the block draws what it returns; it is handed the block's 'language', so one function serves every block. The code stays in the slot, so the copy button and the page's own text are the code as written. Set 'expandable' on a block whose height is capped, such as by '--code-block-max-block-size', and a button under it shows every line and then fewer again, as a docs site's long example does. The button is drawn only while the cap hides something, says whether the block is expanded with 'aria-expanded', names the block it opens with 'aria-controls', and the block carries ':state(expanded)' while it is. Set 'diff' to show a change. Put a unified diff, the output of 'git diff' or 'diff -u', in the same slot, and the block draws the lines it added and removed. The block never computes a diff itself. Line numbers come from the hunk headers and are hidden from the accessibility tree. Changed lines are '<ins>' and '<del>' with the '+' and '-' kept as text, so the change does not depend on color. Where a removed line is paired with the added line that replaced it, the words each does not share with the other are the 'changed' part, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name, and its copy button copies the new version of the file. 'variant="split"' shows the old version beside the new, each removal opposite its replacement. 'context-lines' folds each long run of unchanged lines, keeping that many beside each change, behind a button that shows them and hides them again, as a code host draws a diff written with more context than a reader needs. **A block that scrolls is a tab stop.** While its lines run past its width or its cap, the scroller is a region named for the block, such as "Code, app.ts", that Tab reaches, so a keyboard scrolls it with the arrow keys in every browser. Chromium and Firefox make a scrolling box focusable on their own, and Safari does not. A block that fits is no stop at all. **The code the block draws is marked untranslated**, 'translate="no"' on its '<pre>', so a page translator leaves highlighted lines and a diff as written. Code in the slot takes its translation mode from the element, which writes nothing onto itself, so set 'translate="no"' on the element to keep a translator off plain code too. On the server, the slot renders as ordinary code, so a diff first appears as the patch text in a '<pre>'. The client makes the same first render, which keeps hydration clean, and draws the diff once it can read the content. Diff mode is experimental. The rest of the family is stable. **Several blocks are files**, one shown at a time under a row of tabs, as Sandbox shows its source panes. Put Code Blocks in the default slot of a Code Block, and each is a file named on its tab by its 'label' or, without one, its 'language'. 'file' holds the name of the file shown. The tabs are a tab list: the arrow keys move to a tab and show its file, the two swapping on a right-to-left page, and Home and End go to the first and the last. Choosing one sends 'helix-before-change' with the file's name, which you can cancel, and 'change' once 'file' holds it. The files not shown carry 'hidden', and the one shown draws no name of its own, its tab naming it. One block draws no tabs. A server cannot see the blocks inside, so the client draws the tabs once it upgrades. */
19478
+ /** Renders a '<pre><code>' pair: 'pre' keeps the whitespace, and 'code' marks it as code. Long lines scroll inside the block and do not wrap, because a line break can be significant in code. A copy button is on by default. Set 'no-copy' to remove it. The button copies the slotted text, so there is no second copy of the code to keep in sync. For a fragment of code inside a sentence, use 'Code'. Set 'line-numbers' to number the lines in a gutter beside the code, hidden from the accessibility tree and left out of a copy. Set 'mark-lines' to mark lines a reader should look at, such as '2, 4-6': the block draws a band behind each run, placed where the lines are laid out, so it follows a highlighter's markup and lines that wrap. 'added-lines' and 'removed-lines' mark lines the same way as inserted and deleted, as Expressive Code's 'ins' and 'del' do, in code that is not a diff. The bands are drawn and hidden from screen readers, so say in the text around the block what a marked line means. Set 'wrap' to wrap long lines rather than scroll them; a gutter then numbers each line where it starts. Set 'wrappable' for a button in the header that turns 'wrap' on and off, pressed while the lines wrap. The header holds the name, the 'actions' slot, and the copy button. Slot a control into 'actions', such as a button that sets 'wrap' or one that opens the code in an editor, and the block draws a header for it even with no name. 'copy-icon' and 'copied-icon' replace the copy button's two icons. Set 'highlight' to a function that turns the code into highlighted markup, such as one wrapping Shiki or Prism, and the block draws what it returns; it is handed the block's 'language', so one function serves every block. The code stays in the slot, so the copy button and the page's own text are the code as written. **Code Block ships no grammar**, so plain code costs you no parser. To color code without a highlighter of your own, import one more entry beside the block's. It colors every block by its 'language' ('css', 'html', 'js', 'jsx', 'sh', 'ts', or 'tsx') with the Lezer grammars of the sandbox's editor, in the editor's colors: '''js import '@fusion.dev/helix/code-block' import '@fusion.dev/helix-sandbox/code-block' ''' That entry calls 'registerHighlighter', which you can also call yourself to give every block one highlighter of your own. Set 'expandable' on a block whose height is capped, such as by '--code-block-max-block-size', and a button under it shows every line and then fewer again, as a docs site's long example does. The button is drawn only while the cap hides something, says whether the block is expanded with 'aria-expanded', names the block it opens with 'aria-controls', and the block carries ':state(expanded)' while it is. Set 'diff' to show a change. Put a unified diff, the output of 'git diff' or 'diff -u', in the same slot, and the block draws the lines it added and removed. The block never computes a diff itself. Line numbers come from the hunk headers and are hidden from the accessibility tree. Changed lines are '<ins>' and '<del>' with the '+' and '-' kept as text, so the change does not depend on color. Where a removed line is paired with the added line that replaced it, the words each does not share with the other are the 'changed' part, so the eye goes to what changed within the line. Each file in the patch is its own block under its own name, and its copy button copies the new version of the file. 'variant="split"' shows the old version beside the new, each removal opposite its replacement. 'context-lines' folds each long run of unchanged lines, keeping that many beside each change, behind a button that shows them and hides them again, as a code host draws a diff written with more context than a reader needs. **A block that scrolls is a tab stop.** While its lines run past its width or its cap, the scroller is a region named for the block, such as "Code, app.ts", that Tab reaches, so a keyboard scrolls it with the arrow keys in every browser. Chromium and Firefox make a scrolling box focusable on their own, and Safari does not. A block that fits is no stop at all. **The code the block draws is marked untranslated**, 'translate="no"' on its '<pre>', so a page translator leaves highlighted lines and a diff as written. Code in the slot takes its translation mode from the element, which writes nothing onto itself, so set 'translate="no"' on the element to keep a translator off plain code too. On the server, the slot renders as ordinary code, so a diff first appears as the patch text in a '<pre>'. The client makes the same first render, which keeps hydration clean, and draws the diff once it can read the content. Diff mode is experimental. The rest of the family is stable. **Several blocks are files**, one shown at a time under a row of tabs, as Sandbox shows its source panes. Put Code Blocks in the default slot of a Code Block, and each is a file named on its tab by its 'label' or, without one, its 'language'. 'file' holds the name of the file shown. The tabs are a tab list: the arrow keys move to a tab and show its file, the two swapping on a right-to-left page, and Home and End go to the first and the last. Choosing one sends 'helix-before-change' with the file's name, which you can cancel, and 'change' once 'file' holds it. The files not shown carry 'hidden', and the one shown draws no name of its own, its tab naming it. One block draws no tabs. A server cannot see the blocks inside, so the client draws the tabs once it upgrades. */
19448
19479
  "helix-headless-code-block": DefineCustomElement<
19449
19480
  HelixHeadlessCodeBlock,
19450
19481
  HelixHeadlessCodeBlockVueProps,
@@ -19486,7 +19517,7 @@ export interface WcToolkitVueGlobalComponents {
19486
19517
  HelixHeadlessCopyButtonVueProps,
19487
19518
  HelixHeadlessCopyButtonVueEvents
19488
19519
  >;
19489
- /** Declare the columns as 'TableColumn' children and pass the rows as an array. The schema stays readable in the HTML, and the rows can be windowed, which ten thousand row elements cannot be. '''html <helix-headless-data-table .rows=${rows} sort="name:asc" page-size="20"> <helix-headless-table-column field="name" sortable>Name</helix-headless-table-column> <helix-headless-table-column field="size" text-align="end" sortable .cell=${bytes}>Size</helix-headless-table-column> </helix-headless-data-table> ''' For a short table written out by hand, use 'Table', which takes rows as markup. Sort and filter apply to the whole set, including the rows on other pages. **Write the first page as rows, so the served HTML carries the values.** The table reads each cell from its column, and a server does not pass the column children to this element, so on its own it serves the headings and no values. Write the first page under the columns as 'TableRow' and 'TableCell' elements, in the table's sort and page size and formatted as its columns draw them. The table shows your rows until 'rows' holds a row, then draws its own in their place and leaves yours in the page, unshown. A development build warns when the two differ. In React, map the first page of the same array in the same server component. 'selectable' adds a column of checkboxes, keyed on 'row-key': - A row is selected by its key, so the selection survives a sort, a filter, and a page change. - 'selected' holds the chosen keys, comma separated, the same shape 'Listbox' uses for a multiple choice. As with 'sort', writing it applies the selection, and 'default-selected' holds what the markup declared. - The checkbox in the heading selects every row in the result, across pages, and shows a dash while only some are chosen. - Shift with a press on a checkbox selects every row between it and the row last chosen. - 'selection-behavior="replace"' makes a press or a move select the row alone, as a file list does. Control or Command with a press adds or takes out one row, and Shift with a press selects every row from the one last chosen. To act on a single row, such as opening it, put a link or a button in a cell. **Keyboard.** The grid is one tab stop, and the arrow keys move between its cells, the headings included. | Key | What it does | |---|---| | Right, Left | Moves one cell along the row. Left moves on, on a right-to-left page. | | Down, Up | Moves one row, the heading row and the 'load-more' row included. | | Home, End | Moves to the first or the last cell of the row. | | Control with Home or End | Moves to the first or the last cell of the grid. | | Page Down, Page Up | Moves by the rows that fit in view. | | Enter, F2 | Moves into the cell's controls. Escape moves back to the cell, and Tab moves between the controls of one cell. | | Enter, Space on a sortable heading | Sorts by the column. | | Enter, Space on the 'load-more' row | Sends 'helix-load-more'. | | Space on a row | Selects the row, in a 'selectable' table. Under 'selection-behavior="replace"', selects it alone, and Control or Command with Space adds or takes out the row. | | Down, Up, Page Down, Page Up under 'selection-behavior="replace"' | Selects the row it moves to alone. Control or Command with the key moves without selecting. | | Shift with Down or Up | Selects the rows it moves across, in a 'selectable' table. | | Shift with Space | Selects every row from the one last chosen, in a 'selectable' table. | | Control or Command with A | Selects every row, in a 'selectable' table. | | Right on a row header in a tree grid | Opens a closed row, and moves one cell along an open one. | | Left on a row header in a tree grid | Closes an open row, and moves to the parent of a closed one. | | A letter or a word | Moves to the next row whose row header starts with what you typed. | 'selected' and 'expanded' hold their keys in the order of the rows, as do 'helix-select', 'helix-selected' and 'helix-expand'. Each row is named by its row header, the column marked 'row-header', or the first column with a 'field' where none is. A screen reader says it as a reader moves between rows. **Rows that hold rows.** 'child-field' names the field that holds a row's child rows, and the grid becomes a tree grid. The row header column draws a mark that a press opens and closes a row by, and 'expanded' holds the keys of the open rows, which 'row-key' names. Right on a closed row's header opens it, Left on an open one closes it, and Left on a child moves to its parent. A sort orders the rows under each parent, and a search shows the rows that lead to each match, open. 'load-more' adds a row after the last one with a button that sends 'helix-load-more'. A 'windowed' table also sends it by itself once a reader scrolls within one screen of the end, once for each number of rows. Add the next rows to 'rows', and set 'loading' while they are on their way. When a fetch fails, set 'error-text', such as "The files did not load", and put a button that tries again in the 'error' slot. The line shows after the rows in place of the empty and loading lines, the live region says it, and the table takes the 'error' state. Clear it once you try again. The controls inside the cells leave the tab order, so Tab moves past the whole grid. A windowed table keeps the row holding focus drawn while the rest scroll away. People can resize and reorder the columns. 'resizable' on a column puts a separator on its edge. 'reorderable' on the table puts a grip on each heading that has a 'field', moved by dragging or with the arrow keys. The new order is written to 'order' as a list of fields. Your markup is not rewritten: the table assigns the headings to its header in that order. **'reorderable-rows' lets people move rows.** A column of grips leads each row, named by 'move-row-label'. Drag a grip to move its row, and the table scrolls near an edge. Or press Space or Enter on a grip, or click it, to pick up its row, move it with Down and Up, Home and End, and press Space or Enter again to drop it. A click on another row drops it there, and Escape puts it back. The table says each step in its 'live' region. A drop sends 'helix-before-reorder', which you can refuse, and then 'helix-reorder' with 'kind' set to 'row', whose 'keys' hold every key of 'rows' in the new order. **You move the rows**: set 'rows' to the new order, and the table draws it. Set 'row-key', so a row is known by its key once it has moved. The grips do nothing while a 'sort' is set, since the sort decides the order, and a tree grid draws none. 'csv()' returns the result as text: every row that passes the filter, in the order and the columns on screen. Saving the file is up to you. 'DataTable' has no 'columns' attribute. Each 'TableColumn' is part of the schema, so you size a column with its own 'width'. 'Table' has 'columns' because its cells are markup you write and it can have no columns at all. Written on 'DataTable', 'columns' has no effect, so watch for it when you move a table from 'Table' to 'DataTable'. **The columns are an import of their own.** A column is the Table family's 'TableColumn', which the data table does not register, so a page that writes one imports the Table entry beside the data table: '''js import '@fusion.dev/helix/data-table' import '@fusion.dev/helix/table' ''' In development, a data table holding a column nobody registered says so once the page has loaded, with the line to add. */
19520
+ /** Declare the columns as 'TableColumn' children and pass the rows as an array. The schema stays readable in the HTML, and the rows can be windowed, which ten thousand row elements cannot be. '''html <helix-headless-data-table .rows=${rows} sort="name:asc" page-size="20"> <helix-headless-table-column field="name" sortable>Name</helix-headless-table-column> <helix-headless-table-column field="size" text-align="end" sortable .cell=${bytes}>Size</helix-headless-table-column> </helix-headless-data-table> ''' For a short table written out by hand, use 'Table', which takes rows as markup. Sort and filter apply to the whole set, including the rows on other pages. **Write the first page as rows, so the served HTML carries the values.** The table reads each cell from its column, and a server does not pass the column children to this element, so on its own it serves the headings and no values. Write the first page under the columns as 'TableRow' and 'TableCell' elements, in the table's sort and page size and formatted as its columns draw them. The table shows your rows until 'rows' holds a row, then draws its own in their place and leaves yours in the page, unshown. A development build warns when the two differ. In React, map the first page of the same array in the same server component. 'selectable' adds a column of checkboxes, keyed on 'row-key': - A row is selected by its key, so the selection survives a sort, a filter, and a page change. - 'selected' holds the chosen keys, comma separated, the same shape 'Listbox' uses for a multiple choice. As with 'sort', writing it applies the selection, and 'default-selected' holds what the markup declared. - The checkbox in the heading selects every row in the result, across pages, and shows a dash while only some are chosen. - Shift with a press on a checkbox selects every row between it and the row last chosen. - 'selection-behavior="replace"' makes a press or a move select the row alone, as a file list does. Control or Command with a press adds or takes out one row, and Shift with a press selects every row from the one last chosen. To act on a single row, such as opening it, put a link or a button in a cell. **Keyboard.** The grid is one tab stop, and the arrow keys move between its cells, the headings included. | Key | What it does | |---|---| | Right, Left | Moves one cell along the row. Left moves on, on a right-to-left page. | | Down, Up | Moves one row, the heading row and the 'load-more' row included. | | Home, End | Moves to the first or the last cell of the row. | | Control with Home or End | Moves to the first or the last cell of the grid. | | Page Down, Page Up | Moves by the rows that fit in view. | | Enter, F2 | Moves into the cell's controls. Escape moves back to the cell, and Tab moves between the controls of one cell. | | Enter, Space on a sortable heading | Sorts by the column. | | Enter, Space on the 'load-more' row | Sends 'helix-load-more'. | | Space on a row | Selects the row, in a 'selectable' table. Under 'selection-behavior="replace"', selects it alone, and Control or Command with Space adds or takes out the row. | | Down, Up, Page Down, Page Up under 'selection-behavior="replace"' | Selects the row it moves to alone. Control or Command with the key moves without selecting. | | Shift with Down or Up | Selects the rows it moves across, in a 'selectable' table. | | Shift with Space | Selects every row from the one last chosen, in a 'selectable' table. | | Control or Command with A | Selects every row, in a 'selectable' table. | | Right on a row header in a tree grid | Opens a closed row, and moves one cell along an open one. | | Left on a row header in a tree grid | Closes an open row, and moves to the parent of a closed one. | | A letter or a word | Moves to the next row whose row header starts with what you typed. | 'selected' and 'expanded' hold their keys in the order of the rows, as do 'helix-select', 'helix-selected' and 'helix-expand'. Each row is named by its row header, the column marked 'row-header', or the first column with a 'field' where none is. A screen reader says it as a reader moves between rows. **Rows that hold rows.** 'child-field' names the field that holds a row's child rows, and the grid becomes a tree grid. The row header column draws a mark that a press opens and closes a row by, and 'expanded' holds the keys of the open rows, which 'row-key' names. Right on a closed row's header opens it, Left on an open one closes it, and Left on a child moves to its parent. A sort orders the rows under each parent, and a search shows the rows that lead to each match, open. 'load-more' adds a row after the last one with a button that sends 'helix-load-more'. A 'windowed' table also sends it by itself once a reader scrolls within one screen of the end, once for each number of rows. Add the next rows to 'rows', and set 'loading' while they are on their way. When a fetch fails, set 'error-text', such as "The files did not load", and put a button that tries again in the 'error' slot. The line shows after the rows in place of the empty and loading lines, the live region says it, and the table takes the 'error' state. Clear it once you try again. The controls inside the cells leave the tab order, so Tab moves past the whole grid. A windowed table keeps the row holding focus drawn while the rest scroll away. People can resize and reorder the columns. 'resizable' on a column puts a separator on its edge. 'reorderable' on the table puts a grip on each heading that has a 'field', moved by dragging or with the arrow keys. The new order is written to 'order' as a list of fields. Your markup is not rewritten: the table assigns the headings to its header in that order. **'reorderable-rows' lets people move rows.** A column of grips leads each row, named by 'move-row-label'. Drag a grip to move its row, and the table scrolls near an edge. Or press Space or Enter on a grip, or click it, to pick up its row, move it with Down and Up, Home and End, and press Space or Enter again to drop it. A click on another row drops it there, and Escape puts it back. The table says each step in its 'live' region. A drop sends 'helix-before-reorder', which you can refuse, and then 'helix-reorder' with 'kind' set to 'row', whose 'keys' hold every key of 'rows' in the new order. **You move the rows**: set 'rows' to the new order, and the table draws it. Set 'row-key', so a row is known by its key once it has moved. The grips do nothing while a 'sort' is set, since the sort decides the order, and a tree grid draws none. 'csv()' returns the result as text: every row that passes the filter, in the order and the columns on screen. Saving the file is up to you. Size a column with its own 'width', or every column at once with 'columns', a track list dealt out one track to a column in the order they are written, as 'Table' deals it. A column's 'width' wins in its place. **A table that serves its first page takes its widths from 'columns'**: a server and a stylesheet can read the table's own attributes and not its columns', so the served rows are laid out at the widths the table draws. **The columns are an import of their own.** A column is the Table family's 'TableColumn', which the data table does not register, so a page that writes one imports the Table entry beside the data table: '''js import '@fusion.dev/helix/data-table' import '@fusion.dev/helix/table' ''' In development, a data table holding a column nobody registered says so once the page has loaded, with the line to add. */
19490
19521
  "helix-headless-data-table": DefineCustomElement<
19491
19522
  HelixHeadlessDataTable,
19492
19523
  HelixHeadlessDataTableVueProps,
@@ -19768,7 +19799,7 @@ export interface WcToolkitVueGlobalComponents {
19768
19799
  HelixHeadlessMenuItemVueProps,
19769
19800
  HelixHeadlessMenuItemVueEvents
19770
19801
  >;
19771
- /** The trigger is slotted and stays your own element, as with the tooltip. The menu renders its surface in the top layer with the popover API, so an ancestor with 'overflow: hidden' does not clip it and it needs no 'z-index'. Slot a 'helix-button' or 'helix-icon-button' as the trigger, and the menu tells it that it opens a menu and whether the menu is open, inside its own shadow root. On a plain element, such as a '<button>', the menu writes 'aria-haspopup="menu"' and 'aria-expanded', from a frame after its own first render, so a server's markup is never changed while a framework hydrates it. It never writes 'aria-expanded' where you wrote it yourself. Submenus drill down by default. A submenu replaces the panel's content, and a back row returns to the previous page. One panel stays inside a narrow window, and works on touch screens, which have no hover. Focus follows a mouse resting on a row in either mode, and a drilled page is a 'menu' named by the row that opened it. **'submenus="flyout"' opens each submenu in a panel of its own beside its row**, as React Aria's 'SubmenuTrigger' and Radix's 'Sub' do. Resting the pointer on the row opens it, and a pointer crossing toward the open panel over the rows between keeps it open, as Radix's grace area does. Right Arrow opens a row's submenu on its first row, and Left Arrow or Escape closes it and returns focus to the row, the two arrows swapping on a right-to-left page. The row says 'aria-expanded', and the panel is a 'menu' named by the row. The root holds which page is open, because only one page shows at a time. It sets this on items as a property, never as an attribute. An attribute written onto your element after it upgrades causes a hydration mismatch. Group rows under a heading with 'Menu.Section', which is a 'group' named by its heading. Between runs of rows, a '<helix-divider>' is a separator a screen reader announces. Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first row, and Up Arrow on its last. In the menu, Up and Down Arrow move between rows, Home and End go to the first and the last, a typed letter moves to the next row whose name starts with it, Enter and Space choose (Space on a choice row changes it and leaves the menu open), Right Arrow opens a row's submenu and Left Arrow goes back, the two swapping on a right-to-left page. Left Arrow on the top page does nothing. Escape closes the menu and returns focus to the trigger. Tab closes it and moves on. While it is open, the surface carries the trigger's width as '--floating-anchor-inline-size' and the room left below it as '--floating-available-block-size', as Radix's dropdown menu publishes its trigger's width, for a menu as wide as its trigger: 'helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }'. **The choices in one place.** 'checkedValues' holds the values of the rows that are checked, anywhere in the menu, and setting it checks exactly those rows, as React Aria's 'selectedKeys' does. 'change' is sent on the menu when a reader's choice changes it. With 'context', the trigger is an area and the menu is its context menu: a right-click, a long press, Shift+F10 or the menu key over the area opens it at the pointer, or at the area's corner from the keyboard, as Radix's context menu does. A press on the area does not open it, and closing it returns focus to where it was. A touch or a pen held still on the area opens it too, on every browser, since iOS sends no 'contextmenu' for one. **A trigger with its own action.** With 'open-on="long-press"', a press on the trigger is the trigger's own, and a press held for half a second opens the menu, as React Aria's 'trigger="longPress"' does. Alt+Down or Alt+Up opens it from the keyboard, and the trigger is described by 'long-press-label', which says so. **A filter field.** With 'filterable', the menu opens with focus in a field above its rows, and typing narrows the rows of the page the keys move in, as React Aria's 'Autocomplete' around a 'Menu' does. A row is kept where its words hold the filter, in any case, or where 'filterMatch' says so. Each page starts unfiltered, and the filter is cleared as the menu closes. Where typing keeps no row, the menu shows 'no-results-text'. Focus stays in the field: Up and Down Arrow move the highlight through the rows that are left, Enter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow on a submenu goes back, and Escape clears the filter and then closes the menu. A screen reader hears how many rows the filter keeps ('results-label'). Home, End and the other keys move the caret and type. The field names the highlighted row with 'aria-activedescendant', and the rows are a 'menu' after the field. Cancel 'helix-filter' to keep every row showing and narrow the rows yourself, such as by replacing them with rows from a server. */
19802
+ /** The trigger is slotted and stays your own element, as with the tooltip. The menu renders its surface in the top layer with the popover API, so an ancestor with 'overflow: hidden' does not clip it and it needs no 'z-index'. Slot a 'helix-button' or 'helix-icon-button' as the trigger, and the menu tells it that it opens a menu and whether the menu is open, inside its own shadow root. On a plain element, such as a '<button>', the menu writes 'aria-haspopup="menu"' and 'aria-expanded', from a frame after its own first render, so a server's markup is never changed while a framework hydrates it. It never writes 'aria-expanded' where you wrote it yourself. Submenus drill down by default. A submenu replaces the panel's content, and a back row returns to the previous page. One panel stays inside a narrow window, and works on touch screens, which have no hover. Focus follows a mouse resting on a row in either mode, and a drilled page is a 'menu' named by the row that opened it. **'submenus="flyout"' opens each submenu in a panel of its own beside its row**, as React Aria's 'SubmenuTrigger' and Radix's 'Sub' do. Resting the pointer on the row opens it, and a pointer crossing toward the open panel over the rows between keeps it open, as Radix's grace area does. Right Arrow opens a row's submenu on its first row, and Left Arrow or Escape closes it and returns focus to the row, the two arrows swapping on a right-to-left page. The row says 'aria-expanded', and the panel is a 'menu' named by the row. The root holds which page is open, because only one page shows at a time. It sets this on items as a property, never as an attribute. An attribute written onto your element after it upgrades causes a hydration mismatch. Group rows under a heading with 'Menu.Section', which is a 'group' named by its heading. Between runs of rows, a '<helix-divider>' is a separator a screen reader announces. Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first row, and Up Arrow on its last. In the menu, Up and Down Arrow move between rows, Home and End go to the first and the last, a typed letter moves to the next row whose name starts with it, Enter and Space choose (Space on a choice row changes it and leaves the menu open), Right Arrow opens a row's submenu and Left Arrow goes back, the two swapping on a right-to-left page. Left Arrow on the top page does nothing. Escape closes the menu and returns focus to the trigger. Tab closes it and moves on. While it is open, the surface carries the trigger's width as '--floating-anchor-inline-size' and the room left below it as '--floating-available-block-size', as Radix's dropdown menu publishes its trigger's width, for a menu as wide as its trigger: 'helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }'. **The choices in one place.** 'checkedValues' holds the values of the rows that are checked, anywhere in the menu, and setting it checks exactly those rows, as React Aria's 'selectedKeys' does. 'change' is sent on the menu when a reader's choice changes it. With 'context', the trigger is an area and the menu is its context menu: a right-click, a long press, Shift+F10 or the menu key over the area opens it at the pointer, or at the area's corner from the keyboard, as Radix's context menu does. A press on the area does not open it, and closing it returns focus to where it was. A touch or a pen held still on the area opens it too, on every browser, since iOS sends no 'contextmenu' for one. **A trigger with its own action.** With 'open-on="long-press"', a press on the trigger is the trigger's own, and a press held for half a second opens the menu, as React Aria's 'trigger="longPress"' does. Alt+Down or Alt+Up opens it from the keyboard, and the trigger is described by 'long-press-label', which says so. **A filter field** is a separate import, '@fusion.dev/helix/menu/filter', so a menu that never filters carries none of its code: '''js import '@fusion.dev/helix/menu' import '@fusion.dev/helix/menu/filter' ''' With it imported and 'filterable' set, the menu opens with focus in a field above its rows, and typing narrows the rows of the page the keys move in, as React Aria's 'Autocomplete' around a 'Menu' does. A row is kept where its words hold the filter, in any case, or where 'filterMatch' says so. Each page starts unfiltered, and the filter is cleared as the menu closes. Where typing keeps no row, the menu shows 'no-results-text'. Focus stays in the field: Up and Down Arrow move the highlight through the rows that are left, Enter chooses the highlighted row, Right Arrow opens its submenu, Left Arrow on a submenu goes back, and Escape clears the filter and then closes the menu. A screen reader hears how many rows the filter keeps ('results-label'). Home, End and the other keys move the caret and type. The field names the highlighted row with 'aria-activedescendant', and the rows are a 'menu' after the field. Cancel 'helix-filter' to keep every row showing and narrow the rows yourself, such as by replacing them with rows from a server. */
19772
19803
  "helix-headless-menu": DefineCustomElement<
19773
19804
  HelixHeadlessMenu,
19774
19805
  HelixHeadlessMenuVueProps,
package/types/words.d.ts CHANGED
@@ -3284,6 +3284,13 @@ declare module '@fusion.dev/helix-core' {
3284
3284
  * English: `{kind, select, date {Enter a whole date.} other {Enter a whole time.}}`
3285
3285
  */
3286
3286
  incompleteMessage: Message
3287
+ /**
3288
+ * The words on the list's button that chooses the current time, drawn with
3289
+ * `show-now`.
3290
+ *
3291
+ * English: `Now`
3292
+ */
3293
+ nowLabel: Message
3287
3294
  /**
3288
3295
  * Placeholder text shown before a time is entered.
3289
3296
  *