@fusion.dev/helix-headless 0.4.2 → 0.4.3

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 (44) hide show
  1. package/custom-elements.json +39 -39
  2. package/dist/app-header/root/app-header-root.d.ts +8 -28
  3. package/dist/avatar/group/avatar-group.d.ts +5 -30
  4. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
  5. package/dist/chat/root/chat-root.d.ts +9 -28
  6. package/dist/color-picker/root/color-picker-root.d.ts +10 -28
  7. package/dist/combobox/root/combobox-root.d.ts +18 -60
  8. package/dist/copy-button/root/copy-button-root.d.ts +6 -21
  9. package/dist/data-table/root/data-table-root.d.ts +9 -32
  10. package/dist/date-input/root/date-input-root.d.ts +5 -21
  11. package/dist/date-picker/root/date-picker-root.d.ts +10 -35
  12. package/dist/dialog/root/dialog-root.d.ts +7 -29
  13. package/dist/donut-chart/root/donut-chart-root.d.ts +5 -25
  14. package/dist/file-input/root/file-input-root.d.ts +5 -22
  15. package/dist/heatmap/root/heatmap-root.d.ts +13 -36
  16. package/dist/image/root/image-root.d.ts +5 -22
  17. package/dist/input/root/input-root.d.ts +11 -29
  18. package/dist/kbd/root/kbd-root.d.ts +8 -26
  19. package/dist/legend/root/legend-root.d.ts +6 -24
  20. package/dist/listbox/root/listbox-root.d.ts +4 -26
  21. package/dist/megamenu/root/megamenu-root.d.ts +7 -39
  22. package/dist/meter/root/meter-root.d.ts +6 -24
  23. package/dist/number-input/root/number-input-root.d.ts +11 -20
  24. package/dist/outline/root/outline-root.d.ts +8 -27
  25. package/dist/pagination/root/pagination-root.d.ts +21 -54
  26. package/dist/pagination/summary/pagination-summary.d.ts +10 -31
  27. package/dist/progress/root/progress-root.d.ts +4 -21
  28. package/dist/rating/root/rating-root.d.ts +8 -31
  29. package/dist/slider/root/slider-root.d.ts +9 -32
  30. package/dist/splitter/root/splitter-root.d.ts +17 -85
  31. package/dist/steps/root/steps-root.d.ts +8 -26
  32. package/dist/steps/step/step.d.ts +11 -41
  33. package/dist/toast/item/toast-item.d.ts +6 -30
  34. package/dist/toggle/group/toggle-group.d.ts +7 -25
  35. package/dist/tooltip/root/tooltip-root.d.ts +14 -36
  36. package/dist/tour/root/tour-root.d.ts +6 -29
  37. package/dist/tree/item/tree-item.d.ts +13 -35
  38. package/dist/video/root/video-root.d.ts +12 -40
  39. package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -25
  40. package/dist/virtual-list/root/virtual-list-root.d.ts +5 -44
  41. package/package.json +17 -18
  42. package/{jsx.d.ts → types/jsx.d.ts} +724 -2537
  43. package/{vue.d.ts → types/vue.d.ts} +39 -39
  44. /package/{svelte.d.ts → types/svelte.d.ts} +0 -0
@@ -5,37 +5,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
5
5
  *
6
6
  * @description
7
7
  * Tracks whether the page has scrolled and carries it as the custom state
8
- * `scrolled`, so the styled tier can lift the bar off the page without a scroll
9
- * handler of its own. Scroll position is the one piece of state the server
10
- * genuinely cannot know, so it is read on connect rather than derived: a fresh
11
- * load starts at the top, which is what the server rendered, and a reload
12
- * part-way down corrects on hydration.
8
+ * `scrolled`, so the styled tier can lift the bar without a scroll handler of
9
+ * its own. It is read on connect rather than derived: a fresh load starts at
10
+ * the top, which is what the server rendered, and a reload part-way down
11
+ * corrects on hydration.
13
12
  *
14
13
  * **A custom state and never `data-scrolled`.** An attribute the element writes
15
14
  * onto its own host is one the server did not send, so a hydrating framework
