@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.
- package/custom-elements.json +39 -39
- package/dist/app-header/root/app-header-root.d.ts +8 -28
- package/dist/avatar/group/avatar-group.d.ts +5 -30
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
- package/dist/chat/root/chat-root.d.ts +9 -28
- package/dist/color-picker/root/color-picker-root.d.ts +10 -28
- package/dist/combobox/root/combobox-root.d.ts +18 -60
- package/dist/copy-button/root/copy-button-root.d.ts +6 -21
- package/dist/data-table/root/data-table-root.d.ts +9 -32
- package/dist/date-input/root/date-input-root.d.ts +5 -21
- package/dist/date-picker/root/date-picker-root.d.ts +10 -35
- package/dist/dialog/root/dialog-root.d.ts +7 -29
- package/dist/donut-chart/root/donut-chart-root.d.ts +5 -25
- package/dist/file-input/root/file-input-root.d.ts +5 -22
- package/dist/heatmap/root/heatmap-root.d.ts +13 -36
- package/dist/image/root/image-root.d.ts +5 -22
- package/dist/input/root/input-root.d.ts +11 -29
- package/dist/kbd/root/kbd-root.d.ts +8 -26
- package/dist/legend/root/legend-root.d.ts +6 -24
- package/dist/listbox/root/listbox-root.d.ts +4 -26
- package/dist/megamenu/root/megamenu-root.d.ts +7 -39
- package/dist/meter/root/meter-root.d.ts +6 -24
- package/dist/number-input/root/number-input-root.d.ts +11 -20
- package/dist/outline/root/outline-root.d.ts +8 -27
- package/dist/pagination/root/pagination-root.d.ts +21 -54
- package/dist/pagination/summary/pagination-summary.d.ts +10 -31
- package/dist/progress/root/progress-root.d.ts +4 -21
- package/dist/rating/root/rating-root.d.ts +8 -31
- package/dist/slider/root/slider-root.d.ts +9 -32
- package/dist/splitter/root/splitter-root.d.ts +17 -85
- package/dist/steps/root/steps-root.d.ts +8 -26
- package/dist/steps/step/step.d.ts +11 -41
- package/dist/toast/item/toast-item.d.ts +6 -30
- package/dist/toggle/group/toggle-group.d.ts +7 -25
- package/dist/tooltip/root/tooltip-root.d.ts +14 -36
- package/dist/tour/root/tour-root.d.ts +6 -29
- package/dist/tree/item/tree-item.d.ts +13 -35
- package/dist/video/root/video-root.d.ts +12 -40
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -25
- package/dist/virtual-list/root/virtual-list-root.d.ts +5 -44
- package/package.json +17 -18
- package/{jsx.d.ts → types/jsx.d.ts} +724 -2537
- package/{vue.d.ts → types/vue.d.ts} +39 -39
- /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
|
|
15587
|
-
*
|
|
15588
|
-
*
|
|
15589
|
-
*
|
|
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
|
|
15595
|
-
*
|
|
15596
|
-
*
|
|
15597
|
-
*
|
|
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
|
|
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
|
|
15688
|
-
*
|
|
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
|
|
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
|
|
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
|
|
16248
|
-
*
|
|
16249
|
-
*
|
|
16250
|
-
*
|
|
16251
|
-
* `role="list"` is set explicitly on the `<ol>` even though it is
|
|
16252
|
-
*
|
|
16253
|
-
*
|
|
16254
|
-
*
|
|
16255
|
-
* Items are slotted rather than wrapped, so they are `<ol>` children in the
|
|
16256
|
-
* tree and each carries `role="listitem"` itself.
|
|
16257
|
-
*
|
|
16258
|
-
* **The trail does not measure itself, and the overflow is markup.**
|
|
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
|
|
17079
|
-
* those is a variant of a conversation: they are containers
|
|
17080
|
-
*
|
|
17081
|
-
*
|
|
17082
|
-
*
|
|
17083
|
-
*
|
|
17084
|
-
*
|
|
17085
|
-
*
|
|
17086
|
-
*
|
|
17087
|
-
*
|
|
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
|
|
17938
|
-
* a panel behind a text field
|
|
17939
|
-
*
|
|
17940
|
-
*
|
|
17941
|
-
*
|
|
17942
|
-
*
|
|
17943
|
-
*
|
|
17944
|
-
*
|
|
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
|
|
17955
|
-
*
|
|
17956
|
-
*
|
|
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
|
|
18184
|
-
*
|
|
18185
|
-
* scrolling an option into view.
|
|
18186
|
-
*
|
|
18187
|
-
*
|
|
18188
|
-
*
|
|
18189
|
-
*
|
|
18190
|
-
*
|
|
18191
|
-
*
|
|
18192
|
-
*
|
|
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,
|
|
18203
|
-
*
|
|
18204
|
-
*
|
|
18205
|
-
*
|
|
18206
|
-
*
|
|
18207
|
-
*
|
|
18208
|
-
*
|
|
18209
|
-
*
|
|
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
|
|
18228
|
-
*
|
|
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
|
|
18620
|
-
* failed
|
|
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,
|
|
18625
|
-
*
|
|
18626
|
-
*
|
|
18627
|
-
*
|
|
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
|
|
18856
|
-
*
|
|
18857
|
-
*
|
|
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
|
|
18872
|
-
*
|
|
18873
|
-
*
|
|
18874
|
-
*
|
|
18875
|
-
*
|
|
18876
|
-
*
|
|
18877
|
-
*
|
|
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
|
|
19054
|
-
*
|
|
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
|
|
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
|
|
19060
|
-
*
|
|
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`
|
|
19351
|
-
*
|
|
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
|
-
* `
|
|
19366
|
-
*
|
|
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
|
-
* `
|
|
19372
|
-
*
|
|
19373
|
-
*
|
|
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
|
-
*
|
|
19376
|
-
*
|
|
19377
|
-
*
|
|
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
|
|
19604
|
-
*
|
|
19605
|
-
*
|
|
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
|
|
19610
|
-
*
|
|
19611
|
-
*
|
|
19612
|
-
*
|
|
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,
|
|
19821
|
-
*
|
|
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
|
-
*
|
|
19841
|
-
*
|
|
19842
|
-
*
|
|
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
|
|
20370
|
-
*
|
|
20371
|
-
*
|
|
20372
|
-
* So the input stays,
|
|
20373
|
-
* and the visible trigger is a `<label for
|
|
20374
|
-
* not
|
|
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
|
|
20654
|
-
*
|
|
20655
|
-
*
|
|
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
|
|
20662
|
-
*
|
|
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
|
|
20666
|
-
* in this library uses,
|
|
20667
|
-
*
|
|
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
|
|
20673
|
-
*
|
|
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)`
|
|
20679
|
-
*
|
|
20680
|
-
*
|
|
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
|
|
21155
|
-
*
|
|
21156
|
-
*
|
|
21157
|
-
*
|
|
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
|
|
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
|
|
21281
|
-
* platform.
|
|
21282
|
-
*
|
|
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**,
|
|
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
|
|
21287
|
-
*
|
|
20964
|
+
* its own value through `ElementInternals`, which also carries validity and
|
|
20965
|
+
* answers a form reset.
|
|
21288
20966
|
*
|
|
21289
|
-
* `value` and `defaultValue` are separate
|
|
21290
|
-
* `defaultChecked` are: `value` is what is in the field now
|
|
21291
|
-
*
|
|
21292
|
-
*
|
|
21293
|
-
*
|
|
21294
|
-
*
|
|
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
|
|
21199
|
+
* reading the markup.
|
|
21540
21200
|
*
|
|
21541
|
-
* **One key per element, with `keys` as the stated exception.** A
|
|
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:
|
|
21544
|
-
*
|
|
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
|
|
21551
|
-
*
|
|
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
|
|
21554
|
-
*
|
|
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
|
|
21634
|
-
*
|
|
21635
|
-
*
|
|
21636
|
-
*
|
|
21637
|
-
*
|
|
21638
|
-
*
|
|
21639
|
-
*
|
|
21640
|
-
*
|
|
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.
|
|
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
|
|
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.
|
|
22051
|
-
*
|
|
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.
|
|
22376
|
-
*
|
|
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
|
|
22381
|
-
*
|
|
22382
|
-
*
|
|
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
|
|
22386
|
-
*
|
|
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
|
|
22796
|
-
*
|
|
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
|
-
*
|
|
22817
|
-
*
|
|
22818
|
-
* and
|
|
22819
|
-
*
|
|
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"
|
|
23223
|
-
*
|
|
23224
|
-
*
|
|
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
|
|
23232
|
-
*
|
|
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
|
|
23242
|
-
*
|
|
23243
|
-
*
|
|
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`.
|
|
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
|
|
23253
|
-
*
|
|
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
|
|
23676
|
-
*
|
|
23677
|
-
*
|
|
23678
|
-
*
|
|
23679
|
-
*
|
|
23680
|
-
*
|
|
23681
|
-
*
|
|
23682
|
-
*
|
|
23683
|
-
*
|
|
23684
|
-
*
|
|
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
|
|
23786
|
-
* numbers to show and where the runs break,
|
|
23787
|
-
*
|
|
23788
|
-
*
|
|
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
|
|
23794
|
-
*
|
|
23795
|
-
*
|
|
23796
|
-
*
|
|
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
|
|
23799
|
-
*
|
|
23800
|
-
*
|
|
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
|
|
23810
|
-
*
|
|
23811
|
-
*
|
|
23812
|
-
* `helix-navigate` first, and `preventDefault()`
|
|
23813
|
-
*
|
|
23814
|
-
*
|
|
23815
|
-
*
|
|
23816
|
-
*
|
|
23817
|
-
*
|
|
23818
|
-
*
|
|
23819
|
-
*
|
|
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
|
|
24084
|
-
*
|
|
24085
|
-
*
|
|
24086
|
-
*
|
|
24087
|
-
*
|
|
24088
|
-
*
|
|
24089
|
-
*
|
|
24090
|
-
*
|
|
24091
|
-
*
|
|
24092
|
-
*
|
|
24093
|
-
*
|
|
24094
|
-
*
|
|
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
|
|
24472
|
-
*
|
|
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
|
|
24478
|
-
*
|
|
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
|
|
24990
|
-
*
|
|
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
|
-
*
|
|
25019
|
-
*
|
|
25020
|
-
*
|
|
25021
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
25586
|
-
*
|
|
25587
|
-
*
|
|
25588
|
-
*
|
|
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.**
|
|
26099
|
-
*
|
|
26100
|
-
*
|
|
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,
|
|
26107
|
-
*
|
|
26108
|
-
*
|
|
26109
|
-
*
|
|
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
|
-
*
|
|
26121
|
-
*
|
|
26122
|
-
*
|
|
26123
|
-
*
|
|
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
|
|
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
|
|
26163
|
-
*
|
|
26164
|
-
*
|
|
26165
|
-
*
|
|
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.**
|
|
26451
|
-
*
|
|
26452
|
-
*
|
|
26453
|
-
*
|
|
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
|
|
26459
|
-
*
|
|
26460
|
-
*
|
|
26461
|
-
*
|
|
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.**
|
|
26570
|
-
*
|
|
26571
|
-
*
|
|
26572
|
-
*
|
|
26573
|
-
*
|
|
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
|
|
26583
|
-
* skipped.
|
|
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,
|
|
26588
|
-
*
|
|
26589
|
-
*
|
|
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
|
|
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
|
|
28353
|
-
*
|
|
28354
|
-
*
|
|
28355
|
-
*
|
|
28356
|
-
*
|
|
28357
|
-
*
|
|
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.
|
|
28561
|
-
*
|
|
28562
|
-
*
|
|
28563
|
-
*
|
|
28564
|
-
*
|
|
28565
|
-
*
|
|
28566
|
-
* the
|
|
28567
|
-
*
|
|
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
|
-
*
|
|
28892
|
-
* the
|
|
28893
|
-
*
|
|
28894
|
-
*
|
|
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
|
|
28906
|
-
*
|
|
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
|
-
*
|
|
28914
|
-
*
|
|
28915
|
-
*
|
|
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.**
|
|
28919
|
-
* `
|
|
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
|
|
29103
|
-
*
|
|
29104
|
-
*
|
|
29105
|
-
*
|
|
29106
|
-
*
|
|
29107
|
-
*
|
|
29108
|
-
*
|
|
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.**
|
|
29316
|
-
* branch showing its children is the same state a disclosure holds
|
|
29317
|
-
*
|
|
29318
|
-
*
|
|
29319
|
-
*
|
|
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
|
-
*
|
|
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`
|
|
29327
|
-
*
|
|
29328
|
-
*
|
|
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
|
-
*
|
|
29351
|
-
*
|
|
29352
|
-
*
|
|
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
|
|
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
|
|
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
|
|
29948
|
-
*
|
|
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
|
|
29954
|
-
*
|
|
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
|
|
29960
|
-
*
|
|
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
|
|
29965
|
-
*
|
|
29966
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
30260
|
-
*
|
|
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
|
|
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
|
|
30627
|
-
*
|
|
30628
|
-
*
|
|
30629
|
-
*
|
|
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
|
|
30635
|
-
*
|
|
30636
|
-
*
|
|
30637
|
-
*
|
|
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
|
|
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
|
|
30731
|
-
*
|
|
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
|
|
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
|
|
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
|
|
31303
|
-
*
|
|
31304
|
-
*
|
|
31305
|
-
*
|
|
31306
|
-
* `role="list"` is set explicitly on the `<ol>` even though it is
|
|
31307
|
-
*
|
|
31308
|
-
*
|
|
31309
|
-
*
|
|
31310
|
-
* Items are slotted rather than wrapped, so they are `<ol>` children in the
|
|
31311
|
-
* tree and each carries `role="listitem"` itself.
|
|
31312
|
-
*
|
|
31313
|
-
* **The trail does not measure itself, and the overflow is markup.**
|
|
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
|
|
32150
|
-
* those is a variant of a conversation: they are containers
|
|
32151
|
-
*
|
|
32152
|
-
*
|
|
32153
|
-
*
|
|
32154
|
-
*
|
|
32155
|
-
*
|
|
32156
|
-
*
|
|
32157
|
-
*
|
|
32158
|
-
*
|
|
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
|
|
33023
|
-
* a panel behind a text field
|
|
33024
|
-
*
|
|
33025
|
-
*
|
|
33026
|
-
*
|
|
33027
|
-
*
|
|
33028
|
-
*
|
|
33029
|
-
*
|
|
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
|
|
33040
|
-
*
|
|
33041
|
-
*
|
|
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
|
|
33270
|
-
*
|
|
33271
|
-
* scrolling an option into view.
|
|
33272
|
-
*
|
|
33273
|
-
*
|
|
33274
|
-
*
|
|
33275
|
-
*
|
|
33276
|
-
*
|
|
33277
|
-
*
|
|
33278
|
-
*
|
|
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,
|
|
33289
|
-
*
|
|
33290
|
-
*
|
|
33291
|
-
*
|
|
33292
|
-
*
|
|
33293
|
-
*
|
|
33294
|
-
*
|
|
33295
|
-
*
|
|
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
|
|
33314
|
-
*
|
|
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
|
|
33712
|
-
* failed
|
|
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,
|
|
33717
|
-
*
|
|
33718
|
-
*
|
|
33719
|
-
*
|
|
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
|
|
33949
|
-
*
|
|
33950
|
-
*
|
|
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
|
|
33965
|
-
*
|
|
33966
|
-
*
|
|
33967
|
-
*
|
|
33968
|
-
*
|
|
33969
|
-
*
|
|
33970
|
-
*
|
|
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
|
|
34150
|
-
*
|
|
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
|
|
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
|
|
34156
|
-
*
|
|
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`
|
|
34450
|
-
*
|
|
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
|
-
* `
|
|
34465
|
-
*
|
|
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
|
-
* `
|
|
34471
|
-
*
|
|
34472
|
-
*
|
|
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
|
-
*
|
|
34475
|
-
*
|
|
34476
|
-
*
|
|
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
|
|
34704
|
-
*
|
|
34705
|
-
*
|
|
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
|
|
34710
|
-
*
|
|
34711
|
-
*
|
|
34712
|
-
*
|
|
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,
|
|
34927
|
-
*
|
|
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
|
-
*
|
|
34947
|
-
*
|
|
34948
|
-
*
|
|
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
|
|
35487
|
-
*
|
|
35488
|
-
*
|
|
35489
|
-
* So the input stays,
|
|
35490
|
-
* and the visible trigger is a `<label for
|
|
35491
|
-
* not
|
|
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
|
|
35775
|
-
*
|
|
35776
|
-
*
|
|
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
|
|
35783
|
-
*
|
|
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
|
|
35787
|
-
* in this library uses,
|
|
35788
|
-
*
|
|
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
|
|
35794
|
-
*
|
|
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)`
|
|
35800
|
-
*
|
|
35801
|
-
*
|
|
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
|
|
36283
|
-
*
|
|
36284
|
-
*
|
|
36285
|
-
*
|
|
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
|
|
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
|
|
36412
|
-
* platform.
|
|
36413
|
-
*
|
|
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**,
|
|
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
|
|
36418
|
-
*
|
|
35189
|
+
* its own value through `ElementInternals`, which also carries validity and
|
|
35190
|
+
* answers a form reset.
|
|
36419
35191
|
*
|
|
36420
|
-
* `value` and `defaultValue` are separate
|
|
36421
|
-
* `defaultChecked` are: `value` is what is in the field now
|
|
36422
|
-
*
|
|
36423
|
-
*
|
|
36424
|
-
*
|
|
36425
|
-
*
|
|
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
|
|
35427
|
+
* reading the markup.
|
|
36674
35428
|
*
|
|
36675
|
-
* **One key per element, with `keys` as the stated exception.** A
|
|
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:
|
|
36678
|
-
*
|
|
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
|
|
36685
|
-
*
|
|
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
|
|
36688
|
-
*
|
|
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
|
|
36771
|
-
*
|
|
36772
|
-
*
|
|
36773
|
-
*
|
|
36774
|
-
*
|
|
36775
|
-
*
|
|
36776
|
-
*
|
|
36777
|
-
*
|
|
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.
|
|
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
|
|
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.
|
|
37200
|
-
*
|
|
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.
|
|
37531
|
-
*
|
|
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
|
|
37536
|
-
*
|
|
37537
|
-
*
|
|
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
|
|
37541
|
-
*
|
|
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
|
|
37960
|
-
*
|
|
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
|
-
*
|
|
37981
|
-
*
|
|
37982
|
-
* and
|
|
37983
|
-
*
|
|
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"
|
|
38393
|
-
*
|
|
38394
|
-
*
|
|
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
|
|
38402
|
-
*
|
|
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
|
|
38412
|
-
*
|
|
38413
|
-
*
|
|
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`.
|
|
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
|
|
38423
|
-
*
|
|
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
|
|
38851
|
-
*
|
|
38852
|
-
*
|
|
38853
|
-
*
|
|
38854
|
-
*
|
|
38855
|
-
*
|
|
38856
|
-
*
|
|
38857
|
-
*
|
|
38858
|
-
*
|
|
38859
|
-
*
|
|
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
|
|
38964
|
-
* numbers to show and where the runs break,
|
|
38965
|
-
*
|
|
38966
|
-
*
|
|
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
|
|
38972
|
-
*
|
|
38973
|
-
*
|
|
38974
|
-
*
|
|
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
|
|
38977
|
-
*
|
|
38978
|
-
*
|
|
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
|
|
38988
|
-
*
|
|
38989
|
-
*
|
|
38990
|
-
* `helix-navigate` first, and `preventDefault()`
|
|
38991
|
-
*
|
|
38992
|
-
*
|
|
38993
|
-
*
|
|
38994
|
-
*
|
|
38995
|
-
*
|
|
38996
|
-
*
|
|
38997
|
-
*
|
|
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
|
|
39264
|
-
*
|
|
39265
|
-
*
|
|
39266
|
-
*
|
|
39267
|
-
*
|
|
39268
|
-
*
|
|
39269
|
-
*
|
|
39270
|
-
*
|
|
39271
|
-
*
|
|
39272
|
-
*
|
|
39273
|
-
*
|
|
39274
|
-
*
|
|
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
|
|
39659
|
-
*
|
|
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
|
|
39665
|
-
*
|
|
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
|
|
40190
|
-
*
|
|
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
|
-
*
|
|
40219
|
-
*
|
|
40220
|
-
*
|
|
40221
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
40796
|
-
*
|
|
40797
|
-
*
|
|
40798
|
-
*
|
|
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.**
|
|
41319
|
-
*
|
|
41320
|
-
*
|
|
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,
|
|
41327
|
-
*
|
|
41328
|
-
*
|
|
41329
|
-
*
|
|
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
|
-
*
|
|
41341
|
-
*
|
|
41342
|
-
*
|
|
41343
|
-
*
|
|
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
|
|
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
|
|
41383
|
-
*
|
|
41384
|
-
*
|
|
41385
|
-
*
|
|
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.**
|
|
41680
|
-
*
|
|
41681
|
-
*
|
|
41682
|
-
*
|
|
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
|
|
41688
|
-
*
|
|
41689
|
-
*
|
|
41690
|
-
*
|
|
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.**
|
|
41802
|
-
*
|
|
41803
|
-
*
|
|
41804
|
-
*
|
|
41805
|
-
*
|
|
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
|
|
41815
|
-
* skipped.
|
|
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,
|
|
41820
|
-
*
|
|
41821
|
-
*
|
|
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
|
|
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
|
|
43624
|
-
*
|
|
43625
|
-
*
|
|
43626
|
-
*
|
|
43627
|
-
*
|
|
43628
|
-
*
|
|
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.
|
|
43838
|
-
*
|
|
43839
|
-
*
|
|
43840
|
-
*
|
|
43841
|
-
*
|
|
43842
|
-
*
|
|
43843
|
-
* the
|
|
43844
|
-
*
|
|
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
|
-
*
|
|
44176
|
-
* the
|
|
44177
|
-
*
|
|
44178
|
-
*
|
|
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
|
|
44190
|
-
*
|
|
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
|
-
*
|
|
44198
|
-
*
|
|
44199
|
-
*
|
|
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.**
|
|
44203
|
-
* `
|
|
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
|
|
44390
|
-
*
|
|
44391
|
-
*
|
|
44392
|
-
*
|
|
44393
|
-
*
|
|
44394
|
-
*
|
|
44395
|
-
*
|
|
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.**
|
|
44609
|
-
* branch showing its children is the same state a disclosure holds
|
|
44610
|
-
*
|
|
44611
|
-
*
|
|
44612
|
-
*
|
|
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
|
-
*
|
|
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`
|
|
44620
|
-
*
|
|
44621
|
-
*
|
|
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
|
-
*
|
|
44644
|
-
*
|
|
44645
|
-
*
|
|
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
|
|
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
|
|
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
|
|
45253
|
-
*
|
|
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
|
|
45259
|
-
*
|
|
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
|
|
45265
|
-
*
|
|
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
|
|
45270
|
-
*
|
|
45271
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
45568
|
-
*
|
|
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
|
|
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
|
*
|