stimeo-ui 0.12.0 → 0.14.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 (183) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/cable/index.d.ts +68 -14
  3. package/dist/cable/index.js +438 -152
  4. package/dist/cable/index.js.map +1 -1
  5. package/dist/controllers/accordion_controller.d.ts +1 -1
  6. package/dist/controllers/accordion_controller.js.map +1 -1
  7. package/dist/controllers/alert_dialog_controller.d.ts +1 -1
  8. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  9. package/dist/controllers/announcer_controller.d.ts +1 -1
  10. package/dist/controllers/announcer_controller.js.map +1 -1
  11. package/dist/controllers/auto_submit_controller.js.map +1 -1
  12. package/dist/controllers/breadcrumb_controller.d.ts +1 -1
  13. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  14. package/dist/controllers/calendar_controller.d.ts +4 -3
  15. package/dist/controllers/calendar_controller.js +34 -2
  16. package/dist/controllers/calendar_controller.js.map +1 -1
  17. package/dist/controllers/carousel_controller.js +9 -7
  18. package/dist/controllers/carousel_controller.js.map +1 -1
  19. package/dist/controllers/character_counter_controller.js.map +1 -1
  20. package/dist/controllers/clipboard_controller.d.ts +2 -2
  21. package/dist/controllers/clipboard_controller.js.map +1 -1
  22. package/dist/controllers/collapsible_controller.d.ts +1 -1
  23. package/dist/controllers/collapsible_controller.js.map +1 -1
  24. package/dist/controllers/color_picker_controller.d.ts +1 -1
  25. package/dist/controllers/color_picker_controller.js.map +1 -1
  26. package/dist/controllers/command_palette_controller.d.ts +3 -3
  27. package/dist/controllers/command_palette_controller.js +2 -2
  28. package/dist/controllers/command_palette_controller.js.map +1 -1
  29. package/dist/controllers/conditional_fields_controller.js +7 -1
  30. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  31. package/dist/controllers/confirm_controller.d.ts +2 -2
  32. package/dist/controllers/confirm_controller.js.map +1 -1
  33. package/dist/controllers/context_menu_controller.d.ts +1 -1
  34. package/dist/controllers/context_menu_controller.js.map +1 -1
  35. package/dist/controllers/countdown_controller.d.ts +1 -1
  36. package/dist/controllers/countdown_controller.js.map +1 -1
  37. package/dist/controllers/currency_input_controller.js +68 -23
  38. package/dist/controllers/currency_input_controller.js.map +1 -1
  39. package/dist/controllers/data_grid_controller.d.ts +1 -1
  40. package/dist/controllers/data_grid_controller.js.map +1 -1
  41. package/dist/controllers/date_range_picker_controller.d.ts +3 -3
  42. package/dist/controllers/date_range_picker_controller.js +34 -10
  43. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  44. package/dist/controllers/dialog_controller.d.ts +3 -3
  45. package/dist/controllers/dialog_controller.js.map +1 -1
  46. package/dist/controllers/direct_upload_controller.js +21 -10
  47. package/dist/controllers/direct_upload_controller.js.map +1 -1
  48. package/dist/controllers/dirty_form_controller.js.map +1 -1
  49. package/dist/controllers/dismissible_controller.d.ts +1 -1
  50. package/dist/controllers/dismissible_controller.js.map +1 -1
  51. package/dist/controllers/drawer_controller.d.ts +2 -2
  52. package/dist/controllers/drawer_controller.js +2 -2
  53. package/dist/controllers/drawer_controller.js.map +1 -1
  54. package/dist/controllers/dropdown_controller.d.ts +2 -2
  55. package/dist/controllers/dropdown_controller.js.map +1 -1
  56. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  57. package/dist/controllers/flash_controller.js.map +1 -1
  58. package/dist/controllers/focus_controller.d.ts +2 -2
  59. package/dist/controllers/focus_controller.js.map +1 -1
  60. package/dist/controllers/form_field_controller.js +7 -1
  61. package/dist/controllers/form_field_controller.js.map +1 -1
  62. package/dist/controllers/form_validation_controller.js.map +1 -1
  63. package/dist/controllers/frame_loading_controller.d.ts +3 -3
  64. package/dist/controllers/frame_loading_controller.js.map +1 -1
  65. package/dist/controllers/highlight_controller.js.map +1 -1
  66. package/dist/controllers/hover_card_controller.d.ts +1 -1
  67. package/dist/controllers/hover_card_controller.js.map +1 -1
  68. package/dist/controllers/idle_controller.d.ts +1 -1
  69. package/dist/controllers/idle_controller.js.map +1 -1
  70. package/dist/controllers/input_mask_controller.d.ts +3 -2
  71. package/dist/controllers/input_mask_controller.js +33 -12
  72. package/dist/controllers/input_mask_controller.js.map +1 -1
  73. package/dist/controllers/intersection_controller.js +10 -5
  74. package/dist/controllers/intersection_controller.js.map +1 -1
  75. package/dist/controllers/lazy_frame_controller.js +10 -5
  76. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  77. package/dist/controllers/listbox_controller.js.map +1 -1
  78. package/dist/controllers/local_time_controller.d.ts +4 -3
  79. package/dist/controllers/local_time_controller.js +34 -7
  80. package/dist/controllers/local_time_controller.js.map +1 -1
  81. package/dist/controllers/masonry_controller.d.ts +2 -2
  82. package/dist/controllers/masonry_controller.js +1 -1
  83. package/dist/controllers/masonry_controller.js.map +1 -1
  84. package/dist/controllers/menu_controller.d.ts +1 -1
  85. package/dist/controllers/menu_controller.js +10 -2
  86. package/dist/controllers/menu_controller.js.map +1 -1
  87. package/dist/controllers/menubar_controller.d.ts +2 -2
  88. package/dist/controllers/menubar_controller.js +10 -2
  89. package/dist/controllers/menubar_controller.js.map +1 -1
  90. package/dist/controllers/navigation_menu_controller.d.ts +1 -1
  91. package/dist/controllers/navigation_menu_controller.js +8 -2
  92. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  93. package/dist/controllers/nested_form_controller.js.map +1 -1
  94. package/dist/controllers/network_status_controller.js.map +1 -1
  95. package/dist/controllers/number_input_controller.js.map +1 -1
  96. package/dist/controllers/optimistic_controller.d.ts +23 -10
  97. package/dist/controllers/optimistic_controller.js +141 -20
  98. package/dist/controllers/optimistic_controller.js.map +1 -1
  99. package/dist/controllers/otp_controller.js +23 -10
  100. package/dist/controllers/otp_controller.js.map +1 -1
  101. package/dist/controllers/overflow_indicator_controller.d.ts +1 -1
  102. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  103. package/dist/controllers/overflow_menu_controller.js +10 -1
  104. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  105. package/dist/controllers/pagination_controller.js.map +1 -1
  106. package/dist/controllers/password_reveal_controller.d.ts +1 -1
  107. package/dist/controllers/password_reveal_controller.js.map +1 -1
  108. package/dist/controllers/password_strength_controller.d.ts +2 -1
  109. package/dist/controllers/password_strength_controller.js.map +1 -1
  110. package/dist/controllers/persist_controller.js.map +1 -1
  111. package/dist/controllers/pointer_drag_controller.js +10 -3
  112. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  113. package/dist/controllers/popover_controller.d.ts +1 -1
  114. package/dist/controllers/popover_controller.js.map +1 -1
  115. package/dist/controllers/portal_controller.d.ts +2 -2
  116. package/dist/controllers/portal_controller.js +21 -10
  117. package/dist/controllers/portal_controller.js.map +1 -1
  118. package/dist/controllers/radio_group_controller.d.ts +1 -1
  119. package/dist/controllers/radio_group_controller.js +11 -3
  120. package/dist/controllers/radio_group_controller.js.map +1 -1
  121. package/dist/controllers/read_more_controller.d.ts +1 -1
  122. package/dist/controllers/read_more_controller.js.map +1 -1
  123. package/dist/controllers/relative_time_controller.d.ts +3 -3
  124. package/dist/controllers/relative_time_controller.js +31 -5
  125. package/dist/controllers/relative_time_controller.js.map +1 -1
  126. package/dist/controllers/reset_before_cache_controller.js +23 -10
  127. package/dist/controllers/reset_before_cache_controller.js.map +1 -1
  128. package/dist/controllers/resizable_controller.js +7 -2
  129. package/dist/controllers/resizable_controller.js.map +1 -1
  130. package/dist/controllers/roving_controller.d.ts +1 -1
  131. package/dist/controllers/roving_controller.js +7 -3
  132. package/dist/controllers/roving_controller.js.map +1 -1
  133. package/dist/controllers/scroll_area_controller.js.map +1 -1
  134. package/dist/controllers/scroll_visibility_controller.d.ts +1 -1
  135. package/dist/controllers/scroll_visibility_controller.js +22 -13
  136. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  137. package/dist/controllers/scrollspy_controller.d.ts +1 -1
  138. package/dist/controllers/scrollspy_controller.js +11 -6
  139. package/dist/controllers/scrollspy_controller.js.map +1 -1
  140. package/dist/controllers/sidebar_controller.d.ts +1 -1
  141. package/dist/controllers/sidebar_controller.js.map +1 -1
  142. package/dist/controllers/skeleton_controller.d.ts +2 -2
  143. package/dist/controllers/skeleton_controller.js.map +1 -1
  144. package/dist/controllers/smart_sticky_header_controller.js +23 -12
  145. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  146. package/dist/controllers/spinner_controller.d.ts +3 -3
  147. package/dist/controllers/spinner_controller.js.map +1 -1
  148. package/dist/controllers/sticky_observer_controller.js +10 -5
  149. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  150. package/dist/controllers/submit_once_controller.d.ts +3 -3
  151. package/dist/controllers/submit_once_controller.js.map +1 -1
  152. package/dist/controllers/switch_controller.d.ts +1 -1
  153. package/dist/controllers/switch_controller.js.map +1 -1
  154. package/dist/controllers/tabs_controller.d.ts +1 -1
  155. package/dist/controllers/tabs_controller.js.map +1 -1
  156. package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
  157. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  158. package/dist/controllers/theme_controller.d.ts +5 -5
  159. package/dist/controllers/theme_controller.js +23 -13
  160. package/dist/controllers/theme_controller.js.map +1 -1
  161. package/dist/controllers/toast_controller.js +1 -1
  162. package/dist/controllers/toast_controller.js.map +1 -1
  163. package/dist/controllers/toggle_group_controller.js +11 -3
  164. package/dist/controllers/toggle_group_controller.js.map +1 -1
  165. package/dist/controllers/toolbar_controller.d.ts +1 -1
  166. package/dist/controllers/toolbar_controller.js +7 -3
  167. package/dist/controllers/toolbar_controller.js.map +1 -1
  168. package/dist/controllers/tooltip_controller.d.ts +1 -1
  169. package/dist/controllers/tooltip_controller.js.map +1 -1
  170. package/dist/controllers/transition_controller.d.ts +1 -1
  171. package/dist/controllers/transition_controller.js.map +1 -1
  172. package/dist/controllers/tree_view_controller.d.ts +4 -3
  173. package/dist/controllers/tree_view_controller.js.map +1 -1
  174. package/dist/index.js +259 -202
  175. package/dist/index.js.map +1 -1
  176. package/dist/inspector/cli.d.ts +39 -2
  177. package/dist/inspector/cli.js +81 -8
  178. package/dist/inspector/cli.js.map +1 -1
  179. package/dist/inspector/cli_bin.js +104 -8
  180. package/dist/inspector/cli_bin.js.map +1 -1
  181. package/dist/inspector/examples.json +5 -5
  182. package/dist/inspector/manifest.json +132 -3
  183. package/package.json +9 -11