16
- * reports the tree as mismatched, intermittently: only when the reader reloads
17
- * far enough down the page to pass the threshold. A consumer can answer that
18
- * only by suppressing hydration warnings on an element they did not write.
19
- * `ElementInternals.states` is deliberately not in the DOM, so there is nothing
20
- * for a hydration pass to disagree with, and `:state(scrolled)` selects it. The
21
- * base class made the same move for `data-settled` and its note explains the
22
- * rest.
23
- *
24
- * The listener is passive and reads `scrollY` only, so it never blocks
25
- * scrolling.
26
- *
27
- * Three regions, each in its own wrapper, because the row is a grid and a grid
28
- * needs three items to put the middle one in the middle. A bare slot is
29
- * `display: contents`, so its assigned elements become grid items themselves:
30
- * two actions would take two tracks and push the navigation off center. These
31
- * wrappers earn their boxes, which is the test; they carry no inset or fill of
32
- * their own, so an empty one still paints nothing.
33
- *
34
- * The host is the banner and spans the viewport; the row inside it is what gets
35
- * centered. A banner that is itself narrowed leaves its background stopping
36
- * short of the window edges, which reads as a floating bar rather than as the
37
- * top of the page. That needs one element and one row, not a wrapper as well:
38
- * the host carries the material and `content` carries the measure.
15
+ * reports a mismatch, intermittently: only when the reader reloads far enough
16
+ * down the page. `ElementInternals.states` is not in the DOM, so there is
17
+ * nothing for a hydration pass to disagree with, and `:state(scrolled)` selects
18
+ * it.
39
19
  *
40
20
  * @since 0.1.0
41
21
  * @status stable
@@ -15,40 +15,15 @@ export declare const FOLDS_UP_TO = 12;
15
15
  *
16
16
  * @description
17
17
  * A part of `Avatar` rather than a family of its own: it arranges avatars and
18
- * is about nothing else, and its member is a complete `Avatar` the group did
19
- * not have to explain.
18
+ * is about nothing else.
20
19
  *
21
20
  * **The overflow count is the group's, not a slot.** Which avatars are hidden
22
- * is a fact the group works out from `max` and how many it was given, so a
23
- * consumer writing the "+3" themselves would be writing a number that has to
24
- * agree with a list they do not control.
21
+ * is a fact the group works out from `max`, so a consumer writing the "+3"
22
+ * would be writing a number that has to agree with a list they do not control.
25
23
  *
26
- * **Hidden, not removed.** Past `max`, the extra avatars stay in the DOM and
24
+ * **Hidden, not removed.** Past `max` the extra avatars stay in the DOM and
27
25
  * stop being shown, so nothing re-renders when `max` changes and the accessible
28
- * name can still be built from all of them. The count is what a sighted reader
29
- * gets; the group's own name is what everyone else gets, and "Seven people" is
30
- * more useful than seven names read in a row.
31
- *
32
- * **And hidden by the stylesheet, not by this class.** Hiding from `updated` is
33
- * one update too late and one element too far out: Lit renders on a microtask,
34
- * so an avatar appended past the limit is laid out and painted before anything
35
- * runs to hide it, and marking each one means writing attributes onto markup a
36
- * consumer owns. The styled tier's
37
- * `:host([max="N"]) ::slotted(:nth-child(n + N+1))` is right at the first style
38
- * resolution and writes nothing.
39
- *
40
- * **The fold is finite, and the count agrees with it.** `An+B` takes a literal,
41
- * so there is one selector per value of `max` and the range stops at twelve.
42
- * Past that the group shows everyone, counts nothing and says so, because
43
- * showing everyone is a defensible answer and showing everyone beside a "+5" is
44
- * not. `max` above twelve is a list the consumer should be slicing themselves.
45
- *
46
- * **It is a list.** A row of faces is a set of separate people, and a group
47
- * with no role announces as one run of text. `role="list"` needs its children
48
- * to be `listitem`, which they cannot be told to become without writing an
49
- * attribute onto a consumer's element, so the group carries `role="group"` and
50
- * its name instead: one announcement, correct, and nothing written to anyone
51
- * else's markup.
26
+ * name is still built from all of them.
52
27
  *
53
28
  * @since 0.1.0
54
29
  * @status stable
@@ -4,37 +4,18 @@ import { type PropertyValues, type TemplateResult } from 'lit';
4
4
  * @summary Shows the path to the current page.
5
5
  *
6
6
  * @description
7
- * The host is the landmark, so `aria-label` on it names the trail directly and
8
- * there is no property mirroring one. A page may hold more than one navigation,
9
- * and landmarks are how a screen-reader user chooses between them.
7
+ * The host is the landmark, so `aria-label` on it names the trail directly. A
8
+ * page may hold more than one navigation, and landmarks are how a
9
+ * screen-reader user chooses between them.
10
10
  *
