@fusion.dev/helix-headless 0.4.2 → 0.4.4

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
@@ -16,7 +16,6 @@ import type {
16
16
  HelixCreateEvent,
17
17
  HelixDismissEvent,
18
18
  HelixFilterEvent,
19
- HelixFormElement,
20
19
  HelixHeadlessAccordion,
21
20
  HelixHeadlessAccordionItem,
22
21
  HelixHeadlessAnnouncement,
@@ -15583,37 +15582,17 @@ export type CustomElements = {
15583
15582
 
15584
15583
  /**
15585
15584
  * Tracks whether the page has scrolled and carries it as the custom state
15586
- * `scrolled`, so the styled tier can lift the bar off the page without a scroll
15587
- * handler of its own. Scroll position is the one piece of state the server
15588
- * genuinely cannot know, so it is read on connect rather than derived: a fresh
15589
- * load starts at the top, which is what the server rendered, and a reload
15590
- * part-way down corrects on hydration.
15585
+ * `scrolled`, so the styled tier can lift the bar without a scroll handler of
15586
+ * its own. It is read on connect rather than derived: a fresh load starts at
15587
+ * the top, which is what the server rendered, and a reload part-way down
15588
+ * corrects on hydration.
15591
15589
  *
15592
15590
  * **A custom state and never `data-scrolled`.** An attribute the element writes
15593
15591
  * onto its own host is one the server did not send, so a hydrating framework
15594
- * reports the tree as mismatched, intermittently: only when the reader reloads
15595
- * far enough down the page to pass the threshold. A consumer can answer that
15596
- * only by suppressing hydration warnings on an element they did not write.
15597
- * `ElementInternals.states` is deliberately not in the DOM, so there is nothing
15598
- * for a hydration pass to disagree with, and `:state(scrolled)` selects it. The
15599
- * base class made the same move for `data-settled` and its note explains the
15600
- * rest.
15601
- *
15602
- * The listener is passive and reads `scrollY` only, so it never blocks
15603
- * scrolling.
15604
- *
15605
- * Three regions, each in its own wrapper, because the row is a grid and a grid
15606
- * needs three items to put the middle one in the middle. A bare slot is
15607
- * `display: contents`, so its assigned elements become grid items themselves:
15608
- * two actions would take two tracks and push the navigation off center. These
15609
- * wrappers earn their boxes, which is the test; they carry no inset or fill of
15610
- * their own, so an empty one still paints nothing.
15611
- *
15612
- * The host is the banner and spans the viewport; the row inside it is what gets
15613
- * centered. A banner that is itself narrowed leaves its background stopping
15614
- * short of the window edges, which reads as a floating bar rather than as the
15615
- * top of the page. That needs one element and one row, not a wrapper as well:
15616
- * the host carries the material and `content` carries the measure.
15592
+ * reports a mismatch, intermittently: only when the reader reloads far enough
15593
+ * down the page. `ElementInternals.states` is not in the DOM, so there is
15594
+ * nothing for a hydration pass to disagree with, and `:state(scrolled)` selects
15595
+ * it.
15617
15596
  *
15618
15597
  * ## Attributes & Properties
15619
15598
  *
@@ -15680,40 +15659,15 @@ export type CustomElements = {
15680
15659
 
15681
15660
  /**
15682
15661
  * A part of `Avatar` rather than a family of its own: it arranges avatars and
15683
- * is about nothing else, and its member is a complete `Avatar` the group did
15684
- * not have to explain.
15662
+ * is about nothing else.
15685
15663
  *
15686
15664
  * **The overflow count is the group's, not a slot.** Which avatars are hidden
15687
- * is a fact the group works out from `max` and how many it was given, so a
15688
- * consumer writing the "+3" themselves would be writing a number that has to
15689
- * agree with a list they do not control.
15665
+ * is a fact the group works out from `max`, so a consumer writing the "+3"
15666
+ * would be writing a number that has to agree with a list they do not control.
15690
15667
  *
15691
- * **Hidden, not removed.** Past `max`, the extra avatars stay in the DOM and
15668
+ * **Hidden, not removed.** Past `max` the extra avatars stay in the DOM and
15692
15669
  * stop being shown, so nothing re-renders when `max` changes and the accessible
15693
- * name can still be built from all of them. The count is what a sighted reader
15694
- * gets; the group's own name is what everyone else gets, and "Seven people" is
15695
- * more useful than seven names read in a row.
15696
- *
15697
- * **And hidden by the stylesheet, not by this class.** Hiding from `updated` is
15698
- * one update too late and one element too far out: Lit renders on a microtask,
15699
- * so an avatar appended past the limit is laid out and painted before anything
15700
- * runs to hide it, and marking each one means writing attributes onto markup a
15701
- * consumer owns. The styled tier's
15702
- * `:host([max="N"]) ::slotted(:nth-child(n + N+1))` is right at the first style
15703
- * resolution and writes nothing.
15704
- *
15705
- * **The fold is finite, and the count agrees with it.** `An+B` takes a literal,
15706
- * so there is one selector per value of `max` and the range stops at twelve.
15707
- * Past that the group shows everyone, counts nothing and says so, because
15708
- * showing everyone is a defensible answer and showing everyone beside a "+5" is
15709
- * not. `max` above twelve is a list the consumer should be slicing themselves.
15710
- *
15711
- * **It is a list.** A row of faces is a set of separate people, and a group
15712
- * with no role announces as one run of text. `role="list"` needs its children
15713
- * to be `listitem`, which they cannot be told to become without writing an
15714
- * attribute onto a consumer's element, so the group carries `role="group"` and
15715
- * its name instead: one announcement, correct, and nothing written to anyone
15716
- * else's markup.
15670
+ * name is still built from all of them.
15717
15671
  *
15718
15672
  * ## Attributes & Properties
15719
15673
  *
@@ -16244,37 +16198,18 @@ export type CustomElements = {
16244
16198
  >;
16245
16199
 
16246
16200
  /**
16247
- * The host is the landmark, so `aria-label` on it names the trail directly and
16248
- * there is no property mirroring one. A page may hold more than one navigation,
16249
- * and landmarks are how a screen-reader user chooses between them.
16250
- *
16251
- * `role="list"` is set explicitly on the `<ol>` even though it is already a
16252
- * list: removing the markers with `list-style: none` strips list semantics in
16253
- * Safari, and a breadcrumb trail always removes its markers.
16254
- *
16255
- * Items are slotted rather than wrapped, so they are `<ol>` children in the flat
16256
- * tree and each carries `role="listitem"` itself.
16257
- *
16258
- * **The trail does not measure itself, and the overflow is markup.** Measuring
16259
- * how many crumbs fit can never reach the server: there is no width without a
16260
- * DOM, so the server ships every crumb and the client removes some after
16261
- * hydrating, and a trail that collapses paints wrong on every single load. Nor
16262
- * does anybody specify a breadcrumb in units of fit. Designs say "keep the root
16263
- * and the current page, fold the middle", which is a fact about depth, or "fold
16264
- * below this width", which is a fact CSS knows.
16265
- *
16266
- * So the trail lays out crumbs and separators, and the consumer writes what
16267
- * folds: a `helix-menu` of `helix-menu-item`s in a crumb, where the gap
16268
- * belongs. Server rendered, no observer, no stylesheet, and correct before the
16269
- * first script runs. A trail that should fold only at some widths is a
16270
- * container query in the consumer's own sheet, which is theirs to write and
16271
- * theirs to leave out.
16272
- *
16273
- * **And the crumbs carry no marker for any of it.** CSS can already see it: the
16274
- * crumb with the menu in it is `:has(helix-menu)`, and the middle is
16275
- * `:not(:first-child, [current])`. A marker would be the design rule written
16276
- * twice, once in the HTML and once in the sheet, with nothing keeping the two
16277
- * honest.
16201
+ * The host is the landmark, so `aria-label` on it names the trail directly. A
16202
+ * page may hold more than one navigation, and landmarks are how a
16203
+ * screen-reader user chooses between them.
16204
+ *
16205
+ * `role="list"` is set explicitly on the `<ol>` even though it is one:
16206
+ * `list-style: none` strips list semantics in Safari, and a breadcrumb trail
16207
+ * always removes its markers.
16208
+ *
16209
+ * Items are slotted rather than wrapped, so they are `<ol>` children in the
16210
+ * flat tree and each carries `role="listitem"` itself.
16211
+ *
16212
+ * **The trail does not measure itself, and the overflow is markup.**
16278
16213
  *
16279
16214
  * ## Attributes & Properties
16280
16215
  *
@@ -17075,35 +17010,16 @@ export type CustomElements = {
17075
17010
 
17076
17011
  /**
17077
17012
  * **It has no opinion about where it sits.** A chat is asked for as a floating
17078
- * button, a page, a palette, a sidebar, a modal and an inline block, and none of
17079
- * those is a variant of a conversation: they are containers a conversation is
17080
- * put in, and the containers already exist. `Popover` and `SpeedDial` make the
17081
- * floating one, `Drawer` the sidebar, `Dialog` the modal, `Command` the palette,
17082
- * and a page is a page. Nothing here is positioned, nothing here has a backdrop,
17083
- * and nothing here owns a trigger, because a trigger opens a container and
17084
- * containers own their own. If a form factor needs a mode on this element, the
17085
- * split is wrong.
17086
- *
17087
- * **Scroll ownership is the behavior everything else depends on, and it is the
17088
- * most-got-wrong thing in the category.** A transcript that grows wants to stay
17089
- * at the bottom, except when the reader has scrolled up to read, where pinning
17090
- * is hostile. The rule: pin while the reader is within `threshold` of the
17091
- * bottom, release the moment they leave it, and offer a way back. **Never scroll
17092
- * a reader who is reading.**
17093
- *
17094
- * The element owns it, because it is the only party that knows a message arrived
17095
- * and where the viewport was when it did. `pinned` announces before it moves, so
17096
- * a consumer who wants to own it refuses the request and assigns their own.
17097
- *
17098
- * **The live region announces on completion, not on arrival.** The transcript is
17099
- * `role="log"` with `aria-live="polite"`, and a streaming message carries
17100
- * `aria-busy` while it arrives: a screen reader reading a stream token by token
17101
- * is unusable, and holding the announcement until the flag clears is the only
17102
- * arrangement that works. Somebody typing is a separate status region, so it
17103
- * never interleaves with what was said.
17104
- *
17105
- * **Not a client.** No transport, no protocol, no model. It renders a
17106
- * conversation and reports what the reader did.
17013
+ * button, a page, a palette, a sidebar, a modal and an inline block, and none
17014
+ * of those is a variant of a conversation: they are containers, and the
17015
+ * containers already exist. Nothing here is positioned, nothing has a backdrop,
17016
+ * and nothing owns a trigger. If a form factor needs a mode on this element,
17017
+ * the split is wrong.
17018
+ *
17019
+ * **Scroll ownership is the behavior everything else depends on.** A transcript
17020
+ * that grows wants to stay at the bottom, except when the reader has scrolled
17021
+ * up to read, where pinning is hostile. The rule: pin while the reader is
17022
+ * within `threshold` of the bottom, and let go the moment they leave it.
17107
17023
  *
17108
17024
  * ## Attributes & Properties
17109
17025
  *
@@ -17934,38 +17850,20 @@ export type CustomElements = {
17934
17850
  >;
17935
17851
 
17936
17852
  /**
17937
- * **The picker itself, with no field around it.** Color Input is this element in
17938
- * a panel behind a text field, the same way Date Input is `helix-date-picker` in a
17939
- * panel: a form wants a field, and a settings pane or a toolbar wants the picker
17940
- * sitting flat on the page with nothing to open. Neither should be the other one
17941
- * with parts hidden.
17942
- *
17943
- * **The square is two real range inputs.** Saturation and brightness are each an
17944
- * `<input type="range">`, laid over the square and made invisible, and the
17945
- * handle is drawn from their values. The pointer gets the square; the keyboard
17946
- * gets the arrow keys, Home, End and the page keys; a screen reader gets two
17947
- * sliders that announce a name and a number. All of it is the platform's, and
17948
- * nothing here implements a key handler. There is no `role="application"`, which
17949
- * is the usual way this control is built and amounts to asking a screen reader
17950
- * to stop helping.
17853
+ * **The picker itself, with no field around it.** Color Input is this element
17854
+ * in a panel behind a text field; a settings pane or a toolbar wants the picker
17855
+ * flat on the page with nothing to open.
17856
+ *
17857
+ * **The square is two real range inputs.** Saturation and brightness are each
17858
+ * an `<input type="range">`, laid over the square and made invisible, and the
17859
+ * handle is drawn from their values. The keyboard, the announcements and the
17860
+ * touch targets are the platform's, and there is no `role="application"`.
17951
17861
  *
17952
17862
  * **The working model is HSB, and the value is derived from it.** The reverse
17953
17863
  * loses colors: black is `brightness: 0`, whose hue and saturation are both
17954
- * undefined, so a reader who drags to the bottom of the square and back would
17955
- * get gray where they had red. Holding the model means a color survives a trip
17956
- * through one that has no hue. A value arriving from outside is read into the
17957
- * model once, which is the only moment the conversion runs in that direction.
17958
- *
17959
- * **Every syntax is read; the one `format` names is written.** `#f00`,
17960
- * `#ff0000`, `rgb(255 0 0)`, `rgba(255,0,0,.5)` and `hsl(0 100% 50%)` are all
17961
- * colors. Named colors are the exception, and deliberately: resolving
17962
- * `rebeccapurple` means shipping a table of a hundred and forty or asking the
17963
- * browser, and there is no browser during a server render.
17964
- *
17965
- * The properties below are written by this component and read by whoever draws
17966
- * it. A consumer sets none of them: they carry a number this element computed
17967
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
17968
- * without measuring anything itself.
17864
+ * undefined, so dragging to the bottom of the square and back would give gray
17865
+ * where there had been red. A value arriving from outside is read into the
17866
+ * model once.
17969
17867
  *
17970
17868
  * ## Attributes & Properties
17971
17869
  *
@@ -18180,73 +18078,31 @@ export type CustomElements = {
18180
18078
  >;
18181
18079
 
18182
18080
  /**
18183
- * **The list is `helix-listbox`, and the filtering is its own.** It already
18184
- * owns narrowing, the empty state, the highlight, `aria-activedescendant` and
18185
- * scrolling an option into view. Rewriting them here would be a second copy to
18186
- * keep in step; what is left for this element is the field, the panel and the
18187
- * traffic between them.
18188
- *
18189
- * **The text and the value are two things.** What a reader types is a filter,
18190
- * not an answer: it narrows the list and is thrown away. The value is whichever
18191
- * option they then choose, and the field is rewritten to that option's words
18192
- * once they have. A combobox that treated the typing as the value would submit
18193
- * "jav" to a form, which is the mistake a plain input makes and the reason this
18194
- * component exists.
18195
- *
18196
- * That is also why the field is emptied of its filter on close rather than left
18197
- * holding it: a control reopened still narrowed by the last visit's search is a
18198
- * control whose second use starts from the first one's leftovers. Select
18199
- * records the same.
18081
+ * **The list is `helix-listbox`, and the filtering is its own.** It owns
18082
+ * narrowing, the empty state, the highlight, `aria-activedescendant` and
18083
+ * scrolling an option into view. What is left for this element is the field,
18084
+ * the panel and the traffic between them.
18085
+ *
18086
+ * **The text and the value are two things.** What a reader types is a filter:
18087
+ * it narrows the list and is thrown away. The value is whichever option they
18088
+ * then choose, and the field is rewritten to that option's words once they
18089
+ * have. The filter is cleared on close, so a reopened control does not start
18090
+ * from the last visit's leftovers.
18200
18091
  *
18201
18092
  * **Focus stays in the field, which is the whole of what a combobox is.** The
18202
- * arrows move the list without leaving the text, which is why the listbox has a
18203
- * public `navigate`: the moving, the wrapping, the skipping of disabled options
18204
- * and the seeding from the current value all stay in the one place that already
18205
- * does them.
18206
- *
18207
- * `role="combobox"` on the input rather than on a wrapper, because the thing
18208
- * the pattern describes is the text field, and `aria-controls` can name the
18209
- * listbox because both are in this shadow root. The active option cannot be
18210
- * named that way, being the consumer's light DOM, so it is linked by element
18211
- * reference for the reason Listbox records at length.
18212
- *
18213
- * **With `multiple`, the chosen options are tags in the field.** A field that
18214
- * says "Rust, Ruby, Go" is a sentence the reader has to parse to find out what
18215
- * is in it, and offers nothing to press to take one out: Select does that today
18216
- * and it is the weakest part of it. A tag apiece is one object per answer, each
18217
- * with its own remove control, which is what the reader already believes they
18218
- * are looking at.
18219
- *
18220
- * The panel stays open while more than one can be chosen, because a control
18221
- * that shut after each pick is one the reader has to reopen to keep using. The
18222
- * filter clears on each choice instead, so the next pick starts from the whole
18223
- * list rather than from the last search.
18093
+ * arrows move the list without leaving the text, through the listbox's public
18094
+ * `navigate`. `role="combobox"` is on the input rather than on a wrapper,
18095
+ * because the thing the pattern describes is the text field.
18096
+ *
18097
+ * **With `multiple`, the chosen options are tags in the field**, one object per
18098
+ * answer, each with its own remove control. The panel stays open while more
18099
+ * than one can be chosen and the filter clears on each choice, so the next pick
18100
+ * starts from the whole list.
18224
18101
  *
18225
18102
  * **`creatable` announces, and does not write.** The options are the consumer's
18226
18103
  * light DOM and nothing here puts an element into it: a component that grew the
18227
- * consumer's markup would be a component their framework re-renders over. What
18228
- * this does is offer a row saying what would be added, take the value when the
18229
- * reader presses it, and say so with `helix-create`. A consumer who has to
18230
- * validate first refuses the event and adds nothing.
18231
- *
18232
- * Which leaves a value naming no option, and that is what the words fall back
18233
- * to: for anything chosen the field shows the option's text if there is one and
18234
- * the value itself otherwise. No copy is stored, so a consumer who then adds a
18235
- * real option with that value has its words take over on the next render.
18236
- *
18237
- * **`suggest` finishes the word, and only ever forwards.** The field completes
18238
- * to the first option the typing begins, with the part the reader did not type
18239
- * selected, so the next character replaces it and Delete removes it. Applied on
18240
- * insertion alone: completing after a deletion would put back what the reader
18241
- * just took out, and a field that cannot be shortened is a field that cannot be
18242
- * corrected. Measured as the difference between `insertText` and the several
18243
- * `delete*` input types, which is what the platform already says about which
18244
- * happened.
18245
- *
18246
- * The filter stays what was typed rather than what was completed. Filtering on
18247
- * the completion would narrow the list to the one option it came from, so a
18248
- * reader typing "ru" would be shown "Rust" alone and never learn Ruby was
18249
- * there.
18104
+ * consumer's markup would be one their framework re-renders over. It offers the
18105
+ * row and fires the event; adding the option is the consumer's.
18250
18106
  *
18251
18107
  * ## Attributes & Properties
18252
18108
  *
@@ -18616,29 +18472,14 @@ export type CustomElements = {
18616
18472
  /**
18617
18473
  * **The confirmation is the component.** Writing to the clipboard is three
18618
18474
  * lines; what makes this worth an element is that the platform gives a reader
18619
- * no feedback at all. A press that copies and looks identical to a press that
18620
- * failed is a control nobody trusts, so they press it again, and the second
18621
- * press is indistinguishable from the first.
18475
+ * no feedback at all, so a press that copies looks identical to one that
18476
+ * failed.
18622
18477
  *
18623
18478
  * **Announced after the write, never before.** A clipboard write is a
18624
- * permission the browser may refuse, and it is refused for real reasons: an
18625
- * insecure origin, a document that is not focused, a user agent that requires a
18626
- * gesture this press did not qualify as. So the confirmation and the event both
18627
- * wait for the promise, and a refusal leaves the button exactly as it was.
18628
- * `HelixCopyEvent` is not cancelable for the same reason: by the time there is
18629
- * anything to say, it has already happened.
18630
- *
18631
- * **An icon button, extending IconButton.** Both of this button's faces are
18632
- * icons and it never carries a word, so it is the square control rather than a
18633
- * text button that happens to hold a glyph: it inherits the square box, and
18634
- * with it the rule that an icon-only control must be named. `label` is not
18635
- * optional here for the same reason it is not optional there, and the two
18636
- * faces make it sharper: the accessible name has to describe the press, not
18637
- * whichever picture is showing when a reader arrives.
18638
- *
18639
- * `data-copied`, not a reflected `copied`. State never reflects here: a
18640
- * serialized `copied` attribute would come back from a paste as a button
18641
- * claiming to have copied something it never held.
18479
+ * permission the browser may refuse, for real reasons: an insecure origin, a
18480
+ * document that is not focused, a gesture that did not qualify. The
18481
+ * confirmation and the event both wait for the promise, and a refusal leaves
18482
+ * the button exactly as it was.
18642
18483
  *
18643
18484
  * ## Attributes & Properties
18644
18485
  *
@@ -18852,10 +18693,9 @@ export type CustomElements = {
18852
18693
 
18853
18694
  /**
18854
18695
  * **The schema is markup and the data is a property.** Columns are declared as
18855
- * `helix-table-column` children, because a schema is small, declarative, and
18856
- * something a reader should be able to see in the HTML; rows are handed over as
18857
- * an array, because data is large and a table that draws ten thousand elements
18858
- * cannot window them.
18696
+ * `helix-table-column` children, because a schema is small and something a
18697
+ * reader should see in the HTML; rows are handed over as an array, because a
18698
+ * table that draws ten thousand elements cannot window them.
18859
18699
  *
18860
18700
  * ```html
18861
18701
  * <helix-data-table .rows=${rows} sort="name:asc" page-size="20">
@@ -18868,35 +18708,13 @@ export type CustomElements = {
18868
18708
  * twelve things a person wrote out.
18869
18709
  *
18870
18710
  * **Sort and filter apply to the whole set, never the page.** Sorting the drawn
18871
- * window is correct on the first screen and wrong on every other one, which is
18872
- * how it survives being looked at. The arithmetic lives in `order.ts` where
18873
- * nothing can see a window, and its spec asserts the composition rather than the
18874
- * three steps, because each step alone passes either way.
18875
- *
18876
- * **What it does not do, stated where a consumer will read it: the cell values
18877
- * do not server-render.** The headings do, because a column renders its own, and
18878
- * the row elements do, because their count comes from `rows`. Reading a cell
18879
- * needs the columns, and the columns are markup children that Lit SSR does not
18880
- * hand this element: `children` is undefined there. So a crawler and a reader on
18881
- * a slow connection see a table of the right shape with nothing in it, which is
18882
- * strictly less than `helix-table` serves for a table whose rows are markup.
18883
- *
18884
- * That is the cost of "the schema is markup and the data is a property". Use
18885
- * `helix-table` where the content has to be in the served HTML and the result is
18886
- * small enough to write out; use this where the result is large, and accept that
18887
- * the first paint is a shell. The obvious workaround, a `columns` property
18888
- * beside the markup columns, is deliberately not offered: it splits one source
18889
- * of truth for the columns into two that nothing checks against each other, and
18890
- * a table rendering one way on the server and another in the browser is that
18891
- * failure with a hydration mismatch on top.
18892
- *
18893
- * **Every axis is controlled or uncontrolled, and that is what makes a server
18894
- * mode fall out rather than be bolted on.** `sort`, `filter`, `page` and
18895
- * `page-size` each defer to the consumer when set and seed themselves from a
18896
- * `default-*` when not. A consumer who answers all four holds the data flow:
18897
- * they hear the reader's request, fetch, and hand back a new `rows` with a
18898
- * `total`. Retrofitting that inverts the flow and is a rewrite, so it is here
18899
- * from the start.
18711
+ * window is correct on the first screen and wrong on every other one.
18712
+ *
18713
+ * **The cell values do not server-render.** The headings do, and the row
18714
+ * elements do, but reading a cell needs the columns, and the columns are markup
18715
+ * children Lit SSR does not hand this element. So a crawler sees a table of the
18716
+ * right shape with nothing in it. That is the cost of the first paragraph: use
18717
+ * `helix-table` where the served HTML has to carry the values.
18900
18718
  *
18901
18719
  * ## Attributes & Properties
18902
18720
  *
@@ -19050,29 +18868,13 @@ export type CustomElements = {
19050
18868
  /**
19051
18869
  * **The calendar is `helix-date-picker`, not a second one written here.** It
19052
18870
  * already knows about months, ranges, disabled days, the first day of the week
19053
- * and every keyboard rule a grid owes a reader, and a picker that reimplemented
19054
- * a tenth of that would be a worse grid that also had to be maintained. This
19055
- * element is the field, the overlay, and the translation between them.
18871
+ * and every keyboard rule a grid owes a reader. This element is the field, the
18872
+ * overlay, and the translation between them.
19056
18873
  *
19057
- * **Typed as well as picked, and the typing is the reason it is not
18874
+ * **Typed as well as picked, and the typing is why it is not
19058
18875
  * `<input type="date">`.** The native control gives a free picker and a free
19059
- * locale and takes almost all styling with it, which is a fair trade until a
19060
- * product needs the calendar to match everything around it. What is kept from
19061
- * the native one is the part worth keeping: a real text field, so a reader who
19062
- * knows the date types it and never opens anything.
19063
- *
19064
- * **The value is `YYYY-MM-DD`, always.** That is what a form submits, what
19065
- * `min` and `max` compare against, and what the calendar speaks. What the field
19066
- * *shows* is the same string: a locale-formatted display would have to be parsed
19067
- * back on every keystroke, and half-typed input does not survive a round trip
19068
- * through a formatter. The same reasoning the sandbox records for its two
19069
- * syntaxes, which is that a document being edited must not be a rendering of
19070
- * something else.
19071
- *
19072
- * **Opening does not commit.** The calendar announces a date, this element takes
19073
- * it, and the overlay shuts, because a single date has nothing more to say. A
19074
- * consumer who owns `value` answers the announcement the way they answer any
19075
- * other control here.
18876
+ * locale and takes almost all styling with it. What is kept from it is the part
18877
+ * worth keeping: a real text field.
19076
18878
  *
19077
18879
  * ## Attributes & Properties
19078
18880
  *
@@ -19347,44 +19149,19 @@ export type CustomElements = {
19347
19149
 
19348
19150
  /**
19349
19151
  * A grid of days, per the APG date grid: the whole grid is one tab stop, arrows
19350
- * move by day and week, `PageUp` and `PageDown` move by month, and `Home` and
19351
- * `End` go to the ends of the week. Only the focused cell is in the tab
19352
- * sequence.
19353
- *
19354
- * Roving `tabindex` is written on the cells, which is free here because they
19355
- * are rendered into this shadow root rather than being markup a consumer wrote.
19356
- *
19357
- * Dates are `YYYY-MM-DD` strings and every calculation is in UTC. A local-time
19358
- * `Date` shifts across a timezone or a daylight-saving boundary, so the string
19359
- * is what the component holds and the arithmetic never leaves UTC.
19360
- *
19361
- * `month` is what the grid shows, separately from `value`, so paging through
19362
- * months does not select anything and a consumer can drive the view. Left
19363
- * unset, it follows the first selected date, and then the current month.
19152
+ * move by day and week, `PageUp` and `PageDown` by month, `Home` and `End` to
19153
+ * the ends of the week. Only the focused cell is in the tab sequence.
19364
19154
  *
19365
- * `mode` decides how many dates are held. Absent takes one. `range` takes two
19366
- * and marks everything between them, starting over on the third click rather
19367
- * than replacing an end at random. `multiple` toggles, so clicking a chosen
19368
- * date takes it out. All three read and write the same comma-separated
19369
- * `value`.
19155
+ * **Dates are `YYYY-MM-DD` strings and every calculation is in UTC.** A
19156
+ * local-time `Date` shifts across a timezone or a daylight-saving boundary.
19370
19157
  *
19371
- * `locale` is worth setting where the output is compared across environments.
19372
- * Left unset, month and day names come from the runtime's own locale, and a
19373
- * server and a browser need not agree on what that is.
19158
+ * `month` is what the grid shows, separately from `value`, so paging does not
19159
+ * select anything and a consumer can drive the view. Left unset it follows the
19160
+ * first selected date, then the current month.
19374
19161
  *
19375
- * A control whose value changes dispatches `helix-before-change`:
19376
- * `Input`, `Select`, `Listbox`, `Radio.Group` and `Toggle.Group` all do, and a
19377
- * calendar submitting a date is the same kind of thing. `helix-select` stays
19378
- * what it is elsewhere, which is a row or an item being chosen in something
19379
- * that reports no value at all, such as `Menu` or `Tree`.
19380
- *
19381
- * Paging is `helix-navigate` and not either of those, because it chooses
19382
- * nothing: the view moves and the answer does not.
19383
- *
19384
- * The properties below are written by this component and read by whoever draws
19385
- * it. A consumer sets none of them: they carry a number this element computed
19386
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
19387
- * without measuring anything itself.
19162
+ * `mode` decides how many dates are held: absent takes one, `range` takes two
19163
+ * and marks everything between them, `multiple` toggles. All three read and
19164
+ * write the same comma-separated `value`.
19388
19165
  *
19389
19166
  * ## Attributes & Properties
19390
19167
  *
@@ -19600,37 +19377,15 @@ export type CustomElements = {
19600
19377
  /**
19601
19378
  * A real `<dialog>` opened with `showModal()`, not a div with a role and a
19602
19379
  * hand-built trap. The platform gives four things that are each a day's work to
19603
- * reimplement and easy to get subtly wrong: the top layer, so the dialog is
19604
- * above everything regardless of what `z-index` anyone else wrote; a real
19605
- * backdrop; Escape; and inert-behind, so the page underneath is not reachable
19606
- * by pointer, keyboard, or a screen reader's virtual cursor.
19380
+ * reimplement: the top layer, so the dialog is above everything whatever
19381
+ * `z-index` anyone wrote; a real backdrop; Escape; and inert-behind, so the
19382
+ * page underneath is unreachable by pointer, keyboard or virtual cursor.
19607
19383
  *
19608
19384
  * **`open` drives `showModal()`, and every way it can close comes back through
19609
- * `requestOpen`.** A native dialog can close from three directions: the
19610
- * property, Escape, and a `<form method="dialog">` submit inside it. Left
19611
- * alone, two of those would shut the dialog while the consumer's state still
19612
- * said open, which is the bug that makes a modal impossible to reopen. Escape
19613
- * is intercepted and routed through the request, so `preventDefault()` on the
19614
- * `helix-before-close` refuses it; a close that happens anyway is reflected back.
19615
- *
19616
- * **Nothing here traps focus.** `showModal()` does it, and better: `inert` on
19617
- * the rest of the document is something no JavaScript trap can achieve.
19618
- * `FocusTrapController` stays for the surfaces that are not modal.
19619
- *
19620
- * The regions are bare slots rather than wrappers, for the reason the card's
19621
- * are: an unassigned `<slot>` is `display: contents` and generates no box, so a
19622
- * dialog with no footer has no empty band where one would be.
19623
- *
19624
- * Opened declaratively with the platform's invoker attributes:
19625
- *
19626
- * ```html
19627
- * <helix-button commandfor="confirm" command="--show">Delete…</helix-button>
19628
- * <helix-dialog id="confirm">…</helix-dialog>
19629
- * ```
19630
- *
19631
- * `--show`, `--close` and `--toggle`. Custom commands rather than the built-in
19632
- * `show-modal`, because those are defined against native elements and do
19633
- * nothing when pointed at a custom one.
19385
+ * `requestOpen`.** A native dialog closes from three directions: the property,
19386
+ * Escape, and a `<form method="dialog">` submit. Left alone, two of them would
19387
+ * shut the dialog while the consumer's state still said open, which is the bug
19388
+ * that makes a modal impossible to reopen.
19634
19389
  *
19635
19390
  * ## Attributes & Properties
19636
19391
  *
@@ -19817,32 +19572,12 @@ export type CustomElements = {
19817
19572
  * The chart with the narrowest honest use, so the component is narrow too.
19818
19573
  *
19819
19574
  * **It reads one column and treats the rows as the parts.** Every other chart
19820
- * here takes a column per series; a ring has one whole to divide, and a second
19821
- * ring inside the first is two charts sharing a picture in the most literal
19822
- * way. So the first column of numbers is the series and each row is a slice.
19823
- *
19824
- * **It refuses negative values rather than drawing them.** A share of a whole
19825
- * cannot be less than nothing, and an arc for a negative number either runs
19826
- * backwards over its neighbors or is silently dropped. Those rows are skipped
19827
- * and the total is of what is left, which is the only reading that stays true.
19828
- *
19829
- * **The shape is drawn with a dashed stroke, not with arc commands.** One
19830
- * `<circle>` per slice, its dash set to the slice's share of the circumference
19831
- * and its offset to where the slice begins. Arc paths need the sweep flag and a
19832
- * large-arc flag, both of which flip at values a reader never sees coming, and
19833
- * a slice of exactly one whole becomes a path with no length at all.
19834
- *
19835
- * **And it keeps its aspect ratio**, alone among the charts here. The others
19836
- * set `preserveAspectRatio="none"` so one drawing fills any box and rescue
19837
- * their strokes with `vector-effect`; that rescues strokes and not geometry, so
19838
- * a ring drawn the same way is an ellipse in anything but a square.
19575
+ * here takes a column per series; a ring has one whole to divide, so the first
19576
+ * column of numbers is the series and each row is a slice.
19839
19577
  *
19840
- * The table is the accessible representation and this drawing is `aria-hidden`.
19841
- *
19842
- * The properties below are written by this component and read by whoever draws
19843
- * it. A consumer sets none of them: they carry a number this element computed
19844
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
19845
- * without measuring anything itself.
19578
+ * **It refuses negative values rather than drawing them.** An arc for a
19579
+ * negative number either runs backwards over its neighbors or is silently
19580
+ * dropped. Those rows are skipped and the total is of what is left.
19846
19581
  *
19847
19582
  * ## Attributes & Properties
19848
19583
  *
@@ -20366,29 +20101,12 @@ export type CustomElements = {
20366
20101
  * replaced.** It is the only way to open a file picker: the dialog is a
20367
20102
  * privileged action a script cannot start on its own, and it opens for a click
20368
20103
  * on the input or on a `<label>` pointing at it. A component that draws its own
20369
- * button ends up calling `.click()` on a hidden input anyway, and then has two
20370
- * things a screen reader can find where there is one control.
20371
- *
20372
- * So the input stays, holds the label, the name, the validity and the focus,
20373
- * and the visible trigger is a `<label for>` rather than a button. A label is
20374
- * not focusable and does not need to be: the input is, and Enter and Space on it
20375
- * open the picker because that is what the platform does with a file input.
20376
- *
20377
- * **Dropping is why this is a component rather than an attribute.** A bare file
20378
- * input accepts a drop only on the input itself, which is invisible here, so the
20379
- * field is the drop target and it says when something is over it.
20380
- *
20381
- * **Files are not a value a consumer can hand back.** Every other control here
20382
- * takes the controlled and uncontrolled pair, and this one does not: a `FileList`
20383
- * cannot be constructed from markup, and browsers refuse a consumer writing
20384
- * `value` on a file input outright, because a page that could name a file could
20385
- * read it. So this element owns what was chosen, announces it, and offers
20386
- * `clear()` for the one change a consumer can legitimately ask for.
20387
- *
20388
- * **The list under it is the control's own, not decoration.** A file input with
20389
- * files chosen reports "3 files" and nothing else, which is unusable for
20390
- * checking that the right ones were picked. The names are rendered, and each
20391
- * carries the way to take it back out.
20104
+ * button calls `.click()` on a hidden input anyway, and then has two things a
20105
+ * screen reader can find where there is one control.
20106
+ *
20107
+ * So the input stays, holding the label, the name, the validity and the focus,
20108
+ * and the visible trigger is a `<label for>`. A label is not focusable and does
20109
+ * not need to be: the input is, and Enter and Space on it open the picker.
20392
20110
  *
20393
20111
  * ## Attributes & Properties
20394
20112
  *
@@ -20650,49 +20368,26 @@ export type CustomElements = {
20650
20368
  >;
20651
20369
 
20652
20370
  /**
20653
- * **One family covers both readings, and the split people expect does not
20654
- * exist.** The argument for two is that a contribution graph needs a continuous
20655
- * ramp where uptime needs a category. GitHub's contribution graph is five
20656
- * discrete levels rather than a gradient, so a cell that takes a tone covers
20657
- * both: `rows="1"` is a status strip, `rows="7"` is a contribution graph, and
20658
- * heatmap is the name of that.
20371
+ * **One family covers both readings.** `rows="1"` is a status strip, `rows="7"`
20372
+ * is a contribution graph, and a cell that takes a tone covers both: GitHub's
20373
+ * contribution graph is five discrete levels rather than a gradient.
20659
20374
  *
20660
20375
  * **What it cannot be is a bar chart with flat values**, and the data model is
20661
- * what closes that rather than taste: chart color is per *series* everywhere
20662
- * else here, `--chart-series-1` through `-15`, so ninety differently colored
20663
- * cells would be ninety series.
20376
+ * what closes that: chart color is per *series* everywhere else here, so ninety
20377
+ * differently colored cells would be ninety series.
20664
20378
  *
20665
- * The data is a real `<table>` named by `for`, the same convention every chart
20666
- * in this library uses, which also answers the accessibility question without
20667
- * inventing anything: **the table is the accessible representation**, it is
20668
- * already in the markup, and the drawing is a picture of it. Hide it with
20669
- * `data-hidden-visually` and the reading is still there for anyone who needs it.
20379
+ * **The data is a real `<table>` named by `for`**, the convention every chart
20380
+ * in this library uses, and it is the accessible representation. Hide it with
20381
+ * `data-hidden-visually` and the reading is still there.
20670
20382
  *
20671
20383
  * A cell takes its tone from its own `data-tone`, or from `thresholds` and
20672
- * `tones` bucketing its value. The first is what a status page wants and the
20673
- * second is what a contribution graph wants; the cell's own wins, so a page that
20674
- * already knows a day was degraded does not have to encode that as a number for
20675
- * this component to decode again.
20384
+ * `tones` bucketing its value. The cell's own wins, so a page that already
20385
+ * knows a day was degraded does not encode that as a number to be decoded.
20676
20386
  *
20677
20387
  * **A tone is a name this tier never resolves.** `tone="success"` writes
20678
- * `--heatmap-tone: var(--heatmap-tone-success)` onto the cell and stops there,
20679
- * so what a name is worth is the answering tier's to say: `helix/styled` points
20680
- * the semantic names at the theme's status colors and the numbered ones at a
20681
- * ramp, and a consumer on `headless` declares the same names as whatever they
20682
- * like. Reaching for `var(--helix-color-${tone})` here is the dependency the
20683
- * tiers exist to prevent, and it fails loudly rather than quietly: off-tier that
20684
- * property is not undefined, it is *invalid*, so
20685
- * `background-color: var(--heatmap-tone, …)` declines its own fallback and every
20686
- * cell comes out transparent, leaving a blank page under a row of footer text.
20687
- * `shared/chart/series.css` records the same fault in Bar Chart.
20688
- *
20689
- * **On a narrow container it draws fewer cells rather than thinner ones.**
20690
- * Ninety cells in 320 pixels is three and a half pixels each, which is a smear
20691
- * and not a strip. The cells it drops are the oldest, and it reflects `visible`
20692
- * and fires `helix-resize` when the number changes, because **a summary saying
20693
- * "99.2% over 90 days" above a strip drawing 45 of them is telling the reader
20694
- * something false about the picture in front of them** and nothing about the
20695
- * picture says so.
20388
+ * `--heatmap-tone: var(--heatmap-tone-success)` and stops, so what a name is
20389
+ * worth is the answering tier's to say. Reaching for `var(--helix-color-*)`
20390
+ * here is the dependency the tiers exist to prevent.
20696
20391
  *
20697
20392
  * ## Attributes & Properties
20698
20393
  *
@@ -21151,31 +20846,14 @@ export type CustomElements = {
21151
20846
 
21152
20847
  /**
21153
20848
  * **An element rather than a recipe, because of the part CSS cannot do.**
21154
- * Reserving the box is `aspect-ratio` and needs nothing from anybody; `Link` and
21155
- * the megamenu row are recipes in `preview.css` for exactly that reason. What
21156
- * cannot be written as a rule is *when the picture arrived*: a stylesheet has no
21157
- * way to know, and no way to hear that it never will. So this owns three states
21158
- * and the two events that move between them, and leaves the box to the
20849
+ * Reserving the box is `aspect-ratio` and needs nothing from anybody. What
20850
+ * cannot be written as a rule is *when the picture arrived*: a stylesheet has
20851
+ * no way to know, and no way to hear that it never will. So this owns three
20852
+ * states and the two events that move between them, and leaves the box to the
21159
20853
  * stylesheet.
21160
20854
  *
21161
20855
  * **The placeholder is a slot with nothing in it by default.** A default of
21162
- * `Skeleton` would be right and is not written here: this tier renders no other
21163
- * component, and reaching for one would make the headless package depend on the
21164
- * styled one. The styled tier draws the resting placeholder instead, and a
21165
- * consumer who wants a `Skeleton`, a blurred thumbnail or a solid color slots
21166
- * it.
21167
- *
21168
- * **No source is a loading state, not a fourth one.** A picture whose `src` has
21169
- * not arrived yet is the common case for anything drawn from data, and the
21170
- * useful answer there is the same as for one still on the wire: stand something
21171
- * in its place and keep the ground reserved. So an element with no `src` shows
21172
- * its placeholder and waits, rather than resolving to an empty box that has to
21173
- * be laid out twice.
21174
- *
21175
- * **`alt` is a property and not an afterthought.** An empty string is a real
21176
- * answer, meaning the picture is decoration and a screen reader should skip it,
21177
- * which is why the attribute is always written even when it is empty: omitting
21178
- * it entirely makes a reader announce the file name instead.
20856
+ * `Skeleton` would make this tier depend on a component it does not ship.
21179
20857
  *
21180
20858
  * ## Attributes & Properties
21181
20859
  *
@@ -21277,39 +20955,21 @@ export type CustomElements = {
21277
20955
 
21278
20956
  /**
21279
20957
  * Renders a real `<input>`, so the caret, selection, autofill, spellcheck, the
21280
- * password manager, and the on-screen keyboard a phone chooses all come from the
21281
- * platform. `delegatesFocus` puts focus on it, and it serializes into the
21282
- * server's markup, so the field is usable before any script loads.
20958
+ * password manager and the on-screen keyboard a phone chooses are all the
20959
+ * platform's. It serializes into the server's markup, so the field is usable
20960
+ * before any script loads.
21283
20961
  *
21284
- * **The input inside a shadow root submits nothing**, because the form is on the
20962
+ * **The input inside a shadow root submits nothing**, the form being on the
21285
20963
  * other side of the boundary. The host is form-associated instead and reports
21286
- * its own value through `ElementInternals`, which is also what carries validity
21287
- * and what answers a form reset.
20964
+ * its own value through `ElementInternals`, which also carries validity and
20965
+ * answers a form reset.
21288
20966
  *
21289
- * `value` and `defaultValue` are separate for the reason `checked` and
21290
- * `defaultChecked` are: `value` is what is in the field now and
21291
- * `defaultValue` is what the markup asked for, which is where a reset returns
21292
- * to and is gone the moment anyone types.
21293
- *
21294
- * **Validity is the platform's.** The `type` and `required` are set on the real
21295
- * input and its `validity` is copied onto the host, so an email field rejects
21296
- * what the browser says is not an email rather than what a regular expression
21297
- * here guesses. What this adds is the anchor, so `reportValidity` points the
21298
- * bubble at the input rather than at the host.
21299
- *
21300
- * `pattern`, `minlength` and `maxlength` are forwarded with them.
21301
- *
21302
- * **`clearable` and `reveal` are the field's, not the consumer's.** Neither is
21303
- * a slot's worth of variation: one empties the value, the other flips the type,
21304
- * and both want the same position, the same size and the same disabled
21305
- * behavior. The `end` slot stays for what actually varies, a unit or a prefix.
21306
- *
21307
- * Both opt in rather than following from `type`, and are booleans that default
21308
- * to false. A Lit boolean property that defaults to *true* cannot be turned off
21309
- * from HTML at all, only from script, which is the wrong way round for
21310
- * revealing a password: a consumer should have to ask for it. Drawer's `modal`
21311
- * defaults true for the opposite reason, that losing a focus trap by forgetting
21312
- * a word is worse than having to say so.
20967
+ * `value` and `defaultValue` are separate the way `checked` and
20968
+ * `defaultChecked` are: `value` is what is in the field now, `defaultValue` is
20969
+ * what the markup asked for and where a reset returns to.
20970
+ *
20971
+ * **Validity is the platform's.** `type` and `required` are set on the real
20972
+ * input and its `validity` is copied onto the host.
21313
20973
  *
21314
20974
  * ## Attributes & Properties
21315
20975
  *
@@ -21536,38 +21196,20 @@ export type CustomElements = {
21536
21196
 
21537
21197
  /**
21538
21198
  * Renders a real `<kbd>`, so the passage still means "press this" to anything
21539
- * reading the markup rather than only to a reader looking at it.
21199
+ * reading the markup.
21540
21200
  *
21541
- * **One key per element, with `keys` as the stated exception.** A *sequence* is
21201
+ * **One key per element, with `keys` as the stated exception.** A sequence is
21542
21202
  * several of these with the separator written between them as ordinary text,
21543
- * because that separator is prose: it is "then" in a sequence and "plus" in a
21544
- * simultaneous press, and a component that inserted one would have to guess
21545
- * which. `keys` cannot be guessing, since a chord written `mod+k` has said
21546
- * which it is.
21203
+ * because that separator is prose: "then" in a sequence, "plus" in a chord, and
21204
+ * a component inserting one would have to guess which.
21547
21205
  *
21548
21206
  * **`keys` exists because the glyphs were being typed by hand and were wrong.**
21549
21207
  * A literal `⌘K` in a template tells a reader on Windows to press a key their
21550
- * keyboard does not have, and nothing catches it, a string being a string.
21551
- * Given `mod` this renders `⌘K` on Apple and `Ctrl+K` everywhere else.
21208
+ * keyboard does not have, and nothing catches it. Given `mod` this renders
21209
+ * `⌘K` on Apple and `Ctrl+K` everywhere else.
21552
21210
  *
21553
- * **`within` is what binds it, and it is absent by default.** Without it this
21554
- * draws a key and listens for nothing, which is what every existing use of this
21555
- * component wants. The two values are the two honest lifetimes:
21556
- *
21557
- * - `control` listens within the element's own parent, which is the case this
21558
- * is mostly for: a hint sitting inside the control it belongs to, where the
21559
- * shortcut should work while that control has focus and stop existing when
21560
- * the control does.
21561
- * - `document` listens on the document, for a chord that works from anywhere.
21562
- *
21563
- * **A hidden `kbd` is a dead shortcut, and that is the point rather than a
21564
- * trap.** Binding here ties the key to its own advertisement, so a hint that is
21565
- * not rendered is a shortcut that is not offered. A chord that must outlive its
21566
- * label is a chord whose owner is not a label: give it to whatever owns the
21567
- * action and let this element only describe it.
21568
- *
21569
- * Nothing binds until this upgrades, so a shortcut is not available in the
21570
- * moments before hydration.
21211
+ * **`within` is what binds it, and it is absent by default**, so this draws a
21212
+ * key and listens for nothing unless asked.
21571
21213
  *
21572
21214
  * ## Attributes & Properties
21573
21215
  *
@@ -21630,32 +21272,14 @@ export type CustomElements = {
21630
21272
  /**
21631
21273
  * A legend is a list, so it is a list: not part of a chart, and shared by
21632
21274
  * whichever of them needs one. It takes its entries from the same table the
21633
- * chart reads, through `for`, so the two cannot disagree about how many series
21634
- * there are or what they are called.
21635
- *
21636
- * `entries` picks which way to read that table, and the two ways are the two
21637
- * shapes a chart comes in. `series` is one entry per data column, named by the
21638
- * header row, which is a line or a bar chart. `categories` is one entry per
21639
- * body row, named by its row header, which is a donut: its slices are the rows,
21640
- * and it has no axis to write their names along.
21641
- *
21642
- * **The table is resolved on the client and there is no server pass.** `for` is
21643
- * an id and resolving it wants a document, which the server render does not
21644
- * have, so a legend ships empty and fills in on hydration. The table itself is
21645
- * ordinary markup and is served whole, so nothing is missing from the page
21646
- * before then, only from this list.
21647
- *
21648
- * The table is watched, because a legend that goes stale when its data changes
21649
- * is a legend that has to be told, and nothing else in the page would know to
21650
- * tell it.
21651
- *
21652
- * **Not hidden from a screen reader, though the mapping it draws is a color
21653
- * one.** The argument for hiding it is real: the colors mean nothing to a
21654
- * reader who cannot see them, and the names are already in the table. It stays
21655
- * because the cost of being wrong runs one way. A duplicated list of three
21656
- * words is noise; a consumer who took the table out of the accessibility tree
21657
- * and then found the legend hidden too has a chart nobody can read, and neither
21658
- * decision announces itself.
21275
+ * chart reads, through `for`, so the two cannot disagree.
21276
+ *
21277
+ * `entries` picks which way to read that table. `series` is one entry per data
21278
+ * column, named by the header row, which is a line or a bar chart.
21279
+ * `categories` is one entry per body row, which is a donut: its slices are the
21280
+ * rows and it has no axis to write their names along.
21281
+ *
21282
+ * **The table is resolved on the client and there is no server pass.**
21659
21283
  *
21660
21284
  * ## Attributes & Properties
21661
21285
  *
@@ -22037,37 +21661,15 @@ export type CustomElements = {
22037
21661
  * **The listbox is the control and the options are its vocabulary.** A Select
22038
21662
  * is this with a trigger in front of it, a Combobox is this with a text input,
22039
21663
  * and a command palette is this again: they differ in what opens the list and
22040
- * what filters it, not in what the list is. Building it as its own family is
22041
- * what stops each of those reimplementing the keyboard and the filtering.
21664
+ * what filters it, not in what the list is.
22042
21665
  *
22043
21666
  * **`value` is comma separated when `multiple` is set**, the way
22044
21667
  * `Checkbox.Group`'s is. It stays a string because that is what a form submits
22045
- * and what `MixinControllerValue` holds; an array property would be a second
22046
- * shape for the same fact, and the two would disagree the first time one was
22047
- * set without the other.
21668
+ * and what `MixinControllerValue` holds.
22048
21669
  *
22049
21670
  * **Chosen and active are two different things.** Chosen is the answer; active
22050
- * is where the keyboard is. In a single-select list they move together, which
22051
- * is the radio group pattern and is what a reader expects from arrow keys. With
22052
- * `multiple` they come apart: the arrows move without choosing and Space
22053
- * chooses, because a reader passing over four options on the way to the fifth
22054
- * did not mean to pick all five.
22055
- *
22056
- * **This does not use `KeyboardNavigationController`, and the reason is where
22057
- * focus lives rather than whether moving chooses.** The controller already
22058
- * separates those, taking `origin: 'focus' | 'selection'`. What it cannot do is
22059
- * leave focus alone: `NavigableItem.focusItem()` moves DOM focus to the item,
22060
- * its model being a roving tab stop. A filterable list cannot have that, focus
22061
- * having to stay in the field or typing stops, so what moves is a virtual
22062
- * cursor and `aria-activedescendant` is what says where it is. No flag
22063
- * reconciles the two.
22064
- *
22065
- * **Filtering hides rather than removes.** An option the filter has hidden is
22066
- * still the consumer's element in the consumer's order, so a filter that clears
22067
- * puts the list back exactly as it was with nothing re-rendered. What counts as
22068
- * a match is a plain case-insensitive substring, and a consumer wanting more
22069
- * hides options itself: `filter` is a convenience over the same `hidden` the
22070
- * component uses.
21671
+ * is where the keyboard is. Only the second moves with the arrows, and
21672
+ * `aria-activedescendant` names it while focus stays on the list.
22071
21673
  *
22072
21674
  * ## Attributes & Properties
22073
21675
  *
@@ -22372,49 +21974,17 @@ export type CustomElements = {
22372
21974
  * **A disclosure, not a menu, and that is the whole design.** `role="menu"` and
22373
21975
  * `menuitem` are for an application's commands: they take over the arrow keys,
22374
21976
  * announce "menu" to a reader who asked for navigation, and put every link
22375
- * inside a role that is not a link. What this is, is a button that shows and
22376
- * hides a region of the consumer's own anchors, which is the pattern the APG
22377
- * gives for site navigation and the one that leaves a middle click, a modified
21977
+ * inside a role that is not a link. This is a button that shows and hides a
21978
+ * region of the consumer's own anchors, which leaves a middle click, a modified
22378
21979
  * click and the status bar working. `Menu` remains right for a row of commands.
22379
21980
  *
22380
- * **It renders no links**, for the reason `Navigation` gives: a router renders
22381
- * its own anchor and cannot render one inside this shadow root. The panel is a
22382
- * slot, and what goes in it is lists and headings the consumer wrote.
21981
+ * **It renders no links.** A router renders its own anchor and cannot render
21982
+ * one inside this shadow root, so the panel is a slot and what goes in it is
21983
+ * the lists and headings the consumer wrote.
22383
21984
  *
22384
21985
  * **It opens on hover, and a press is always the fallback.** `open-on` says
22385
- * which, and hover is the resting value because a nav bar is the one place a
22386
- * reader expects to sweep along a row and see each section: making them click,
22387
- * read, click again to compare two is the interaction hover exists to save.
22388
- *
22389
- * Hover is not the only way in, and the code is mostly about that. There is no
22390
- * hover on a touch screen, so a tap opens the panel there whatever `open-on`
22391
- * says, which is why the pointer type is checked rather than assumed. Focus
22392
- * still opens nothing, for the same reason a tab through a nav bar should not
22393
- * unfold it, but Enter on the trigger does, and a keyboard press arrives as a
22394
- * click with no pointer behind it.
22395
- *
22396
- * A mouse click on a trigger the pointer is already sitting on is the case
22397
- * worth naming: toggling there would close the panel and the pointer, still on
22398
- * the trigger, would open it again, so the trigger would flicker and never
22399
- * close. In hover mode the mouse's own clicks are left alone and hover governs
22400
- * on its own. Escape and a click away still close it.
22401
- *
22402
- * The delays are intent, not decoration. Opening waits, so a pointer crossing
22403
- * the bar on its way somewhere else opens nothing; closing waits longer, so the
22404
- * diagonal from the trigger down into the panel does not pass through a gap and
22405
- * shut it. Moving along a bar where a panel is already down opens the next one
22406
- * at once, because at that point the reader is reading the bar, not crossing it.
22407
- *
22408
- * **Focus is not trapped and not moved.** A disclosure leaves the reader on the
22409
- * trigger and the panel follows in the tab order, which is what the markup
22410
- * already says, so Tab walks into the links and out the far side without
22411
- * anything managing it. Escape closes and puts focus back, because Escape is
22412
- * the one key that has to return the reader to where they were.
22413
- *
22414
- * The custom property below is written by this component and read by whoever
22415
- * draws it. A consumer never sets it: it carries a number this element computed
22416
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
22417
- * without measuring anything itself.
21986
+ * which, and hover is the resting value because a nav bar is where a reader
21987
+ * expects to sweep along a row and see each section.
22418
21988
  *
22419
21989
  * ## Attributes & Properties
22420
21990
  *
@@ -22792,31 +22362,13 @@ export type CustomElements = {
22792
22362
  * **Not `Progress`, and the difference is the whole component.** A progress bar
22793
22363
  * reports how far along a task is: it starts empty, ends full, and full is
22794
22364
  * always the good end. A meter reports a level in a range that is not going
22795
- * anywhere, and which end is good is a fact about the thing being measured.
22796
- * Disk usage, a battery, a score, a rate limit. So there is no `indeterminate`
22797
- * here: a measurement whose value is unknown is not a measurement.
22798
- *
22799
- * **`low`, `high` and `optimum` are the reason it exists**, and they follow the
22800
- * HTML specification's own rule. The three thresholds cut the range into a low
22801
- * band, a middle and a high band, and `optimum` says which of the three is the
22802
- * one to be in. The band the value falls in is then the good one, the one next
22803
- * to it is fair, and the one two away is poor.
22804
- *
22805
- * **Without thresholds there are no bands, and this is where it parts company
22806
- * with `<meter>`.** The platform defaults `optimum` to the midpoint and both
22807
- * thresholds to the ends, so a bare `<meter value="20" max="100">` computes as
22808
- * optimum and every browser paints it green. A gauge with nothing said about it
22809
- * is not good news; it is a reading. Declared thresholds turn the color on.
22810
- *
22811
- * **And the bands are drawn as well as colored.** A tick sits at `low` and at
22812
- * `high`, so the reading can be placed against them without seeing color at
22813
- * all, which is the same call the carousel's current dot makes by lengthening
22814
- * rather than only changing color.
22365
+ * anywhere, and which end is good is a fact about the thing measured. So there
22366
+ * is no `indeterminate`: a measurement whose value is unknown is not one.
22815
22367
  *
22816
- * The properties below are written by this component and read by whoever draws
22817
- * it. A consumer sets none of them: they carry a number this element computed
22818
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
22819
- * without measuring anything itself.
22368
+ * **`low`, `high` and `optimum` are the reason it exists**, following the HTML
22369
+ * specification's own rule. The three cut the range into a low band, a middle
22370
+ * and a high band, and `optimum` says which is the one to be in; the band next
22371
+ * to it is fair and the one two away is poor.
22820
22372
  *
22821
22373
  * ## Attributes & Properties
22822
22374
  *
@@ -23219,17 +22771,13 @@ export type CustomElements = {
23219
22771
  >;
23220
22772
 
23221
22773
  /**
23222
- * **A family rather than `Input`'s `type="number"`, and rather than a part of
23223
- * it.** `Input` already takes that type and will keep it: a bare numeric field
23224
- * in a form is a text field with a different keyboard, and that is all it needs
23225
- * to be. This is a different control. It renders two buttons, binds four keys
23226
- * that `Input` does not, and owns clamping and stepping, so it is an alternative
23227
- * and not a variant. Namespacing it under `Input` would say it is contained by
23228
- * one, which is what `IconButton` is top-level for.
22774
+ * **A family rather than `Input`'s `type="number"`.** It renders two buttons,
22775
+ * binds four keys `Input` does not, and owns clamping and stepping, so it is an
22776
+ * alternative and not a variant.
23229
22777
  *
23230
22778
  * **The field is `type="text"` with `inputmode="decimal"`, and that is a
23231
- * measurement rather than a preference.** Asked of a real browser, `type=number`
23232
- * fails three ways this control cannot live with:
22779
+ * measurement.** Asked of a real browser, `type=number` fails three ways this
22780
+ * control cannot live with:
23233
22781
  *
23234
22782
  * ```
23235
22783
  * typed "12e" into type=number → .value === ""
@@ -23238,21 +22786,16 @@ export type CustomElements = {
23238
22786
  * same keystrokes into type=text → .value === "12e"
23239
22787
  * ```
23240
22788
  *
23241
- * The first is fatal on its own: the element cannot see what the reader typed,
23242
- * so a controlled value is destroyed by a keystroke and there is nothing left to
23243
- * correct or to report. The second changes a value because a page scrolled past.
23244
- * The third means the caret cannot be managed at all, which any correcting or
23245
- * formatting field needs. `inputmode` is what keeps the phone keypad, which is
22789
+ * The first is fatal alone: the element cannot see what the reader typed. The
22790
+ * second changes a value because a page scrolled past. The third means the
22791
+ * caret cannot be managed at all. `inputmode` keeps the phone keypad, which is
23246
22792
  * the one thing `type=number` was giving.
23247
22793
  *
23248
22794
  * Validity is still the platform's, through `min`, `max` and `step` mirrored
23249
- * onto the host's own `setValidity`. What is not mirrored is the field's
23250
- * `type`, because a text field has no opinion about numbers.
22795
+ * onto the host's own `setValidity`.
23251
22796
  *
23252
- * **Stepping is separate from typing.** A reader mid-way through "1" of "12"
23253
- * has not asked for anything to be clamped, so the value is only pulled into
23254
- * range when they step, blur, or the form asks. Clamping on every keystroke is
23255
- * what makes a field that cannot be typed backwards into.
22797
+ * **Stepping is separate from typing**, so a reader mid-way through a number is
22798
+ * not corrected under their hands.
23256
22799
  *
23257
22800
  * ## Attributes & Properties
23258
22801
  *
@@ -23672,35 +23215,16 @@ export type CustomElements = {
23672
23215
 
23673
23216
  /**
23674
23217
  * A table of contents, named for the job. It sits beside `Navigation`, which is
23675
- * the same job at the other scale: one navigates a site, the other navigates a
23676
- * document. `Contents` and `TableOfContents` are both taken by something else,
23677
- * `display: contents` and the `content` part in one case and the `Table` family
23678
- * in the other.
23679
- *
23680
- * **The links are the consumer's own anchors**, the same as `Navigation`. A router
23681
- * renders its own `<a>` and cannot render one inside this shadow root, and the
23682
- * hrefs are fragments the page already knows.
23683
- *
23684
- * **What is current is decided by position, not by intersection.** The obvious
23685
- * build is an `IntersectionObserver` with a thin band near the top of the
23686
- * window, and it fails in both directions: with headings far apart nothing is
23687
- * in the band and the marker goes out entirely, and with headings close
23688
- * together several are and it flickers between them. So the observer is only
23689
- * the *trigger*, and the answer is computed from where the headings actually
23690
- * are: the current section is the last one whose top has passed the reading
23691
- * line, or the first heading before any of them has.
23692
- *
23693
- * That rule is what a reader means. Two headings on screen at once are not
23694
- * ambiguous to a person: they are reading under the upper one.
23695
- *
23696
- * **`aria-current="location"`, and it is written onto the consumer's anchor.**
23697
- * This library does not normally write to light-DOM children, because an
23698
- * attribute added after upgrade is one a server's markup never had. It is right
23699
- * here for the reason `Carousel` names its slides: what is current is derived
23700
- * from scroll position, so no server could have rendered it and there is
23701
- * nothing for hydration to disagree with. `location` rather than `page`, which
23702
- * is what `Navigation` uses: `page` means this is the page, and every one of these
23703
- * is the same page.
23218
+ * the same job at the other scale: one navigates a site, the other a document.
23219
+ *
23220
+ * **The links are the consumer's own anchors.** A router renders its own `<a>`
23221
+ * and cannot render one inside this shadow root, and the hrefs are fragments
23222
+ * the page already knows.
23223
+ *
23224
+ * **What is current is decided by position, not by intersection.** An
23225
+ * `IntersectionObserver` with a band near the top fails in both directions:
23226
+ * with headings far apart nothing is in the band and the marker goes out, and
23227
+ * with headings close together several are in it at once.
23704
23228
  *
23705
23229
  * ## Attributes & Properties
23706
23230
  *
@@ -23782,67 +23306,34 @@ export type CustomElements = {
23782
23306
  >;
23783
23307
 
23784
23308
  /**
23785
- * The component is the truncation. Given a page and a total it works out which
23786
- * numbers to show and where the runs break, which is the whole of what a
23787
- * consumer would otherwise write by hand and get subtly wrong; everything else
23788
- * here is markup around that. So this is data-driven rather than composed:
23789
- * `<helix-pagination page="4" pages="12">` rather than twelve slotted children
23790
- * a consumer has to keep in step with their own query.
23309
+ * **The component is the truncation.** Given a page and a total it works out
23310
+ * which numbers to show and where the runs break, so this is data-driven rather
23311
+ * than composed: `<helix-pagination page="4" pages="12">` rather than twelve
23312
+ * slotted children a consumer keeps in step with their own query.
23791
23313
  *
23792
23314
  * **The width does not change as you page.** The run around the current page is
23793
- * `siblings` either side normally, and grows to absorb a gap slot when it meets
23794
- * a boundary, so the control holds the same number of slots from the first page
23795
- * to the last. Every arrangement that lets the count vary makes the buttons move
23796
- * under the pointer between one click and the next.
23315
+ * `siblings` either side, and grows to absorb a gap slot at a boundary, so the
23316
+ * control holds the same number of slots from the first page to the last.
23317
+ * Anything that lets the count vary moves the buttons under the pointer between
23318
+ * one click and the next.
23797
23319
  *
23798
- * **A gap is only drawn where it hides more than one page.** An ellipsis
23799
- * standing in for a single number costs the same space as the number and tells
23800
- * the reader less.
23801
- *
23802
- * **And a gap is a control.** It goes to the middle of the run it stands over,
23803
- * which is the binary-search step: any page in a set of any size is a handful of
23804
- * presses, where a jump of a fixed size would need forty of them on a set of a
23805
- * hundred and twenty-eight. A menu listing the hidden pages was the other idea
23806
- * and the arithmetic refuses it, for the reasons on `renderGap`.
23320
+ * **A gap is only drawn where it hides more than one page, and a gap is a
23321
+ * control.** It goes to the middle of the run it stands over, which is the
23322
+ * binary-search step: any page in a set of any size is a handful of presses.
23807
23323
  *
23808
23324
  * **`href` is what makes these links.** Set it and every page renders an `<a>`
23809
- * with `{page}` filled in, so the server's output is crawlable, a middle click
23810
- * opens a tab, and the address bar is the state. Left unset they are buttons,
23811
- * which is right for a table paging in place. Either way the click announces
23812
- * `helix-navigate` first, and `preventDefault()` on it stops the navigation as
23813
- * well as the change: that is how a router takes over without the page reloading
23814
- * underneath it.
23815
- *
23816
- * **`helix-navigate` and not `helix-change`**, for the reason the calendar pages
23817
- * with it too. Moving to page four chooses nothing; it moves the view over a
23818
- * result that has not changed. A consumer driving the view has to be able to
23819
- * hear that without being told an answer changed.
23820
- *
23821
- * **The count and the page-size control are their own elements.** A slot can
23822
- * only offer one place: at one end of one row, in one order, on one axis.
23823
- * `Pagination.Summary` and `Pagination.Size` sit beside this one instead, so
23824
- * the direction and the order of a footer are the consumer's, which is what
23825
- * they were always going to want. `total` and `page-size` stay here for the
23826
- * arithmetic below and nothing else.
23827
- *
23828
- * **A single page renders nothing.** A control offering one page offers no
23829
- * navigation, and the row it sits in should close over it rather than hold a
23830
- * space for a thing that cannot be used. Reported through
23831
- * `ElementInternals.states` rather than an attribute on the host, because an
23832
- * attribute written at upgrade is markup a server's output never had and a
23833
- * framework reports the difference; a custom state carries the same fact to a
23834
- * stylesheet and none of that to the DOM.
23835
- *
23836
- * **And a page change is announced.** Moving the page moves `aria-current` onto
23837
- * a different element, which a screen reader does not announce, so a reader who
23838
- * pressed 5 hears the word "5" from the button they were on and nothing at all
23839
- * about having arrived. A polite live region says where they now are. It ships
23840
- * empty and is filled only on a change, because a region populated as it enters
23841
- * the document announces itself on arrival.
23842
- *
23843
- * `page` is what the element holds and `default-page` seeds it. A consumer
23844
- * paging through a router refuses `helix-navigate` and assigns their own, which
23845
- * is how they take the decision.
23325
+ * with `{page}` filled in, so the output is crawlable, a middle click opens a
23326
+ * tab, and the address bar is the state. Left unset they are buttons, which is
23327
+ * right for a table paging in place. Either way the click announces
23328
+ * `helix-navigate` first, and `preventDefault()` stops the navigation as well
23329
+ * as the change, which is how a router takes over.
23330
+ *
23331
+ * **`helix-navigate` and not `helix-change`.** Moving to page four chooses
23332
+ * nothing; it moves the view over a result that has not changed.
23333
+ *
23334
+ * **The count and the page-size control are their own elements.**
23335
+ * `Pagination.Summary` and `Pagination.Size` sit beside this one, because a
23336
+ * slot can only offer one place: at one end of one row, in one order.
23846
23337
  *
23847
23338
  * ## Attributes & Properties
23848
23339
  *
@@ -24080,39 +23571,18 @@ export type CustomElements = {
24080
23571
 
24081
23572
  /**
24082
23573
  * Its own element rather than a part of `Pagination`, so a consumer decides
24083
- * where it goes. Inside the run it could only ever be at one end of one row;
24084
- * beside it, it goes above, below, in a table's caption, or on the other side of
24085
- * the page, and the direction and order of the whole footer are the consumer's.
24086
- *
24087
- * **It repeats `page`, `page-size` and `total`, and the cost of that is skew
24088
- * rather than verbosity.** Those three come from the consumer's own query, so
24089
- * writing them on two elements is one variable used twice; what it risks is the
24090
- * two disagreeing, and a count reading `76-100 of 248` beside a run showing page
24091
- * 7 is the same failure this element's own clamping exists to prevent, arriving
24092
- * from the outside instead.
24093
- *
24094
- * **Nothing removes it at this level, and that was measured rather than
24095
- * assumed.** A coordinating root can only reach children the consumer laid out
24096
- * by writing attributes onto them, which a framework reports as a hydration
24097
- * error, or through context, which is dead on a server: `@lit/context`
24098
- * subscribes from `connectedCallback`, and Lit SSR does not call it, so every
24099
- * value is `undefined` in exactly the render this element exists to be part of.
24100
- * Confirmed against Lit SSR directly. The fork is real: children in the light
24101
- * DOM mean the consumer owns the layout and no root can feed them; children in a
24102
- * shadow root mean a root feeds them by ordinary binding and owns the layout.
24103
- *
24104
- * **It resolves one level up, at a composite, and the state is why.** `page`,
24105
- * `page-size` and `total` are facts about a *result*, not about a pagination, so
24106
- * the element that should hold them once is the one that holds the result: a
24107
- * data table composing a pagination inside itself, rather than a pagination root
24108
- * invented to hold three pagination elements together. That root would have been
24109
- * plumbing; a table's paging state is the thing itself. And because a composite
24110
- * renders its parts into its own shadow root, it lands on the side of the fork
24111
- * where binding works and the server renders, at no cost to anyone.
24112
- *
24113
- * Renders nothing without a `total` and a `page-size`. A wrong count is worse
24114
- * than none: it is the one number in a footer a reader cannot check against
24115
- * anything else on screen.
23574
+ * where it goes: above, below, in a table's caption, or on the other side of
23575
+ * the page. Inside the run it could only ever be at one end of one row.
23576
+ *
23577
+ * **It repeats `page`, `page-size` and `total`, and the cost of that is skew.**
23578
+ * Those three come from the consumer's own query, so writing them on two
23579
+ * elements is one variable used twice; what it risks is the two disagreeing.
23580
+ *
23581
+ * **Nothing removes that at this level, and it was measured.** A coordinating
23582
+ * root can only reach light-DOM children by writing attributes onto them, which
23583
+ * a framework reports as a hydration error, or through context, which is dead
23584
+ * on a server: `@lit/context` subscribes from `connectedCallback`, and Lit SSR
23585
+ * does not call it.
24116
23586
  *
24117
23587
  * ## Attributes & Properties
24118
23588
  *
@@ -24468,32 +23938,15 @@ export type CustomElements = {
24468
23938
 
24469
23939
  /**
24470
23940
  * Determinate by default, and `indeterminate` for a task whose total is not
24471
- * known yet. `Loader` is still the right answer where the wait is short or has
24472
- * no place of its own on the page; a bar earns its width where the work is the
24473
- * subject of the region it sits in.
23941
+ * known yet. `Loader` is still right where the wait is short or has no place of
23942
+ * its own on the page.
24474
23943
  *
24475
23944
  * A bar that fills at a made-up rate would be a bar that lies, so the
24476
23945
  * indeterminate one does not fill: it runs a segment across the track, which
24477
- * says work is happening and claims no proportion at all. `aria-valuenow` is
24478
- * omitted with it, which is the platform's own signal for the same thing.
23946
+ * says work is happening and claims no proportion. `aria-valuenow` is omitted
23947
+ * with it, which is the platform's own signal for the same thing.
24479
23948
  *
24480
23949
  * **The fill is a fraction of the track, written as a custom property.**
24481
- * `--progress-fraction` is derived from `value` and `max` rather than measured,
24482
- * so it renders on a server with no layout and needs nothing after upgrade. That
24483
- * is what keeps it out of the class of geometry this library writes only on the
24484
- * client. A consumer never sets it: it carries a number this element computed
24485
- * and CSS cannot, which is what lets a stylesheet draw the thing without
24486
- * measuring anything itself.
24487
- *
24488
- * **`value` is clamped, and out-of-range input is not an error.** A count that
24489
- * runs past its own total is ordinary in real applications, and a bar that
24490
- * overflows its track or reports `aria-valuenow` above `aria-valuemax` is worse
24491
- * than one that reads as finished.
24492
- *
24493
- * Semantics are on the host through `ElementInternals`, the same as everywhere
24494
- * else: a `role` in the shadow root announces correctly and leaves the host
24495
- * anonymous to anything walking the light DOM, and a `role` written onto the
24496
- * host as an attribute is one a server's markup never had.
24497
23950
  *
24498
23951
  * ## Attributes & Properties
24499
23952
  *
@@ -24986,39 +24439,16 @@ export type CustomElements = {
24986
24439
  /**
24987
24440
  * **Half marks decide the shape.** Supporting them means the value is not an
24988
24441
  * integer and the targets are not the marks: five stars at a half step is ten
24989
- * places to press, and a mark that is filled to the middle. The pointer handling
24990
- * and `step` are both built around that rather than added over it.
24991
- *
24992
- * **A partial mark is the whole mark, clipped.** Not a second glyph filled to
24993
- * the middle: that needs a matching pair drawn for every mark anybody uses, and
24994
- * the moment a consumer wants a heart or a circle they need to draw one too. The
24995
- * fill is the same marks over the same marks, cut off partway, so any mark works
24996
- * and any fraction does.
24997
- *
24998
- * **Read-only is not this control grayed out, it is a different thing.** The
24999
- * commoner use is showing a score nobody is being asked for, a product's
25000
- * average, and that is not a control at all: it takes no focus, answers no keys,
25001
- * has no options to choose between, and reads as one thing rather than as five.
25002
- * So `readonly` is `role="img"` with the score in its name, where the control is
25003
- * a radio group. A disabled control is still a control and still says so; this
25004
- * is not one.
25005
- *
25006
- * **Moving is choosing here**, which is the radio group's reading and the
25007
- * opposite of `Menu`'s: arriving at four stars *is* rating it four, because
25008
- * nothing else follows and there is nothing to confirm. That is what
25009
- * `KeyboardNavigationController` takes `selects` for, and why this can use it
25010
- * where a menu cannot.
25011
- *
25012
- * **The mark is a stylesheet's, not a slot's.** A slot projects its content
25013
- * once, and there are two layers of marks here: slotting a star would put it in
25014
- * the track or the fill and leave the other empty. So the mark is a shape the
25015
- * styled tier masks with, which is also what lets a partial one be a clip of the
25016
- * whole rather than a second drawing of it.
24442
+ * places to press. The pointer handling and `step` are built around that
24443
+ * rather than added over it.
25017
24444
  *
25018
- * The properties below are written by this component and read by whoever draws
25019
- * it. A consumer sets none of them: they carry a number this element computed
25020
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
25021
- * without measuring anything itself.
24445
+ * **A partial mark is the whole mark, clipped**, not a second glyph filled to
24446
+ * the middle: the fill is the same marks over the same marks, cut off partway,
24447
+ * so any mark works and any fraction does.
24448
+ *
24449
+ * **Read-only is not this control grayed out.** The commoner use is showing a
24450
+ * score nobody is being asked for, which is a reading rather than a disabled
24451
+ * input, and it is announced as one.
25022
24452
  *
25023
24453
  * ## Attributes & Properties
25024
24454
  *
@@ -25547,45 +24977,22 @@ export type CustomElements = {
25547
24977
 
25548
24978
  /**
25549
24979
  * A real `<input type="range">`, so the drag, the arrow keys, Home and End, the
25550
- * page keys and the touch target are all the platform's. Every one of those is
25551
- * a thing a hand-built slider gets wrong, and the last is the one nobody
24980
+ * page keys and the touch target are the platform's. The last is the one nobody
25552
24981
  * notices: a native range has a hit area larger than its thumb, sized by the
25553
24982
  * platform for a finger.
25554
24983
  *
25555
24984
  * **The value is a string, like every other form control's.** A range submits
25556
24985
  * text and `MixinControllerValue` holds text, so the number is a reading of the
25557
- * value rather than the value itself. `valueAsNumber` is there for anything
25558
- * doing arithmetic on it.
25559
- *
25560
- * **Marks are drawn rather than left to `<datalist>`.** A datalist's ticks
25561
- * cannot be styled at all, and Firefox does not render them for a range at all,
25562
- * so the platform's version is a mark that looks like someone else's design
25563
- * where it appears and no mark where it does not. Drawing them costs the
25564
- * semantics nothing, because a mark is decoration: what a reader can actually
25565
- * land on is `step`, which the input enforces whether or not anything is drawn.
25566
- *
25567
- * `markers` is a count rather than a flag tied to `step`. A flag reads well
25568
- * until a slider from zero to a hundred stepping by one asks for a hundred and
25569
- * one ticks, and then it is either noise or a silent refusal to draw. A number
25570
- * is what the reader sees, so it cannot surprise anyone.
25571
- *
25572
- * **A range is two of them, not a hand-built one.** There is no native
25573
- * two-thumb range, so two are stacked on one track and each thumb keeps its own
25574
- * drag, its own arrow keys, its own Home and End and its own finger-sized hit
25575
- * area. Rebuilding would throw away every argument this component is made of,
25576
- * to gain a second handle.
25577
- *
25578
- * Crossing is stopped in the handler rather than by the bounds, and that is not
25579
- * the obvious way round. Giving the lower input `max` of the upper reads well
25580
- * and breaks the drawing: an input's thumb sits at a fraction of *its own*
25581
- * range, so a lower thumb bounded at the upper one paints against a shorter
25582
- * track and the two stop lining up. Both inputs span the whole range and the
25583
- * values are clamped against each other on the way in.
24986
+ * value. `valueAsNumber` is there for arithmetic.
25584
24987
  *
25585
- * The properties below are written by this component and read by whoever draws
25586
- * it. A consumer sets none of them: they carry a number this element computed
25587
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
25588
- * without measuring anything itself.
24988
+ * **Marks are drawn rather than left to `<datalist>`**, whose ticks cannot be
24989
+ * styled and which Firefox does not render for a range at all. A mark is
24990
+ * decoration; what a reader can land on is `step`, which the input enforces
24991
+ * whether or not anything is drawn. `markers` is a count rather than a flag, so
24992
+ * a slider from zero to a hundred cannot silently ask for a hundred and one.
24993
+ *
24994
+ * **A range is two of them.** There is no native two-thumb range, so two are
24995
+ * stacked on one track and each thumb keeps its own.
25589
24996
  *
25590
24997
  * ## Attributes & Properties
25591
24998
  *
@@ -26095,101 +25502,33 @@ export type CustomElements = {
26095
25502
  >;
26096
25503
 
26097
25504
  /**
26098
- * **One axis, and nesting is how you get two.** The sandbox this was taken from
26099
- * moves a cross: a divider down the middle, another across the bottom, and a
26100
- * corner that moves both. That is a layout rather than a component, and every
26101
- * part of it that is worth sharing is one divider between two panes. A splitter
26102
- * inside a splitter gives the cross back, and gives the three-pane and the
26103
- * four-pane arrangements it never had.
25505
+ * **One axis, and nesting is how you get two.** A splitter inside a splitter
25506
+ * gives back the cross, and gives the three-pane and four-pane arrangements a
25507
+ * single divider never had.
26104
25508
  *
26105
25509
  * **Where two of them cross there is a corner, and it moves both.** A splitter
26106
- * slotted into a pane of another, at right angles to it, has one end of its
26107
- * divider sitting exactly on the other's. That end grows a handle: `move` under
26108
- * the pointer, both arrow axes on the keyboard, and a drag that carries the two
26109
- * positions at once.
26110
- *
26111
- * **The outer splitter draws it and the nested one announces itself upward.**
26112
- * The nested one drawing its own is the tempting version, since it already
26113
- * knows where its divider begins and needs no measurement of the other, and it
26114
- * is clipped: the crossing lies on the boundary between a pane and the divider
26115
- * beside it, a handle centered there reaches back over the boundary, and a pane
26116
- * is `overflow: auto`. Exactly half the corner is cut off. The outer separator
26117
- * is the one element that already straddles the seam, so the corner belongs in
26118
- * it.
25510
+ * slotted into a pane of another, at right angles to it, grows a handle at the
25511
+ * crossing: `move` under the pointer, both arrow axes on the keyboard, and a
25512
+ * drag that carries the two positions at once. It appears at `firstUpdated`
25513
+ * rather than in the served markup, being an affordance rather than content,
25514
+ * and a splitter with no corner yet is a splitter with two working dividers.
26119
25515
  *
26120
- * That makes the channel between the two a single call in a single direction:
26121
- * `cross(child, at)` says where the child crosses, `moveTo` drives either one,
26122
- * and neither reads the other's state. The child is what calls it, because a
26123
- * parent cannot poll for a child that has not upgraded yet.
26124
- *
26125
- * The one number it carries is a percentage rather than a measurement, which is
26126
- * what keeps either of them from measuring the other, and it assumes the nested
26127
- * splitter fills its pane. That is what slotting one into a pane does. Give the
26128
- * nested splitter its own inset, or wrap it in something smaller than the pane,
26129
- * and the corner is drawn where the crossing would be rather than where it is.
26130
- *
26131
- * **It is a client-side enhancement and says so.** Finding the parent means
26132
- * inspecting the tree, which a server cannot do, so the corner appears at
26133
- * `firstUpdated` and never in the served markup. That is allowed for exactly
26134
- * this: it is an affordance rather than content, and a splitter with no corner
26135
- * yet is a splitter with two working dividers.
26136
- *
26137
- * Where two dividers are parallel there is no corner, because there is nothing
26138
- * to take hold of. Where they cross without a corner, the inner divider takes
26139
- * the pointer: every separator sits on the same layer, so a tie goes to document
26140
- * order and a deeper splitter is always later.
26141
- *
26142
- * **A divider that is moving says so, whoever is moving it.** `:hover` cannot
26143
- * carry that: a drag holds the pointer through capture and a fast one leaves the
26144
- * target behind, and a corner moves the nested divider while the reader is on
26145
- * the crossing, nowhere near it. So a drag in progress is a state, and both
26146
- * dividers a corner moves are lit for as long as it moves them.
26147
- *
26148
- * **The divider is a real `role="separator"` with `aria-valuenow`, moved by the
26149
- * arrow keys as well as by pointer.** A divider only a mouse can move is
26150
- * unusable without one, which is the reason the sandbox's carries the same, and
26151
- * `Home` and `End` take it to its bounds.
25516
+ * **The divider is a real `role="separator"` with `aria-valuenow`**, moved by
25517
+ * the arrow keys as well as by pointer, with `Home` and `End` taking it to its
25518
+ * bounds. A drag in progress is a state rather than `:hover`, so both dividers
25519
+ * a corner moves are lit for as long as it moves them.
26152
25520
  *
26153
25521
  * **It goes where it is put, all the way to either end.** `min` and `max` are
26154
25522
  * nothing and everything unless a consumer says otherwise, because a divider
26155
- * that stops dead short of the edge gives a reader no way to put a pane away.
26156
- * Where a pane should keep a sliver of itself, only whoever put the tabs on it
26157
- * knows how much, so they say so.
25523
+ * that stops short of the edge gives a reader no way to put a pane away.
26158
25524
  *
26159
25525
  * **A pane can be shut, and that is not the same as a divider at the edge.**
26160
25526
  * The geometry is identical and the knowledge is not: only a shut pane knows
26161
25527
  * where to open back to. So `collapsed` is a second state rather than a reading
26162
- * of the position, and the position it opens to is simply the one collapsing
26163
- * never overwrote. `collapsed-size` keeps a sliver showing where a pane has a
26164
- * tab strip worth leaving, and collapse overrides `min` and `max`, which is
26165
- * what those are for: they keep a pane from vanishing by accident, and this is
26166
- * the deliberate version.
26167
- *
26168
- * The two are kept in step in one direction only: a drag that settles on the
26169
- * collapsed size latches shut, and any move opens it again. Otherwise a reader
26170
- * could drag a pane closed and the consumer's own button would still be
26171
- * offering to close it.
26172
- *
26173
- * A pane shut to nothing is told apart from one shut to a sliver, because the
26174
- * two want different dividers: a sliver still has a boundary worth drawing, and
26175
- * nothing leaves the divider sitting on the container's own edge.
26176
- *
26177
- * **The box is measured once, when a drag starts.** Measuring per move is a
26178
- * forced layout on every pointer event, in the middle of a gesture whose whole
26179
- * job is to stay ahead of the pointer, and nothing about the box moves while the
26180
- * divider does.
26181
- *
26182
- * **`helix-before-resize` fires when it settles, not while it moves.** A drag is a
26183
- * stream of positions and only the one it ends at is a preference; announcing
26184
- * each would ask a consumer to write to storage a hundred times to record one
26185
- * decision. Nothing is stored here either: where a preference lives, and whether
26186
- * it should be kept at all, is the consumer's to decide, and a component writing
26187
- * to storage on its own would be deciding for all of them under a key it chose.
26188
- *
26189
- * The properties below are written by this component and read by whoever draws
26190
- * it. A consumer sets none of them: they carry a number this element computed
26191
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
26192
- * without measuring anything itself.
25528
+ * of the position, and the position it opens to is the one collapsing never
25529
+ * overwrote. `collapsed-size` keeps a sliver showing where a pane has a tab
25530
+ * strip worth leaving, and collapse overrides `min` and `max`, which is what
25531
+ * those are for.
26193
25532
  *
26194
25533
  * ## Attributes & Properties
26195
25534
  *
@@ -26447,34 +25786,16 @@ export type CustomElements = {
26447
25786
  >;
26448
25787
 
26449
25788
  /**
26450
- * **`active` names where the reader is. `complete` stays on each step.** They
26451
- * are two different facts and only one of them is positional. Deriving both
26452
- * from a position is the obvious design and it is wrong the first time anybody
26453
- * steps back: return to stage one of three and stages one and two are still
26454
- * finished, while "everything before the active one" says only the first is.
26455
- * So this element drives `current` and never touches `complete`.
25789
+ * **`active` names where the reader is. `complete` stays on each step.** Only
25790
+ * one of them is positional: return to stage one of three and stages one and
25791
+ * two are still finished, where "everything before the active one" says only
25792
+ * the first is. So this element drives `current` and never touches `complete`.
26456
25793
  *
26457
25794
  * **`active` is optional, and a sequence without it still renders.** Left
26458
- * unset, each step's own `current` stands and nothing here overwrites it, which
26459
- * is what lets the whole sequence be right in the server's markup: this element
26460
- * would have to count its slotted children to know which one is third, and the
26461
- * server has no children to count. Set it, and it wins, because it is a
26462
- * statement about the sequence where the attribute on a step is a statement
26463
- * about one step.
26464
- *
26465
- * That is also why the numbering is not JavaScript. It is a CSS counter in the
26466
- * tier above, which the browser resolves at layout with no script at all, so
26467
- * the third step reads "3" in the server's own markup.
26468
- *
26469
- * **The connector belongs to the step, not to the list.** Each one draws the
26470
- * line that arrives at it and hides it when it is first, the same arrangement
26471
- * Breadcrumbs uses for its separator and for the same reason: a line drawn
26472
- * between items needs either an index or a parent that counts, and drawing it
26473
- * on the item needs neither.
26474
- *
26475
- * `role="list"` on the host rather than an `<ol>` in the shadow root. The steps
26476
- * are the consumer's elements in the light DOM, so an `<ol>` here would be a
26477
- * list whose items are somewhere else.
25795
+ * unset, each step's own `current` stands, which is what lets the whole
25796
+ * sequence be right in the server's markup: this element would have to count
25797
+ * its slotted children to know which is third, and the server has none to
25798
+ * count.
26478
25799
  *
26479
25800
  * ## Attributes & Properties
26480
25801
  *
@@ -26566,51 +25887,21 @@ export type CustomElements = {
26566
25887
  >;
26567
25888
 
26568
25889
  /**
26569
- * **The name is a button, and only the name.** A stepper is something a reader
26570
- * goes back through, and the thing they reach for is the name of the stage. The
26571
- * marker is `aria-hidden` decoration, so wrapping it in the button would add
26572
- * hit area and no meaning: the accessible name would be the text either way,
26573
- * and what is pressable would stop being the same shape as what is readable.
26574
- *
26575
- * It is `helix-button`, not a `<button>` this element resets and dresses: the
26576
- * hover wash, the focus ring and the disabled treatment are decisions the
26577
- * button already carries. `ghost` is the quiet shape, transparent until it is
26578
- * pointed at.
26579
- *
26580
- * It says nothing about where a reader may go. Every step is pressable and
25890
+ * **The name is a button, and only the name.** The marker is `aria-hidden`
25891
+ * decoration, so wrapping it would add hit area and no meaning. It is
25892
+ * `helix-button` rather than a `<button>` this element resets: the hover wash,
25893
+ * the focus ring and the disabled treatment are decisions the button carries.
25894
+ *
25895
+ * **It says nothing about where a reader may go.** Every step is pressable and
26581
25896
  * announces itself with `helix-select`; refusing the ones ahead is `disabled`,
26582
- * which the consumer sets because only the consumer knows whether a form can be
26583
- * skipped. A component that guessed would be wrong on the first wizard that
26584
- * lets you jump to the end.
25897
+ * which the consumer sets, because only they know whether a form can be
25898
+ * skipped.
26585
25899
  *
26586
25900
  * **The marker is a slot whose fallback is the state.** A finished stage shows
26587
- * a check, the current one a target, and one not yet reached an empty ring:
26588
- * three marks that say what a reader wants to know without a legend. A consumer
26589
- * who wants their own fills the slot instead.
26590
- *
26591
- * The step renders exactly one of the three, chosen from its own two booleans.
26592
- * Rendering all three and hiding two in CSS would work and is worse: the
26593
- * accessibility tree would carry marks that are not there, and the markup would
26594
- * say three things about a stage that is one.
26595
- *
26596
- * Numbering belongs to the tier above. `numeric` hides the mark and shows a CSS
26597
- * counter, which the browser resolves at layout, so the digit costs no script
26598
- * and is right in the server's markup however the steps are ordered. Nothing
26599
- * here knows which appearance is in use.
26600
- *
26601
- * **`complete` and `current` are separate, and both can be false.** A stage
26602
- * that is neither is one the reader has not reached, which is the majority of
26603
- * any sequence and therefore the state that needs no attribute. They can also
26604
- * both be true: a reader who steps back into a finished stage is in it and has
26605
- * finished it, and a stepper that forgets the second is one that loses its
26606
- * checks the moment somebody reviews their answers.
26607
- *
26608
- * **The `content` slot opens on the current step, and only down a column.** A
26609
- * row has no room under a step to put a form in, and stretching one to fit
26610
- * would set every step's height by the tallest. `current` is what opens it, so
26611
- * the state that says where the reader is is also the state that shows them the
26612
- * stage: one attribute, no second flag to keep in step with it, and it renders
26613
- * open on the server rather than after hydration.
25901
+ * a check, the current one a target, one not yet reached an empty ring. Exactly
25902
+ * one is rendered, chosen from the step's own two booleans, rather than three
25903
+ * with two hidden in CSS: the accessibility tree would otherwise carry marks
25904
+ * that are not there.
26614
25905
  *
26615
25906
  * ## Attributes & Properties
26616
25907
  *
@@ -28344,40 +27635,16 @@ export type CustomElements = {
28344
27635
 
28345
27636
  /**
28346
27637
  * An element rather than a slot, because it carries a timeout, a tone, a
28347
- * dismiss control and a lifetime that pauses: behavior, state and API, which
28348
- * is the test for whether a region becomes an element in this library.
27638
+ * dismiss control and a lifetime that pauses: behavior, state and API.
28349
27639
  *
28350
27640
  * **The timer is the item's own.** Held by the region, one message arriving
28351
27641
  * would restart another's, so a stack of three would go from three seconds each
28352
- * to nine for the last one. Each message is on its own clock from the moment it
28353
- * is rendered.
28354
- *
28355
- * **A message is the opposite of the page it is over.** Inverted by default,
28356
- * because a thing arriving in a corner has to be told apart from the page in
28357
- * the moment before it is read, and inverting does that without spending a
28358
- * color that means something. It is a flip of `color-scheme` rather than a
28359
- * named inverse surface: every token in the subtree re-resolves, so a `Retry`
28360
- * a consumer slots in comes out right without knowing where it is. `Tooltip`
28361
- * can name the inverse surface directly because it holds no controls; this
28362
- * cannot. Set `data-color-mode` on the region to take the page's mode instead.
28363
- *
28364
- * **No duration means it stays.** That is the safe default rather than the
28365
- * common one: anything carrying an action has to still be there when the reader
28366
- * decides to take it, and a component cannot tell from the outside whether the
28367
- * message it was given is disposable.
28368
- *
28369
- * **The clock stops while it is being read.** Hover pauses it, and so does
28370
- * focus landing anywhere inside, which is the case that matters more: a
28371
- * keyboard reader tabbing towards the action in a toast is exactly the person a
28372
- * timer must not race. Both resume where they left off rather than starting
28373
- * again, so a message half-read does not get a full second life every time a
28374
- * pointer crosses it.
28375
- *
28376
- * **Going away is a request, never an act.** It dispatches a cancelable
28377
- * `helix-dismiss` and does nothing else: the consumer owns the list, so the
28378
- * item removing itself would leave the two disagreeing. Auto-dismiss and the
28379
- * dismiss control raise the same event, so a consumer handles one path and not
28380
- * two.
27642
+ * to nine for the last.
27643
+ *
27644
+ * **A message is the opposite of the page it is over.** Inverted by default, so
27645
+ * a thing arriving in a corner is told apart from the page before it is read,
27646
+ * and by a flip of `color-scheme` rather than by spending a color that means
27647
+ * something.
28381
27648
  *
28382
27649
  * ## Attributes & Properties
28383
27650
  *
@@ -28557,32 +27824,14 @@ export type CustomElements = {
28557
27824
 
28558
27825
  /**
28559
27826
  * The indicator is one element that travels, not a background that appears on
28560
- * whichever item is current. That difference is the whole point: a fill that
28561
- * swaps is two things changing at once and reads as a flicker, while one that
28562
- * moves is a single object the eye follows, and it says where the selection
28563
- * came from as well as where it went.
28564
- *
28565
- * Its whole box is measured from the selected item and written onto
28566
- * the indicator as custom properties, because labels are different lengths and
28567
- * no proportion of the group is the right answer. Measurement is client-side by
28568
- * necessity, so the server renders the indicator hidden and it fades in once it
28569
- * has somewhere to be, which is the harmless direction: it appears rather than
28570
- * jumping from a wrong place.
28571
- *
28572
- * A radio group, and only that. Navigation is links marked with `aria-current`
28573
- * and styled by the `data-navigation-item` recipe: radio semantics would announce a
28574
- * set of destinations as a set of choices. A tab controls a panel.
28575
- *
28576
- * Being a radio group, it is a form control, and it says so through
28577
- * `HelixFormElement`: it reports its value under a `name`, comes back to the
28578
- * markup's choice on reset, and restores the one a reader made when the browser
28579
- * brings a form back.
28580
- *
28581
- * The semantics were already right: the host has carried `role="radiogroup"`
28582
- * and the items `role="radio"` from the start. What none of it did was reach a
28583
- * form. A button in a shadow root submits nothing whatever its role, so the
28584
- * value has to be reported by the host, which is the only thing a form can
28585
- * see.
27827
+ * whichever item is current. A fill that swaps is two things changing at once
27828
+ * and reads as a flicker; one that moves is a single object the eye follows,
27829
+ * and it says where the selection came from as well as where it went.
27830
+ *
27831
+ * Its box is measured from the selected item and written onto the indicator as
27832
+ * custom properties, labels being different lengths. Measurement is client-side
27833
+ * by necessity, so the server renders the indicator hidden and it fades in once
27834
+ * it has somewhere to be, which is the harmless direction.
28586
27835
  *
28587
27836
  * ## Attributes & Properties
28588
27837
  *
@@ -28886,57 +28135,35 @@ export type CustomElements = {
28886
28135
  /**
28887
28136
  * The trigger is slotted and stays the consumer's own element. The bubble is
28888
28137
  * rendered here, in the top layer through the popover API, so it clears any
28889
- * ancestor with `overflow: hidden` without a `z-index` anywhere.
28138
+ * ancestor with `overflow: hidden` without a `z-index` anywhere. Position comes
28139
+ * from `FloatingController`, which flips to another side when the preferred one
28140
+ * does not fit.
28890
28141
  *
28891
- * Position comes from `FloatingController`, which flips to another side when
28892
- * the preferred one does not fit and slides along it to stay in view.
28893
- *
28894
- * **Two forms, and they are not equivalent for a screen reader.**
28895
- *
28896
- * Wrapping is the convenience form and is right where the bubble decorates a
28897
- * control that already says what it is. The trigger stays the consumer's own
28898
- * element, slotted, and nothing here can describe it: an IDREF cannot cross a
28899
- * shadow boundary, an element reference is valid only into the same tree or a
28900
- * shadow-including *ancestor* (the bubble's tree is neither, it is inward), and
28901
- * a string on the trigger means writing to markup the consumer server-rendered.
28902
- * All three measured.
28142
+ * **Two forms, and they are not equivalent for a screen reader.** Wrapping is
28143
+ * the convenience form and is right where the bubble decorates a control that
28144
+ * already says what it is: nothing here can describe a slotted trigger, an
28145
+ * IDREF being unable to cross a shadow boundary.
28903
28146
  *
28904
28147
  * `for` is the form that works. The tooltip sits *beside* the trigger in the
28905
- * consumer's own tree and names it by id, so both are in one tree and an IDREF
28906
- * between them is legal in the ordinary way:
28148
+ * consumer's own tree and names it by id, so an IDREF between them is legal in
28149
+ * the ordinary way:
28907
28150
  *
28908
28151
  * ```html
28909
28152
  * <helix-button id="save" aria-describedby="save-tip">Save</helix-button>
28910
28153
  * <helix-tooltip id="save-tip" for="save" content="Save your work"></helix-tooltip>
28911
28154
  * ```
28912
28155
  *
28913
- * Note that the reference points at *this host*, not at the bubble inside its
28914
- * shadow root: the description is computed from the flat tree, which descends
28915
- * into shadow content on its own.
28156
+ * The reference points at *this host*, not at the bubble in its shadow root:
28157
+ * the description is computed from the flat tree, which descends into shadow
28158
+ * content on its own.
28916
28159
  *
28917
28160
  * **The consumer writes that `aria-describedby`, and nothing here writes it for
28918
- * them.** WebAwesome and Spectrum Web Components both do write it, with
28919
- * `setAttribute` on the trigger at runtime, which is the one thing this library
28920
- * declines everywhere: React rendered that element on the server without the
28921
- * attribute and reports a mismatch it will not patch up. Two ids in the markup
28922
- * is the whole cost of the version that is correct before any JavaScript runs.
28923
- *
28924
- * Because it is the consumer's line to write, it is also theirs to forget, so
28925
- * `for` audits itself on first open and says so once, rather than on every
28926
- * open, since a warning that repeats is one people learn to filter out.
28161
+ * them.** Setting it at runtime is a hydration mismatch React will not patch
28162
+ * up. `for` audits itself on first open and warns once where it is missing.
28927
28163
  *
28928
28164
  * It shows on hover and on focus, and hides on leave, on blur, on Escape, and
28929
28165
  * once the trigger has been activated: the hint is spent when the control has
28930
28166
  * been used.
28931
- * A tooltip that answers only the pointer is one a keyboard reader never sees.
28932
- *
28933
- * The pointer waits out `delay` first, or sweeping a row of controls flashes a
28934
- * tooltip for each of them. Focus does not wait: a keyboard reader landing on a
28935
- * control has already committed to it.
28936
- *
28937
- * Open state comes from `MixinControllerOpen`, so it announces `helix-before-open` and
28938
- * `helix-before-close` like every other overlay here, and a consumer can drive it with
28939
- * `open` where they need to.
28940
28167
  *
28941
28168
  * ## Attributes & Properties
28942
28169
  *
@@ -29099,36 +28326,13 @@ export type CustomElements = {
29099
28326
  *
29100
28327
  * **The spotlight is a shadow, not a hole.** The scrim is a box the size of the
29101
28328
  * current target with an enormous spread on its `box-shadow`, so the darkness
29102
- * is what the shadow paints and the target is simply where the box is. A
29103
- * `clip-path` on a full-screen scrim is the other way to do it and is worse
29104
- * here: it needs the viewport in the same coordinate space as the cut, which
29105
- * stops being true the moment anything between them is transformed.
29106
- *
29107
- * **It measures, and this is a case where measuring is the only option.** The
29108
- * target is an element somewhere else on the page whose position nothing can
29109
- * know statically. That is different from a trail folding by width, where the
29110
- * design rule was expressible and the measurement was answering a question
29111
- * nobody had asked. Here the question is "where is that button", and there is
29112
- * no other way to ask it.
29113
- *
29114
- * **Nothing is measured on the server and nothing needs to be.** A tour starts
29115
- * closed and a closed tour draws nothing, so the server renders the stops as
29116
- * inert markup and the first frame is correct. This is also what makes it
29117
- * acceptable for the root to write `current` onto stops it does not own: there
29118
- * is no server state for the write to disagree with.
29119
- *
29120
- * **It cannot point inside a modal, and nothing can fix that here.**
29121
- * `showModal()` makes everything outside the dialog's own subtree inert, so a
29122
- * panel anywhere else is unpressable however the top layer is ordered: this is
29123
- * what modal means rather than a stacking accident. Measured with a modal
29124
- * `Drawer` open, `elementsFromPoint` over the tour's own Done button returned
29125
- * the drawer, the press light-dismissed the drawer, and the tour heard nothing
29126
- * at all. Anything a tour points into has to stay reachable, which for `Drawer`
29127
- * and `Dialog` means not modal while the tour is running.
29128
- *
29129
- * **Focus is not trapped.** A reader has to be able to look at, and reach, the
29130
- * thing being pointed at. `Escape` leaves, which is the one binding a tour
29131
- * needs and the one every reader already tries.
28329
+ * is what the shadow paints. A `clip-path` on a full-screen scrim needs the
28330
+ * viewport in the same coordinate space as the cut, which stops being true the
28331
+ * moment anything between them is transformed.
28332
+ *
28333
+ * **It measures, and the target is an element elsewhere on the page whose
28334
+ * position nothing can know statically.** Nothing is measured on the server and
28335
+ * nothing needs to be: a tour starts when a reader asks for it.
29132
28336
  *
29133
28337
  * ## Attributes & Properties
29134
28338
  *
@@ -29312,45 +28516,23 @@ export type CustomElements = {
29312
28516
  >;
29313
28517
 
29314
28518
  /**
29315
- * **`open`, on `MixinControllerOpen`, rather than a bare boolean of its own.** A
29316
- * branch showing its children is the same state a disclosure holds, and
29317
- * `AccordionItem` is on that mixin too. A hand-written toggle announces nothing,
29318
- * so a consumer can neither know a branch opened nor own the state.
29319
- * `aria-expanded` is still what the row renders, because that is the attribute a
29320
- * tree uses; the property is what differs, not the semantics.
28519
+ * **`open`, on `MixinControllerOpen`, rather than a bare boolean of its own.**
28520
+ * A branch showing its children is the same state a disclosure holds. A
28521
+ * hand-written toggle announces nothing, so a consumer could neither know a
28522
+ * branch opened nor own the state. `aria-expanded` is still what the row
28523
+ * renders: the property differs, not the semantics.
29321
28524
  *
29322
- * An element rather than a slot because it owns state: whether it is open,
29323
- * whether it is selected, and whether it is the one holding focus.
28525
+ * An element rather than a slot, because it owns state: whether it is open,
28526
+ * selected, and whether it holds focus.
29324
28527
  *
29325
28528
  * A branch is any item with something slotted into `children`, detected in
29326
- * `firstUpdated` rather than declared by the consumer. That is a client-side
29327
- * enhancement by necessity, since the server cannot inspect children, so the
29328
- * server renders the node as a leaf and the twisty appears on hydration. It
29329
- * appears rather than disappearing, which is the harmless direction.
29330
- *
29331
- * **`href` makes the row itself the link.** A tree used as navigation is a list
29332
- * of links, and the row is what a reader presses: with the anchor slotted into
29333
- * the name instead, everything outside the words is dead, Enter does nothing,
29334
- * and there is no middle-click, no status bar and no open-in-new-tab. Given an
29335
- * `href` the row *is* an `<a>`, so the platform provides all of that and the
29336
- * keyboard needs no handler at all.
29337
- *
29338
- * It changes the shape of the ARIA, which is why it is a property and not the
29339
- * default. An anchor cannot contain the group, since the group holds more
29340
- * anchors and nesting them is invalid, so the row carries `treeitem` and the
29341
- * group becomes its sibling under a presentational wrapper. That is exactly the
29342
- * navigation flavor of the tree pattern, and the arrangement without an `href`
29343
- * stays as it was: `treeitem` containing `group`, which is what an `<li>`
29344
- * holding a `<ul>` is.
29345
- *
29346
- * A consumer whose framework owns routing slots its own link instead and leaves
29347
- * `href` unset. The row follows that one too, so the whole row works either
29348
- * way; what the anchor adds is what only a real anchor can give.
28529
+ * `firstUpdated` because the server cannot inspect children. The server renders
28530
+ * the node as a leaf and the twisty appears on hydration, which is the harmless
28531
+ * direction.
29349
28532
  *
29350
- * The properties below are written by this component and read by whoever draws
29351
- * it. A consumer sets none of them: they carry a number this element computed
29352
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
29353
- * without measuring anything itself.
28533
+ * **`href` makes the row itself the link.** With the anchor slotted into the
28534
+ * name instead, everything outside the words is dead: no Enter, no middle
28535
+ * click, no status bar. Given an `href` the row *is* an `<a>`.
29354
28536
  *
29355
28537
  * ## Attributes & Properties
29356
28538
  *
@@ -29745,35 +28927,13 @@ export type CustomElements = {
29745
28927
  /**
29746
28928
  * The entries again, reachable without leaving the picture. A playlist beside
29747
28929
  * the player is a list a reader scrolls to; the same list in the control bar is
29748
- * one they open over the video, which is what a full-screen player has and what
29749
- * a phone has room for.
28930
+ * one they open over the video.
29750
28931
  *
29751
28932
  * **It is placed by the consumer, not rendered by the playlist**, and that is
29752
- * forced rather than chosen. A shadow root cannot project into a sibling's
28933
+ * forced rather than chosen: a shadow root cannot project into a sibling's
29753
28934
  * light DOM, so nothing the playlist renders can land inside the player's
29754
28935
  * control bar. What can is an element the consumer writes there, which is what
29755
- * `Video`'s `controls` slot is for:
29756
- *
29757
- * ```html
29758
- * <helix-video-playlist>
29759
- * <helix-video slot="player" controls>
29760
- * <helix-video-playlist-menu slot="controls"></helix-video-playlist-menu>
29761
- * </helix-video>
29762
- * <helix-video-playlist-item value="one" src="/one.mp4">One</helix-video-playlist-item>
29763
- * </helix-video-playlist>
29764
- * ```
29765
- *
29766
- * So it finds its playlist upward rather than being handed one, and that chain
29767
- * crosses a shadow boundary in the ordinary arrangement, which is why it is
29768
- * `closestInstance` and not `closest`.
29769
- *
29770
- * **Choosing dispatches `helix-select`, the same event an entry dispatches.**
29771
- * It never writes `active` on the playlist, which looks like the shorter path
29772
- * and skips the cancelable request: an assignment applies the change with no
29773
- * `helix-before-activate` for anyone to refuse. Announcing is what an entry
29774
- * does, the playlist already listens for it, and a consumer refusing a
29775
- * selection gets `preventDefault()` on one event rather than two paths that
29776
- * behave differently.
28936
+ * `Video`'s `controls` slot is for.
29777
28937
  *
29778
28938
  * ## Attributes & Properties
29779
28939
  *
@@ -29944,57 +29104,29 @@ export type CustomElements = {
29944
29104
 
29945
29105
  /**
29946
29106
  * **The picture is a real `<video>`.** Decoding, buffering, captions, Picture
29947
- * in Picture, AirPlay and the codecs a device happens to have are all the
29948
- * platform's, and none of them can be had from anything else. What is replaced
29949
- * is the control bar, which is the one part of a video element that cannot be
29950
- * styled and looks different in every browser.
29107
+ * in Picture, AirPlay and whatever codecs a device has are the platform's. What
29108
+ * is replaced is the control bar, which is the one part that cannot be styled.
29951
29109
  *
29952
29110
  * **Every control is a real control.** The scrubber and the volume are
29953
- * `<input type="range">`, so a reader gets arrow keys, Home and End, the
29954
- * platform's own touch target and its screen reader announcement without this
29955
- * element implementing any of it. Drawing a div and listening for pointer moves
29956
- * is how a media player ends up unusable from a keyboard.
29111
+ * `<input type="range">`, so arrow keys, Home and End, the platform's touch
29112
+ * target and its screen reader announcement all come for free.
29957
29113
  *
29958
29114
  * **Native controls are the fallback, not the default.** Where a consumer sets
29959
- * `controls`, the browser's bar is used and this one is not drawn: two sets of
29960
- * controls over one video is worse than either alone, and a consumer who asked
29961
- * for the native bar has a reason.
29115
+ * `controls` the browser's bar is used and this one is not drawn, and the keys
29116
+ * below are not bound: two handlers on one press is a video that seeks twice.
29962
29117
  *
29963
29118
  * The keys are the ones every player uses: Space and `k` to play or pause, the
29964
- * arrows to seek and to change the volume, `m` to mute, `f` for fullscreen.
29965
- * They are bound on this element rather than on the document, because a video
29966
- * is not a palette: keys belong to it only while a reader is on it. Where
29967
- * `controls` is set they are not bound at all, since two handlers on one press
29968
- * is a video that seeks twice, and the focus stop goes with them.
29119
+ * arrows to seek and to change volume, `m` to mute, `f` for fullscreen. They
29120
+ * are bound on this element rather than on the document, because a video is not
29121
+ * a palette.
29969
29122
  *
29970
29123
  * **`<source>` and `<track>` are copied into the video, never slotted into it.**
29971
29124
  * A media element runs resource selection over its own child *nodes*, and a slot
29972
29125
  * is one node, so slotted sources reach it as nothing: no text tracks, no
29973
29126
  * current source, `readyState` zero. A video given sources that way does not
29974
- * merely lack captions, it does not play.
29975
- *
29976
- * They are copied rather than moved, because the consumer's light DOM is theirs
29977
- * and a framework that re-renders it would find its children gone. The copies
29978
- * are rebuilt whenever the slot changes and the video is asked to load again,
29979
- * which is what makes a `<track>` added later take effect.
29980
- *
29981
- * **The lock screen and a headset's buttons work, and one player owns them.**
29982
- * There is one `navigator.mediaSession` per page, so the rule is stated rather
29983
- * than left to render order: whichever player was started last owns it, which
29984
- * is what a reader means by "this one" when they press play on their
29985
- * headphones. The title comes from `label` and the artwork from `poster`.
29986
- *
29987
- * **`remote` sends the picture somewhere else.** The Remote Playback API is
29988
- * what Safari implements for AirPlay and Chrome for Cast, so one control covers
29989
- * both and the platform supplies the device list. It is offered only once
29990
- * something has answered `watchAvailability`: a button that opens an empty list
29991
- * is worse than no button, and a consumer who wants none can set
29992
- * `disableremoteplayback` on this element.
29993
- *
29994
- * The properties below are written by this component and read by whoever draws
29995
- * it. A consumer sets none of them: they carry a number this element computed
29996
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
29997
- * without measuring anything itself.
29127
+ * merely lack captions, it does not play. They are copied rather than moved,
29128
+ * because the consumer's light DOM is theirs, and rebuilt whenever the slot
29129
+ * changes.
29998
29130
  *
29999
29131
  * ## Attributes & Properties
30000
29132
  *
@@ -30252,54 +29384,15 @@ export type CustomElements = {
30252
29384
  * `<template>` child says what one row looks like: elements carrying
30253
29385
  * `data-field="name"` are filled with that field of the item.
30254
29386
  *
30255
- * Both halves are markup, and that is the whole reason for the shape.
30256
- * `VirtualizeController` says why the obvious alternatives are shut: an `items`
29387
+ * Both halves are markup, and that is the reason for the shape. An `items`
30257
29388
  * property cannot survive React hydration, which skips every property it would
30258
29389
  * have to apply imperatively, and light-DOM children exist by the time anything
30259
- * could decide not to create them. Text in the document is neither. A server
30260
- * emits it, React re-emits it as a child rather than applying it, and it is one
30261
- * node whatever the row count.
29390
+ * could decide not to create them. Text in the document is neither, and it is
29391
+ * one node whatever the row count.
30262
29392
  *
30263
29393
  * **The accessible version is not a `<table>`**, the way it is for the charts
30264
29394
  * that share this `for="<id>"` shape: ten thousand rows in one is the cost this
30265
- * exists to avoid. It is the rendered window plus `aria-setsize` and
30266
- * `aria-posinset`, which is what says "four thousand of ten thousand" rather
30267
- * than "four of twenty".
30268
- *
30269
- * **Rows are light DOM, deliberately.** They are cloned from the consumer's
30270
- * template and appended to the host, so a document rule reaches them, the base
30271
- * layer applies, and a class in the template means what it says. Cloned into
30272
- * the shadow root they would be markup the consumer wrote and could not style,
30273
- * which is the one thing a row template must not be.
30274
- *
30275
- * **Reading the source is client-only**, because a server has no document to
30276
- * query. The window renders empty from the server and fills on the first update,
30277
- * which is the same client-side enhancement rule every tree-reading component
30278
- * here follows.
30279
- *
30280
- * **On this tier the consumer gives the viewport its box**, and the component
30281
- * cannot do it for them: `helix/headless` ships no stylesheet, and a height is a
30282
- * decision rather than a fact this could publish. So a base list wants two rules
30283
- * before it is a list at all:
30284
- *
30285
- * ```css
30286
- * helix-headless-virtual-list::part(viewport) {
30287
- * block-size: 12rem;
30288
- * overflow-y: auto;
30289
- * }
30290
- * ```
30291
- *
30292
- * **Without them it is not a scroller**, and the failure is worse than it
30293
- * sounds. `scrollTop` is always zero, so nothing ever windows; and the box has
30294
- * no height of its own, so `clientHeight` is a function of the rows just drawn.
30295
- * Measuring then moves what is being measured, and the two need not converge:
30296
- * measured in Chromium at 500 rows, it settled into a two-cycle between 378 and
30297
- * 379 rows and stayed there, at two and a half thousand passes in eight seconds.
30298
- * `VirtualizeController` gives up after ten passes and says so, so this now
30299
- * draws a bad window rather than stopping the page, but a bad window is still
30300
- * the answer until the rules are written.
30301
- *
30302
- * The styled tier writes them for you, with `--virtual-list-block-size`.
29395
+ * exists to avoid. It is the rendered window plus `aria-setsize`.
30303
29396
  *
30304
29397
  * ## Attributes & Properties
30305
29398
  *
@@ -30623,37 +29716,17 @@ export type CustomElementsSolidJs = {
30623
29716
 
30624
29717
  /**
30625
29718
  * Tracks whether the page has scrolled and carries it as the custom state
30626
- * `scrolled`, so the styled tier can lift the bar off the page without a scroll
30627
- * handler of its own. Scroll position is the one piece of state the server
30628
- * genuinely cannot know, so it is read on connect rather than derived: a fresh
30629
- * load starts at the top, which is what the server rendered, and a reload
30630
- * part-way down corrects on hydration.
29719
+ * `scrolled`, so the styled tier can lift the bar without a scroll handler of
29720
+ * its own. It is read on connect rather than derived: a fresh load starts at
29721
+ * the top, which is what the server rendered, and a reload part-way down
29722
+ * corrects on hydration.
30631
29723
  *
30632
29724
  * **A custom state and never `data-scrolled`.** An attribute the element writes
30633
29725
  * onto its own host is one the server did not send, so a hydrating framework
30634
- * reports the tree as mismatched, intermittently: only when the reader reloads
30635
- * far enough down the page to pass the threshold. A consumer can answer that
30636
- * only by suppressing hydration warnings on an element they did not write.
30637
- * `ElementInternals.states` is deliberately not in the DOM, so there is nothing
30638
- * for a hydration pass to disagree with, and `:state(scrolled)` selects it. The
30639
- * base class made the same move for `data-settled` and its note explains the
30640
- * rest.
30641
- *
30642
- * The listener is passive and reads `scrollY` only, so it never blocks
30643
- * scrolling.
30644
- *
30645
- * Three regions, each in its own wrapper, because the row is a grid and a grid
30646
- * needs three items to put the middle one in the middle. A bare slot is
30647
- * `display: contents`, so its assigned elements become grid items themselves:
30648
- * two actions would take two tracks and push the navigation off center. These
30649
- * wrappers earn their boxes, which is the test; they carry no inset or fill of
30650
- * their own, so an empty one still paints nothing.
30651
- *
30652
- * The host is the banner and spans the viewport; the row inside it is what gets
30653
- * centered. A banner that is itself narrowed leaves its background stopping
30654
- * short of the window edges, which reads as a floating bar rather than as the
30655
- * top of the page. That needs one element and one row, not a wrapper as well:
30656
- * the host carries the material and `content` carries the measure.
29726
+ * reports a mismatch, intermittently: only when the reader reloads far enough
29727
+ * down the page. `ElementInternals.states` is not in the DOM, so there is
29728
+ * nothing for a hydration pass to disagree with, and `:state(scrolled)` selects
29729
+ * it.
30657
29730
  *
30658
29731
  * ## Attributes & Properties
30659
29732
  *
@@ -30723,40 +29796,15 @@ export type CustomElementsSolidJs = {
30723
29796
 
30724
29797
  /**
30725
29798
  * A part of `Avatar` rather than a family of its own: it arranges avatars and
30726
- * is about nothing else, and its member is a complete `Avatar` the group did
30727
- * not have to explain.
29799
+ * is about nothing else.
30728
29800
  *
30729
29801
  * **The overflow count is the group's, not a slot.** Which avatars are hidden
30730
- * is a fact the group works out from `max` and how many it was given, so a
30731
- * consumer writing the "+3" themselves would be writing a number that has to
30732
- * agree with a list they do not control.
29802
+ * is a fact the group works out from `max`, so a consumer writing the "+3"
29803
+ * would be writing a number that has to agree with a list they do not control.
30733
29804
  *
30734
- * **Hidden, not removed.** Past `max`, the extra avatars stay in the DOM and
29805
+ * **Hidden, not removed.** Past `max` the extra avatars stay in the DOM and
30735
29806
  * stop being shown, so nothing re-renders when `max` changes and the accessible
30736
- * name can still be built from all of them. The count is what a sighted reader
30737
- * gets; the group's own name is what everyone else gets, and "Seven people" is
30738
- * more useful than seven names read in a row.
30739
- *
30740
- * **And hidden by the stylesheet, not by this class.** Hiding from `updated` is
30741
- * one update too late and one element too far out: Lit renders on a microtask,
30742
- * so an avatar appended past the limit is laid out and painted before anything
30743
- * runs to hide it, and marking each one means writing attributes onto markup a
30744
- * consumer owns. The styled tier's
30745
- * `:host([max="N"]) ::slotted(:nth-child(n + N+1))` is right at the first style
30746
- * resolution and writes nothing.
30747
- *
30748
- * **The fold is finite, and the count agrees with it.** `An+B` takes a literal,
30749
- * so there is one selector per value of `max` and the range stops at twelve.
30750
- * Past that the group shows everyone, counts nothing and says so, because
30751
- * showing everyone is a defensible answer and showing everyone beside a "+5" is
30752
- * not. `max` above twelve is a list the consumer should be slicing themselves.
30753
- *
30754
- * **It is a list.** A row of faces is a set of separate people, and a group
30755
- * with no role announces as one run of text. `role="list"` needs its children
30756
- * to be `listitem`, which they cannot be told to become without writing an
30757
- * attribute onto a consumer's element, so the group carries `role="group"` and
30758
- * its name instead: one announcement, correct, and nothing written to anyone
30759
- * else's markup.
29807
+ * name is still built from all of them.
30760
29808
  *
30761
29809
  * ## Attributes & Properties
30762
29810
  *
@@ -31299,37 +30347,18 @@ export type CustomElementsSolidJs = {
31299
30347
  >;
31300
30348
 
31301
30349
  /**
31302
- * The host is the landmark, so `aria-label` on it names the trail directly and
31303
- * there is no property mirroring one. A page may hold more than one navigation,
31304
- * and landmarks are how a screen-reader user chooses between them.
31305
- *
31306
- * `role="list"` is set explicitly on the `<ol>` even though it is already a
31307
- * list: removing the markers with `list-style: none` strips list semantics in
31308
- * Safari, and a breadcrumb trail always removes its markers.
31309
- *
31310
- * Items are slotted rather than wrapped, so they are `<ol>` children in the flat
31311
- * tree and each carries `role="listitem"` itself.
31312
- *
31313
- * **The trail does not measure itself, and the overflow is markup.** Measuring
31314
- * how many crumbs fit can never reach the server: there is no width without a
31315
- * DOM, so the server ships every crumb and the client removes some after
31316
- * hydrating, and a trail that collapses paints wrong on every single load. Nor
31317
- * does anybody specify a breadcrumb in units of fit. Designs say "keep the root
31318
- * and the current page, fold the middle", which is a fact about depth, or "fold
31319
- * below this width", which is a fact CSS knows.
31320
- *
31321
- * So the trail lays out crumbs and separators, and the consumer writes what
31322
- * folds: a `helix-menu` of `helix-menu-item`s in a crumb, where the gap
31323
- * belongs. Server rendered, no observer, no stylesheet, and correct before the
31324
- * first script runs. A trail that should fold only at some widths is a
31325
- * container query in the consumer's own sheet, which is theirs to write and
31326
- * theirs to leave out.
31327
- *
31328
- * **And the crumbs carry no marker for any of it.** CSS can already see it: the
31329
- * crumb with the menu in it is `:has(helix-menu)`, and the middle is
31330
- * `:not(:first-child, [current])`. A marker would be the design rule written
31331
- * twice, once in the HTML and once in the sheet, with nothing keeping the two
31332
- * honest.
30350
+ * The host is the landmark, so `aria-label` on it names the trail directly. A
30351
+ * page may hold more than one navigation, and landmarks are how a
30352
+ * screen-reader user chooses between them.
30353
+ *
30354
+ * `role="list"` is set explicitly on the `<ol>` even though it is one:
30355
+ * `list-style: none` strips list semantics in Safari, and a breadcrumb trail
30356
+ * always removes its markers.
30357
+ *
30358
+ * Items are slotted rather than wrapped, so they are `<ol>` children in the
30359
+ * flat tree and each carries `role="listitem"` itself.
30360
+ *
30361
+ * **The trail does not measure itself, and the overflow is markup.**
31333
30362
  *
31334
30363
  * ## Attributes & Properties
31335
30364
  *
@@ -32146,35 +31175,16 @@ export type CustomElementsSolidJs = {
32146
31175
 
32147
31176
  /**
32148
31177
  * **It has no opinion about where it sits.** A chat is asked for as a floating
32149
- * button, a page, a palette, a sidebar, a modal and an inline block, and none of
32150
- * those is a variant of a conversation: they are containers a conversation is
32151
- * put in, and the containers already exist. `Popover` and `SpeedDial` make the
32152
- * floating one, `Drawer` the sidebar, `Dialog` the modal, `Command` the palette,
32153
- * and a page is a page. Nothing here is positioned, nothing here has a backdrop,
32154
- * and nothing here owns a trigger, because a trigger opens a container and
32155
- * containers own their own. If a form factor needs a mode on this element, the
32156
- * split is wrong.
32157
- *
32158
- * **Scroll ownership is the behavior everything else depends on, and it is the
32159
- * most-got-wrong thing in the category.** A transcript that grows wants to stay
32160
- * at the bottom, except when the reader has scrolled up to read, where pinning
32161
- * is hostile. The rule: pin while the reader is within `threshold` of the
32162
- * bottom, release the moment they leave it, and offer a way back. **Never scroll
32163
- * a reader who is reading.**
32164
- *
32165
- * The element owns it, because it is the only party that knows a message arrived
32166
- * and where the viewport was when it did. `pinned` announces before it moves, so
32167
- * a consumer who wants to own it refuses the request and assigns their own.
32168
- *
32169
- * **The live region announces on completion, not on arrival.** The transcript is
32170
- * `role="log"` with `aria-live="polite"`, and a streaming message carries
32171
- * `aria-busy` while it arrives: a screen reader reading a stream token by token
32172
- * is unusable, and holding the announcement until the flag clears is the only
32173
- * arrangement that works. Somebody typing is a separate status region, so it
32174
- * never interleaves with what was said.
32175
- *
32176
- * **Not a client.** No transport, no protocol, no model. It renders a
32177
- * conversation and reports what the reader did.
31178
+ * button, a page, a palette, a sidebar, a modal and an inline block, and none
31179
+ * of those is a variant of a conversation: they are containers, and the
31180
+ * containers already exist. Nothing here is positioned, nothing has a backdrop,
31181
+ * and nothing owns a trigger. If a form factor needs a mode on this element,
31182
+ * the split is wrong.
31183
+ *
31184
+ * **Scroll ownership is the behavior everything else depends on.** A transcript
31185
+ * that grows wants to stay at the bottom, except when the reader has scrolled
31186
+ * up to read, where pinning is hostile. The rule: pin while the reader is
31187
+ * within `threshold` of the bottom, and let go the moment they leave it.
32178
31188
  *
32179
31189
  * ## Attributes & Properties
32180
31190
  *
@@ -33019,38 +32029,20 @@ export type CustomElementsSolidJs = {
33019
32029
  >;
33020
32030
 
33021
32031
  /**
33022
- * **The picker itself, with no field around it.** Color Input is this element in
33023
- * a panel behind a text field, the same way Date Input is `helix-date-picker` in a
33024
- * panel: a form wants a field, and a settings pane or a toolbar wants the picker
33025
- * sitting flat on the page with nothing to open. Neither should be the other one
33026
- * with parts hidden.
33027
- *
33028
- * **The square is two real range inputs.** Saturation and brightness are each an
33029
- * `<input type="range">`, laid over the square and made invisible, and the
33030
- * handle is drawn from their values. The pointer gets the square; the keyboard
33031
- * gets the arrow keys, Home, End and the page keys; a screen reader gets two
33032
- * sliders that announce a name and a number. All of it is the platform's, and
33033
- * nothing here implements a key handler. There is no `role="application"`, which
33034
- * is the usual way this control is built and amounts to asking a screen reader
33035
- * to stop helping.
32032
+ * **The picker itself, with no field around it.** Color Input is this element
32033
+ * in a panel behind a text field; a settings pane or a toolbar wants the picker
32034
+ * flat on the page with nothing to open.
32035
+ *
32036
+ * **The square is two real range inputs.** Saturation and brightness are each
32037
+ * an `<input type="range">`, laid over the square and made invisible, and the
32038
+ * handle is drawn from their values. The keyboard, the announcements and the
32039
+ * touch targets are the platform's, and there is no `role="application"`.
33036
32040
  *
33037
32041
  * **The working model is HSB, and the value is derived from it.** The reverse
33038
32042
  * loses colors: black is `brightness: 0`, whose hue and saturation are both
33039
- * undefined, so a reader who drags to the bottom of the square and back would
33040
- * get gray where they had red. Holding the model means a color survives a trip
33041
- * through one that has no hue. A value arriving from outside is read into the
33042
- * model once, which is the only moment the conversion runs in that direction.
33043
- *
33044
- * **Every syntax is read; the one `format` names is written.** `#f00`,
33045
- * `#ff0000`, `rgb(255 0 0)`, `rgba(255,0,0,.5)` and `hsl(0 100% 50%)` are all
33046
- * colors. Named colors are the exception, and deliberately: resolving
33047
- * `rebeccapurple` means shipping a table of a hundred and forty or asking the
33048
- * browser, and there is no browser during a server render.
33049
- *
33050
- * The properties below are written by this component and read by whoever draws
33051
- * it. A consumer sets none of them: they carry a number this element computed
33052
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
33053
- * without measuring anything itself.
32043
+ * undefined, so dragging to the bottom of the square and back would give gray
32044
+ * where there had been red. A value arriving from outside is read into the
32045
+ * model once.
33054
32046
  *
33055
32047
  * ## Attributes & Properties
33056
32048
  *
@@ -33266,73 +32258,31 @@ export type CustomElementsSolidJs = {
33266
32258
  >;
33267
32259
 
33268
32260
  /**
33269
- * **The list is `helix-listbox`, and the filtering is its own.** It already
33270
- * owns narrowing, the empty state, the highlight, `aria-activedescendant` and
33271
- * scrolling an option into view. Rewriting them here would be a second copy to
33272
- * keep in step; what is left for this element is the field, the panel and the
33273
- * traffic between them.
33274
- *
33275
- * **The text and the value are two things.** What a reader types is a filter,
33276
- * not an answer: it narrows the list and is thrown away. The value is whichever
33277
- * option they then choose, and the field is rewritten to that option's words
33278
- * once they have. A combobox that treated the typing as the value would submit
33279
- * "jav" to a form, which is the mistake a plain input makes and the reason this
33280
- * component exists.
33281
- *
33282
- * That is also why the field is emptied of its filter on close rather than left
33283
- * holding it: a control reopened still narrowed by the last visit's search is a
33284
- * control whose second use starts from the first one's leftovers. Select
33285
- * records the same.
32261
+ * **The list is `helix-listbox`, and the filtering is its own.** It owns
32262
+ * narrowing, the empty state, the highlight, `aria-activedescendant` and
32263
+ * scrolling an option into view. What is left for this element is the field,
32264
+ * the panel and the traffic between them.
32265
+ *
32266
+ * **The text and the value are two things.** What a reader types is a filter:
32267
+ * it narrows the list and is thrown away. The value is whichever option they
32268
+ * then choose, and the field is rewritten to that option's words once they
32269
+ * have. The filter is cleared on close, so a reopened control does not start
32270
+ * from the last visit's leftovers.
33286
32271
  *
33287
32272
  * **Focus stays in the field, which is the whole of what a combobox is.** The
33288
- * arrows move the list without leaving the text, which is why the listbox has a
33289
- * public `navigate`: the moving, the wrapping, the skipping of disabled options
33290
- * and the seeding from the current value all stay in the one place that already
33291
- * does them.
33292
- *
33293
- * `role="combobox"` on the input rather than on a wrapper, because the thing
33294
- * the pattern describes is the text field, and `aria-controls` can name the
33295
- * listbox because both are in this shadow root. The active option cannot be
33296
- * named that way, being the consumer's light DOM, so it is linked by element
33297
- * reference for the reason Listbox records at length.
33298
- *
33299
- * **With `multiple`, the chosen options are tags in the field.** A field that
33300
- * says "Rust, Ruby, Go" is a sentence the reader has to parse to find out what
33301
- * is in it, and offers nothing to press to take one out: Select does that today
33302
- * and it is the weakest part of it. A tag apiece is one object per answer, each
33303
- * with its own remove control, which is what the reader already believes they
33304
- * are looking at.
33305
- *
33306
- * The panel stays open while more than one can be chosen, because a control
33307
- * that shut after each pick is one the reader has to reopen to keep using. The
33308
- * filter clears on each choice instead, so the next pick starts from the whole
33309
- * list rather than from the last search.
32273
+ * arrows move the list without leaving the text, through the listbox's public
32274
+ * `navigate`. `role="combobox"` is on the input rather than on a wrapper,
32275
+ * because the thing the pattern describes is the text field.
32276
+ *
32277
+ * **With `multiple`, the chosen options are tags in the field**, one object per
32278
+ * answer, each with its own remove control. The panel stays open while more
32279
+ * than one can be chosen and the filter clears on each choice, so the next pick
32280
+ * starts from the whole list.
33310
32281
  *
33311
32282
  * **`creatable` announces, and does not write.** The options are the consumer's
33312
32283
  * light DOM and nothing here puts an element into it: a component that grew the
33313
- * consumer's markup would be a component their framework re-renders over. What
33314
- * this does is offer a row saying what would be added, take the value when the
33315
- * reader presses it, and say so with `helix-create`. A consumer who has to
33316
- * validate first refuses the event and adds nothing.
33317
- *
33318
- * Which leaves a value naming no option, and that is what the words fall back
33319
- * to: for anything chosen the field shows the option's text if there is one and
33320
- * the value itself otherwise. No copy is stored, so a consumer who then adds a
33321
- * real option with that value has its words take over on the next render.
33322
- *
33323
- * **`suggest` finishes the word, and only ever forwards.** The field completes
33324
- * to the first option the typing begins, with the part the reader did not type
33325
- * selected, so the next character replaces it and Delete removes it. Applied on
33326
- * insertion alone: completing after a deletion would put back what the reader
33327
- * just took out, and a field that cannot be shortened is a field that cannot be
33328
- * corrected. Measured as the difference between `insertText` and the several
33329
- * `delete*` input types, which is what the platform already says about which
33330
- * happened.
33331
- *
33332
- * The filter stays what was typed rather than what was completed. Filtering on
33333
- * the completion would narrow the list to the one option it came from, so a
33334
- * reader typing "ru" would be shown "Rust" alone and never learn Ruby was
33335
- * there.
32284
+ * consumer's markup would be one their framework re-renders over. It offers the
32285
+ * row and fires the event; adding the option is the consumer's.
33336
32286
  *
33337
32287
  * ## Attributes & Properties
33338
32288
  *
@@ -33708,29 +32658,14 @@ export type CustomElementsSolidJs = {
33708
32658
  /**
33709
32659
  * **The confirmation is the component.** Writing to the clipboard is three
33710
32660
  * lines; what makes this worth an element is that the platform gives a reader
33711
- * no feedback at all. A press that copies and looks identical to a press that
33712
- * failed is a control nobody trusts, so they press it again, and the second
33713
- * press is indistinguishable from the first.
32661
+ * no feedback at all, so a press that copies looks identical to one that
32662
+ * failed.
33714
32663
  *
33715
32664
  * **Announced after the write, never before.** A clipboard write is a
33716
- * permission the browser may refuse, and it is refused for real reasons: an
33717
- * insecure origin, a document that is not focused, a user agent that requires a
33718
- * gesture this press did not qualify as. So the confirmation and the event both
33719
- * wait for the promise, and a refusal leaves the button exactly as it was.
33720
- * `HelixCopyEvent` is not cancelable for the same reason: by the time there is
33721
- * anything to say, it has already happened.
33722
- *
33723
- * **An icon button, extending IconButton.** Both of this button's faces are
33724
- * icons and it never carries a word, so it is the square control rather than a
33725
- * text button that happens to hold a glyph: it inherits the square box, and
33726
- * with it the rule that an icon-only control must be named. `label` is not
33727
- * optional here for the same reason it is not optional there, and the two
33728
- * faces make it sharper: the accessible name has to describe the press, not
33729
- * whichever picture is showing when a reader arrives.
33730
- *
33731
- * `data-copied`, not a reflected `copied`. State never reflects here: a
33732
- * serialized `copied` attribute would come back from a paste as a button
33733
- * claiming to have copied something it never held.
32665
+ * permission the browser may refuse, for real reasons: an insecure origin, a
32666
+ * document that is not focused, a gesture that did not qualify. The
32667
+ * confirmation and the event both wait for the promise, and a refusal leaves
32668
+ * the button exactly as it was.
33734
32669
  *
33735
32670
  * ## Attributes & Properties
33736
32671
  *
@@ -33945,10 +32880,9 @@ export type CustomElementsSolidJs = {
33945
32880
 
33946
32881
  /**
33947
32882
  * **The schema is markup and the data is a property.** Columns are declared as
33948
- * `helix-table-column` children, because a schema is small, declarative, and
33949
- * something a reader should be able to see in the HTML; rows are handed over as
33950
- * an array, because data is large and a table that draws ten thousand elements
33951
- * cannot window them.
32883
+ * `helix-table-column` children, because a schema is small and something a
32884
+ * reader should see in the HTML; rows are handed over as an array, because a
32885
+ * table that draws ten thousand elements cannot window them.
33952
32886
  *
33953
32887
  * ```html
33954
32888
  * <helix-data-table .rows=${rows} sort="name:asc" page-size="20">
@@ -33961,35 +32895,13 @@ export type CustomElementsSolidJs = {
33961
32895
  * twelve things a person wrote out.
33962
32896
  *
33963
32897
  * **Sort and filter apply to the whole set, never the page.** Sorting the drawn
33964
- * window is correct on the first screen and wrong on every other one, which is
33965
- * how it survives being looked at. The arithmetic lives in `order.ts` where
33966
- * nothing can see a window, and its spec asserts the composition rather than the
33967
- * three steps, because each step alone passes either way.
33968
- *
33969
- * **What it does not do, stated where a consumer will read it: the cell values
33970
- * do not server-render.** The headings do, because a column renders its own, and
33971
- * the row elements do, because their count comes from `rows`. Reading a cell
33972
- * needs the columns, and the columns are markup children that Lit SSR does not
33973
- * hand this element: `children` is undefined there. So a crawler and a reader on
33974
- * a slow connection see a table of the right shape with nothing in it, which is
33975
- * strictly less than `helix-table` serves for a table whose rows are markup.
33976
- *
33977
- * That is the cost of "the schema is markup and the data is a property". Use
33978
- * `helix-table` where the content has to be in the served HTML and the result is
33979
- * small enough to write out; use this where the result is large, and accept that
33980
- * the first paint is a shell. The obvious workaround, a `columns` property
33981
- * beside the markup columns, is deliberately not offered: it splits one source
33982
- * of truth for the columns into two that nothing checks against each other, and
33983
- * a table rendering one way on the server and another in the browser is that
33984
- * failure with a hydration mismatch on top.
33985
- *
33986
- * **Every axis is controlled or uncontrolled, and that is what makes a server
33987
- * mode fall out rather than be bolted on.** `sort`, `filter`, `page` and
33988
- * `page-size` each defer to the consumer when set and seed themselves from a
33989
- * `default-*` when not. A consumer who answers all four holds the data flow:
33990
- * they hear the reader's request, fetch, and hand back a new `rows` with a
33991
- * `total`. Retrofitting that inverts the flow and is a rewrite, so it is here
33992
- * from the start.
32898
+ * window is correct on the first screen and wrong on every other one.
32899
+ *
32900
+ * **The cell values do not server-render.** The headings do, and the row
32901
+ * elements do, but reading a cell needs the columns, and the columns are markup
32902
+ * children Lit SSR does not hand this element. So a crawler sees a table of the
32903
+ * right shape with nothing in it. That is the cost of the first paragraph: use
32904
+ * `helix-table` where the served HTML has to carry the values.
33993
32905
  *
33994
32906
  * ## Attributes & Properties
33995
32907
  *
@@ -34146,29 +33058,13 @@ export type CustomElementsSolidJs = {
34146
33058
  /**
34147
33059
  * **The calendar is `helix-date-picker`, not a second one written here.** It
34148
33060
  * already knows about months, ranges, disabled days, the first day of the week
34149
- * and every keyboard rule a grid owes a reader, and a picker that reimplemented
34150
- * a tenth of that would be a worse grid that also had to be maintained. This
34151
- * element is the field, the overlay, and the translation between them.
33061
+ * and every keyboard rule a grid owes a reader. This element is the field, the
33062
+ * overlay, and the translation between them.
34152
33063
  *
34153
- * **Typed as well as picked, and the typing is the reason it is not
33064
+ * **Typed as well as picked, and the typing is why it is not
34154
33065
  * `<input type="date">`.** The native control gives a free picker and a free
34155
- * locale and takes almost all styling with it, which is a fair trade until a
34156
- * product needs the calendar to match everything around it. What is kept from
34157
- * the native one is the part worth keeping: a real text field, so a reader who
34158
- * knows the date types it and never opens anything.
34159
- *
34160
- * **The value is `YYYY-MM-DD`, always.** That is what a form submits, what
34161
- * `min` and `max` compare against, and what the calendar speaks. What the field
34162
- * *shows* is the same string: a locale-formatted display would have to be parsed
34163
- * back on every keystroke, and half-typed input does not survive a round trip
34164
- * through a formatter. The same reasoning the sandbox records for its two
34165
- * syntaxes, which is that a document being edited must not be a rendering of
34166
- * something else.
34167
- *
34168
- * **Opening does not commit.** The calendar announces a date, this element takes
34169
- * it, and the overlay shuts, because a single date has nothing more to say. A
34170
- * consumer who owns `value` answers the announcement the way they answer any
34171
- * other control here.
33066
+ * locale and takes almost all styling with it. What is kept from it is the part
33067
+ * worth keeping: a real text field.
34172
33068
  *
34173
33069
  * ## Attributes & Properties
34174
33070
  *
@@ -34446,44 +33342,19 @@ export type CustomElementsSolidJs = {
34446
33342
 
34447
33343
  /**
34448
33344
  * A grid of days, per the APG date grid: the whole grid is one tab stop, arrows
34449
- * move by day and week, `PageUp` and `PageDown` move by month, and `Home` and
34450
- * `End` go to the ends of the week. Only the focused cell is in the tab
34451
- * sequence.
34452
- *
34453
- * Roving `tabindex` is written on the cells, which is free here because they
34454
- * are rendered into this shadow root rather than being markup a consumer wrote.
34455
- *
34456
- * Dates are `YYYY-MM-DD` strings and every calculation is in UTC. A local-time
34457
- * `Date` shifts across a timezone or a daylight-saving boundary, so the string
34458
- * is what the component holds and the arithmetic never leaves UTC.
34459
- *
34460
- * `month` is what the grid shows, separately from `value`, so paging through
34461
- * months does not select anything and a consumer can drive the view. Left
34462
- * unset, it follows the first selected date, and then the current month.
33345
+ * move by day and week, `PageUp` and `PageDown` by month, `Home` and `End` to
33346
+ * the ends of the week. Only the focused cell is in the tab sequence.
34463
33347
  *
34464
- * `mode` decides how many dates are held. Absent takes one. `range` takes two
34465
- * and marks everything between them, starting over on the third click rather
34466
- * than replacing an end at random. `multiple` toggles, so clicking a chosen
34467
- * date takes it out. All three read and write the same comma-separated
34468
- * `value`.
33348
+ * **Dates are `YYYY-MM-DD` strings and every calculation is in UTC.** A
33349
+ * local-time `Date` shifts across a timezone or a daylight-saving boundary.
34469
33350
  *
34470
- * `locale` is worth setting where the output is compared across environments.
34471
- * Left unset, month and day names come from the runtime's own locale, and a
34472
- * server and a browser need not agree on what that is.
33351
+ * `month` is what the grid shows, separately from `value`, so paging does not
33352
+ * select anything and a consumer can drive the view. Left unset it follows the
33353
+ * first selected date, then the current month.
34473
33354
  *
34474
- * A control whose value changes dispatches `helix-before-change`:
34475
- * `Input`, `Select`, `Listbox`, `Radio.Group` and `Toggle.Group` all do, and a
34476
- * calendar submitting a date is the same kind of thing. `helix-select` stays
34477
- * what it is elsewhere, which is a row or an item being chosen in something
34478
- * that reports no value at all, such as `Menu` or `Tree`.
34479
- *
34480
- * Paging is `helix-navigate` and not either of those, because it chooses
34481
- * nothing: the view moves and the answer does not.
34482
- *
34483
- * The properties below are written by this component and read by whoever draws
34484
- * it. A consumer sets none of them: they carry a number this element computed
34485
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
34486
- * without measuring anything itself.
33355
+ * `mode` decides how many dates are held: absent takes one, `range` takes two
33356
+ * and marks everything between them, `multiple` toggles. All three read and
33357
+ * write the same comma-separated `value`.
34487
33358
  *
34488
33359
  * ## Attributes & Properties
34489
33360
  *
@@ -34700,37 +33571,15 @@ export type CustomElementsSolidJs = {
34700
33571
  /**
34701
33572
  * A real `<dialog>` opened with `showModal()`, not a div with a role and a
34702
33573
  * hand-built trap. The platform gives four things that are each a day's work to
34703
- * reimplement and easy to get subtly wrong: the top layer, so the dialog is
34704
- * above everything regardless of what `z-index` anyone else wrote; a real
34705
- * backdrop; Escape; and inert-behind, so the page underneath is not reachable
34706
- * by pointer, keyboard, or a screen reader's virtual cursor.
33574
+ * reimplement: the top layer, so the dialog is above everything whatever
33575
+ * `z-index` anyone wrote; a real backdrop; Escape; and inert-behind, so the
33576
+ * page underneath is unreachable by pointer, keyboard or virtual cursor.
34707
33577
  *
34708
33578
  * **`open` drives `showModal()`, and every way it can close comes back through
34709
- * `requestOpen`.** A native dialog can close from three directions: the
34710
- * property, Escape, and a `<form method="dialog">` submit inside it. Left
34711
- * alone, two of those would shut the dialog while the consumer's state still
34712
- * said open, which is the bug that makes a modal impossible to reopen. Escape
34713
- * is intercepted and routed through the request, so `preventDefault()` on the
34714
- * `helix-before-close` refuses it; a close that happens anyway is reflected back.
34715
- *
34716
- * **Nothing here traps focus.** `showModal()` does it, and better: `inert` on
34717
- * the rest of the document is something no JavaScript trap can achieve.
34718
- * `FocusTrapController` stays for the surfaces that are not modal.
34719
- *
34720
- * The regions are bare slots rather than wrappers, for the reason the card's
34721
- * are: an unassigned `<slot>` is `display: contents` and generates no box, so a
34722
- * dialog with no footer has no empty band where one would be.
34723
- *
34724
- * Opened declaratively with the platform's invoker attributes:
34725
- *
34726
- * ```html
34727
- * <helix-button commandfor="confirm" command="--show">Delete…</helix-button>
34728
- * <helix-dialog id="confirm">…</helix-dialog>
34729
- * ```
34730
- *
34731
- * `--show`, `--close` and `--toggle`. Custom commands rather than the built-in
34732
- * `show-modal`, because those are defined against native elements and do
34733
- * nothing when pointed at a custom one.
33579
+ * `requestOpen`.** A native dialog closes from three directions: the property,
33580
+ * Escape, and a `<form method="dialog">` submit. Left alone, two of them would
33581
+ * shut the dialog while the consumer's state still said open, which is the bug
33582
+ * that makes a modal impossible to reopen.
34734
33583
  *
34735
33584
  * ## Attributes & Properties
34736
33585
  *
@@ -34923,32 +33772,12 @@ export type CustomElementsSolidJs = {
34923
33772
  * The chart with the narrowest honest use, so the component is narrow too.
34924
33773
  *
34925
33774
  * **It reads one column and treats the rows as the parts.** Every other chart
34926
- * here takes a column per series; a ring has one whole to divide, and a second
34927
- * ring inside the first is two charts sharing a picture in the most literal
34928
- * way. So the first column of numbers is the series and each row is a slice.
34929
- *
34930
- * **It refuses negative values rather than drawing them.** A share of a whole
34931
- * cannot be less than nothing, and an arc for a negative number either runs
34932
- * backwards over its neighbors or is silently dropped. Those rows are skipped
34933
- * and the total is of what is left, which is the only reading that stays true.
34934
- *
34935
- * **The shape is drawn with a dashed stroke, not with arc commands.** One
34936
- * `<circle>` per slice, its dash set to the slice's share of the circumference
34937
- * and its offset to where the slice begins. Arc paths need the sweep flag and a
34938
- * large-arc flag, both of which flip at values a reader never sees coming, and
34939
- * a slice of exactly one whole becomes a path with no length at all.
34940
- *
34941
- * **And it keeps its aspect ratio**, alone among the charts here. The others
34942
- * set `preserveAspectRatio="none"` so one drawing fills any box and rescue
34943
- * their strokes with `vector-effect`; that rescues strokes and not geometry, so
34944
- * a ring drawn the same way is an ellipse in anything but a square.
33775
+ * here takes a column per series; a ring has one whole to divide, so the first
33776
+ * column of numbers is the series and each row is a slice.
34945
33777
  *
34946
- * The table is the accessible representation and this drawing is `aria-hidden`.
34947
- *
34948
- * The properties below are written by this component and read by whoever draws
34949
- * it. A consumer sets none of them: they carry a number this element computed
34950
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
34951
- * without measuring anything itself.
33778
+ * **It refuses negative values rather than drawing them.** An arc for a
33779
+ * negative number either runs backwards over its neighbors or is silently
33780
+ * dropped. Those rows are skipped and the total is of what is left.
34952
33781
  *
34953
33782
  * ## Attributes & Properties
34954
33783
  *
@@ -35483,29 +34312,12 @@ export type CustomElementsSolidJs = {
35483
34312
  * replaced.** It is the only way to open a file picker: the dialog is a
35484
34313
  * privileged action a script cannot start on its own, and it opens for a click
35485
34314
  * on the input or on a `<label>` pointing at it. A component that draws its own
35486
- * button ends up calling `.click()` on a hidden input anyway, and then has two
35487
- * things a screen reader can find where there is one control.
35488
- *
35489
- * So the input stays, holds the label, the name, the validity and the focus,
35490
- * and the visible trigger is a `<label for>` rather than a button. A label is
35491
- * not focusable and does not need to be: the input is, and Enter and Space on it
35492
- * open the picker because that is what the platform does with a file input.
35493
- *
35494
- * **Dropping is why this is a component rather than an attribute.** A bare file
35495
- * input accepts a drop only on the input itself, which is invisible here, so the
35496
- * field is the drop target and it says when something is over it.
35497
- *
35498
- * **Files are not a value a consumer can hand back.** Every other control here
35499
- * takes the controlled and uncontrolled pair, and this one does not: a `FileList`
35500
- * cannot be constructed from markup, and browsers refuse a consumer writing
35501
- * `value` on a file input outright, because a page that could name a file could
35502
- * read it. So this element owns what was chosen, announces it, and offers
35503
- * `clear()` for the one change a consumer can legitimately ask for.
35504
- *
35505
- * **The list under it is the control's own, not decoration.** A file input with
35506
- * files chosen reports "3 files" and nothing else, which is unusable for
35507
- * checking that the right ones were picked. The names are rendered, and each
35508
- * carries the way to take it back out.
34315
+ * button calls `.click()` on a hidden input anyway, and then has two things a
34316
+ * screen reader can find where there is one control.
34317
+ *
34318
+ * So the input stays, holding the label, the name, the validity and the focus,
34319
+ * and the visible trigger is a `<label for>`. A label is not focusable and does
34320
+ * not need to be: the input is, and Enter and Space on it open the picker.
35509
34321
  *
35510
34322
  * ## Attributes & Properties
35511
34323
  *
@@ -35771,49 +34583,26 @@ export type CustomElementsSolidJs = {
35771
34583
  >;
35772
34584
 
35773
34585
  /**
35774
- * **One family covers both readings, and the split people expect does not
35775
- * exist.** The argument for two is that a contribution graph needs a continuous
35776
- * ramp where uptime needs a category. GitHub's contribution graph is five
35777
- * discrete levels rather than a gradient, so a cell that takes a tone covers
35778
- * both: `rows="1"` is a status strip, `rows="7"` is a contribution graph, and
35779
- * heatmap is the name of that.
34586
+ * **One family covers both readings.** `rows="1"` is a status strip, `rows="7"`
34587
+ * is a contribution graph, and a cell that takes a tone covers both: GitHub's
34588
+ * contribution graph is five discrete levels rather than a gradient.
35780
34589
  *
35781
34590
  * **What it cannot be is a bar chart with flat values**, and the data model is
35782
- * what closes that rather than taste: chart color is per *series* everywhere
35783
- * else here, `--chart-series-1` through `-15`, so ninety differently colored
35784
- * cells would be ninety series.
34591
+ * what closes that: chart color is per *series* everywhere else here, so ninety
34592
+ * differently colored cells would be ninety series.
35785
34593
  *
35786
- * The data is a real `<table>` named by `for`, the same convention every chart
35787
- * in this library uses, which also answers the accessibility question without
35788
- * inventing anything: **the table is the accessible representation**, it is
35789
- * already in the markup, and the drawing is a picture of it. Hide it with
35790
- * `data-hidden-visually` and the reading is still there for anyone who needs it.
34594
+ * **The data is a real `<table>` named by `for`**, the convention every chart
34595
+ * in this library uses, and it is the accessible representation. Hide it with
34596
+ * `data-hidden-visually` and the reading is still there.
35791
34597
  *
35792
34598
  * A cell takes its tone from its own `data-tone`, or from `thresholds` and
35793
- * `tones` bucketing its value. The first is what a status page wants and the
35794
- * second is what a contribution graph wants; the cell's own wins, so a page that
35795
- * already knows a day was degraded does not have to encode that as a number for
35796
- * this component to decode again.
34599
+ * `tones` bucketing its value. The cell's own wins, so a page that already
34600
+ * knows a day was degraded does not encode that as a number to be decoded.
35797
34601
  *
35798
34602
  * **A tone is a name this tier never resolves.** `tone="success"` writes
35799
- * `--heatmap-tone: var(--heatmap-tone-success)` onto the cell and stops there,
35800
- * so what a name is worth is the answering tier's to say: `helix/styled` points
35801
- * the semantic names at the theme's status colors and the numbered ones at a
35802
- * ramp, and a consumer on `headless` declares the same names as whatever they
35803
- * like. Reaching for `var(--helix-color-${tone})` here is the dependency the
35804
- * tiers exist to prevent, and it fails loudly rather than quietly: off-tier that
35805
- * property is not undefined, it is *invalid*, so
35806
- * `background-color: var(--heatmap-tone, …)` declines its own fallback and every
35807
- * cell comes out transparent, leaving a blank page under a row of footer text.
35808
- * `shared/chart/series.css` records the same fault in Bar Chart.
35809
- *
35810
- * **On a narrow container it draws fewer cells rather than thinner ones.**
35811
- * Ninety cells in 320 pixels is three and a half pixels each, which is a smear
35812
- * and not a strip. The cells it drops are the oldest, and it reflects `visible`
35813
- * and fires `helix-resize` when the number changes, because **a summary saying
35814
- * "99.2% over 90 days" above a strip drawing 45 of them is telling the reader
35815
- * something false about the picture in front of them** and nothing about the
35816
- * picture says so.
34603
+ * `--heatmap-tone: var(--heatmap-tone-success)` and stops, so what a name is
34604
+ * worth is the answering tier's to say. Reaching for `var(--helix-color-*)`
34605
+ * here is the dependency the tiers exist to prevent.
35817
34606
  *
35818
34607
  * ## Attributes & Properties
35819
34608
  *
@@ -36279,31 +35068,14 @@ export type CustomElementsSolidJs = {
36279
35068
 
36280
35069
  /**
36281
35070
  * **An element rather than a recipe, because of the part CSS cannot do.**
36282
- * Reserving the box is `aspect-ratio` and needs nothing from anybody; `Link` and
36283
- * the megamenu row are recipes in `preview.css` for exactly that reason. What
36284
- * cannot be written as a rule is *when the picture arrived*: a stylesheet has no
36285
- * way to know, and no way to hear that it never will. So this owns three states
36286
- * and the two events that move between them, and leaves the box to the
35071
+ * Reserving the box is `aspect-ratio` and needs nothing from anybody. What
35072
+ * cannot be written as a rule is *when the picture arrived*: a stylesheet has
35073
+ * no way to know, and no way to hear that it never will. So this owns three
35074
+ * states and the two events that move between them, and leaves the box to the
36287
35075
  * stylesheet.
36288
35076
  *
36289
35077
  * **The placeholder is a slot with nothing in it by default.** A default of
36290
- * `Skeleton` would be right and is not written here: this tier renders no other
36291
- * component, and reaching for one would make the headless package depend on the
36292
- * styled one. The styled tier draws the resting placeholder instead, and a
36293
- * consumer who wants a `Skeleton`, a blurred thumbnail or a solid color slots
36294
- * it.
36295
- *
36296
- * **No source is a loading state, not a fourth one.** A picture whose `src` has
36297
- * not arrived yet is the common case for anything drawn from data, and the
36298
- * useful answer there is the same as for one still on the wire: stand something
36299
- * in its place and keep the ground reserved. So an element with no `src` shows
36300
- * its placeholder and waits, rather than resolving to an empty box that has to
36301
- * be laid out twice.
36302
- *
36303
- * **`alt` is a property and not an afterthought.** An empty string is a real
36304
- * answer, meaning the picture is decoration and a screen reader should skip it,
36305
- * which is why the attribute is always written even when it is empty: omitting
36306
- * it entirely makes a reader announce the file name instead.
35078
+ * `Skeleton` would make this tier depend on a component it does not ship.
36307
35079
  *
36308
35080
  * ## Attributes & Properties
36309
35081
  *
@@ -36408,39 +35180,21 @@ export type CustomElementsSolidJs = {
36408
35180
 
36409
35181
  /**
36410
35182
  * Renders a real `<input>`, so the caret, selection, autofill, spellcheck, the
36411
- * password manager, and the on-screen keyboard a phone chooses all come from the
36412
- * platform. `delegatesFocus` puts focus on it, and it serializes into the
36413
- * server's markup, so the field is usable before any script loads.
35183
+ * password manager and the on-screen keyboard a phone chooses are all the
35184
+ * platform's. It serializes into the server's markup, so the field is usable
35185
+ * before any script loads.
36414
35186
  *
36415
- * **The input inside a shadow root submits nothing**, because the form is on the
35187
+ * **The input inside a shadow root submits nothing**, the form being on the
36416
35188
  * other side of the boundary. The host is form-associated instead and reports
36417
- * its own value through `ElementInternals`, which is also what carries validity
36418
- * and what answers a form reset.
35189
+ * its own value through `ElementInternals`, which also carries validity and
35190
+ * answers a form reset.
36419
35191
  *
36420
- * `value` and `defaultValue` are separate for the reason `checked` and
36421
- * `defaultChecked` are: `value` is what is in the field now and
36422
- * `defaultValue` is what the markup asked for, which is where a reset returns
36423
- * to and is gone the moment anyone types.
36424
- *
36425
- * **Validity is the platform's.** The `type` and `required` are set on the real
36426
- * input and its `validity` is copied onto the host, so an email field rejects
36427
- * what the browser says is not an email rather than what a regular expression
36428
- * here guesses. What this adds is the anchor, so `reportValidity` points the
36429
- * bubble at the input rather than at the host.
36430
- *
36431
- * `pattern`, `minlength` and `maxlength` are forwarded with them.
36432
- *
36433
- * **`clearable` and `reveal` are the field's, not the consumer's.** Neither is
36434
- * a slot's worth of variation: one empties the value, the other flips the type,
36435
- * and both want the same position, the same size and the same disabled
36436
- * behavior. The `end` slot stays for what actually varies, a unit or a prefix.
36437
- *
36438
- * Both opt in rather than following from `type`, and are booleans that default
36439
- * to false. A Lit boolean property that defaults to *true* cannot be turned off
36440
- * from HTML at all, only from script, which is the wrong way round for
36441
- * revealing a password: a consumer should have to ask for it. Drawer's `modal`
36442
- * defaults true for the opposite reason, that losing a focus trap by forgetting
36443
- * a word is worse than having to say so.
35192
+ * `value` and `defaultValue` are separate the way `checked` and
35193
+ * `defaultChecked` are: `value` is what is in the field now, `defaultValue` is
35194
+ * what the markup asked for and where a reset returns to.
35195
+ *
35196
+ * **Validity is the platform's.** `type` and `required` are set on the real
35197
+ * input and its `validity` is copied onto the host.
36444
35198
  *
36445
35199
  * ## Attributes & Properties
36446
35200
  *
@@ -36670,38 +35424,20 @@ export type CustomElementsSolidJs = {
36670
35424
 
36671
35425
  /**
36672
35426
  * Renders a real `<kbd>`, so the passage still means "press this" to anything
36673
- * reading the markup rather than only to a reader looking at it.
35427
+ * reading the markup.
36674
35428
  *
36675
- * **One key per element, with `keys` as the stated exception.** A *sequence* is
35429
+ * **One key per element, with `keys` as the stated exception.** A sequence is
36676
35430
  * several of these with the separator written between them as ordinary text,
36677
- * because that separator is prose: it is "then" in a sequence and "plus" in a
36678
- * simultaneous press, and a component that inserted one would have to guess
36679
- * which. `keys` cannot be guessing, since a chord written `mod+k` has said
36680
- * which it is.
35431
+ * because that separator is prose: "then" in a sequence, "plus" in a chord, and
35432
+ * a component inserting one would have to guess which.
36681
35433
  *
36682
35434
  * **`keys` exists because the glyphs were being typed by hand and were wrong.**
36683
35435
  * A literal `⌘K` in a template tells a reader on Windows to press a key their
36684
- * keyboard does not have, and nothing catches it, a string being a string.
36685
- * Given `mod` this renders `⌘K` on Apple and `Ctrl+K` everywhere else.
35436
+ * keyboard does not have, and nothing catches it. Given `mod` this renders
35437
+ * `⌘K` on Apple and `Ctrl+K` everywhere else.
36686
35438
  *
36687
- * **`within` is what binds it, and it is absent by default.** Without it this
36688
- * draws a key and listens for nothing, which is what every existing use of this
36689
- * component wants. The two values are the two honest lifetimes:
36690
- *
36691
- * - `control` listens within the element's own parent, which is the case this
36692
- * is mostly for: a hint sitting inside the control it belongs to, where the
36693
- * shortcut should work while that control has focus and stop existing when
36694
- * the control does.
36695
- * - `document` listens on the document, for a chord that works from anywhere.
36696
- *
36697
- * **A hidden `kbd` is a dead shortcut, and that is the point rather than a
36698
- * trap.** Binding here ties the key to its own advertisement, so a hint that is
36699
- * not rendered is a shortcut that is not offered. A chord that must outlive its
36700
- * label is a chord whose owner is not a label: give it to whatever owns the
36701
- * action and let this element only describe it.
36702
- *
36703
- * Nothing binds until this upgrades, so a shortcut is not available in the
36704
- * moments before hydration.
35439
+ * **`within` is what binds it, and it is absent by default**, so this draws a
35440
+ * key and listens for nothing unless asked.
36705
35441
  *
36706
35442
  * ## Attributes & Properties
36707
35443
  *
@@ -36767,32 +35503,14 @@ export type CustomElementsSolidJs = {
36767
35503
  /**
36768
35504
  * A legend is a list, so it is a list: not part of a chart, and shared by
36769
35505
  * whichever of them needs one. It takes its entries from the same table the
36770
- * chart reads, through `for`, so the two cannot disagree about how many series
36771
- * there are or what they are called.
36772
- *
36773
- * `entries` picks which way to read that table, and the two ways are the two
36774
- * shapes a chart comes in. `series` is one entry per data column, named by the
36775
- * header row, which is a line or a bar chart. `categories` is one entry per
36776
- * body row, named by its row header, which is a donut: its slices are the rows,
36777
- * and it has no axis to write their names along.
36778
- *
36779
- * **The table is resolved on the client and there is no server pass.** `for` is
36780
- * an id and resolving it wants a document, which the server render does not
36781
- * have, so a legend ships empty and fills in on hydration. The table itself is
36782
- * ordinary markup and is served whole, so nothing is missing from the page
36783
- * before then, only from this list.
36784
- *
36785
- * The table is watched, because a legend that goes stale when its data changes
36786
- * is a legend that has to be told, and nothing else in the page would know to
36787
- * tell it.
36788
- *
36789
- * **Not hidden from a screen reader, though the mapping it draws is a color
36790
- * one.** The argument for hiding it is real: the colors mean nothing to a
36791
- * reader who cannot see them, and the names are already in the table. It stays
36792
- * because the cost of being wrong runs one way. A duplicated list of three
36793
- * words is noise; a consumer who took the table out of the accessibility tree
36794
- * and then found the legend hidden too has a chart nobody can read, and neither
36795
- * decision announces itself.
35506
+ * chart reads, through `for`, so the two cannot disagree.
35507
+ *
35508
+ * `entries` picks which way to read that table. `series` is one entry per data
35509
+ * column, named by the header row, which is a line or a bar chart.
35510
+ * `categories` is one entry per body row, which is a donut: its slices are the
35511
+ * rows and it has no axis to write their names along.
35512
+ *
35513
+ * **The table is resolved on the client and there is no server pass.**
36796
35514
  *
36797
35515
  * ## Attributes & Properties
36798
35516
  *
@@ -37186,37 +35904,15 @@ export type CustomElementsSolidJs = {
37186
35904
  * **The listbox is the control and the options are its vocabulary.** A Select
37187
35905
  * is this with a trigger in front of it, a Combobox is this with a text input,
37188
35906
  * and a command palette is this again: they differ in what opens the list and
37189
- * what filters it, not in what the list is. Building it as its own family is
37190
- * what stops each of those reimplementing the keyboard and the filtering.
35907
+ * what filters it, not in what the list is.
37191
35908
  *
37192
35909
  * **`value` is comma separated when `multiple` is set**, the way
37193
35910
  * `Checkbox.Group`'s is. It stays a string because that is what a form submits
37194
- * and what `MixinControllerValue` holds; an array property would be a second
37195
- * shape for the same fact, and the two would disagree the first time one was
37196
- * set without the other.
35911
+ * and what `MixinControllerValue` holds.
37197
35912
  *
37198
35913
  * **Chosen and active are two different things.** Chosen is the answer; active
37199
- * is where the keyboard is. In a single-select list they move together, which
37200
- * is the radio group pattern and is what a reader expects from arrow keys. With
37201
- * `multiple` they come apart: the arrows move without choosing and Space
37202
- * chooses, because a reader passing over four options on the way to the fifth
37203
- * did not mean to pick all five.
37204
- *
37205
- * **This does not use `KeyboardNavigationController`, and the reason is where
37206
- * focus lives rather than whether moving chooses.** The controller already
37207
- * separates those, taking `origin: 'focus' | 'selection'`. What it cannot do is
37208
- * leave focus alone: `NavigableItem.focusItem()` moves DOM focus to the item,
37209
- * its model being a roving tab stop. A filterable list cannot have that, focus
37210
- * having to stay in the field or typing stops, so what moves is a virtual
37211
- * cursor and `aria-activedescendant` is what says where it is. No flag
37212
- * reconciles the two.
37213
- *
37214
- * **Filtering hides rather than removes.** An option the filter has hidden is
37215
- * still the consumer's element in the consumer's order, so a filter that clears
37216
- * puts the list back exactly as it was with nothing re-rendered. What counts as
37217
- * a match is a plain case-insensitive substring, and a consumer wanting more
37218
- * hides options itself: `filter` is a convenience over the same `hidden` the
37219
- * component uses.
35914
+ * is where the keyboard is. Only the second moves with the arrows, and
35915
+ * `aria-activedescendant` names it while focus stays on the list.
37220
35916
  *
37221
35917
  * ## Attributes & Properties
37222
35918
  *
@@ -37527,49 +36223,17 @@ export type CustomElementsSolidJs = {
37527
36223
  * **A disclosure, not a menu, and that is the whole design.** `role="menu"` and
37528
36224
  * `menuitem` are for an application's commands: they take over the arrow keys,
37529
36225
  * announce "menu" to a reader who asked for navigation, and put every link
37530
- * inside a role that is not a link. What this is, is a button that shows and
37531
- * hides a region of the consumer's own anchors, which is the pattern the APG
37532
- * gives for site navigation and the one that leaves a middle click, a modified
36226
+ * inside a role that is not a link. This is a button that shows and hides a
36227
+ * region of the consumer's own anchors, which leaves a middle click, a modified
37533
36228
  * click and the status bar working. `Menu` remains right for a row of commands.
37534
36229
  *
37535
- * **It renders no links**, for the reason `Navigation` gives: a router renders
37536
- * its own anchor and cannot render one inside this shadow root. The panel is a
37537
- * slot, and what goes in it is lists and headings the consumer wrote.
36230
+ * **It renders no links.** A router renders its own anchor and cannot render
36231
+ * one inside this shadow root, so the panel is a slot and what goes in it is
36232
+ * the lists and headings the consumer wrote.
37538
36233
  *
37539
36234
  * **It opens on hover, and a press is always the fallback.** `open-on` says
37540
- * which, and hover is the resting value because a nav bar is the one place a
37541
- * reader expects to sweep along a row and see each section: making them click,
37542
- * read, click again to compare two is the interaction hover exists to save.
37543
- *
37544
- * Hover is not the only way in, and the code is mostly about that. There is no
37545
- * hover on a touch screen, so a tap opens the panel there whatever `open-on`
37546
- * says, which is why the pointer type is checked rather than assumed. Focus
37547
- * still opens nothing, for the same reason a tab through a nav bar should not
37548
- * unfold it, but Enter on the trigger does, and a keyboard press arrives as a
37549
- * click with no pointer behind it.
37550
- *
37551
- * A mouse click on a trigger the pointer is already sitting on is the case
37552
- * worth naming: toggling there would close the panel and the pointer, still on
37553
- * the trigger, would open it again, so the trigger would flicker and never
37554
- * close. In hover mode the mouse's own clicks are left alone and hover governs
37555
- * on its own. Escape and a click away still close it.
37556
- *
37557
- * The delays are intent, not decoration. Opening waits, so a pointer crossing
37558
- * the bar on its way somewhere else opens nothing; closing waits longer, so the
37559
- * diagonal from the trigger down into the panel does not pass through a gap and
37560
- * shut it. Moving along a bar where a panel is already down opens the next one
37561
- * at once, because at that point the reader is reading the bar, not crossing it.
37562
- *
37563
- * **Focus is not trapped and not moved.** A disclosure leaves the reader on the
37564
- * trigger and the panel follows in the tab order, which is what the markup
37565
- * already says, so Tab walks into the links and out the far side without
37566
- * anything managing it. Escape closes and puts focus back, because Escape is
37567
- * the one key that has to return the reader to where they were.
37568
- *
37569
- * The custom property below is written by this component and read by whoever
37570
- * draws it. A consumer never sets it: it carries a number this element computed
37571
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
37572
- * without measuring anything itself.
36235
+ * which, and hover is the resting value because a nav bar is where a reader
36236
+ * expects to sweep along a row and see each section.
37573
36237
  *
37574
36238
  * ## Attributes & Properties
37575
36239
  *
@@ -37956,31 +36620,13 @@ export type CustomElementsSolidJs = {
37956
36620
  * **Not `Progress`, and the difference is the whole component.** A progress bar
37957
36621
  * reports how far along a task is: it starts empty, ends full, and full is
37958
36622
  * always the good end. A meter reports a level in a range that is not going
37959
- * anywhere, and which end is good is a fact about the thing being measured.
37960
- * Disk usage, a battery, a score, a rate limit. So there is no `indeterminate`
37961
- * here: a measurement whose value is unknown is not a measurement.
37962
- *
37963
- * **`low`, `high` and `optimum` are the reason it exists**, and they follow the
37964
- * HTML specification's own rule. The three thresholds cut the range into a low
37965
- * band, a middle and a high band, and `optimum` says which of the three is the
37966
- * one to be in. The band the value falls in is then the good one, the one next
37967
- * to it is fair, and the one two away is poor.
37968
- *
37969
- * **Without thresholds there are no bands, and this is where it parts company
37970
- * with `<meter>`.** The platform defaults `optimum` to the midpoint and both
37971
- * thresholds to the ends, so a bare `<meter value="20" max="100">` computes as
37972
- * optimum and every browser paints it green. A gauge with nothing said about it
37973
- * is not good news; it is a reading. Declared thresholds turn the color on.
37974
- *
37975
- * **And the bands are drawn as well as colored.** A tick sits at `low` and at
37976
- * `high`, so the reading can be placed against them without seeing color at
37977
- * all, which is the same call the carousel's current dot makes by lengthening
37978
- * rather than only changing color.
36623
+ * anywhere, and which end is good is a fact about the thing measured. So there
36624
+ * is no `indeterminate`: a measurement whose value is unknown is not one.
37979
36625
  *
37980
- * The properties below are written by this component and read by whoever draws
37981
- * it. A consumer sets none of them: they carry a number this element computed
37982
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
37983
- * without measuring anything itself.
36626
+ * **`low`, `high` and `optimum` are the reason it exists**, following the HTML
36627
+ * specification's own rule. The three cut the range into a low band, a middle
36628
+ * and a high band, and `optimum` says which is the one to be in; the band next
36629
+ * to it is fair and the one two away is poor.
37984
36630
  *
37985
36631
  * ## Attributes & Properties
37986
36632
  *
@@ -38389,17 +37035,13 @@ export type CustomElementsSolidJs = {
38389
37035
  >;
38390
37036
 
38391
37037
  /**
38392
- * **A family rather than `Input`'s `type="number"`, and rather than a part of
38393
- * it.** `Input` already takes that type and will keep it: a bare numeric field
38394
- * in a form is a text field with a different keyboard, and that is all it needs
38395
- * to be. This is a different control. It renders two buttons, binds four keys
38396
- * that `Input` does not, and owns clamping and stepping, so it is an alternative
38397
- * and not a variant. Namespacing it under `Input` would say it is contained by
38398
- * one, which is what `IconButton` is top-level for.
37038
+ * **A family rather than `Input`'s `type="number"`.** It renders two buttons,
37039
+ * binds four keys `Input` does not, and owns clamping and stepping, so it is an
37040
+ * alternative and not a variant.
38399
37041
  *
38400
37042
  * **The field is `type="text"` with `inputmode="decimal"`, and that is a
38401
- * measurement rather than a preference.** Asked of a real browser, `type=number`
38402
- * fails three ways this control cannot live with:
37043
+ * measurement.** Asked of a real browser, `type=number` fails three ways this
37044
+ * control cannot live with:
38403
37045
  *
38404
37046
  * ```
38405
37047
  * typed "12e" into type=number → .value === ""
@@ -38408,21 +37050,16 @@ export type CustomElementsSolidJs = {
38408
37050
  * same keystrokes into type=text → .value === "12e"
38409
37051
  * ```
38410
37052
  *
38411
- * The first is fatal on its own: the element cannot see what the reader typed,
38412
- * so a controlled value is destroyed by a keystroke and there is nothing left to
38413
- * correct or to report. The second changes a value because a page scrolled past.
38414
- * The third means the caret cannot be managed at all, which any correcting or
38415
- * formatting field needs. `inputmode` is what keeps the phone keypad, which is
37053
+ * The first is fatal alone: the element cannot see what the reader typed. The
37054
+ * second changes a value because a page scrolled past. The third means the
37055
+ * caret cannot be managed at all. `inputmode` keeps the phone keypad, which is
38416
37056
  * the one thing `type=number` was giving.
38417
37057
  *
38418
37058
  * Validity is still the platform's, through `min`, `max` and `step` mirrored
38419
- * onto the host's own `setValidity`. What is not mirrored is the field's
38420
- * `type`, because a text field has no opinion about numbers.
37059
+ * onto the host's own `setValidity`.
38421
37060
  *
38422
- * **Stepping is separate from typing.** A reader mid-way through "1" of "12"
38423
- * has not asked for anything to be clamped, so the value is only pulled into
38424
- * range when they step, blur, or the form asks. Clamping on every keystroke is
38425
- * what makes a field that cannot be typed backwards into.
37061
+ * **Stepping is separate from typing**, so a reader mid-way through a number is
37062
+ * not corrected under their hands.
38426
37063
  *
38427
37064
  * ## Attributes & Properties
38428
37065
  *
@@ -38847,35 +37484,16 @@ export type CustomElementsSolidJs = {
38847
37484
 
38848
37485
  /**
38849
37486
  * A table of contents, named for the job. It sits beside `Navigation`, which is
38850
- * the same job at the other scale: one navigates a site, the other navigates a
38851
- * document. `Contents` and `TableOfContents` are both taken by something else,
38852
- * `display: contents` and the `content` part in one case and the `Table` family
38853
- * in the other.
38854
- *
38855
- * **The links are the consumer's own anchors**, the same as `Navigation`. A router
38856
- * renders its own `<a>` and cannot render one inside this shadow root, and the
38857
- * hrefs are fragments the page already knows.
38858
- *
38859
- * **What is current is decided by position, not by intersection.** The obvious
38860
- * build is an `IntersectionObserver` with a thin band near the top of the
38861
- * window, and it fails in both directions: with headings far apart nothing is
38862
- * in the band and the marker goes out entirely, and with headings close
38863
- * together several are and it flickers between them. So the observer is only
38864
- * the *trigger*, and the answer is computed from where the headings actually
38865
- * are: the current section is the last one whose top has passed the reading
38866
- * line, or the first heading before any of them has.
38867
- *
38868
- * That rule is what a reader means. Two headings on screen at once are not
38869
- * ambiguous to a person: they are reading under the upper one.
38870
- *
38871
- * **`aria-current="location"`, and it is written onto the consumer's anchor.**
38872
- * This library does not normally write to light-DOM children, because an
38873
- * attribute added after upgrade is one a server's markup never had. It is right
38874
- * here for the reason `Carousel` names its slides: what is current is derived
38875
- * from scroll position, so no server could have rendered it and there is
38876
- * nothing for hydration to disagree with. `location` rather than `page`, which
38877
- * is what `Navigation` uses: `page` means this is the page, and every one of these
38878
- * is the same page.
37487
+ * the same job at the other scale: one navigates a site, the other a document.
37488
+ *
37489
+ * **The links are the consumer's own anchors.** A router renders its own `<a>`
37490
+ * and cannot render one inside this shadow root, and the hrefs are fragments
37491
+ * the page already knows.
37492
+ *
37493
+ * **What is current is decided by position, not by intersection.** An
37494
+ * `IntersectionObserver` with a band near the top fails in both directions:
37495
+ * with headings far apart nothing is in the band and the marker goes out, and
37496
+ * with headings close together several are in it at once.
38879
37497
  *
38880
37498
  * ## Attributes & Properties
38881
37499
  *
@@ -38960,67 +37578,34 @@ export type CustomElementsSolidJs = {
38960
37578
  >;
38961
37579
 
38962
37580
  /**
38963
- * The component is the truncation. Given a page and a total it works out which
38964
- * numbers to show and where the runs break, which is the whole of what a
38965
- * consumer would otherwise write by hand and get subtly wrong; everything else
38966
- * here is markup around that. So this is data-driven rather than composed:
38967
- * `<helix-pagination page="4" pages="12">` rather than twelve slotted children
38968
- * a consumer has to keep in step with their own query.
37581
+ * **The component is the truncation.** Given a page and a total it works out
37582
+ * which numbers to show and where the runs break, so this is data-driven rather
37583
+ * than composed: `<helix-pagination page="4" pages="12">` rather than twelve
37584
+ * slotted children a consumer keeps in step with their own query.
38969
37585
  *
38970
37586
  * **The width does not change as you page.** The run around the current page is
38971
- * `siblings` either side normally, and grows to absorb a gap slot when it meets
38972
- * a boundary, so the control holds the same number of slots from the first page
38973
- * to the last. Every arrangement that lets the count vary makes the buttons move
38974
- * under the pointer between one click and the next.
37587
+ * `siblings` either side, and grows to absorb a gap slot at a boundary, so the
37588
+ * control holds the same number of slots from the first page to the last.
37589
+ * Anything that lets the count vary moves the buttons under the pointer between
37590
+ * one click and the next.
38975
37591
  *
38976
- * **A gap is only drawn where it hides more than one page.** An ellipsis
38977
- * standing in for a single number costs the same space as the number and tells
38978
- * the reader less.
38979
- *
38980
- * **And a gap is a control.** It goes to the middle of the run it stands over,
38981
- * which is the binary-search step: any page in a set of any size is a handful of
38982
- * presses, where a jump of a fixed size would need forty of them on a set of a
38983
- * hundred and twenty-eight. A menu listing the hidden pages was the other idea
38984
- * and the arithmetic refuses it, for the reasons on `renderGap`.
37592
+ * **A gap is only drawn where it hides more than one page, and a gap is a
37593
+ * control.** It goes to the middle of the run it stands over, which is the
37594
+ * binary-search step: any page in a set of any size is a handful of presses.
38985
37595
  *
38986
37596
  * **`href` is what makes these links.** Set it and every page renders an `<a>`
38987
- * with `{page}` filled in, so the server's output is crawlable, a middle click
38988
- * opens a tab, and the address bar is the state. Left unset they are buttons,
38989
- * which is right for a table paging in place. Either way the click announces
38990
- * `helix-navigate` first, and `preventDefault()` on it stops the navigation as
38991
- * well as the change: that is how a router takes over without the page reloading
38992
- * underneath it.
38993
- *
38994
- * **`helix-navigate` and not `helix-change`**, for the reason the calendar pages
38995
- * with it too. Moving to page four chooses nothing; it moves the view over a
38996
- * result that has not changed. A consumer driving the view has to be able to
38997
- * hear that without being told an answer changed.
38998
- *
38999
- * **The count and the page-size control are their own elements.** A slot can
39000
- * only offer one place: at one end of one row, in one order, on one axis.
39001
- * `Pagination.Summary` and `Pagination.Size` sit beside this one instead, so
39002
- * the direction and the order of a footer are the consumer's, which is what
39003
- * they were always going to want. `total` and `page-size` stay here for the
39004
- * arithmetic below and nothing else.
39005
- *
39006
- * **A single page renders nothing.** A control offering one page offers no
39007
- * navigation, and the row it sits in should close over it rather than hold a
39008
- * space for a thing that cannot be used. Reported through
39009
- * `ElementInternals.states` rather than an attribute on the host, because an
39010
- * attribute written at upgrade is markup a server's output never had and a
39011
- * framework reports the difference; a custom state carries the same fact to a
39012
- * stylesheet and none of that to the DOM.
39013
- *
39014
- * **And a page change is announced.** Moving the page moves `aria-current` onto
39015
- * a different element, which a screen reader does not announce, so a reader who
39016
- * pressed 5 hears the word "5" from the button they were on and nothing at all
39017
- * about having arrived. A polite live region says where they now are. It ships
39018
- * empty and is filled only on a change, because a region populated as it enters
39019
- * the document announces itself on arrival.
39020
- *
39021
- * `page` is what the element holds and `default-page` seeds it. A consumer
39022
- * paging through a router refuses `helix-navigate` and assigns their own, which
39023
- * is how they take the decision.
37597
+ * with `{page}` filled in, so the output is crawlable, a middle click opens a
37598
+ * tab, and the address bar is the state. Left unset they are buttons, which is
37599
+ * right for a table paging in place. Either way the click announces
37600
+ * `helix-navigate` first, and `preventDefault()` stops the navigation as well
37601
+ * as the change, which is how a router takes over.
37602
+ *
37603
+ * **`helix-navigate` and not `helix-change`.** Moving to page four chooses
37604
+ * nothing; it moves the view over a result that has not changed.
37605
+ *
37606
+ * **The count and the page-size control are their own elements.**
37607
+ * `Pagination.Summary` and `Pagination.Size` sit beside this one, because a
37608
+ * slot can only offer one place: at one end of one row, in one order.
39024
37609
  *
39025
37610
  * ## Attributes & Properties
39026
37611
  *
@@ -39260,39 +37845,18 @@ export type CustomElementsSolidJs = {
39260
37845
 
39261
37846
  /**
39262
37847
  * Its own element rather than a part of `Pagination`, so a consumer decides
39263
- * where it goes. Inside the run it could only ever be at one end of one row;
39264
- * beside it, it goes above, below, in a table's caption, or on the other side of
39265
- * the page, and the direction and order of the whole footer are the consumer's.
39266
- *
39267
- * **It repeats `page`, `page-size` and `total`, and the cost of that is skew
39268
- * rather than verbosity.** Those three come from the consumer's own query, so
39269
- * writing them on two elements is one variable used twice; what it risks is the
39270
- * two disagreeing, and a count reading `76-100 of 248` beside a run showing page
39271
- * 7 is the same failure this element's own clamping exists to prevent, arriving
39272
- * from the outside instead.
39273
- *
39274
- * **Nothing removes it at this level, and that was measured rather than
39275
- * assumed.** A coordinating root can only reach children the consumer laid out
39276
- * by writing attributes onto them, which a framework reports as a hydration
39277
- * error, or through context, which is dead on a server: `@lit/context`
39278
- * subscribes from `connectedCallback`, and Lit SSR does not call it, so every
39279
- * value is `undefined` in exactly the render this element exists to be part of.
39280
- * Confirmed against Lit SSR directly. The fork is real: children in the light
39281
- * DOM mean the consumer owns the layout and no root can feed them; children in a
39282
- * shadow root mean a root feeds them by ordinary binding and owns the layout.
39283
- *
39284
- * **It resolves one level up, at a composite, and the state is why.** `page`,
39285
- * `page-size` and `total` are facts about a *result*, not about a pagination, so
39286
- * the element that should hold them once is the one that holds the result: a
39287
- * data table composing a pagination inside itself, rather than a pagination root
39288
- * invented to hold three pagination elements together. That root would have been
39289
- * plumbing; a table's paging state is the thing itself. And because a composite
39290
- * renders its parts into its own shadow root, it lands on the side of the fork
39291
- * where binding works and the server renders, at no cost to anyone.
39292
- *
39293
- * Renders nothing without a `total` and a `page-size`. A wrong count is worse
39294
- * than none: it is the one number in a footer a reader cannot check against
39295
- * anything else on screen.
37848
+ * where it goes: above, below, in a table's caption, or on the other side of
37849
+ * the page. Inside the run it could only ever be at one end of one row.
37850
+ *
37851
+ * **It repeats `page`, `page-size` and `total`, and the cost of that is skew.**
37852
+ * Those three come from the consumer's own query, so writing them on two
37853
+ * elements is one variable used twice; what it risks is the two disagreeing.
37854
+ *
37855
+ * **Nothing removes that at this level, and it was measured.** A coordinating
37856
+ * root can only reach light-DOM children by writing attributes onto them, which
37857
+ * a framework reports as a hydration error, or through context, which is dead
37858
+ * on a server: `@lit/context` subscribes from `connectedCallback`, and Lit SSR
37859
+ * does not call it.
39296
37860
  *
39297
37861
  * ## Attributes & Properties
39298
37862
  *
@@ -39655,32 +38219,15 @@ export type CustomElementsSolidJs = {
39655
38219
 
39656
38220
  /**
39657
38221
  * Determinate by default, and `indeterminate` for a task whose total is not
39658
- * known yet. `Loader` is still the right answer where the wait is short or has
39659
- * no place of its own on the page; a bar earns its width where the work is the
39660
- * subject of the region it sits in.
38222
+ * known yet. `Loader` is still right where the wait is short or has no place of
38223
+ * its own on the page.
39661
38224
  *
39662
38225
  * A bar that fills at a made-up rate would be a bar that lies, so the
39663
38226
  * indeterminate one does not fill: it runs a segment across the track, which
39664
- * says work is happening and claims no proportion at all. `aria-valuenow` is
39665
- * omitted with it, which is the platform's own signal for the same thing.
38227
+ * says work is happening and claims no proportion. `aria-valuenow` is omitted
38228
+ * with it, which is the platform's own signal for the same thing.
39666
38229
  *
39667
38230
  * **The fill is a fraction of the track, written as a custom property.**
39668
- * `--progress-fraction` is derived from `value` and `max` rather than measured,
39669
- * so it renders on a server with no layout and needs nothing after upgrade. That
39670
- * is what keeps it out of the class of geometry this library writes only on the
39671
- * client. A consumer never sets it: it carries a number this element computed
39672
- * and CSS cannot, which is what lets a stylesheet draw the thing without
39673
- * measuring anything itself.
39674
- *
39675
- * **`value` is clamped, and out-of-range input is not an error.** A count that
39676
- * runs past its own total is ordinary in real applications, and a bar that
39677
- * overflows its track or reports `aria-valuenow` above `aria-valuemax` is worse
39678
- * than one that reads as finished.
39679
- *
39680
- * Semantics are on the host through `ElementInternals`, the same as everywhere
39681
- * else: a `role` in the shadow root announces correctly and leaves the host
39682
- * anonymous to anything walking the light DOM, and a `role` written onto the
39683
- * host as an attribute is one a server's markup never had.
39684
38231
  *
39685
38232
  * ## Attributes & Properties
39686
38233
  *
@@ -40186,39 +38733,16 @@ export type CustomElementsSolidJs = {
40186
38733
  /**
40187
38734
  * **Half marks decide the shape.** Supporting them means the value is not an
40188
38735
  * integer and the targets are not the marks: five stars at a half step is ten
40189
- * places to press, and a mark that is filled to the middle. The pointer handling
40190
- * and `step` are both built around that rather than added over it.
40191
- *
40192
- * **A partial mark is the whole mark, clipped.** Not a second glyph filled to
40193
- * the middle: that needs a matching pair drawn for every mark anybody uses, and
40194
- * the moment a consumer wants a heart or a circle they need to draw one too. The
40195
- * fill is the same marks over the same marks, cut off partway, so any mark works
40196
- * and any fraction does.
40197
- *
40198
- * **Read-only is not this control grayed out, it is a different thing.** The
40199
- * commoner use is showing a score nobody is being asked for, a product's
40200
- * average, and that is not a control at all: it takes no focus, answers no keys,
40201
- * has no options to choose between, and reads as one thing rather than as five.
40202
- * So `readonly` is `role="img"` with the score in its name, where the control is
40203
- * a radio group. A disabled control is still a control and still says so; this
40204
- * is not one.
40205
- *
40206
- * **Moving is choosing here**, which is the radio group's reading and the
40207
- * opposite of `Menu`'s: arriving at four stars *is* rating it four, because
40208
- * nothing else follows and there is nothing to confirm. That is what
40209
- * `KeyboardNavigationController` takes `selects` for, and why this can use it
40210
- * where a menu cannot.
40211
- *
40212
- * **The mark is a stylesheet's, not a slot's.** A slot projects its content
40213
- * once, and there are two layers of marks here: slotting a star would put it in
40214
- * the track or the fill and leave the other empty. So the mark is a shape the
40215
- * styled tier masks with, which is also what lets a partial one be a clip of the
40216
- * whole rather than a second drawing of it.
38736
+ * places to press. The pointer handling and `step` are built around that
38737
+ * rather than added over it.
40217
38738
  *
40218
- * The properties below are written by this component and read by whoever draws
40219
- * it. A consumer sets none of them: they carry a number this element computed
40220
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
40221
- * without measuring anything itself.
38739
+ * **A partial mark is the whole mark, clipped**, not a second glyph filled to
38740
+ * the middle: the fill is the same marks over the same marks, cut off partway,
38741
+ * so any mark works and any fraction does.
38742
+ *
38743
+ * **Read-only is not this control grayed out.** The commoner use is showing a
38744
+ * score nobody is being asked for, which is a reading rather than a disabled
38745
+ * input, and it is announced as one.
40222
38746
  *
40223
38747
  * ## Attributes & Properties
40224
38748
  *
@@ -40757,45 +39281,22 @@ export type CustomElementsSolidJs = {
40757
39281
 
40758
39282
  /**
40759
39283
  * A real `<input type="range">`, so the drag, the arrow keys, Home and End, the
40760
- * page keys and the touch target are all the platform's. Every one of those is
40761
- * a thing a hand-built slider gets wrong, and the last is the one nobody
39284
+ * page keys and the touch target are the platform's. The last is the one nobody
40762
39285
  * notices: a native range has a hit area larger than its thumb, sized by the
40763
39286
  * platform for a finger.
40764
39287
  *
40765
39288
  * **The value is a string, like every other form control's.** A range submits
40766
39289
  * text and `MixinControllerValue` holds text, so the number is a reading of the
40767
- * value rather than the value itself. `valueAsNumber` is there for anything
40768
- * doing arithmetic on it.
40769
- *
40770
- * **Marks are drawn rather than left to `<datalist>`.** A datalist's ticks
40771
- * cannot be styled at all, and Firefox does not render them for a range at all,
40772
- * so the platform's version is a mark that looks like someone else's design
40773
- * where it appears and no mark where it does not. Drawing them costs the
40774
- * semantics nothing, because a mark is decoration: what a reader can actually
40775
- * land on is `step`, which the input enforces whether or not anything is drawn.
40776
- *
40777
- * `markers` is a count rather than a flag tied to `step`. A flag reads well
40778
- * until a slider from zero to a hundred stepping by one asks for a hundred and
40779
- * one ticks, and then it is either noise or a silent refusal to draw. A number
40780
- * is what the reader sees, so it cannot surprise anyone.
40781
- *
40782
- * **A range is two of them, not a hand-built one.** There is no native
40783
- * two-thumb range, so two are stacked on one track and each thumb keeps its own
40784
- * drag, its own arrow keys, its own Home and End and its own finger-sized hit
40785
- * area. Rebuilding would throw away every argument this component is made of,
40786
- * to gain a second handle.
40787
- *
40788
- * Crossing is stopped in the handler rather than by the bounds, and that is not
40789
- * the obvious way round. Giving the lower input `max` of the upper reads well
40790
- * and breaks the drawing: an input's thumb sits at a fraction of *its own*
40791
- * range, so a lower thumb bounded at the upper one paints against a shorter
40792
- * track and the two stop lining up. Both inputs span the whole range and the
40793
- * values are clamped against each other on the way in.
39290
+ * value. `valueAsNumber` is there for arithmetic.
40794
39291
  *
40795
- * The properties below are written by this component and read by whoever draws
40796
- * it. A consumer sets none of them: they carry a number this element computed
40797
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
40798
- * without measuring anything itself.
39292
+ * **Marks are drawn rather than left to `<datalist>`**, whose ticks cannot be
39293
+ * styled and which Firefox does not render for a range at all. A mark is
39294
+ * decoration; what a reader can land on is `step`, which the input enforces
39295
+ * whether or not anything is drawn. `markers` is a count rather than a flag, so
39296
+ * a slider from zero to a hundred cannot silently ask for a hundred and one.
39297
+ *
39298
+ * **A range is two of them.** There is no native two-thumb range, so two are
39299
+ * stacked on one track and each thumb keeps its own.
40799
39300
  *
40800
39301
  * ## Attributes & Properties
40801
39302
  *
@@ -41315,101 +39816,33 @@ export type CustomElementsSolidJs = {
41315
39816
  >;
41316
39817
 
41317
39818
  /**
41318
- * **One axis, and nesting is how you get two.** The sandbox this was taken from
41319
- * moves a cross: a divider down the middle, another across the bottom, and a
41320
- * corner that moves both. That is a layout rather than a component, and every
41321
- * part of it that is worth sharing is one divider between two panes. A splitter
41322
- * inside a splitter gives the cross back, and gives the three-pane and the
41323
- * four-pane arrangements it never had.
39819
+ * **One axis, and nesting is how you get two.** A splitter inside a splitter
39820
+ * gives back the cross, and gives the three-pane and four-pane arrangements a
39821
+ * single divider never had.
41324
39822
  *
41325
39823
  * **Where two of them cross there is a corner, and it moves both.** A splitter
41326
- * slotted into a pane of another, at right angles to it, has one end of its
41327
- * divider sitting exactly on the other's. That end grows a handle: `move` under
41328
- * the pointer, both arrow axes on the keyboard, and a drag that carries the two
41329
- * positions at once.
41330
- *
41331
- * **The outer splitter draws it and the nested one announces itself upward.**
41332
- * The nested one drawing its own is the tempting version, since it already
41333
- * knows where its divider begins and needs no measurement of the other, and it
41334
- * is clipped: the crossing lies on the boundary between a pane and the divider
41335
- * beside it, a handle centered there reaches back over the boundary, and a pane
41336
- * is `overflow: auto`. Exactly half the corner is cut off. The outer separator
41337
- * is the one element that already straddles the seam, so the corner belongs in
41338
- * it.
39824
+ * slotted into a pane of another, at right angles to it, grows a handle at the
39825
+ * crossing: `move` under the pointer, both arrow axes on the keyboard, and a
39826
+ * drag that carries the two positions at once. It appears at `firstUpdated`
39827
+ * rather than in the served markup, being an affordance rather than content,
39828
+ * and a splitter with no corner yet is a splitter with two working dividers.
41339
39829
  *
41340
- * That makes the channel between the two a single call in a single direction:
41341
- * `cross(child, at)` says where the child crosses, `moveTo` drives either one,
41342
- * and neither reads the other's state. The child is what calls it, because a
41343
- * parent cannot poll for a child that has not upgraded yet.
41344
- *
41345
- * The one number it carries is a percentage rather than a measurement, which is
41346
- * what keeps either of them from measuring the other, and it assumes the nested
41347
- * splitter fills its pane. That is what slotting one into a pane does. Give the
41348
- * nested splitter its own inset, or wrap it in something smaller than the pane,
41349
- * and the corner is drawn where the crossing would be rather than where it is.
41350
- *
41351
- * **It is a client-side enhancement and says so.** Finding the parent means
41352
- * inspecting the tree, which a server cannot do, so the corner appears at
41353
- * `firstUpdated` and never in the served markup. That is allowed for exactly
41354
- * this: it is an affordance rather than content, and a splitter with no corner
41355
- * yet is a splitter with two working dividers.
41356
- *
41357
- * Where two dividers are parallel there is no corner, because there is nothing
41358
- * to take hold of. Where they cross without a corner, the inner divider takes
41359
- * the pointer: every separator sits on the same layer, so a tie goes to document
41360
- * order and a deeper splitter is always later.
41361
- *
41362
- * **A divider that is moving says so, whoever is moving it.** `:hover` cannot
41363
- * carry that: a drag holds the pointer through capture and a fast one leaves the
41364
- * target behind, and a corner moves the nested divider while the reader is on
41365
- * the crossing, nowhere near it. So a drag in progress is a state, and both
41366
- * dividers a corner moves are lit for as long as it moves them.
41367
- *
41368
- * **The divider is a real `role="separator"` with `aria-valuenow`, moved by the
41369
- * arrow keys as well as by pointer.** A divider only a mouse can move is
41370
- * unusable without one, which is the reason the sandbox's carries the same, and
41371
- * `Home` and `End` take it to its bounds.
39830
+ * **The divider is a real `role="separator"` with `aria-valuenow`**, moved by
39831
+ * the arrow keys as well as by pointer, with `Home` and `End` taking it to its
39832
+ * bounds. A drag in progress is a state rather than `:hover`, so both dividers
39833
+ * a corner moves are lit for as long as it moves them.
41372
39834
  *
41373
39835
  * **It goes where it is put, all the way to either end.** `min` and `max` are
41374
39836
  * nothing and everything unless a consumer says otherwise, because a divider
41375
- * that stops dead short of the edge gives a reader no way to put a pane away.
41376
- * Where a pane should keep a sliver of itself, only whoever put the tabs on it
41377
- * knows how much, so they say so.
39837
+ * that stops short of the edge gives a reader no way to put a pane away.
41378
39838
  *
41379
39839
  * **A pane can be shut, and that is not the same as a divider at the edge.**
41380
39840
  * The geometry is identical and the knowledge is not: only a shut pane knows
41381
39841
  * where to open back to. So `collapsed` is a second state rather than a reading
41382
- * of the position, and the position it opens to is simply the one collapsing
41383
- * never overwrote. `collapsed-size` keeps a sliver showing where a pane has a
41384
- * tab strip worth leaving, and collapse overrides `min` and `max`, which is
41385
- * what those are for: they keep a pane from vanishing by accident, and this is
41386
- * the deliberate version.
41387
- *
41388
- * The two are kept in step in one direction only: a drag that settles on the
41389
- * collapsed size latches shut, and any move opens it again. Otherwise a reader
41390
- * could drag a pane closed and the consumer's own button would still be
41391
- * offering to close it.
41392
- *
41393
- * A pane shut to nothing is told apart from one shut to a sliver, because the
41394
- * two want different dividers: a sliver still has a boundary worth drawing, and
41395
- * nothing leaves the divider sitting on the container's own edge.
41396
- *
41397
- * **The box is measured once, when a drag starts.** Measuring per move is a
41398
- * forced layout on every pointer event, in the middle of a gesture whose whole
41399
- * job is to stay ahead of the pointer, and nothing about the box moves while the
41400
- * divider does.
41401
- *
41402
- * **`helix-before-resize` fires when it settles, not while it moves.** A drag is a
41403
- * stream of positions and only the one it ends at is a preference; announcing
41404
- * each would ask a consumer to write to storage a hundred times to record one
41405
- * decision. Nothing is stored here either: where a preference lives, and whether
41406
- * it should be kept at all, is the consumer's to decide, and a component writing
41407
- * to storage on its own would be deciding for all of them under a key it chose.
41408
- *
41409
- * The properties below are written by this component and read by whoever draws
41410
- * it. A consumer sets none of them: they carry a number this element computed
41411
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
41412
- * without measuring anything itself.
39842
+ * of the position, and the position it opens to is the one collapsing never
39843
+ * overwrote. `collapsed-size` keeps a sliver showing where a pane has a tab
39844
+ * strip worth leaving, and collapse overrides `min` and `max`, which is what
39845
+ * those are for.
41413
39846
  *
41414
39847
  * ## Attributes & Properties
41415
39848
  *
@@ -41676,34 +40109,16 @@ export type CustomElementsSolidJs = {
41676
40109
  >;
41677
40110
 
41678
40111
  /**
41679
- * **`active` names where the reader is. `complete` stays on each step.** They
41680
- * are two different facts and only one of them is positional. Deriving both
41681
- * from a position is the obvious design and it is wrong the first time anybody
41682
- * steps back: return to stage one of three and stages one and two are still
41683
- * finished, while "everything before the active one" says only the first is.
41684
- * So this element drives `current` and never touches `complete`.
40112
+ * **`active` names where the reader is. `complete` stays on each step.** Only
40113
+ * one of them is positional: return to stage one of three and stages one and
40114
+ * two are still finished, where "everything before the active one" says only
40115
+ * the first is. So this element drives `current` and never touches `complete`.
41685
40116
  *
41686
40117
  * **`active` is optional, and a sequence without it still renders.** Left
41687
- * unset, each step's own `current` stands and nothing here overwrites it, which
41688
- * is what lets the whole sequence be right in the server's markup: this element
41689
- * would have to count its slotted children to know which one is third, and the
41690
- * server has no children to count. Set it, and it wins, because it is a
41691
- * statement about the sequence where the attribute on a step is a statement
41692
- * about one step.
41693
- *
41694
- * That is also why the numbering is not JavaScript. It is a CSS counter in the
41695
- * tier above, which the browser resolves at layout with no script at all, so
41696
- * the third step reads "3" in the server's own markup.
41697
- *
41698
- * **The connector belongs to the step, not to the list.** Each one draws the
41699
- * line that arrives at it and hides it when it is first, the same arrangement
41700
- * Breadcrumbs uses for its separator and for the same reason: a line drawn
41701
- * between items needs either an index or a parent that counts, and drawing it
41702
- * on the item needs neither.
41703
- *
41704
- * `role="list"` on the host rather than an `<ol>` in the shadow root. The steps
41705
- * are the consumer's elements in the light DOM, so an `<ol>` here would be a
41706
- * list whose items are somewhere else.
40118
+ * unset, each step's own `current` stands, which is what lets the whole
40119
+ * sequence be right in the server's markup: this element would have to count
40120
+ * its slotted children to know which is third, and the server has none to
40121
+ * count.
41707
40122
  *
41708
40123
  * ## Attributes & Properties
41709
40124
  *
@@ -41798,51 +40213,21 @@ export type CustomElementsSolidJs = {
41798
40213
  >;
41799
40214
 
41800
40215
  /**
41801
- * **The name is a button, and only the name.** A stepper is something a reader
41802
- * goes back through, and the thing they reach for is the name of the stage. The
41803
- * marker is `aria-hidden` decoration, so wrapping it in the button would add
41804
- * hit area and no meaning: the accessible name would be the text either way,
41805
- * and what is pressable would stop being the same shape as what is readable.
41806
- *
41807
- * It is `helix-button`, not a `<button>` this element resets and dresses: the
41808
- * hover wash, the focus ring and the disabled treatment are decisions the
41809
- * button already carries. `ghost` is the quiet shape, transparent until it is
41810
- * pointed at.
41811
- *
41812
- * It says nothing about where a reader may go. Every step is pressable and
40216
+ * **The name is a button, and only the name.** The marker is `aria-hidden`
40217
+ * decoration, so wrapping it would add hit area and no meaning. It is
40218
+ * `helix-button` rather than a `<button>` this element resets: the hover wash,
40219
+ * the focus ring and the disabled treatment are decisions the button carries.
40220
+ *
40221
+ * **It says nothing about where a reader may go.** Every step is pressable and
41813
40222
  * announces itself with `helix-select`; refusing the ones ahead is `disabled`,
41814
- * which the consumer sets because only the consumer knows whether a form can be
41815
- * skipped. A component that guessed would be wrong on the first wizard that
41816
- * lets you jump to the end.
40223
+ * which the consumer sets, because only they know whether a form can be
40224
+ * skipped.
41817
40225
  *
41818
40226
  * **The marker is a slot whose fallback is the state.** A finished stage shows
41819
- * a check, the current one a target, and one not yet reached an empty ring:
41820
- * three marks that say what a reader wants to know without a legend. A consumer
41821
- * who wants their own fills the slot instead.
41822
- *
41823
- * The step renders exactly one of the three, chosen from its own two booleans.
41824
- * Rendering all three and hiding two in CSS would work and is worse: the
41825
- * accessibility tree would carry marks that are not there, and the markup would
41826
- * say three things about a stage that is one.
41827
- *
41828
- * Numbering belongs to the tier above. `numeric` hides the mark and shows a CSS
41829
- * counter, which the browser resolves at layout, so the digit costs no script
41830
- * and is right in the server's markup however the steps are ordered. Nothing
41831
- * here knows which appearance is in use.
41832
- *
41833
- * **`complete` and `current` are separate, and both can be false.** A stage
41834
- * that is neither is one the reader has not reached, which is the majority of
41835
- * any sequence and therefore the state that needs no attribute. They can also
41836
- * both be true: a reader who steps back into a finished stage is in it and has
41837
- * finished it, and a stepper that forgets the second is one that loses its
41838
- * checks the moment somebody reviews their answers.
41839
- *
41840
- * **The `content` slot opens on the current step, and only down a column.** A
41841
- * row has no room under a step to put a form in, and stretching one to fit
41842
- * would set every step's height by the tallest. `current` is what opens it, so
41843
- * the state that says where the reader is is also the state that shows them the
41844
- * stage: one attribute, no second flag to keep in step with it, and it renders
41845
- * open on the server rather than after hydration.
40227
+ * a check, the current one a target, one not yet reached an empty ring. Exactly
40228
+ * one is rendered, chosen from the step's own two booleans, rather than three
40229
+ * with two hidden in CSS: the accessibility tree would otherwise carry marks
40230
+ * that are not there.
41846
40231
  *
41847
40232
  * ## Attributes & Properties
41848
40233
  *
@@ -43615,40 +42000,16 @@ export type CustomElementsSolidJs = {
43615
42000
 
43616
42001
  /**
43617
42002
  * An element rather than a slot, because it carries a timeout, a tone, a
43618
- * dismiss control and a lifetime that pauses: behavior, state and API, which
43619
- * is the test for whether a region becomes an element in this library.
42003
+ * dismiss control and a lifetime that pauses: behavior, state and API.
43620
42004
  *
43621
42005
  * **The timer is the item's own.** Held by the region, one message arriving
43622
42006
  * would restart another's, so a stack of three would go from three seconds each
43623
- * to nine for the last one. Each message is on its own clock from the moment it
43624
- * is rendered.
43625
- *
43626
- * **A message is the opposite of the page it is over.** Inverted by default,
43627
- * because a thing arriving in a corner has to be told apart from the page in
43628
- * the moment before it is read, and inverting does that without spending a
43629
- * color that means something. It is a flip of `color-scheme` rather than a
43630
- * named inverse surface: every token in the subtree re-resolves, so a `Retry`
43631
- * a consumer slots in comes out right without knowing where it is. `Tooltip`
43632
- * can name the inverse surface directly because it holds no controls; this
43633
- * cannot. Set `data-color-mode` on the region to take the page's mode instead.
43634
- *
43635
- * **No duration means it stays.** That is the safe default rather than the
43636
- * common one: anything carrying an action has to still be there when the reader
43637
- * decides to take it, and a component cannot tell from the outside whether the
43638
- * message it was given is disposable.
43639
- *
43640
- * **The clock stops while it is being read.** Hover pauses it, and so does
43641
- * focus landing anywhere inside, which is the case that matters more: a
43642
- * keyboard reader tabbing towards the action in a toast is exactly the person a
43643
- * timer must not race. Both resume where they left off rather than starting
43644
- * again, so a message half-read does not get a full second life every time a
43645
- * pointer crosses it.
43646
- *
43647
- * **Going away is a request, never an act.** It dispatches a cancelable
43648
- * `helix-dismiss` and does nothing else: the consumer owns the list, so the
43649
- * item removing itself would leave the two disagreeing. Auto-dismiss and the
43650
- * dismiss control raise the same event, so a consumer handles one path and not
43651
- * two.
42007
+ * to nine for the last.
42008
+ *
42009
+ * **A message is the opposite of the page it is over.** Inverted by default, so
42010
+ * a thing arriving in a corner is told apart from the page before it is read,
42011
+ * and by a flip of `color-scheme` rather than by spending a color that means
42012
+ * something.
43652
42013
  *
43653
42014
  * ## Attributes & Properties
43654
42015
  *
@@ -43834,32 +42195,14 @@ export type CustomElementsSolidJs = {
43834
42195
 
43835
42196
  /**
43836
42197
  * The indicator is one element that travels, not a background that appears on
43837
- * whichever item is current. That difference is the whole point: a fill that
43838
- * swaps is two things changing at once and reads as a flicker, while one that
43839
- * moves is a single object the eye follows, and it says where the selection
43840
- * came from as well as where it went.
43841
- *
43842
- * Its whole box is measured from the selected item and written onto
43843
- * the indicator as custom properties, because labels are different lengths and
43844
- * no proportion of the group is the right answer. Measurement is client-side by
43845
- * necessity, so the server renders the indicator hidden and it fades in once it
43846
- * has somewhere to be, which is the harmless direction: it appears rather than
43847
- * jumping from a wrong place.
43848
- *
43849
- * A radio group, and only that. Navigation is links marked with `aria-current`
43850
- * and styled by the `data-navigation-item` recipe: radio semantics would announce a
43851
- * set of destinations as a set of choices. A tab controls a panel.
43852
- *
43853
- * Being a radio group, it is a form control, and it says so through
43854
- * `HelixFormElement`: it reports its value under a `name`, comes back to the
43855
- * markup's choice on reset, and restores the one a reader made when the browser
43856
- * brings a form back.
43857
- *
43858
- * The semantics were already right: the host has carried `role="radiogroup"`
43859
- * and the items `role="radio"` from the start. What none of it did was reach a
43860
- * form. A button in a shadow root submits nothing whatever its role, so the
43861
- * value has to be reported by the host, which is the only thing a form can
43862
- * see.
42198
+ * whichever item is current. A fill that swaps is two things changing at once
42199
+ * and reads as a flicker; one that moves is a single object the eye follows,
42200
+ * and it says where the selection came from as well as where it went.
42201
+ *
42202
+ * Its box is measured from the selected item and written onto the indicator as
42203
+ * custom properties, labels being different lengths. Measurement is client-side
42204
+ * by necessity, so the server renders the indicator hidden and it fades in once
42205
+ * it has somewhere to be, which is the harmless direction.
43863
42206
  *
43864
42207
  * ## Attributes & Properties
43865
42208
  *
@@ -44170,57 +42513,35 @@ export type CustomElementsSolidJs = {
44170
42513
  /**
44171
42514
  * The trigger is slotted and stays the consumer's own element. The bubble is
44172
42515
  * rendered here, in the top layer through the popover API, so it clears any
44173
- * ancestor with `overflow: hidden` without a `z-index` anywhere.
42516
+ * ancestor with `overflow: hidden` without a `z-index` anywhere. Position comes
42517
+ * from `FloatingController`, which flips to another side when the preferred one
42518
+ * does not fit.
44174
42519
  *
44175
- * Position comes from `FloatingController`, which flips to another side when
44176
- * the preferred one does not fit and slides along it to stay in view.
44177
- *
44178
- * **Two forms, and they are not equivalent for a screen reader.**
44179
- *
44180
- * Wrapping is the convenience form and is right where the bubble decorates a
44181
- * control that already says what it is. The trigger stays the consumer's own
44182
- * element, slotted, and nothing here can describe it: an IDREF cannot cross a
44183
- * shadow boundary, an element reference is valid only into the same tree or a
44184
- * shadow-including *ancestor* (the bubble's tree is neither, it is inward), and
44185
- * a string on the trigger means writing to markup the consumer server-rendered.
44186
- * All three measured.
42520
+ * **Two forms, and they are not equivalent for a screen reader.** Wrapping is
42521
+ * the convenience form and is right where the bubble decorates a control that
42522
+ * already says what it is: nothing here can describe a slotted trigger, an
42523
+ * IDREF being unable to cross a shadow boundary.
44187
42524
  *
44188
42525
  * `for` is the form that works. The tooltip sits *beside* the trigger in the
44189
- * consumer's own tree and names it by id, so both are in one tree and an IDREF
44190
- * between them is legal in the ordinary way:
42526
+ * consumer's own tree and names it by id, so an IDREF between them is legal in
42527
+ * the ordinary way:
44191
42528
  *
44192
42529
  * ```html
44193
42530
  * <helix-button id="save" aria-describedby="save-tip">Save</helix-button>
44194
42531
  * <helix-tooltip id="save-tip" for="save" content="Save your work"></helix-tooltip>
44195
42532
  * ```
44196
42533
  *
44197
- * Note that the reference points at *this host*, not at the bubble inside its
44198
- * shadow root: the description is computed from the flat tree, which descends
44199
- * into shadow content on its own.
42534
+ * The reference points at *this host*, not at the bubble in its shadow root:
42535
+ * the description is computed from the flat tree, which descends into shadow
42536
+ * content on its own.
44200
42537
  *
44201
42538
  * **The consumer writes that `aria-describedby`, and nothing here writes it for
44202
- * them.** WebAwesome and Spectrum Web Components both do write it, with
44203
- * `setAttribute` on the trigger at runtime, which is the one thing this library
44204
- * declines everywhere: React rendered that element on the server without the
44205
- * attribute and reports a mismatch it will not patch up. Two ids in the markup
44206
- * is the whole cost of the version that is correct before any JavaScript runs.
44207
- *
44208
- * Because it is the consumer's line to write, it is also theirs to forget, so
44209
- * `for` audits itself on first open and says so once, rather than on every
44210
- * open, since a warning that repeats is one people learn to filter out.
42539
+ * them.** Setting it at runtime is a hydration mismatch React will not patch
42540
+ * up. `for` audits itself on first open and warns once where it is missing.
44211
42541
  *
44212
42542
  * It shows on hover and on focus, and hides on leave, on blur, on Escape, and
44213
42543
  * once the trigger has been activated: the hint is spent when the control has
44214
42544
  * been used.
44215
- * A tooltip that answers only the pointer is one a keyboard reader never sees.
44216
- *
44217
- * The pointer waits out `delay` first, or sweeping a row of controls flashes a
44218
- * tooltip for each of them. Focus does not wait: a keyboard reader landing on a
44219
- * control has already committed to it.
44220
- *
44221
- * Open state comes from `MixinControllerOpen`, so it announces `helix-before-open` and
44222
- * `helix-before-close` like every other overlay here, and a consumer can drive it with
44223
- * `open` where they need to.
44224
42545
  *
44225
42546
  * ## Attributes & Properties
44226
42547
  *
@@ -44386,36 +42707,13 @@ export type CustomElementsSolidJs = {
44386
42707
  *
44387
42708
  * **The spotlight is a shadow, not a hole.** The scrim is a box the size of the
44388
42709
  * current target with an enormous spread on its `box-shadow`, so the darkness
44389
- * is what the shadow paints and the target is simply where the box is. A
44390
- * `clip-path` on a full-screen scrim is the other way to do it and is worse
44391
- * here: it needs the viewport in the same coordinate space as the cut, which
44392
- * stops being true the moment anything between them is transformed.
44393
- *
44394
- * **It measures, and this is a case where measuring is the only option.** The
44395
- * target is an element somewhere else on the page whose position nothing can
44396
- * know statically. That is different from a trail folding by width, where the
44397
- * design rule was expressible and the measurement was answering a question
44398
- * nobody had asked. Here the question is "where is that button", and there is
44399
- * no other way to ask it.
44400
- *
44401
- * **Nothing is measured on the server and nothing needs to be.** A tour starts
44402
- * closed and a closed tour draws nothing, so the server renders the stops as
44403
- * inert markup and the first frame is correct. This is also what makes it
44404
- * acceptable for the root to write `current` onto stops it does not own: there
44405
- * is no server state for the write to disagree with.
44406
- *
44407
- * **It cannot point inside a modal, and nothing can fix that here.**
44408
- * `showModal()` makes everything outside the dialog's own subtree inert, so a
44409
- * panel anywhere else is unpressable however the top layer is ordered: this is
44410
- * what modal means rather than a stacking accident. Measured with a modal
44411
- * `Drawer` open, `elementsFromPoint` over the tour's own Done button returned
44412
- * the drawer, the press light-dismissed the drawer, and the tour heard nothing
44413
- * at all. Anything a tour points into has to stay reachable, which for `Drawer`
44414
- * and `Dialog` means not modal while the tour is running.
44415
- *
44416
- * **Focus is not trapped.** A reader has to be able to look at, and reach, the
44417
- * thing being pointed at. `Escape` leaves, which is the one binding a tour
44418
- * needs and the one every reader already tries.
42710
+ * is what the shadow paints. A `clip-path` on a full-screen scrim needs the
42711
+ * viewport in the same coordinate space as the cut, which stops being true the
42712
+ * moment anything between them is transformed.
42713
+ *
42714
+ * **It measures, and the target is an element elsewhere on the page whose
42715
+ * position nothing can know statically.** Nothing is measured on the server and
42716
+ * nothing needs to be: a tour starts when a reader asks for it.
44419
42717
  *
44420
42718
  * ## Attributes & Properties
44421
42719
  *
@@ -44605,45 +42903,23 @@ export type CustomElementsSolidJs = {
44605
42903
  >;
44606
42904
 
44607
42905
  /**
44608
- * **`open`, on `MixinControllerOpen`, rather than a bare boolean of its own.** A
44609
- * branch showing its children is the same state a disclosure holds, and
44610
- * `AccordionItem` is on that mixin too. A hand-written toggle announces nothing,
44611
- * so a consumer can neither know a branch opened nor own the state.
44612
- * `aria-expanded` is still what the row renders, because that is the attribute a
44613
- * tree uses; the property is what differs, not the semantics.
42906
+ * **`open`, on `MixinControllerOpen`, rather than a bare boolean of its own.**
42907
+ * A branch showing its children is the same state a disclosure holds. A
42908
+ * hand-written toggle announces nothing, so a consumer could neither know a
42909
+ * branch opened nor own the state. `aria-expanded` is still what the row
42910
+ * renders: the property differs, not the semantics.
44614
42911
  *
44615
- * An element rather than a slot because it owns state: whether it is open,
44616
- * whether it is selected, and whether it is the one holding focus.
42912
+ * An element rather than a slot, because it owns state: whether it is open,
42913
+ * selected, and whether it holds focus.
44617
42914
  *
44618
42915
  * A branch is any item with something slotted into `children`, detected in
44619
- * `firstUpdated` rather than declared by the consumer. That is a client-side
44620
- * enhancement by necessity, since the server cannot inspect children, so the
44621
- * server renders the node as a leaf and the twisty appears on hydration. It
44622
- * appears rather than disappearing, which is the harmless direction.
44623
- *
44624
- * **`href` makes the row itself the link.** A tree used as navigation is a list
44625
- * of links, and the row is what a reader presses: with the anchor slotted into
44626
- * the name instead, everything outside the words is dead, Enter does nothing,
44627
- * and there is no middle-click, no status bar and no open-in-new-tab. Given an
44628
- * `href` the row *is* an `<a>`, so the platform provides all of that and the
44629
- * keyboard needs no handler at all.
44630
- *
44631
- * It changes the shape of the ARIA, which is why it is a property and not the
44632
- * default. An anchor cannot contain the group, since the group holds more
44633
- * anchors and nesting them is invalid, so the row carries `treeitem` and the
44634
- * group becomes its sibling under a presentational wrapper. That is exactly the
44635
- * navigation flavor of the tree pattern, and the arrangement without an `href`
44636
- * stays as it was: `treeitem` containing `group`, which is what an `<li>`
44637
- * holding a `<ul>` is.
44638
- *
44639
- * A consumer whose framework owns routing slots its own link instead and leaves
44640
- * `href` unset. The row follows that one too, so the whole row works either
44641
- * way; what the anchor adds is what only a real anchor can give.
42916
+ * `firstUpdated` because the server cannot inspect children. The server renders
42917
+ * the node as a leaf and the twisty appears on hydration, which is the harmless
42918
+ * direction.
44642
42919
  *
44643
- * The properties below are written by this component and read by whoever draws
44644
- * it. A consumer sets none of them: they carry a number this element computed
44645
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
44646
- * without measuring anything itself.
42920
+ * **`href` makes the row itself the link.** With the anchor slotted into the
42921
+ * name instead, everything outside the words is dead: no Enter, no middle
42922
+ * click, no status bar. Given an `href` the row *is* an `<a>`.
44647
42923
  *
44648
42924
  * ## Attributes & Properties
44649
42925
  *
@@ -45048,35 +43324,13 @@ export type CustomElementsSolidJs = {
45048
43324
  /**
45049
43325
  * The entries again, reachable without leaving the picture. A playlist beside
45050
43326
  * the player is a list a reader scrolls to; the same list in the control bar is
45051
- * one they open over the video, which is what a full-screen player has and what
45052
- * a phone has room for.
43327
+ * one they open over the video.
45053
43328
  *
45054
43329
  * **It is placed by the consumer, not rendered by the playlist**, and that is
45055
- * forced rather than chosen. A shadow root cannot project into a sibling's
43330
+ * forced rather than chosen: a shadow root cannot project into a sibling's
45056
43331
  * light DOM, so nothing the playlist renders can land inside the player's
45057
43332
  * control bar. What can is an element the consumer writes there, which is what
45058
- * `Video`'s `controls` slot is for:
45059
- *
45060
- * ```html
45061
- * <helix-video-playlist>
45062
- * <helix-video slot="player" controls>
45063
- * <helix-video-playlist-menu slot="controls"></helix-video-playlist-menu>
45064
- * </helix-video>
45065
- * <helix-video-playlist-item value="one" src="/one.mp4">One</helix-video-playlist-item>
45066
- * </helix-video-playlist>
45067
- * ```
45068
- *
45069
- * So it finds its playlist upward rather than being handed one, and that chain
45070
- * crosses a shadow boundary in the ordinary arrangement, which is why it is
45071
- * `closestInstance` and not `closest`.
45072
- *
45073
- * **Choosing dispatches `helix-select`, the same event an entry dispatches.**
45074
- * It never writes `active` on the playlist, which looks like the shorter path
45075
- * and skips the cancelable request: an assignment applies the change with no
45076
- * `helix-before-activate` for anyone to refuse. Announcing is what an entry
45077
- * does, the playlist already listens for it, and a consumer refusing a
45078
- * selection gets `preventDefault()` on one event rather than two paths that
45079
- * behave differently.
43333
+ * `Video`'s `controls` slot is for.
45080
43334
  *
45081
43335
  * ## Attributes & Properties
45082
43336
  *
@@ -45249,57 +43503,29 @@ export type CustomElementsSolidJs = {
45249
43503
 
45250
43504
  /**
45251
43505
  * **The picture is a real `<video>`.** Decoding, buffering, captions, Picture
45252
- * in Picture, AirPlay and the codecs a device happens to have are all the
45253
- * platform's, and none of them can be had from anything else. What is replaced
45254
- * is the control bar, which is the one part of a video element that cannot be
45255
- * styled and looks different in every browser.
43506
+ * in Picture, AirPlay and whatever codecs a device has are the platform's. What
43507
+ * is replaced is the control bar, which is the one part that cannot be styled.
45256
43508
  *
45257
43509
  * **Every control is a real control.** The scrubber and the volume are
45258
- * `<input type="range">`, so a reader gets arrow keys, Home and End, the
45259
- * platform's own touch target and its screen reader announcement without this
45260
- * element implementing any of it. Drawing a div and listening for pointer moves
45261
- * is how a media player ends up unusable from a keyboard.
43510
+ * `<input type="range">`, so arrow keys, Home and End, the platform's touch
43511
+ * target and its screen reader announcement all come for free.
45262
43512
  *
45263
43513
  * **Native controls are the fallback, not the default.** Where a consumer sets
45264
- * `controls`, the browser's bar is used and this one is not drawn: two sets of
45265
- * controls over one video is worse than either alone, and a consumer who asked
45266
- * for the native bar has a reason.
43514
+ * `controls` the browser's bar is used and this one is not drawn, and the keys
43515
+ * below are not bound: two handlers on one press is a video that seeks twice.
45267
43516
  *
45268
43517
  * The keys are the ones every player uses: Space and `k` to play or pause, the
45269
- * arrows to seek and to change the volume, `m` to mute, `f` for fullscreen.
45270
- * They are bound on this element rather than on the document, because a video
45271
- * is not a palette: keys belong to it only while a reader is on it. Where
45272
- * `controls` is set they are not bound at all, since two handlers on one press
45273
- * is a video that seeks twice, and the focus stop goes with them.
43518
+ * arrows to seek and to change volume, `m` to mute, `f` for fullscreen. They
43519
+ * are bound on this element rather than on the document, because a video is not
43520
+ * a palette.
45274
43521
  *
45275
43522
  * **`<source>` and `<track>` are copied into the video, never slotted into it.**
45276
43523
  * A media element runs resource selection over its own child *nodes*, and a slot
45277
43524
  * is one node, so slotted sources reach it as nothing: no text tracks, no
45278
43525
  * current source, `readyState` zero. A video given sources that way does not
45279
- * merely lack captions, it does not play.
45280
- *
45281
- * They are copied rather than moved, because the consumer's light DOM is theirs
45282
- * and a framework that re-renders it would find its children gone. The copies
45283
- * are rebuilt whenever the slot changes and the video is asked to load again,
45284
- * which is what makes a `<track>` added later take effect.
45285
- *
45286
- * **The lock screen and a headset's buttons work, and one player owns them.**
45287
- * There is one `navigator.mediaSession` per page, so the rule is stated rather
45288
- * than left to render order: whichever player was started last owns it, which
45289
- * is what a reader means by "this one" when they press play on their
45290
- * headphones. The title comes from `label` and the artwork from `poster`.
45291
- *
45292
- * **`remote` sends the picture somewhere else.** The Remote Playback API is
45293
- * what Safari implements for AirPlay and Chrome for Cast, so one control covers
45294
- * both and the platform supplies the device list. It is offered only once
45295
- * something has answered `watchAvailability`: a button that opens an empty list
45296
- * is worse than no button, and a consumer who wants none can set
45297
- * `disableremoteplayback` on this element.
45298
- *
45299
- * The properties below are written by this component and read by whoever draws
45300
- * it. A consumer sets none of them: they carry a number this element computed
45301
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
45302
- * without measuring anything itself.
43526
+ * merely lack captions, it does not play. They are copied rather than moved,
43527
+ * because the consumer's light DOM is theirs, and rebuilt whenever the slot
43528
+ * changes.
45303
43529
  *
45304
43530
  * ## Attributes & Properties
45305
43531
  *
@@ -45560,54 +43786,15 @@ export type CustomElementsSolidJs = {
45560
43786
  * `<template>` child says what one row looks like: elements carrying
45561
43787
  * `data-field="name"` are filled with that field of the item.
45562
43788
  *
45563
- * Both halves are markup, and that is the whole reason for the shape.
45564
- * `VirtualizeController` says why the obvious alternatives are shut: an `items`
43789
+ * Both halves are markup, and that is the reason for the shape. An `items`
45565
43790
  * property cannot survive React hydration, which skips every property it would
45566
43791
  * have to apply imperatively, and light-DOM children exist by the time anything
45567
- * could decide not to create them. Text in the document is neither. A server
45568
- * emits it, React re-emits it as a child rather than applying it, and it is one
45569
- * node whatever the row count.
43792
+ * could decide not to create them. Text in the document is neither, and it is
43793
+ * one node whatever the row count.
45570
43794
  *
45571
43795
  * **The accessible version is not a `<table>`**, the way it is for the charts
45572
43796
  * that share this `for="<id>"` shape: ten thousand rows in one is the cost this
45573
- * exists to avoid. It is the rendered window plus `aria-setsize` and
45574
- * `aria-posinset`, which is what says "four thousand of ten thousand" rather
45575
- * than "four of twenty".
45576
- *
45577
- * **Rows are light DOM, deliberately.** They are cloned from the consumer's
45578
- * template and appended to the host, so a document rule reaches them, the base
45579
- * layer applies, and a class in the template means what it says. Cloned into
45580
- * the shadow root they would be markup the consumer wrote and could not style,
45581
- * which is the one thing a row template must not be.
45582
- *
45583
- * **Reading the source is client-only**, because a server has no document to
45584
- * query. The window renders empty from the server and fills on the first update,
45585
- * which is the same client-side enhancement rule every tree-reading component
45586
- * here follows.
45587
- *
45588
- * **On this tier the consumer gives the viewport its box**, and the component
45589
- * cannot do it for them: `helix/headless` ships no stylesheet, and a height is a
45590
- * decision rather than a fact this could publish. So a base list wants two rules
45591
- * before it is a list at all:
45592
- *
45593
- * ```css
45594
- * helix-headless-virtual-list::part(viewport) {
45595
- * block-size: 12rem;
45596
- * overflow-y: auto;
45597
- * }
45598
- * ```
45599
- *
45600
- * **Without them it is not a scroller**, and the failure is worse than it
45601
- * sounds. `scrollTop` is always zero, so nothing ever windows; and the box has
45602
- * no height of its own, so `clientHeight` is a function of the rows just drawn.
45603
- * Measuring then moves what is being measured, and the two need not converge:
45604
- * measured in Chromium at 500 rows, it settled into a two-cycle between 378 and
45605
- * 379 rows and stayed there, at two and a half thousand passes in eight seconds.
45606
- * `VirtualizeController` gives up after ten passes and says so, so this now
45607
- * draws a bad window rather than stopping the page, but a bad window is still
45608
- * the answer until the rules are written.
45609
- *
45610
- * The styled tier writes them for you, with `--virtual-list-block-size`.
43797
+ * exists to avoid. It is the rendered window plus `aria-setsize`.
45611
43798
  *
45612
43799
  * ## Attributes & Properties
45613
43800
  *