package/CHANGELOG.md CHANGED
@@ -7,6 +7,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
  While the version is `0.x`, the public API (the `stimeo--*` data attributes) may
8
8
  change between releases.
9
9
 
10
+ ## [0.14.0] - 2026-09-19
11
+
12
+ Minor release with no new components. input-mask changes what a broken `tokens`
13
+ source falls back to, and currency-input, local-time, and relative-time narrow
14
+ which failures they absorb, so read Changed before upgrading. The Inspector
15
+ manifest stays on schema v12.
16
+
17
+ ### Added
18
+
19
+ - Inspector: `missing-action-event` (error) — a `data-action` that omits the
20
+ event on an element with no default one binds nothing, while the markup still
21
+ reads as wired. The elements that have a default are `<a>`, `<button>`,
22
+ `<details>`, `<form>`, `<input>`, `<select>`, and `<textarea>`.
23
+ - Inspector: `valueSyntaxConstraints` reports a `stimeo--otp` `pattern` that is
24
+ not a regular expression, and a `stimeo--input-mask` `tokens` that is not a
25
+ JSON object of them, before the page runs.
26
+
27
+ ### Changed
28
+
29
+ - input-mask: a `tokens` source that does not compile leaves that key on its
30
+ default (`9`, `a`, `*`) instead of dropping the key, and a source that
31
+ compiles only against the anchors the controller adds — `0)|(1` — is refused.
32
+ - currency-input, local-time, and relative-time absorb only what a declaration
33
+ can get wrong: a locale, time zone, currency code, or digit count `Intl`
34
+ rejects. Any other failure surfaces.
35
+ - Inspector: a `data-action` that omits the event resolves to the one Stimulus
36
+ binds for that element, so a shorthand on a `<form>` reports
37
+ `missing-action-completion` where it passed in silence.
38
+ - The markup examples in the published types name the event
39
+ (`click->stimeo--dialog#open`).
40
+
41
+ ## [0.13.0] - 2026-09-13
42
+
43
+ Minor release with no new components. The three server-bound components are
44
+ reworked — live-counter, presence, and optimistic — and each changed a contract,
45
+ so read Changed before upgrading. The Inspector manifest stays on schema v12.
46
+
47
+ ### Changed
48
+
49
+ - live-counter: a broadcast whose `count` or `delta` is not an integer is
50
+ ignored, a `delta` param that is not an integer falls back to `1`, and a
51
+ declared `channel` keeps the gate closed until the subscription is confirmed.
52
+ A delta carrying your own `id` is applied unless an optimistic add of the same
53
+ size is still outstanding. Runtime changes to `channel` / `params`
54
+ re-subscribe.
55
+ - presence: on `disconnect()` a leave notice is sent by the last element claiming
56
+ that `id` rather than by every element; `pagehide` still sends from each one,
57
+ because the whole page is going away. A `channel` key in `params` no longer
58
+ overrides the declared `channel`, `heartbeat` / `timeout` fall back to their
59
+ defaults unless finite, positive and within the browser timer ceiling
60
+ (2147483647 ms) — typing-indicator's `timeout` takes the same bound — and
61
+ `template` clones only its root element.
62
+ - optimistic: `turbo:submit-end` is matched to the submission it names instead of
63
+ to any ending that reaches the element, so a submission whose ending never
64
+ arrives no longer strands the element. The `data-optimistic-toggled` marker
65
+ carries the authored value to restore instead of `"true"`, `aria-busy` gets the
66
+ same record (`data-optimistic-busy`), and a rollback writes those records back
67
+ rather than inverting the current value — `hidden="until-found"` no longer
68
+ degrades to a bare `hidden`, and an element registered for both `show` and
69
+ `hide` returns to its authored state.
70
+
71
+ ### Fixed
72
+
73
+ - calendar: a malformed `<html lang>` (an `en_US`-style tag that `Intl` rejects)
74
+ no longer stops the month grid from painting. The month label falls back to
75
+ English while the 42 cells, the single tab stop, and the `monthchange` /
76
+ `select` conditions stay as they were; any other failure of the label
77
+ formatter still propagates.
78
+
10
79
  ## [0.12.0] - 2026-09-06