11
- * `role="list"` is set explicitly on the `<ol>` even though it is already a
12
- * list: removing the markers with `list-style: none` strips list semantics in
13
- * Safari, and a breadcrumb trail always removes its markers.
11
+ * `role="list"` is set explicitly on the `<ol>` even though it is one:
12
+ * `list-style: none` strips list semantics in Safari, and a breadcrumb trail
13
+ * always removes its markers.
14
14
  *
15
- * Items are slotted rather than wrapped, so they are `<ol>` children in the flat
16
- * tree and each carries `role="listitem"` itself.
15
+ * Items are slotted rather than wrapped, so they are `<ol>` children in the
16
+ * flat tree and each carries `role="listitem"` itself.
17
17
  *
18
- * **The trail does not measure itself, and the overflow is markup.** Measuring
19
- * how many crumbs fit can never reach the server: there is no width without a
20
- * DOM, so the server ships every crumb and the client removes some after
21
- * hydrating, and a trail that collapses paints wrong on every single load. Nor
22
- * does anybody specify a breadcrumb in units of fit. Designs say "keep the root
23
- * and the current page, fold the middle", which is a fact about depth, or "fold
24
- * below this width", which is a fact CSS knows.
25
- *
26
- * So the trail lays out crumbs and separators, and the consumer writes what
27
- * folds: a `helix-menu` of `helix-menu-item`s in a crumb, where the gap
28
- * belongs. Server rendered, no observer, no stylesheet, and correct before the
29
- * first script runs. A trail that should fold only at some widths is a
30
- * container query in the consumer's own sheet, which is theirs to write and
31
- * theirs to leave out.
32
- *
33
- * **And the crumbs carry no marker for any of it.** CSS can already see it: the
34
- * crumb with the menu in it is `:has(helix-menu)`, and the middle is
35
- * `:not(:first-child, [current])`. A marker would be the design rule written
36
- * twice, once in the HTML and once in the sheet, with nothing keeping the two
37
- * honest.
18
+ * **The trail does not measure itself, and the overflow is markup.**
38
19
  *
39
20
  * @since 0.1.0
40
21
  * @status stable
@@ -7,35 +7,16 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
7
7
  *
8
8
  * @description
9
9
  * **It has no opinion about where it sits.** A chat is asked for as a floating
10
- * button, a page, a palette, a sidebar, a modal and an inline block, and none of
11
- * those is a variant of a conversation: they are containers a conversation is
12
- * put in, and the containers already exist. `Popover` and `SpeedDial` make the
13
- * floating one, `Drawer` the sidebar, `Dialog` the modal, `Command` the palette,
14
- * and a page is a page. Nothing here is positioned, nothing here has a backdrop,
15
- * and nothing here owns a trigger, because a trigger opens a container and
16
- * containers own their own. If a form factor needs a mode on this element, the
17
- * split is wrong.
10
+ * button, a page, a palette, a sidebar, a modal and an inline block, and none
11
+ * of those is a variant of a conversation: they are containers, and the
12
+ * containers already exist. Nothing here is positioned, nothing has a backdrop,
13
+ * and nothing owns a trigger. If a form factor needs a mode on this element,
14
+ * the split is wrong.
18
15
  *
19
- * **Scroll ownership is the behavior everything else depends on, and it is the
20
- * most-got-wrong thing in the category.** A transcript that grows wants to stay
21
- * at the bottom, except when the reader has scrolled up to read, where pinning
22
- * is hostile. The rule: pin while the reader is within `threshold` of the
23
- * bottom, release the moment they leave it, and offer a way back. **Never scroll
24
- * a reader who is reading.**
25
- *
26
- * The element owns it, because it is the only party that knows a message arrived
27
- * and where the viewport was when it did. `pinned` announces before it moves, so
28
- * a consumer who wants to own it refuses the request and assigns their own.
29
- *
30
- * **The live region announces on completion, not on arrival.** The transcript is
31
- * `role="log"` with `aria-live="polite"`, and a streaming message carries
32
- * `aria-busy` while it arrives: a screen reader reading a stream token by token
33
- * is unusable, and holding the announcement until the flag clears is the only
34
- * arrangement that works. Somebody typing is a separate status region, so it
35
- * never interleaves with what was said.
36
- *
37
- * **Not a client.** No transport, no protocol, no model. It renders a
38
- * conversation and reports what the reader did.
16
+ * **Scroll ownership is the behavior everything else depends on.** A transcript
17
+ * that grows wants to stay at the bottom, except when the reader has scrolled
18
+ * up to read, where pinning is hostile. The rule: pin while the reader is
19
+ * within `threshold` of the bottom, and let go the moment they leave it.
39
20
  *
