@fusion.dev/helix-headless 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/custom-elements.json +61 -65
  2. package/dist/chat/composer/chat-composer.d.ts +1 -1
  3. package/dist/chat/message/chat-message.d.ts +1 -1
  4. package/dist/chat/message/chat-message.js +1 -1
  5. package/dist/chat/root/chat-root.d.ts +1 -1
  6. package/dist/color-picker/root/color-picker-root.js +1 -2
  7. package/dist/date-picker/root/date-picker-root.d.ts +1 -1
  8. package/dist/element-events.generated.js +0 -1
  9. package/dist/format-date/root/format-date-root.d.ts +1 -1
  10. package/dist/notifications/group/notification-group.d.ts +17 -3
  11. package/dist/notifications/group/notification-group.js +8 -11
  12. package/dist/notifications/notification/notification.d.ts +3 -1
  13. package/dist/notifications/notification/notification.js +1 -1
  14. package/dist/notifications/root/notifications-root.d.ts +8 -3
  15. package/dist/option/root/option-root.d.ts +21 -11
  16. package/dist/option/root/option-root.js +2 -3
  17. package/dist/radio/root/radio-root.d.ts +16 -5
  18. package/dist/radio/root/radio-root.js +2 -3
  19. package/dist/slider/root/slider-root.d.ts +10 -3
  20. package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
  21. package/dist/speed-dial/root/speed-dial-root.d.ts +1 -1
  22. package/dist/splitter/root/splitter-root.d.ts +26 -3
  23. package/dist/splitter/root/splitter-root.js +4 -3
  24. package/dist/toast/item/toast-item.d.ts +1 -1
  25. package/dist/toast/root/toast-root.d.ts +2 -2
  26. package/dist/toggle/group/toggle-group.d.ts +45 -1
  27. package/dist/toggle/group/toggle-group.js +11 -0
  28. package/dist/toggle/root/toggle-root.d.ts +17 -6
  29. package/dist/toggle/root/toggle-root.js +2 -3
  30. package/dist/tour/root/tour-root.d.ts +0 -1
  31. package/package.json +5 -5
  32. package/types/jsx.d.ts +246 -80
  33. package/types/vue.d.ts +58 -22