11
80
 
12
81
  Minor release with no new components. Six existing ones are reworked — count-up,
@@ -999,6 +1068,8 @@ Initial public alpha: 101 behavior-only, accessible Stimulus controllers driven
999
1068
  by `data-*` attributes, shipping no CSS. Published to npm (with provenance) and
1000
1069
  RubyGems.
1001
1070
 
1071
+ [0.14.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.14.0
1072
+ [0.13.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.13.0
1002
1073
  [0.12.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.12.0
1003
1074
  [0.11.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.11.0
1004
1075
  [0.10.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.10.0
@@ -14,19 +14,25 @@ import { Controller, Application } from '@hotwired/stimulus';
14
14
  * data-stimeo--live-counter-params-value='{"post":42}'
15
15
  * data-stimeo--live-counter-id-value="<%= SecureRandom.uuid %>">
16
16
  * <span data-stimeo--live-counter-target="value">128</span>
17
- * <button type="button" data-action="stimeo--live-counter#increment"
17
+ * <button type="button" data-action="click->stimeo--live-counter#increment"
18
18
  * data-stimeo--live-counter-target="trigger">♥</button>
19
19
  * </div>
20
20
  *
21
21
  * Wire contract — the broadcast is either **authoritative** or a **delta**:
22
22
  * `{ count: 129 }` sets the absolute value (naturally idempotent; preferred —
23
23
  * the server owns the number), while `{ delta: 1, by: "17" }` adds to it,
24
- * skipped when `by` matches this client's `id` (the optimistic increment
25
- * already applied it). `increment` performs `increment` on the channel with
26
- * `{ id, delta }`; the server persists and broadcasts. Without an own `id`
27
- * the delta echo is indistinguishable from a foreign delta, so the optimistic
28
- * bump is skipped and the broadcast applies the increment exactly once — set
29
- * `id` (any per-client string, e.g. `SecureRandom.uuid`) for optimistic UX.
24
+ * skipped when `by` matches this client's `id` **and its amount matches an
25
+ * optimistic bump this client is still waiting to see echoed**. A counter
26
+ * holding no such guess a sibling on the page, this user's other tab, one
27
+ * stepping by a different amount applies the delta like any other, so every
28
+ * display converges. Only whole numbers are accepted: the
29
+ * display is the state, and a value that cannot be read back from text is not
30
+ * a count. `increment` performs `increment` on the channel with `{ id, delta }`;
31
+ * the server persists and broadcasts. Without an own `id` the delta echo is
32
+ * indistinguishable from a foreign delta, so the optimistic bump is skipped and
33
+ * the broadcast applies the increment exactly once — set `id` (any per-client,
34
+ * per-tab string, e.g. `SecureRandom.uuid`) for optimistic UX. Comparing `by`
35
+ * to `id` is an echo guard, not authentication — identity belongs to the server.
30
36
  *
31
37
  * `change` dispatches `{ count }`.
32
38
  *
@@ -38,7 +44,10 @@ import { Controller, Application } from '@hotwired/stimulus';
38
44
  * subscription lifecycle (via the shared confirmation-aware subscription):
39
45
  * increments are dropped before confirmation AND while the connection is down
40
46
  * (`disconnected` shuts the gate until Action Cable re-confirms), so the
41
- * display never advances past what the server can receive. A refused
47
+ * display never advances past what the server can receive. The gate reads the
48
+ * declaration, not the subscription object: while a `channel` is declared it
49
+ * stays shut until that subscription confirms, including the window where one
50
+ * has yet to be opened. A refused
42
51
  * subscription publishes the `data-live-counter-rejected` hook (cleared on
43
52
  * `connect()` — rejection is transient server state) so the consumer's CSS can
44
53
  * disable the trigger. Optional `trigger` targets make that declarative: they
@@ -47,9 +56,15 @@ import { Controller, Application } from '@hotwired/stimulus';
47
56
  * required, and a disabled form control is announced as such by AT. An
48
57
  * authored `disabled` (set by the consumer for its own reasons) is respected:
49
58
  * only a disabled this controller applied — tracked via a marker attribute —
50
- * is ever lifted. Channel-less (local-only) counters never disable their
51
- * triggers. There are no timers; the subscription is released on
52
- * `disconnect()` (Turbo navigation included).
59
+ * is ever lifted, and it is given back when the controller or the target goes
60
+ * away. A trigger that holds focus keeps it: the disable waits for it to blur,
61
+ * since taking focus away mid-outage strands a keyboard user. Channel-less
62
+ * (local-only) counters never disable their triggers. `announceText` is opt-in
63
+ * and empty by default; when set, reconciled counts reach the page's shared
64
+ * announcer, debounced so a burst is one message. The subscription follows the
65
+ * declaration — a `channel` or `params` change moves it — and is released on
66
+ * `disconnect()` (Turbo navigation included) along with any pending
67
+ * announcement.
53
68
  */
54
69
  declare class LiveCounterController extends Controller<HTMLElement> {
55
70
  #private;
@@ -67,6 +82,10 @@ declare class LiveCounterController extends Controller<HTMLElement> {
67
82
  type: StringConstructor;
68
83
  default: string;
69
84
  };
85
+ announceText: {
86
+ type: StringConstructor;
87
+ default: string;
88
+ };
70
89
  };
71
90
  static actions: readonly ["increment"];
72
91
  static events: readonly ["change"];
@@ -76,17 +95,23 @@ declare class LiveCounterController extends Controller<HTMLElement> {
76
95
  channelValue: string;
77
96
  paramsValue: string;
78
97
  idValue: string;
98
+ announceTextValue: string;
79
99
  /**
80
- * Re-parses the identifier parameters when the declaration changes.
100
+ * Re-parses the identifier parameters and moves the subscription to the
101
+ * identifier they now name.
81
102
  *
82
103
  * A malformed declaration falls back to no parameters, so the identifier keeps
83
104
  * naming the channel instead of the subscription never being created at all.
84
105
  */
85
106
  paramsValueChanged(): void;
107
+ /** Moves the subscription when the declaration names a different channel. */
108
+ channelValueChanged(): void;
86
109
  connect(): void;
87
110
  disconnect(): void;
88
111
  /** Late-added triggers (e.g. via a Turbo Stream) pick up the current gate. */
89
112
  triggerTargetConnected(target: HTMLElement): void;
113
+ /** A trigger that stops being one keeps nothing this controller lent it. */
114
+ triggerTargetDisconnected(target: HTMLElement): void;
90
115
  /**
91
116
  * Optimistic local increment: bumps the display immediately, then asks the
92
117
  * server to persist and broadcast. The step comes from the action param
@@ -110,6 +135,11 @@ declare class LiveCounterController extends Controller<HTMLElement> {
110
135
  * `disconnect()` never runs); a lost notice is caught by the expiry. Ships in
111
136
  * the opt-in `stimeo-ui/cable` subpath (`@rails/actioncable` optional peer).
112
137
  *
138
+ * The notice speaks for a *peer*, not for a wire subscription: on `disconnect()`
139
+ * only the last element claiming a given `id` on a given identifier sends it, so a
140
+ * sibling that stays mounted keeps the peer in every roster. `pagehide` takes the
141
+ * whole page with it, so there every element sends and peers absorb the duplicates.
142
+ *
113
143
  * Roster convergence: a late joiner would otherwise see peers only as their
114
144
  * next heartbeats arrive, so on hearing a beacon from an *unknown* peer, each
115
145
  * client re-announces itself (at most one such answer every 2s) — the
@@ -146,7 +176,11 @@ declare class LiveCounterController extends Controller<HTMLElement> {
146
176
  * `data-presence-id`), and the `count` target renders through localizable
147
177
  * `data-zero` / `data-one` / `data-other` templates (`%{count}`). Richer
148
178
  * per-user rendering (avatars, links) belongs to the consumer via the `join` /
149
- * `leave` / `change` events or a server-rendered Turbo Stream. The `id`
179
+ * `leave` / `change` events or a server-rendered Turbo Stream. A `template` holds
180
+ * one root element: the clone appended for a peer, and the node removed when the
181
+ * peer goes, are that same element. Roster changes reach assistive tech only when
182
+ * the consumer opts in through `announceJoinText` / `announceLeaveText` — reading
183
+ * out every entry and exit of a busy room is noise, so silence is the default. The `id`
150
184
  * comparison is display-level echo suppression, not authentication — identity
151
185
  * belongs to the server. Sending tracks the full subscription lifecycle (via
152
186
  * the shared confirmation-aware subscription): beacons — heartbeats, the
@@ -159,7 +193,8 @@ declare class LiveCounterController extends Controller<HTMLElement> {
159
193
  * `data-live-counter-rejected`. Presence is transient: `connect()` clears
160
194
  * whatever a Turbo cache snapshot preserved (hooks + rendered clones), renders
161
195
  * the known-empty count (the `data-present*` hooks stay absent until the first
162
- * beacon), and the stream re-populates; the subscription, heartbeat interval,
196
+ * beacon), and the stream re-populates; a `count` or `list` target swapped in by a
197
+ * Stream or a morph arrives empty and is drawn from the roster as it connects; the subscription, heartbeat interval,
163
198
  * per-peer expiry timers, and the `pagehide` listener are all released on
164
199
  * `disconnect()` (Turbo navigation included).
165
200
  */
@@ -191,6 +226,14 @@ declare class PresenceController extends Controller<HTMLElement> {
191
226
  type: NumberConstructor;
192
227
  default: number;
193
228
  };
229
+ announceJoinText: {
230
+ type: StringConstructor;
231
+ default: string;
232
+ };
233
+ announceLeaveText: {
234
+ type: StringConstructor;
235
+ default: string;
236
+ };
194
237
  };
195
238
  static events: readonly ["join", "leave", "change"];
196
239
  readonly hasCountTarget: boolean;
@@ -205,6 +248,8 @@ declare class PresenceController extends Controller<HTMLElement> {
205
248
  nameValue: string;
206
249
  heartbeatValue: number;
207
250
  timeoutValue: number;
251
+ announceJoinTextValue: string;
252
+ announceLeaveTextValue: string;
208
253
  /**
209
254
  * Re-parses the identifier parameters when the declaration changes.
210
255
  *
@@ -212,6 +257,15 @@ declare class PresenceController extends Controller<HTMLElement> {
212
257
  * naming the channel instead of the subscription never being created at all.
213
258
  */
214
259
  paramsValueChanged(): void;
260
+ /**
261
+ * Draws the roster into a list target, which arrives empty from a Turbo Stream
262
+ * replacement or a morph. Stimulus runs this before `connect()` on the first mount
263
+ * too, where the roster is still empty and clearing whatever a cache snapshot
264
+ * preserved is what `connect()` goes on to do anyway.
265
+ */
266
+ listTargetConnected(): void;
267
+ /** Paints the roster size into a count target that arrives blank, for the same reason. */
268
+ countTargetConnected(): void;
215
269
  connect(): void;
216
270
  disconnect(): void;
217
271
  }