40
21
  * @since 0.1.0
41
22
  * @status experimental
@@ -9,38 +9,20 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
9
9
  * @summary Picks a color, from a square and two ramps.
10
10
  *
11
11
  * @description
12
- * **The picker itself, with no field around it.** Color Input is this element in
13
- * a panel behind a text field, the same way Date Input is `helix-date-picker` in a
14
- * panel: a form wants a field, and a settings pane or a toolbar wants the picker
15
- * sitting flat on the page with nothing to open. Neither should be the other one
16
- * with parts hidden.
12
+ * **The picker itself, with no field around it.** Color Input is this element
13
+ * in a panel behind a text field; a settings pane or a toolbar wants the picker
14
+ * flat on the page with nothing to open.
17
15
  *
18
- * **The square is two real range inputs.** Saturation and brightness are each an
19
- * `<input type="range">`, laid over the square and made invisible, and the
20
- * handle is drawn from their values. The pointer gets the square; the keyboard
21
- * gets the arrow keys, Home, End and the page keys; a screen reader gets two
22
- * sliders that announce a name and a number. All of it is the platform's, and
23
- * nothing here implements a key handler. There is no `role="application"`, which
24
- * is the usual way this control is built and amounts to asking a screen reader
25
- * to stop helping.
16
+ * **The square is two real range inputs.** Saturation and brightness are each
17
+ * an `<input type="range">`, laid over the square and made invisible, and the
18
+ * handle is drawn from their values. The keyboard, the announcements and the
19
+ * touch targets are the platform's, and there is no `role="application"`.
26
20
  *
27
21
  * **The working model is HSB, and the value is derived from it.** The reverse
28
22
  * loses colors: black is `brightness: 0`, whose hue and saturation are both
29
- * undefined, so a reader who drags to the bottom of the square and back would
30
- * get gray where they had red. Holding the model means a color survives a trip
31
- * through one that has no hue. A value arriving from outside is read into the
32
- * model once, which is the only moment the conversion runs in that direction.
33
- *
34
- * **Every syntax is read; the one `format` names is written.** `#f00`,
35
- * `#ff0000`, `rgb(255 0 0)`, `rgba(255,0,0,.5)` and `hsl(0 100% 50%)` are all
36
- * colors. Named colors are the exception, and deliberately: resolving
37
- * `rebeccapurple` means shipping a table of a hundred and forty or asking the
38
- * browser, and there is no browser during a server render.
39
- *
40
- * The properties below are written by this component and read by whoever draws
41
- * it. A consumer sets none of them: they carry a number this element computed
42
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
43
- * without measuring anything itself.
23
+ * undefined, so dragging to the bottom of the square and back would give gray
24
+ * where there had been red. A value arriving from outside is read into the
25
+ * model once.
44
26
  *
45
27
  * @since 0.1.0
46
28
  * @status experimental
@@ -7,73 +7,31 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
7
7
  * @summary A field that filters a list as it is typed into.
8
8
  *
9
9
  * @description
10
- * **The list is `helix-listbox`, and the filtering is its own.** It already
11
- * owns narrowing, the empty state, the highlight, `aria-activedescendant` and
12
- * scrolling an option into view. Rewriting them here would be a second copy to
13
- * keep in step; what is left for this element is the field, the panel and the
14
- * traffic between them.
10
+ * **The list is `helix-listbox`, and the filtering is its own.** It owns
11
+ * narrowing, the empty state, the highlight, `aria-activedescendant` and
12
+ * scrolling an option into view. What is left for this element is the field,
13
+ * the panel and the traffic between them.
15
14
  *
16
- * **The text and the value are two things.** What a reader types is a filter,
17
- * not an answer: it narrows the list and is thrown away. The value is whichever
18
- * option they then choose, and the field is rewritten to that option's words
19
- * once they have. A combobox that treated the typing as the value would submit
20
- * "jav" to a form, which is the mistake a plain input makes and the reason this
21
- * component exists.
22
- *
23
- * That is also why the field is emptied of its filter on close rather than left
24
- * holding it: a control reopened still narrowed by the last visit's search is a
25
- * control whose second use starts from the first one's leftovers. Select
26
- * records the same.
15
+ * **The text and the value are two things.** What a reader types is a filter:
16
+ * it narrows the list and is thrown away. The value is whichever option they
17
+ * then choose, and the field is rewritten to that option's words once they
18
+ * have. The filter is cleared on close, so a reopened control does not start
19
+ * from the last visit's leftovers.
27
20
  *