@@ -11148,7 +11148,7 @@
11148
11148
  "helix": {
11149
11149
  "category": "forms",
11150
11150
  "since": "0.1.0",
11151
- "status": "experimental",
11151
+ "status": "stable",
11152
11152
  "documentation": "https://fusion.dev/helix/components/chat",
11153
11153
  "aliases": [
11154
11154
  "Message box",
@@ -11882,7 +11882,7 @@
11882
11882
  "helix": {
11883
11883
  "category": "feedback",
11884
11884
  "since": "0.1.0",
11885
- "status": "experimental",
11885
+ "status": "stable",
11886
11886
  "documentation": "https://fusion.dev/helix/components/chat",
11887
11887
  "aliases": [
11888
11888
  "Message",
@@ -13286,7 +13286,7 @@
13286
13286
  "helix": {
13287
13287
  "category": "feedback",
13288
13288
  "since": "0.1.0",
13289
- "status": "experimental",
13289
+ "status": "stable",
13290
13290
  "documentation": "https://fusion.dev/helix/components/chat",
13291
13291
  "aliases": [
13292
13292
  "Conversation",
@@ -30667,7 +30667,7 @@
30667
30667
  "helix": {
30668
30668
  "category": "forms",
30669
30669
  "since": "0.1.0",
30670
- "status": "experimental",
30670
+ "status": "stable",
30671
30671
  "documentation": "https://fusion.dev/helix/components/date-picker",
30672
30672
  "aliases": [
30673
30673
  "Calendar",
@@ -42521,7 +42521,7 @@
42521
42521
  "helix": {
42522
42522
  "category": "typography",
42523
42523
  "since": "0.1.0",
42524
- "status": "experimental",
42524
+ "status": "stable",
42525
42525
  "documentation": "https://fusion.dev/helix/components/format-date",
42526
42526
  "aliases": [
42527
42527
  "RelativeTime",
@@ -42533,7 +42533,7 @@
42533
42533
  "part": "Root",
42534
42534
  "examples": [
42535
42535
  {
42536
- "description": "The same readings on the headless tier, where the value is the element's own text.",
42536
+ "description": "The same readings on the headless tier, with every rule written by hand.",
42537
42537
  "slug": "preview"
42538
42538
  }
42539
42539
  ],
@@ -57791,6 +57791,16 @@
57791
57791
  "description": "How many the group says it stands for, which is the count or the rows.",
57792
57792
  "readonly": true
57793
57793
  },
57794
+ {
57795
+ "kind": "field",
57796
+ "name": "counted",
57797
+ "type": {
57798
+ "text": "number | undefined"
57799
+ },
57800
+ "privacy": "private",
57801
+ "description": "The same number where anything can know it, and nothing where nothing can.\n\n**A server has no rows to count and must not say zero.** `items` reads\n`knownChildren`, which is empty on a server and while hydrating what one\nsent, so a group written around three notifications with no `count` of its\nown served `<span part=\"count\">0</span>`: a crawler, and a reader before the\npage has run, given a group that says it holds nothing over the three rows\nunderneath it. Not knowing is not zero, which is the rule `MixinCollection`\nalready states about an empty list.\n\nA declared `count` is a fact about the group rather than about its children,\nso it serves whole, which is the shape a feed trimmed by a server already\nwants: it is the number the rows were cut from.",
57802
+ "readonly": true
57803
+ },
57794
57804
  {
57795
57805
  "kind": "method",
57796
57806
  "name": "assign",
@@ -57808,16 +57818,6 @@
57808
57818
  "privacy": "private",
57809
57819
  "readonly": true
57810
57820
  },
57811
- {
57812
- "kind": "field",
57813
- "name": "folded",
57814
- "type": {
57815
- "text": "number"
57816
- },
57817
- "privacy": "private",
57818
- "description": "How many rows the collapse is hiding, for the control to say so.",
57819
- "readonly": true
57820
- },
57821
57821
  {
57822
57822
  "kind": "field",
57823
57823
  "name": "open",
@@ -58348,7 +58348,7 @@
58348
58348
  "helix": {
58349
58349
  "category": "feedback",
58350
58350
  "since": "0.24.0",
58351
- "status": "experimental",
58351
+ "status": "stable",
58352
58352
  "documentation": "https://fusion.dev/helix/components/notifications",
58353
58353
  "aliases": [
58354
58354
  "NotificationSection",
@@ -58481,6 +58481,10 @@
58481
58481
  "description": "A block belonging to the row rather than a line about it: a quoted comment, a status moving from one value to another, a preview. Unlike `caption` nothing here sets a size or an ink, because whatever fills it usually brings its own.",
58482
58482
  "name": "detail"
58483
58483
  },
58484
+ {
58485
+ "description": "Replaces the glyph inside the dismiss control, which is drawn only where the row is `dismissible`.",
58486
+ "name": "dismiss"
58487
+ },
58484
58488
  {
58485
58489
  "description": "An avatar or icon identifying who or what it came from.",
58486
58490
  "name": "media"
@@ -59058,7 +59062,7 @@
59058
59062
  "helix": {
59059
59063
  "category": "feedback",
59060
59064
  "since": "0.1.0",
59061
- "status": "experimental",
59065
+ "status": "stable",
59062
59066
  "documentation": "https://fusion.dev/helix/components/notifications",
59063
59067
  "aliases": [
59064
59068
  "Notification item",
@@ -59283,7 +59287,7 @@
59283
59287
  "text": "void"
59284
59288
  }
59285
59289
  },
59286
- "description": "Says whether anything in the feed has media, so every item can hold the\ncolumn open whether or not it has one of its own.\n\n**A fact no item can answer for itself**, which is why it is here. An item\nknows about its own media slot and nothing about its neighbors, so a feed\nwhere some rows have an avatar and some do not draws two different left\nedges for its text: measured on a four item feed, the rows without media\nstarted their text 32 pixels to the left of the rows with it. The styled\ntier turns this into a width; this tier ships no stylesheet and is\nunaffected.\n\nRead off the light DOM rather than off the items, so it does not depend on\nwhich children have upgraded by the time this runs."
59290
+ "description": "Says whether anything in the feed has media, so every item can hold the\ncolumn open whether or not it has one of its own.\n\n**A fact no item can answer for itself**, which is why it is here. An item\nknows about its own media slot and nothing about its neighbors, so a feed\nwhere some rows have an avatar and some do not draws two different left\nedges for its text: measured on a four item feed, the rows without media\nstarted their text 32 pixels to the left of the rows with it. The styled\ntier turns this into a width; this tier ships no stylesheet and is\nunaffected.\n\n**What is asked of each row is its light DOM, not the row.** A notification\npublishes no property for this, and asking one would make the answer depend\non the row having drawn itself; a `[slot=\"media\"]` child is there from the\nmoment the markup is parsed. The rows themselves come from `items`, which\ndoes need them upgraded, and that is the honest limit rather than a claim\nthis had made the other way: a row that upgrades late is counted on the next\nupdate, which its own `slotchange` asks for."
59287
59291
  },
59288
59292
  {
59289
59293
  "kind": "method",
@@ -59917,7 +59921,7 @@
59917
59921
  "helix": {
59918
59922
  "category": "feedback",
59919
59923
  "since": "0.1.0",
59920
- "status": "experimental",
59924
+ "status": "stable",
59921
59925
  "documentation": "https://fusion.dev/helix/components/notifications",
59922
59926
  "aliases": [
59923
59927
  "Notification feed",
@@ -63024,13 +63028,7 @@
63024
63028
  "type": {
63025
63029
  "text": "boolean"
63026
63030
  },
63027
- "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so what is captured here is what\nthe markup said at upgrade, before anything could overwrite it: read the\nattribute later and the listbox's own writes answer instead.\n\n**The deeper half is 302 and is not this.** State reflecting under the\ndeclaration's name is the fault `TreeItem` already avoids by mirroring to\n`data-selected`, and four families here still write `selected` back into a\nconsumer's markup. Splitting them means moving what every stylesheet selects\non, which is a change of its own rather than a property being added."
63028
- },
63029
- {
63030
- "kind": "field",
63031
- "name": "seeded",
63032
- "privacy": "private",
63033
- "description": "What the markup said, read once at construction for the reason above."
63031
+ "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so the declaration is the\nattribute and the state is the property.\n\n**The attribute, read when it is asked for, and never a snapshot taken in\nthe constructor.** A field initializer runs there, and an element the HTML\nparser created has none of its attributes yet at that moment: measured on\nthis element, on `Radio` and on `Toggle`, `<helix-option value=\"a\"\nselected>` reported `defaultSelected` as `false` both from parsed markup\nand from `createElement` followed by `setAttribute`, which is every way a\nconsumer writes one. The snapshot could only ever be true for an element\nalready in the document when `customElements.define` ran.\n\nNothing overwrites it either, which is what makes reading it late correct\nrather than merely later: `selected` does not reflect, for the reason\n`willUpdate` records, so the listbox's writes never reach the attribute and\nwhat it says is what the markup said.\n\n**The deeper half is not this.** State reflecting under the declaration's\nname is the fault `TreeItem` avoids by mirroring to `data-selected`.\nSplitting them means moving what every stylesheet selects on, which is a\nchange of its own rather than a property being added."
63034
63032
  },
63035
63033
  {
63036
63034
  "kind": "field",
@@ -71504,13 +71502,7 @@
71504
71502
  "type": {
71505
71503
  "text": "boolean"
71506
71504
  },
71507
- "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so what is captured here is what\nthe markup said at upgrade, before anything could overwrite it: read the\nattribute later and the listbox's own writes answer instead.\n\n**The deeper half is not this.** State reflecting under the declaration's\nname is the fault `TreeItem` avoids by mirroring to `data-selected`.\nSplitting them means moving what every stylesheet selects on, which is a\nchange of its own rather than a property being added."
71508
- },
71509
- {
71510
- "kind": "field",
71511
- "name": "seeded",
71512
- "privacy": "private",
71513
- "description": "What the markup said, read once at construction for the reason above."
71505
+ "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so the declaration is the\nattribute and the state is the property.\n\n**The attribute, read when it is asked for, and never a snapshot taken in\nthe constructor.** A field initializer runs there, and an element the HTML\nparser created has none of its attributes yet at that moment: measured on\nthis element, on `Option` and on `Toggle`, `<helix-radio value=\"a\"\nselected>` reported `defaultSelected` as `false` both from parsed markup\nand from `createElement` followed by `setAttribute`, which is every way a\nconsumer writes one. The snapshot could only ever be true for an element\nalready in the document when `customElements.define` ran.\n\nNothing overwrites it either, which is what makes reading it late correct\nrather than merely later: `selected` does not reflect, for the reason\n`willUpdate` records, so the group's writes never reach the attribute and\nwhat it says is what the markup said.\n\n**The deeper half is not this.** State reflecting under the declaration's\nname is the fault `TreeItem` avoids by mirroring to `data-selected`.\nSplitting them means moving what every stylesheet selects on, which is a\nchange of its own rather than a property being added."
71514
71506
  },
71515
71507
  {
71516
71508
  "kind": "field",
@@ -77355,7 +77347,7 @@
77355
77347
  "declarations": [
77356
77348
  {
77357
77349
  "kind": "class",
77358
- "description": "A real `<input type=\"range\">`, so the drag, the arrow keys, Home and End, the\npage keys and the touch target are the platform's. The last is the one nobody\nnotices: a native range has a hit area larger than its thumb, sized by the\nplatform for a finger.\n\n**The value is a string, like every other form control's.** A range submits\ntext and `MixinControllerValue` holds text, so the number is a reading of the\nvalue. `valueAsNumber` is there for arithmetic.\n\n**Marks are drawn rather than left to `<datalist>`**, whose ticks cannot be\nstyled and which Firefox does not render for a range at all. A mark is\ndecoration; what a reader can land on is `step`, which the input enforces\nwhether or not anything is drawn. `markers` is a count rather than a flag, so\na slider from zero to a hundred cannot silently ask for a hundred and one.\n\n**A range is two of them.** There is no native two-thumb range, so two are\nstacked on one track and each thumb keeps its own.",
77350
+ "description": "A real `<input type=\"range\">`, so the drag, the arrow keys, Home and End, the\npage keys and the touch target are the platform's. The last is the one nobody\nnotices: a native range has a hit area larger than its thumb, sized by the\nplatform for a finger.\n\n**The value is a string, like every other form control's.** A range submits\ntext and `MixinControllerValue` holds text, so the number is a reading of the\nvalue. `valueAsNumber` is there for arithmetic.\n\n**Marks are drawn rather than left to `<datalist>`**, whose ticks cannot be\nstyled and which Firefox does not render for a range at all. A mark is\ndecoration; what a reader can land on is `step`, which the input enforces\nwhether or not anything is drawn. `markers` is a count rather than a flag, so\na slider from zero to a hundred cannot silently ask for a hundred and one.\n\n**A range is two of them.** There is no native two-thumb range, so two are\nstacked on one track and each thumb keeps its own.\n\n**`required` arrives with the field mixin and cannot fail here**, which is\nworth saying rather than leaving a reader to find. A range is never empty:\nthe platform shows its own midpoint whatever is set, and `willUpdate` seeds\nthat midpoint into `defaultValue` so the value agrees with the handle from the\nfirst render. HTML does not apply `required` to a range either, so it stays\noff the control and the marker beside the label is all it does.",
77359
77351
  "name": "HelixHeadlessSlider",
77360
77352
  "cssProperties": [
77361
77353
  {
@@ -77363,7 +77355,7 @@
77363
77355
  "name": "--slider-fraction"
77364
77356
  },
77365
77357
  {
77366
- "description": "Where the filled span starts, as a percentage of the track.",
77358
+ "description": "Where a range's filled span starts, as a fraction of the track, 0 to 1.",
77367
77359
  "name": "--slider-from"
77368
77360
  },
77369
77361
  {
@@ -77371,7 +77363,7 @@
77371
77363
  "name": "--slider-marker-at"
77372
77364
  },
77373
77365
  {
77374
- "description": "Where the filled span ends, as a percentage of the track.",
77366
+ "description": "Where a range's filled span ends, as a fraction of the track, 0 to 1.",
77375
77367
  "name": "--slider-to"
77376
77368
  }
77377
77369
  ],
@@ -78720,7 +78712,7 @@
78720
78712
  "helix": {
78721
78713
  "category": "forms",
78722
78714
  "since": "0.1.0",
78723
- "status": "experimental",
78715
+ "status": "stable",
78724
78716
  "documentation": "https://fusion.dev/helix/components/slider",
78725
78717
  "aliases": [
78726
78718
  "Range",
@@ -79830,7 +79822,7 @@
79830
79822
  "helix": {
79831
79823
  "category": "actions",
79832
79824
  "since": "0.1.0",
79833
- "status": "experimental",
79825
+ "status": "stable",
79834
79826
  "documentation": "https://fusion.dev/helix/components/speed-dial",
79835
79827
  "aliases": [
79836
79828
  "Speed dial action",
@@ -80567,7 +80559,7 @@
80567
80559
  "helix": {
80568
80560
  "category": "actions",
80569
80561
  "since": "0.1.0",
80570
- "status": "experimental",
80562
+ "status": "stable",
80571
80563
  "documentation": "https://fusion.dev/helix/components/speed-dial",
80572
80564
  "aliases": [
80573
80565
  "FAB",
@@ -81074,7 +81066,7 @@
81074
81066
  }
81075
81067
  }
81076
81068
  ],
81077
- "description": "Asks to move, and applies it where the position is this element's to move.\n\nNot announced per step: `helix-before-resize` is the settling, below. A drag that\nannounced every position would be asking a consumer to record a hundred\ndecisions to keep one."
81069
+ "description": "Moves the divider under a gesture that is still happening.\n\nNot announced per step: `helix-before-resize` is the settling, below. A drag that\nannounced every position would be asking a consumer to record a hundred\ndecisions to keep one.\n\n**A drag only, which is the whole of why applying before announcing is\nright here.** The divider has to follow the hand, and the one number worth\na decision is where the hand let go. Nothing discrete calls this: a key and\na double click go straight to `settle`, so their announcement comes before\ntheir change and refusing one takes the decision, and the corner's arrows\nalready did."
81078
81070
  },
81079
81071
  {
81080
81072
  "kind": "method",
@@ -81093,7 +81085,7 @@
81093
81085
  }
81094
81086
  }
81095
81087
  ],
81096
- "description": "Says the arrangement has settled, so a consumer can keep it.\n\nThrough the audited path, so a consumer who owns `position` is told what was\nasked for and decides, and one who does not has already had it applied."
81088
+ "description": "Says the arrangement has settled, so a consumer can keep it.\n\nThrough the audited path, so a consumer who owns `position` is told what was\nasked for and decides, and one who does not has already had it applied.\n\n**The second announcement is conditional on the first, because it is derived\nfrom it.** `shutAt` reads the position the gesture ended on, so a refused\n`helix-before-resize` leaves a collapse computed from a number that was\nrefused. Announced anyway, the refusal produced the outcome it was refusing:\nmeasured on a divider at 40 with a listener calling `preventDefault`, Home\nleft `position` reporting 0 and `collapsed` reporting `start`, because the\ncollapse applied and `position` reads the sliver once a pane is shut. The\nreturn of the first request is what says so, and it was being dropped: a\ncancelable event dispatched as a bare statement with nothing reading the\nanswer, which is the shape the navigation cohort named on `Outline` and left.\n\nRefusing the collapse alone still leaves the resize, which is the other way\nround and is coherent: the divider goes where the drag put it and the pane\nis not declared shut. What a consumer cannot have is a pane that collapses\nout from under a position they said no to."
81097
81089
  },
81098
81090
  {
81099
81091
  "kind": "field",
@@ -81597,7 +81589,7 @@
81597
81589
  "type": {
81598
81590
  "text": "HelixBeforeCollapseEvent"
81599
81591
  },
81600
- "description": "Fired before a pane shuts or reopens, and cancelable.",
81592
+ "description": "Fired before a pane shuts or reopens, and only where the position it is derived from stood. Cancelable: refusing it leaves the pane as it was and the divider where the gesture put it.",
81601
81593
  "name": "helix-before-collapse",
81602
81594
  "reactProp": "onhelix-before-collapse"
81603
81595
  },
@@ -81605,7 +81597,7 @@
81605
81597
  "type": {
81606
81598
  "text": "HelixBeforeResizeEvent"
81607
81599
  },
81608
- "description": "Fired before the divider settles, and cancelable.",
81600
+ "description": "Fired before the divider settles. Cancelable: refusing it takes the whole of where the gesture ended, so no collapse follows from it either. A drag has already drawn itself by then and holds where it was dropped until the consumer assigns their own.",
81609
81601
  "name": "helix-before-resize",
81610
81602
  "reactProp": "onhelix-before-resize"
81611
81603
  }
@@ -96647,7 +96639,7 @@
96647
96639
  "summary": "One message in the toast region.",
96648
96640
  "helix": {
96649
96641
  "since": "0.1.0",
96650
- "status": "experimental",
96642
+ "status": "stable",
96651
96643
  "documentation": "https://fusion.dev/helix/components/toast",
96652
96644
  "tier": "headless",
96653
96645
  "group": "BaseToast",
@@ -97091,12 +97083,11 @@
97091
97083
  "helix": {
97092
97084
  "category": "overlays",
97093
97085
  "since": "0.1.0",
97094
- "status": "experimental",
97086
+ "status": "stable",
97095
97087
  "documentation": "https://fusion.dev/helix/components/toast",
97096
97088
  "aliases": [
97097
97089
  "Toaster",
97098
- "Snackbar",
97099
- "Notifications"
97090
+ "Snackbar"
97100
97091
  ],
97101
97092
  "tier": "headless",
97102
97093
  "group": "BaseToast",
@@ -97186,9 +97177,28 @@
97186
97177
  {
97187
97178
  "description": "The group's items.",
97188
97179
  "name": ""
97180
+ },
97181
+ {
97182
+ "description": "Whatever sits after the track on its own line, such as a count or a reset.",
97183
+ "name": "end"
97184
+ },
97185
+ {
97186
+ "description": "Whatever sits before the track on its own line, such as an icon or a caption.",
97187
+ "name": "start"
97189
97188
  }
97190
97189
  ],
97191
97190
  "members": [
97191
+ {
97192
+ "kind": "method",
97193
+ "name": "adopt",
97194
+ "privacy": "private",
97195
+ "return": {
97196
+ "type": {
97197
+ "text": "void"
97198
+ }
97199
+ },
97200
+ "description": "Takes the markup's own answer where nothing has set a value.\n\n**The case a server renders**, and `Tabs` records the same fault from the\nother side. This element cannot choose on the server, having no children to\ncount, so a consumer whose first paint is right wrote `selected` on the\nitem: that serves `aria-checked=\"true\"`, and `sync` then cleared it one\nframe later, because `value` is `''` and nothing matches it. The shipped\n`disabled` example is exactly that markup, and drew both of its groups with\nnothing chosen.\n\n**Onto `defaultValue`, never onto `value`**, which is the same call\n`Slider` makes about the midpoint it seeds: what the markup declared is a\nfact about the markup, so it is where a reset returns to rather than\nsomething the reader chose. It also makes the group report the answer it is\nshowing, which marking the item alone would not: a `required` group would\notherwise tell a reader a value is missing while they are looking at one.\n\nA written `value` still wins, a declared property being a seed and a\ncorrection, and a group with neither still marks nothing at all.\n\n**The property and never `defaultSelected`, which is the attribute.** React\nassigns a JSX prop as a property where the custom element has one, and\nwrites no attribute at all, so keying on the attribute answers for markup\nand not for JSX. Measured by the parity check on the shipped `disabled`\nexample, whose two syntaxes are the same tree: 192 pixels apart, the HTML\nmarking `List` and the TSX marking nothing. The attribute seeds the\nproperty at upgrade, so reading the property covers both.\n\nRead before `sync` writes to it, which is the only moment it still holds\nwhat the consumer declared: after that it holds this group's answer, and\n`value` is no longer empty, so this returns above.\n\n**Called from `willUpdate` and from the slot, never from `sync`**, which\nruns in `updated`: a reactive property set there schedules a second update,\nand Lit's development build warns about exactly that once per group. From\n`willUpdate` the first render already carries the value, which is the pass\nthat has to be right. `children` is undefined on the server, whose element\nshim carries attributes and no tree, and that is the same guard\n`MixinCollection` records for the same reason."
97201
+ },
97192
97202
  {
97193
97203
  "kind": "method",
97194
97204
  "name": "sync",
@@ -98278,7 +98288,7 @@
98278
98288
  "summary": "A row of options with the selection marked by a moving indicator.",
98279
98289
  "helix": {
98280
98290
  "since": "0.1.0",
98281
- "status": "experimental",
98291
+ "status": "stable",
98282
98292
  "documentation": "https://fusion.dev/helix/components/toggle",
98283
98293
  "aliases": [
98284
98294
  "SegmentedControl",
@@ -98376,13 +98386,7 @@
98376
98386
  "type": {
98377
98387
  "text": "boolean"
98378
98388
  },
98379
- "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so what is captured here is what\nthe markup said at upgrade, before anything could overwrite it: read the\nattribute later and the listbox's own writes answer instead.\n\n**The deeper half is not this.** State reflecting under the declaration's\nname is the fault `TreeItem` avoids by mirroring to `data-selected`.\nSplitting them means moving what every stylesheet selects on, which is a\nchange of its own rather than a property being added."
98380
- },
98381
- {
98382
- "kind": "field",
98383
- "name": "seeded",
98384
- "privacy": "private",
98385
- "description": "What the markup said, read once at construction for the reason above."
98389
+ "description": "Whether the markup declared this one chosen, which is what a reset returns to.\n\n`<option selected>` reflects to `defaultSelected` and `option.selected` is\nlive state that does not reflect, and those are two different facts. This\nelement has one `selected` doing both jobs, so the declaration is the\nattribute and the state is the property.\n\n**The attribute, read when it is asked for, and never a snapshot taken in\nthe constructor.** A field initializer runs there, and an element the HTML\nparser created has none of its attributes yet at that moment: measured on\nthis element, on `Option` and on `Radio`, `<helix-toggle value=\"light\"\nselected>` reported `defaultSelected` as `false` both from parsed markup\nand from `createElement` followed by `setAttribute`, which is every way a\nconsumer writes one. The snapshot could only ever be true for an element\nalready in the document when `customElements.define` ran.\n\nNothing overwrites it either, which is what makes reading it late correct\nrather than merely later: `selected` does not reflect, for the reason\n`willUpdate` records, so the group's writes never reach the attribute and\nwhat it says is what the markup said.\n\n**The deeper half is not this.** State reflecting under the declaration's\nname is the fault `TreeItem` avoids by mirroring to `data-selected`.\nSplitting them means moving what every stylesheet selects on, which is a\nchange of its own rather than a property being added."
98386
98390
  },
98387
98391
  {
98388
98392
  "kind": "field",
@@ -98825,7 +98829,7 @@
98825
98829
  "helix": {
98826
98830
  "category": "actions",
98827
98831
  "since": "0.1.0",
98828
- "status": "experimental",
98832
+ "status": "stable",
98829
98833
  "documentation": "https://fusion.dev/helix/components/toggle",
98830
98834
  "aliases": [
98831
98835
  "Segment",
@@ -101153,14 +101157,6 @@
101153
101157
  "description": "A stop's own controls asking the tour to move, dispatched by the stop and heard here because the tour is what moves.",
101154
101158
  "name": "helix-tour-ask",
101155
101159
  "reactProp": "onhelix-tour-ask"
101156
- },
101157
- {
101158
- "type": {
101159
- "text": "Event"
101160
- },
101161
- "description": "Says the state moved, carrying `newState` and `oldState`.",
101162
- "name": "toggle",
101163
- "reactProp": "ontoggle"
101164
101160
  }
101165
101161
  ],
101166
101162
  "attributes": [
@@ -19,7 +19,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
19
19
  * of what the reader wrote.
20
20
  *
21
21
  * @since 0.1.0
22
- * @status experimental
22
+ * @status stable
23
23
  * @category forms
24
24
  * @aliases Message box, Prompt input
25
25
  * @documentation https://fusion.dev/helix/components/chat
@@ -23,7 +23,7 @@ export declare const FAILED_LABEL = "Not sent";
23
23
  * completion is the only version of this that works.
24
24
  *
25
25
  * @since 0.1.0
26
- * @status experimental
26
+ * @status stable
27
27
  * @category feedback
28
28
  * @aliases Message, Bubble, Turn
29
29
  * @documentation https://fusion.dev/helix/components/chat
@@ -40,7 +40,7 @@ let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixEleme
40
40
  this.clock = Date.now();
41
41
  }
42
42
  hostAria(this.internals, { role: 'article' });
43
- this.toggleAttribute('aria-busy', this.state === 'streaming');
43
+ this.internals.ariaBusy = this.state === 'streaming' ? 'true' : null;
44
44
  }
45
45
  renderTime() {
46
46
  const moment = this.moment;
@@ -69,7 +69,7 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
69
69
  * turns as children.
70
70
  *
71
71
  * @since 0.1.0
72
- * @status experimental
72
+ * @status stable
73
73
  * @category feedback
74
74
  * @aliases Conversation, Transcript, Thread, Messages
75
75
  * @documentation https://fusion.dev/helix/components/chat
@@ -264,8 +264,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
264
264
  @click=${() => this.handleSwatch(preset)}
265
265
  ></button>`;
266
266
  })}
267
- </div>`}
268
- </div>`;
267
+ </div>`}`;
269
268
  }
270
269
  };
271
270
  __decorate([
@@ -21,7 +21,7 @@ declare const HelixHeadlessDatePicker_base: (new (...args: any[]) => import("@fu
21
21
  * write the same comma-separated `value`.
22
22
  *
23
23
  * @since 0.1.0
24
- * @status experimental
24
+ * @status stable
25
25
  * @category forms
26
26
  * @aliases Calendar, Date grid, Month view
27
27
  * @documentation https://fusion.dev/helix/components/date-picker
@@ -138,7 +138,6 @@ registerElementEvents({
138
138
  'helix-before-close',
139
139
  'helix-complete',
140
140
  'helix-tour-ask',
141
- 'toggle',
142
141
  ],
143
142
  'helix-headless-tour-stop': ['helix-tour-ask'],
144
143
  'helix-headless-tree': ['helix-activate', 'helix-before-activate', 'helix-select'],
@@ -30,7 +30,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
30
30
  * "yesterday".
31
31
  *
32
32
  * @since 0.1.0
33
- * @status experimental
33
+ * @status stable
34
34
  * @category typography
35
35
  * @aliases RelativeTime, Timestamp, TimeAgo
36
36
  * @documentation https://fusion.dev/helix/components/format-date
@@ -27,7 +27,7 @@ declare const HelixHeadlessNotificationGroup_base: (new (...args: any[]) => impo
27
27
  * Left off, it is the number of rows.
28
28
  *
29
29
  * @since 0.24.0
30
- * @status experimental
30
+ * @status stable
31
31
  * @category feedback
32
32
  * @aliases NotificationSection, FeedGroup
33
33
  * @documentation https://fusion.dev/helix/components/notifications
@@ -100,6 +100,22 @@ export declare class HelixHeadlessNotificationGroup extends HelixHeadlessNotific
100
100
  get items(): HelixHeadlessNotification[];
101
101
  /** How many the group says it stands for, which is the count or the rows. */
102
102
  get total(): number;
103
+ /**
104
+ * The same number where anything can know it, and nothing where nothing can.
105
+ *
106
+ * **A server has no rows to count and must not say zero.** `items` reads
107
+ * `knownChildren`, which is empty on a server and while hydrating what one
108
+ * sent, so a group written around three notifications with no `count` of its
109
+ * own served `<span part="count">0</span>`: a crawler, and a reader before the
110
+ * page has run, given a group that says it holds nothing over the three rows
111
+ * underneath it. Not knowing is not zero, which is the rule `MixinCollection`
112
+ * already states about an empty list.
113
+ *
114
+ * A declared `count` is a fact about the group rather than about its children,
115
+ * so it serves whole, which is the shape a feed trimmed by a server already
116
+ * wants: it is the number the rows were cut from.
117
+ */
118
+ private get counted();
103
119
  protected willUpdate(changed: PropertyValues): void;
104
120
  protected firstUpdated(changed: PropertyValues): void;
105
121
  protected updated(changed: PropertyValues): void;
@@ -119,8 +135,6 @@ export declare class HelixHeadlessNotificationGroup extends HelixHeadlessNotific
119
135
  */
120
136
  private assign;
121
137
  private readonly handleToggle;
122
- /** How many rows the collapse is hiding, for the control to say so. */
123
- private get folded();
124
138
  protected render(): TemplateResult;
125
139
  }
126
140
  declare global {
@@ -29,6 +29,9 @@ let HelixHeadlessNotificationGroup = class HelixHeadlessNotificationGroup extend
29
29
  get total() {
30
30
  return this.count ?? this.items.length;
31
31
  }
32
+ get counted() {
33
+ return this.count ?? (this.childrenKnown ? this.items.length : undefined);
34
+ }
32
35
  willUpdate(changed) {
33
36
  super.willUpdate(changed);
34
37
  hostAria(this.internals, this.label === '' ? { role: 'group' } : { label: this.label, role: 'group' });
@@ -60,11 +63,9 @@ let HelixHeadlessNotificationGroup = class HelixHeadlessNotificationGroup extend
60
63
  const label = this.renderRoot?.querySelector?.('slot[name="label"]');
61
64
  label?.assign?.(...[...this.children].filter((child) => child.getAttribute('slot') === 'label'));
62
65
  }
63
- get folded() {
64
- return Math.max(this.items.length - 1, 0);
65
- }
66
66
  render() {
67
- const collapsed = this.collapsible && !this.open;
67
+ const counted = this.counted;
68
+ const count = html `<span part="count">${counted ?? nothing}</span>`;
68
69
  return html `<div part="header">
69
70
  ${this.collapsible
70
71
  ? html `<button
@@ -76,17 +77,13 @@ let HelixHeadlessNotificationGroup = class HelixHeadlessNotificationGroup extend
76
77
  @click=${this.handleToggle}
77
78
  >
78
79
  <span part="label"><slot name="label">${this.label}</slot></span>
79
- <span part="count">${this.total}</span>
80
+ ${count}
80
81
  </button>`
81
82
  : html `<span part="label"><slot name="label">${this.label}</slot></span>
82
- <span part="count">${this.total}</span>`}
83
+ ${count}`}
83
84
  <span part="action"><slot name="action"></slot></span>
84
85
  </div>
85
- <div
86
- id=${ITEMS_ID}
87
- part="items"
88
- aria-label=${collapsed && this.folded > 0 ? `${this.folded} more` : nothing}
89
- >
86
+ <div id=${ITEMS_ID} part="items">
90
87
  <slot></slot>
91
88
  </div>`;
92
89
  }
@@ -30,7 +30,7 @@ import '../../format-date/index.js';
30
30
  * cancelable, and a `read` set by the consumer makes this element defer entirely.
31
31
  *
32
32
  * @since 0.1.0
33
- * @status experimental
33
+ * @status stable
34
34
  * @category feedback
35
35
  * @aliases Notification item, Inbox item
36
36
  * @documentation https://fusion.dev/helix/components/notifications
@@ -44,6 +44,8 @@ import '../../format-date/index.js';
44
44
  * @slot detail - A block belonging to the row rather than a line about it: a quoted
45
45
  * comment, a status moving from one value to another, a preview. Unlike `caption` nothing
46
46
  * here sets a size or an ink, because whatever fills it usually brings its own.
47
+ * @slot dismiss - Replaces the glyph inside the dismiss control, which is drawn
48
+ * only where the row is `dismissible`.
47
49
  * @slot media - An avatar or icon identifying who or what it came from.
48
50
  *
49
51
  * @event {HelixDismissEvent} helix-dismiss - Fired when a reader asks to remove it, and cancelable.
@@ -22,7 +22,7 @@ let HelixHeadlessNotification = class HelixHeadlessNotification extends HelixEle
22
22
  this.isNotification = true;
23
23
  this.readState = undefined;
24
24
  this.handleActions = () => {
25
- this.markControls();
25
+ this.markActions();
26
26
  };
27
27
  this.handleDismiss = (event) => {
28
28
  event.stopPropagation();
@@ -25,7 +25,7 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
25
25
  * either of them counting.
26
26
  *
27
27
  * @since 0.1.0
28
- * @status experimental
28
+ * @status stable
29
29
  * @category feedback
30
30
  * @aliases Notification feed, Inbox, Activity
31
31
  * @documentation https://fusion.dev/helix/components/notifications
@@ -174,8 +174,13 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
174
174
  * tier turns this into a width; this tier ships no stylesheet and is
175
175
  * unaffected.
176
176
  *
177
- * Read off the light DOM rather than off the items, so it does not depend on
178
- * which children have upgraded by the time this runs.
177
+ * **What is asked of each row is its light DOM, not the row.** A notification
178
+ * publishes no property for this, and asking one would make the answer depend
179
+ * on the row having drawn itself; a `[slot="media"]` child is there from the
180
+ * moment the markup is parsed. The rows themselves come from `items`, which
181
+ * does need them upgraded, and that is the honest limit rather than a claim
182
+ * this had made the other way: a row that upgrades late is counted on the next
183
+ * update, which its own `slotchange` asks for.
179
184
  */
180
185
  private markMedia;
181
186
  /**