28
21
  * **Focus stays in the field, which is the whole of what a combobox is.** The
29
- * arrows move the list without leaving the text, which is why the listbox has a
30
- * public `navigate`: the moving, the wrapping, the skipping of disabled options
31
- * and the seeding from the current value all stay in the one place that already
32
- * does them.
33
- *
34
- * `role="combobox"` on the input rather than on a wrapper, because the thing
35
- * the pattern describes is the text field, and `aria-controls` can name the
36
- * listbox because both are in this shadow root. The active option cannot be
37
- * named that way, being the consumer's light DOM, so it is linked by element
38
- * reference for the reason Listbox records at length.
39
- *
40
- * **With `multiple`, the chosen options are tags in the field.** A field that
41
- * says "Rust, Ruby, Go" is a sentence the reader has to parse to find out what
42
- * is in it, and offers nothing to press to take one out: Select does that today
43
- * and it is the weakest part of it. A tag apiece is one object per answer, each
44
- * with its own remove control, which is what the reader already believes they
45
- * are looking at.
22
+ * arrows move the list without leaving the text, through the listbox's public
23
+ * `navigate`. `role="combobox"` is on the input rather than on a wrapper,
24
+ * because the thing the pattern describes is the text field.
46
25
  *
47
- * The panel stays open while more than one can be chosen, because a control
48
- * that shut after each pick is one the reader has to reopen to keep using. The
49
- * filter clears on each choice instead, so the next pick starts from the whole
50
- * list rather than from the last search.
26
+ * **With `multiple`, the chosen options are tags in the field**, one object per
27
+ * answer, each with its own remove control. The panel stays open while more
28
+ * than one can be chosen and the filter clears on each choice, so the next pick
29
+ * starts from the whole list.
51
30
  *
52
31
  * **`creatable` announces, and does not write.** The options are the consumer's
53
32
  * light DOM and nothing here puts an element into it: a component that grew the
54
- * consumer's markup would be a component their framework re-renders over. What
55
- * this does is offer a row saying what would be added, take the value when the
56
- * reader presses it, and say so with `helix-create`. A consumer who has to
57
- * validate first refuses the event and adds nothing.
58
- *
59
- * Which leaves a value naming no option, and that is what the words fall back
60
- * to: for anything chosen the field shows the option's text if there is one and
61
- * the value itself otherwise. No copy is stored, so a consumer who then adds a
62
- * real option with that value has its words take over on the next render.
63
- *
64
- * **`suggest` finishes the word, and only ever forwards.** The field completes
65
- * to the first option the typing begins, with the part the reader did not type
66
- * selected, so the next character replaces it and Delete removes it. Applied on
67
- * insertion alone: completing after a deletion would put back what the reader
68
- * just took out, and a field that cannot be shortened is a field that cannot be
69
- * corrected. Measured as the difference between `insertText` and the several
70
- * `delete*` input types, which is what the platform already says about which
71
- * happened.
72
- *
73
- * The filter stays what was typed rather than what was completed. Filtering on
74
- * the completion would narrow the list to the one option it came from, so a
75
- * reader typing "ru" would be shown "Rust" alone and never learn Ruby was
76
- * there.
33
+ * consumer's markup would be one their framework re-renders over. It offers the
34
+ * row and fires the event; adding the option is the consumer's.
77
35
  *
78
36
  * @since 0.1.0
79
37
  * @status experimental
@@ -7,29 +7,14 @@ import '../../tooltip/index.js';
7
7
  * @description
8
8
  * **The confirmation is the component.** Writing to the clipboard is three
9
9
  * lines; what makes this worth an element is that the platform gives a reader
10
- * no feedback at all. A press that copies and looks identical to a press that
11
- * failed is a control nobody trusts, so they press it again, and the second
12
- * press is indistinguishable from the first.
10
+ * no feedback at all, so a press that copies looks identical to one that
11
+ * failed.
13
12
  *
14
13
  * **Announced after the write, never before.** A clipboard write is a
15
- * permission the browser may refuse, and it is refused for real reasons: an
16
- * insecure origin, a document that is not focused, a user agent that requires a
17
- * gesture this press did not qualify as. So the confirmation and the event both
18
- * wait for the promise, and a refusal leaves the button exactly as it was.
19
- * `HelixCopyEvent` is not cancelable for the same reason: by the time there is
20
- * anything to say, it has already happened.
21
- *
22
- * **An icon button, extending IconButton.** Both of this button's faces are
23
- * icons and it never carries a word, so it is the square control rather than a
24
- * text button that happens to hold a glyph: it inherits the square box, and
25
- * with it the rule that an icon-only control must be named. `label` is not
26
- * optional here for the same reason it is not optional there, and the two
27
- * faces make it sharper: the accessible name has to describe the press, not
28
- * whichever picture is showing when a reader arrives.
29
- *
30
- * `data-copied`, not a reflected `copied`. State never reflects here: a
31
- * serialized `copied` attribute would come back from a paste as a button
32
- * claiming to have copied something it never held.
14
+ * permission the browser may refuse, for real reasons: an insecure origin, a
15
+ * document that is not focused, a gesture that did not qualify. The
16
+ * confirmation and the event both wait for the promise, and a refusal leaves
17
+ * the button exactly as it was.
33
18
  *
34
19
  * @since 0.1.0
35
20
  * @status experimental
@@ -9,10 +9,9 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
9
9
  *
10
10
  * @description
11
11
  * **The schema is markup and the data is a property.** Columns are declared as
12
- * `helix-table-column` children, because a schema is small, declarative, and
13
- * something a reader should be able to see in the HTML; rows are handed over as
14
- * an array, because data is large and a table that draws ten thousand elements
15
- * cannot window them.
12
+ * `helix-table-column` children, because a schema is small and something a
13
+ * reader should see in the HTML; rows are handed over as an array, because a
14
+ * table that draws ten thousand elements cannot window them.
16
15
  *
17
16
  * ```html
18
17
  * <helix-data-table .rows=${rows} sort="name:asc" page-size="20">
@@ -25,35 +24,13 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
25
24
  * twelve things a person wrote out.
26
25
  *
27
26
  * **Sort and filter apply to the whole set, never the page.** Sorting the drawn
28
- * window is correct on the first screen and wrong on every other one, which is
29
- * how it survives being looked at. The arithmetic lives in `order.ts` where
30
- * nothing can see a window, and its spec asserts the composition rather than the
31
- * three steps, because each step alone passes either way.
27
+ * window is correct on the first screen and wrong on every other one.
32
28
  *
33
- * **What it does not do, stated where a consumer will read it: the cell values
34
- * do not server-render.** The headings do, because a column renders its own, and
35
- * the row elements do, because their count comes from `rows`. Reading a cell
36
- * needs the columns, and the columns are markup children that Lit SSR does not
37
- * hand this element: `children` is undefined there. So a crawler and a reader on
38
- * a slow connection see a table of the right shape with nothing in it, which is
39
- * strictly less than `helix-table` serves for a table whose rows are markup.
40
- *
41
- * That is the cost of "the schema is markup and the data is a property". Use
42
- * `helix-table` where the content has to be in the served HTML and the result is
43
- * small enough to write out; use this where the result is large, and accept that
44
- * the first paint is a shell. The obvious workaround, a `columns` property
45
- * beside the markup columns, is deliberately not offered: it splits one source
46
- * of truth for the columns into two that nothing checks against each other, and
47
- * a table rendering one way on the server and another in the browser is that
48
- * failure with a hydration mismatch on top.
49
- *
50
- * **Every axis is controlled or uncontrolled, and that is what makes a server
51
- * mode fall out rather than be bolted on.** `sort`, `filter`, `page` and
52
- * `page-size` each defer to the consumer when set and seed themselves from a
53
- * `default-*` when not. A consumer who answers all four holds the data flow:
54
- * they hear the reader's request, fetch, and hand back a new `rows` with a
55
- * `total`. Retrofitting that inverts the flow and is a rewrite, so it is here
56
- * from the start.
29
+ * **The cell values do not server-render.** The headings do, and the row
30
+ * elements do, but reading a cell needs the columns, and the columns are markup
31
+ * children Lit SSR does not hand this element. So a crawler sees a table of the
32
+ * right shape with nothing in it. That is the cost of the first paragraph: use
33
+ * `helix-table` where the served HTML has to carry the values.
57
34
  *
58
35
  * @since 0.1.0
59
36
  * @status experimental
@@ -9,29 +9,13 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
9
9
  * @description
10
10
  * **The calendar is `helix-date-picker`, not a second one written here.** It
11
11
  * already knows about months, ranges, disabled days, the first day of the week
12
- * and every keyboard rule a grid owes a reader, and a picker that reimplemented
13
- * a tenth of that would be a worse grid that also had to be maintained. This
14
- * element is the field, the overlay, and the translation between them.
12
+ * and every keyboard rule a grid owes a reader. This element is the field, the
13
+ * overlay, and the translation between them.
15
14
  *
16
- * **Typed as well as picked, and the typing is the reason it is not
15
+ * **Typed as well as picked, and the typing is why it is not
17
16
  * `<input type="date">`.** The native control gives a free picker and a free
18
- * locale and takes almost all styling with it, which is a fair trade until a
19
- * product needs the calendar to match everything around it. What is kept from
20
- * the native one is the part worth keeping: a real text field, so a reader who
21
- * knows the date types it and never opens anything.
22
- *
23
- * **The value is `YYYY-MM-DD`, always.** That is what a form submits, what
24
- * `min` and `max` compare against, and what the calendar speaks. What the field
25
- * *shows* is the same string: a locale-formatted display would have to be parsed
26
- * back on every keystroke, and half-typed input does not survive a round trip
27
- * through a formatter. The same reasoning the sandbox records for its two
28
- * syntaxes, which is that a document being edited must not be a rendering of
29
- * something else.
30
- *
31
- * **Opening does not commit.** The calendar announces a date, this element takes
32
- * it, and the overlay shuts, because a single date has nothing more to say. A
33
- * consumer who owns `value` answers the announcement the way they answer any
34
- * other control here.
17
+ * locale and takes almost all styling with it. What is kept from it is the part
18
+ * worth keeping: a real text field.
35
19
  *
36
20
  * @since 0.1.0
37
21
  * @status experimental
@@ -6,44 +6,19 @@ declare const HelixHeadlessDatePicker_base: (new (...args: any[]) => import("@fu
6
6
  *
7
7
  * @description
8
8
  * A grid of days, per the APG date grid: the whole grid is one tab stop, arrows
9
- * move by day and week, `PageUp` and `PageDown` move by month, and `Home` and
10
- * `End` go to the ends of the week. Only the focused cell is in the tab
11
- * sequence.
9
+ * move by day and week, `PageUp` and `PageDown` by month, `Home` and `End` to
10
+ * the ends of the week. Only the focused cell is in the tab sequence.
12
11
  *
13
- * Roving `tabindex` is written on the cells, which is free here because they
14
- * are rendered into this shadow root rather than being markup a consumer wrote.
12
+ * **Dates are `YYYY-MM-DD` strings and every calculation is in UTC.** A
13
+ * local-time `Date` shifts across a timezone or a daylight-saving boundary.
15
14
  *
16
- * Dates are `YYYY-MM-DD` strings and every calculation is in UTC. A local-time
17
- * `Date` shifts across a timezone or a daylight-saving boundary, so the string
18
- * is what the component holds and the arithmetic never leaves UTC.
15
+ * `month` is what the grid shows, separately from `value`, so paging does not
16
+ * select anything and a consumer can drive the view. Left unset it follows the
17
+ * first selected date, then the current month.
19
18
  *
20
- * `month` is what the grid shows, separately from `value`, so paging through
21
- * months does not select anything and a consumer can drive the view. Left
22
- * unset, it follows the first selected date, and then the current month.
23
- *
24
- * `mode` decides how many dates are held. Absent takes one. `range` takes two
25
- * and marks everything between them, starting over on the third click rather
26
- * than replacing an end at random. `multiple` toggles, so clicking a chosen
27
- * date takes it out. All three read and write the same comma-separated
28
- * `value`.
29
- *
30
- * `locale` is worth setting where the output is compared across environments.
31
- * Left unset, month and day names come from the runtime's own locale, and a
32
- * server and a browser need not agree on what that is.
33
- *
34
- * A control whose value changes dispatches `helix-before-change`:
35
- * `Input`, `Select`, `Listbox`, `Radio.Group` and `Toggle.Group` all do, and a
36
- * calendar submitting a date is the same kind of thing. `helix-select` stays
37
- * what it is elsewhere, which is a row or an item being chosen in something
38
- * that reports no value at all, such as `Menu` or `Tree`.
39
- *
40
- * Paging is `helix-navigate` and not either of those, because it chooses
41
- * nothing: the view moves and the answer does not.
42
- *
43
- * The properties below are written by this component and read by whoever draws
44
- * it. A consumer sets none of them: they carry a number this element computed
45
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
46
- * without measuring anything itself.
19
+ * `mode` decides how many dates are held: absent takes one, `range` takes two
20
+ * and marks everything between them, `multiple` toggles. All three read and
21
+ * write the same comma-separated `value`.
47
22
  *
48
23
  * @since 0.1.0
49
24
  * @status experimental
@@ -7,37 +7,15 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
7
7
  * @description
8
8
  * A real `<dialog>` opened with `showModal()`, not a div with a role and a
9
9
  * hand-built trap. The platform gives four things that are each a day's work to
10
- * reimplement and easy to get subtly wrong: the top layer, so the dialog is
11
- * above everything regardless of what `z-index` anyone else wrote; a real
12
- * backdrop; Escape; and inert-behind, so the page underneath is not reachable
13
- * by pointer, keyboard, or a screen reader's virtual cursor.
10
+ * reimplement: the top layer, so the dialog is above everything whatever
11
+ * `z-index` anyone wrote; a real backdrop; Escape; and inert-behind, so the
12
+ * page underneath is unreachable by pointer, keyboard or virtual cursor.
14
13
  *
15
14
  * **`open` drives `showModal()`, and every way it can close comes back through
16
- * `requestOpen`.** A native dialog can close from three directions: the
17
- * property, Escape, and a `<form method="dialog">` submit inside it. Left
18
- * alone, two of those would shut the dialog while the consumer's state still
19
- * said open, which is the bug that makes a modal impossible to reopen. Escape
20
- * is intercepted and routed through the request, so `preventDefault()` on the
21
- * `helix-before-close` refuses it; a close that happens anyway is reflected back.
22
- *
23
- * **Nothing here traps focus.** `showModal()` does it, and better: `inert` on
24
- * the rest of the document is something no JavaScript trap can achieve.
25
- * `FocusTrapController` stays for the surfaces that are not modal.
26
- *
27
- * The regions are bare slots rather than wrappers, for the reason the card's
28
- * are: an unassigned `<slot>` is `display: contents` and generates no box, so a
29
- * dialog with no footer has no empty band where one would be.
30
- *
31
- * Opened declaratively with the platform's invoker attributes:
32
- *
33
- * ```html
34
- * <helix-button commandfor="confirm" command="--show">Delete…</helix-button>
35
- * <helix-dialog id="confirm">…</helix-dialog>
36
- * ```
37
- *
38
- * `--show`, `--close` and `--toggle`. Custom commands rather than the built-in
39
- * `show-modal`, because those are defined against native elements and do
40
- * nothing when pointed at a custom one.
15
+ * `requestOpen`.** A native dialog closes from three directions: the property,
16
+ * Escape, and a `<form method="dialog">` submit. Left alone, two of them would
17
+ * shut the dialog while the consumer's state still said open, which is the bug
18
+ * that makes a modal impossible to reopen.
41
19
  *
42
20
  * @since 0.1.0
43
21
  * @status stable
@@ -9,32 +9,12 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
9
9
  * The chart with the narrowest honest use, so the component is narrow too.
10
10
  *
11
11
  * **It reads one column and treats the rows as the parts.** Every other chart
12
- * here takes a column per series; a ring has one whole to divide, and a second
13
- * ring inside the first is two charts sharing a picture in the most literal
14
- * way. So the first column of numbers is the series and each row is a slice.
12
+ * here takes a column per series; a ring has one whole to divide, so the first
13
+ * column of numbers is the series and each row is a slice.
15
14
  *
16
- * **It refuses negative values rather than drawing them.** A share of a whole
17
- * cannot be less than nothing, and an arc for a negative number either runs
18
- * backwards over its neighbors or is silently dropped. Those rows are skipped
19
- * and the total is of what is left, which is the only reading that stays true.
20
- *
21
- * **The shape is drawn with a dashed stroke, not with arc commands.** One
22
- * `<circle>` per slice, its dash set to the slice's share of the circumference
23
- * and its offset to where the slice begins. Arc paths need the sweep flag and a
24
- * large-arc flag, both of which flip at values a reader never sees coming, and
25
- * a slice of exactly one whole becomes a path with no length at all.
26
- *
27
- * **And it keeps its aspect ratio**, alone among the charts here. The others
28
- * set `preserveAspectRatio="none"` so one drawing fills any box and rescue
29
- * their strokes with `vector-effect`; that rescues strokes and not geometry, so
30
- * a ring drawn the same way is an ellipse in anything but a square.
31
- *
32
- * The table is the accessible representation and this drawing is `aria-hidden`.
33
- *
34
- * The properties below are written by this component and read by whoever draws
35
- * it. A consumer sets none of them: they carry a number this element computed
36
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
37
- * without measuring anything itself.
15
+ * **It refuses negative values rather than drawing them.** An arc for a
16
+ * negative number either runs backwards over its neighbors or is silently
17
+ * dropped. Those rows are skipped and the total is of what is left.
38
18
  *
39
19
  * @since 0.1.0
40
20
  * @status experimental