stimeo-ui 0.10.0 → 0.12.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.
- package/CHANGELOG.md +145 -0
- package/dist/cable/index.d.ts +79 -14
- package/dist/cable/index.js +249 -45
- package/dist/cable/index.js.map +1 -1
- package/dist/controllers/count_up_controller.d.ts +12 -10
- package/dist/controllers/count_up_controller.js +74 -35
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.d.ts +20 -7
- package/dist/controllers/intersection_controller.js +55 -8
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +31 -9
- package/dist/controllers/lazy_frame_controller.js +81 -19
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +20 -3
- package/dist/controllers/pointer_drag_controller.js +68 -18
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +16 -3
- package/dist/controllers/portal_controller.js +32 -11
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.d.ts +22 -14
- package/dist/controllers/preview_guard_controller.js +180 -20
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.d.ts +18 -9
- package/dist/controllers/reading_progress_controller.js +177 -6
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +15 -3
- package/dist/controllers/roving_controller.js +127 -14
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.js +13 -2
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +17 -8
- package/dist/controllers/smart_sticky_header_controller.js +52 -10
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +38 -8
- package/dist/controllers/sortable_controller.js +241 -67
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +23 -7
- package/dist/controllers/stick_to_bottom_controller.js +149 -28
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.js +13 -2
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/index.js +934 -285
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.js +1 -0
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +1 -0
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +4 -4
- package/dist/inspector/manifest.json +16 -56
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,149 @@ 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.12.0] - 2026-09-06
|
|
11
|
+
|
|
12
|
+
Minor release with no new components. Six existing ones are reworked — count-up,
|
|
13
|
+
intersection, lazy-frame, reading-progress, smart-sticky-header, and sortable —
|
|
14
|
+
and the number reading count-up gained reaches live-counter too. Most of them
|
|
15
|
+
changed a contract, so read Removed and Changed before upgrading. The Inspector
|
|
16
|
+
manifest stays on schema v12.
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
|
|
20
|
+
- sortable: the `status` target, its `data-grabbed` / `data-moved` /
|
|
21
|
+
`data-dropped` / `data-canceled` templates, and the English fallback wording.
|
|
22
|
+
Seat a `stimeo--announcer` on the page and set `announceGrabbedText` /
|
|
23
|
+
`announceMovedText` / `announceDroppedText` / `announceCanceledText`
|
|
24
|
+
(`{name}` / `{position}` / `{total}`); an unset one announces nothing.
|
|
25
|
+
`stimeo check` stops asking for the live region and warns when no announcer
|
|
26
|
+
is seated.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- count-up: only the text node holding the number is animated, and while it
|
|
31
|
+
ticks it is wrapped in a `role="img"` element named with the authored text —
|
|
32
|
+
the host's own `aria-label` and `role` are never touched, and sibling markup
|
|
33
|
+
stays where it was.
|
|
34
|
+
- count-up and live-counter read a formatted number by one rule: the first
|
|
35
|
+
numeric token, group separators dropped, the fraction truncated, and a hyphen
|
|
36
|
+
a sign only where it opens the token — `"Sign-ups: 1,200"` reads 1200, not
|
|
37
|
+
-1200.
|
|
38
|
+
- intersection: `0` is always among the observed lines, so a non-zero
|
|
39
|
+
`threshold` also reports the element leaving for good (one more `change`;
|
|
40
|
+
`data-passed` and the ratio property follow the departure to its end), and an
|
|
41
|
+
exit across the start edge reports `position: "before"` while the element
|
|
42
|
+
still overlaps the root.
|
|
43
|
+
- lazy-frame: a re-fetch needs a genuine re-entry — the frame is seen inside the
|
|
44
|
+
observed area, leaves it, and comes back; where a connection or a
|
|
45
|
+
focus-started load first finds it is the baseline. A frame with `once` off is
|
|
46
|
+
armed again after a cache restore, and `load` names the URL that was fetched.
|
|
47
|
+
- reading-progress: an article with no layout box is not measured, the
|
|
48
|
+
article's own box is watched so late-settling content re-measures, and the
|
|
49
|
+
connect frame is the baseline — a restored scroll position does not fire
|
|
50
|
+
`complete`. Both faces of the custom property are leased: the element's copy
|
|
51
|
+
is returned on `disconnect()` too, an authored `:root` declaration comes back,
|
|
52
|
+
and a later writer is left alone.
|
|
53
|
+
- smart-sticky-header: `change` fires on transitions only (connecting is
|
|
54
|
+
silent), and the `offset` zone is decided ahead of the jitter guard.
|
|
55
|
+
- sortable: insertion is relative to the neighbouring item — the `list`-less
|
|
56
|
+
markup works and the last slot is after the last item — and a drag signal from
|
|
57
|
+
a pointer-drag nested inside an item no longer moves the card. The pickup slot
|
|
58
|
+
is remembered as neighbours, so rows inserted or removed mid-drag shift neither
|
|
59
|
+
the restore nor `from`; only laid-out siblings take part in pointer following;
|
|
60
|
+
and a session whose item leaves the item set ends instead of refusing every
|
|
61
|
+
later grab. pointer-drag consumes `Home` / `End` while grabbed.
|
|
62
|
+
- A declaration that cannot be read falls back to its default: count-up's
|
|
63
|
+
`duration` / `from`, smart-sticky-header's `offset`, and a `rootSelector` /
|
|
64
|
+
`containerSelector` that does not parse (intersection, sticky-observer,
|
|
65
|
+
smart-sticky-header) observes the viewport or the window. Runtime changes to
|
|
66
|
+
intersection's `threshold`, lazy-frame's `url` / `rootMargin`, and
|
|
67
|
+
smart-sticky-header's `offset` are followed.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- lazy-frame: focus moving inside a loaded frame no longer re-fetches it, the
|
|
72
|
+
first intersection after a focus-started load is not a re-entry, and an empty
|
|
73
|
+
`url` is never written to `src`.
|
|
74
|
+
- intersection: with `once`, a handler calling `refresh()` from `enter` no longer
|
|
75
|
+
clears the one-shot marker, so a cache restore does not fire `enter` again.
|
|
76
|
+
- reading-progress: hiding a half-read article no longer publishes `1` and
|
|
77
|
+
`complete`.
|
|
78
|
+
|
|
79
|
+
## [0.11.0] - 2026-09-05
|
|
80
|
+
|
|
81
|
+
Minor release with no new components. Eight existing ones are reworked — the three
|
|
82
|
+
cable controllers (live-counter, presence, typing-indicator) plus pointer-drag,
|
|
83
|
+
portal, preview-guard, roving, and stick-to-bottom. Two of them changed a contract,
|
|
84
|
+
so read Removed before upgrading. The Inspector manifest stays on schema v12.
|
|
85
|
+
|
|
86
|
+
### Removed
|
|
87
|
+
|
|
88
|
+
- preview-guard: the `mode` Value. `placeholder` alone decides the guard's form —
|
|
89
|
+
empty (the default) hides the element with `visibility`, and any other text takes
|
|
90
|
+
the place of its content.
|
|
91
|
+
- typing-indicator: the live region on the `status` target. It is a plain visible
|
|
92
|
+
slot now — drop its `aria-live`, seat a `stimeo--announcer` on the page, and set
|
|
93
|
+
`announceOneText` / `announceManyText`. `stimeo check` stops asking for the
|
|
94
|
+
live-region semantics too.
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- typing-indicator: `announceOneText` / `announceManyText` (`{name}` / `{names}` /
|
|
99
|
+
`{count}`), debounced through the shared announcer.
|
|
100
|
+
- pointer-drag: a `reset` action that returns the element to its origin — dropping
|
|
101
|
+
the committed follow offset and cancelling an in-flight drag.
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- The cable controllers share one wire subscription per identifier (channel +
|
|
106
|
+
params), so a second widget on the same stream sends instead of waiting on a
|
|
107
|
+
confirmation that never comes. A caller joining a confirmed or refused
|
|
108
|
+
identifier is told so on the next microtask, and the wire is released when the
|
|
109
|
+
last one leaves.
|
|
110
|
+
- Cable identifier parameters are read by the controller, so an unreadable
|
|
111
|
+
`params` declaration falls back to the channel alone instead of stopping the
|
|
112
|
+
subscription from being created at all.
|
|
113
|
+
- An element moved within the page keeps what it was carrying: pointer-drag's
|
|
114
|
+
session and the attributes it lends its handles, portal's teleport,
|
|
115
|
+
preview-guard's guard, and roving's tab stop.
|
|
116
|
+
- A declaration that cannot be read falls back to its default — typing-indicator's
|
|
117
|
+
`timeout` / `throttle`, stick-to-bottom's `threshold`, and portal's `to`, which
|
|
118
|
+
now lands the node at the default destination instead of leaving it in place.
|
|
119
|
+
- A key that steers an IME conversion is left to the composition (pointer-drag,
|
|
120
|
+
roving), roving passes a modified `Home` / `End` through to the browser, and
|
|
121
|
+
pointer-drag leaves a press to a native control or editing surface inside the
|
|
122
|
+
handle.
|
|
123
|
+
- roving: an item that cannot take focus — `hidden`, natively `disabled`,
|
|
124
|
+
including through a `fieldset` — is neither a move target nor a tab-stop
|
|
125
|
+
candidate, and the horizontal arrow pair follows the writing direction.
|
|
126
|
+
- pointer-drag: the `touch-action` and `tabindex` lent to a handle are given back
|
|
127
|
+
when an element stops being one, and a handle that leaves the controller ends
|
|
128
|
+
its session in `cancel`.
|
|
129
|
+
- preview-guard: the rewind Turbo's snapshot needs runs on `turbo:before-cache`,
|
|
130
|
+
the inline `visibility` is leased so an authored declaration survives, and the
|
|
131
|
+
child markup a placeholder displaced is put back intact.
|
|
132
|
+
- Transient state is re-derived on connect rather than trusted from a restored
|
|
133
|
+
snapshot: the cable controllers' rejection hooks, stick-to-bottom's
|
|
134
|
+
`data-pinned` / `data-has-new`, and preview-guard's `data-preview-hidden`.
|
|
135
|
+
- A swap at runtime is followed rather than left behind: typing-indicator repaints
|
|
136
|
+
a `status` slot swapped in mid-conversation, stick-to-bottom moves its append
|
|
137
|
+
watch onto a `content` target that arrives or leaves and re-derives pinned from a
|
|
138
|
+
`threshold` changed on the element, and preview-guard re-forms a guard that is
|
|
139
|
+
already up to match a changed `placeholder`.
|
|
140
|
+
|
|
141
|
+
### Fixed
|
|
142
|
+
|
|
143
|
+
- stick-to-bottom: a container connected without a box holds unpinned until the
|
|
144
|
+
layout arrives, so what arrives meanwhile is flagged rather than followed into a
|
|
145
|
+
box that cannot move.
|
|
146
|
+
- pointer-drag: an in-flight follow offset leaves the DOM on teardown, so a
|
|
147
|
+
re-inserted element does not read it back as a committed base.
|
|
148
|
+
- portal: an instance that has been replaced on the same element no longer rewinds
|
|
149
|
+
the teleport the live one holds.
|
|
150
|
+
- typing-indicator: a name carrying `$&`, `` $` ``, `$'` or `$$` is written into the
|
|
151
|
+
status copy literally instead of expanding into the template's own text.
|
|
152
|
+
|
|
10
153
|
## [0.10.0] - 2026-08-31
|
|
11
154
|
|
|
12
155
|
Minor release with no new components. Eight existing ones are reworked — anchored,
|
|
@@ -856,6 +999,8 @@ Initial public alpha: 101 behavior-only, accessible Stimulus controllers driven
|
|
|
856
999
|
by `data-*` attributes, shipping no CSS. Published to npm (with provenance) and
|
|
857
1000
|
RubyGems.
|
|
858
1001
|
|
|
1002
|
+
[0.12.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.12.0
|
|
1003
|
+
[0.11.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.11.0
|
|
859
1004
|
[0.10.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.10.0
|
|
860
1005
|
[0.9.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.9.0
|
|
861
1006
|
[0.8.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.8.0
|
package/dist/cable/index.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ import { Controller, Application } from '@hotwired/stimulus';
|
|
|
28
28
|
* bump is skipped and the broadcast applies the increment exactly once — set
|
|
29
29
|
* `id` (any per-client string, e.g. `SecureRandom.uuid`) for optimistic UX.
|
|
30
30
|
*
|
|
31
|
+
* `change` dispatches `{ count }`.
|
|
32
|
+
*
|
|
31
33
|
* @remarks
|
|
32
34
|
* Behavior only — the displayed number IS the state, and the **DOM is the
|
|
33
35
|
* source of truth**: the server renders the initial count into the `value`
|
|
@@ -58,8 +60,8 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
58
60
|
default: string;
|
|
59
61
|
};
|
|
60
62
|
params: {
|
|
61
|
-
type:
|
|
62
|
-
default:
|
|
63
|
+
type: StringConstructor;
|
|
64
|
+
default: string;
|
|
63
65
|
};
|
|
64
66
|
id: {
|
|
65
67
|
type: StringConstructor;
|
|
@@ -72,8 +74,15 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
72
74
|
readonly valueTarget: HTMLElement;
|
|
73
75
|
readonly triggerTargets: HTMLElement[];
|
|
74
76
|
channelValue: string;
|
|
75
|
-
paramsValue:
|
|
77
|
+
paramsValue: string;
|
|
76
78
|
idValue: string;
|
|
79
|
+
/**
|
|
80
|
+
* Re-parses the identifier parameters when the declaration changes.
|
|
81
|
+
*
|
|
82
|
+
* A malformed declaration falls back to no parameters, so the identifier keeps
|
|
83
|
+
* naming the channel instead of the subscription never being created at all.
|
|
84
|
+
*/
|
|
85
|
+
paramsValueChanged(): void;
|
|
77
86
|
connect(): void;
|
|
78
87
|
disconnect(): void;
|
|
79
88
|
/** Late-added triggers (e.g. via a Turbo Stream) pick up the current gate. */
|
|
@@ -103,7 +112,7 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
103
112
|
*
|
|
104
113
|
* Roster convergence: a late joiner would otherwise see peers only as their
|
|
105
114
|
* next heartbeats arrive, so on hearing a beacon from an *unknown* peer, each
|
|
106
|
-
* client re-announces itself (
|
|
115
|
+
* client re-announces itself (at most one such answer every 2s) — the
|
|
107
116
|
* roster converges in one round-trip instead of one heartbeat period.
|
|
108
117
|
*
|
|
109
118
|
* Markup contract (identifier: `stimeo--presence`):
|
|
@@ -125,6 +134,9 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
125
134
|
* { id: data["id"], name: data["name"], leaving: data["leaving"] })
|
|
126
135
|
* end
|
|
127
136
|
*
|
|
137
|
+
* `join` dispatches `{ id, name }`; `leave` dispatches `{ id }`; `change` dispatches
|
|
138
|
+
* `{ users }`.
|
|
139
|
+
*
|
|
128
140
|
* @remarks
|
|
129
141
|
* Behavior only — the dot/stack look is the consumer's CSS, keyed off the
|
|
130
142
|
* `data-present` / `data-present-count` hooks. The roster counts and renders
|
|
@@ -160,8 +172,8 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
160
172
|
default: string;
|
|
161
173
|
};
|
|
162
174
|
params: {
|
|
163
|
-
type:
|
|
164
|
-
default:
|
|
175
|
+
type: StringConstructor;
|
|
176
|
+
default: string;
|
|
165
177
|
};
|
|
166
178
|
id: {
|
|
167
179
|
type: StringConstructor;
|
|
@@ -188,11 +200,18 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
188
200
|
readonly hasTemplateTarget: boolean;
|
|
189
201
|
readonly templateTarget: HTMLTemplateElement;
|
|
190
202
|
channelValue: string;
|
|
191
|
-
paramsValue:
|
|
203
|
+
paramsValue: string;
|
|
192
204
|
idValue: string;
|
|
193
205
|
nameValue: string;
|
|
194
206
|
heartbeatValue: number;
|
|
195
207
|
timeoutValue: number;
|
|
208
|
+
/**
|
|
209
|
+
* Re-parses the identifier parameters when the declaration changes.
|
|
210
|
+
*
|
|
211
|
+
* A malformed declaration falls back to no parameters, so the identifier keeps
|
|
212
|
+
* naming the channel instead of the subscription never being created at all.
|
|
213
|
+
*/
|
|
214
|
+
paramsValueChanged(): void;
|
|
196
215
|
connect(): void;
|
|
197
216
|
disconnect(): void;
|
|
198
217
|
}
|
|
@@ -201,7 +220,7 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
201
220
|
* Headless **typing indicator** — a *server-bound* behavior: a controller whose
|
|
202
221
|
* state lives on the server stream, not in client memory. Typing in the composer
|
|
203
222
|
* throttle-broadcasts a `typing` signal over an Action Cable channel; received
|
|
204
|
-
* signals from *other* clients render "X is typing…" into a `status`
|
|
223
|
+
* signals from *other* clients render "X is typing…" into a visible `status` slot
|
|
205
224
|
* and auto-clear after `timeout` ms of silence. The whole behavior is HTML + a
|
|
206
225
|
* broadcast — no app JS, no client store, no reconciler. Ships in the opt-in
|
|
207
226
|
* `stimeo-ui/cable` subpath (`@rails/actioncable` optional peer); the core stays
|
|
@@ -211,9 +230,10 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
211
230
|
* <div data-controller="stimeo--typing-indicator"
|
|
212
231
|
* data-stimeo--typing-indicator-channel-value="TypingChannel"
|
|
213
232
|
* data-stimeo--typing-indicator-params-value='{"room":"chat_42"}'
|
|
214
|
-
* data-stimeo--typing-indicator-name-value="Alice"
|
|
233
|
+
* data-stimeo--typing-indicator-name-value="Alice"
|
|
234
|
+
* data-stimeo--typing-indicator-announce-one-text-value="{name} is typing">
|
|
215
235
|
* <textarea data-stimeo--typing-indicator-target="input"></textarea>
|
|
216
|
-
* <p
|
|
236
|
+
* <p data-stimeo--typing-indicator-target="status"
|
|
217
237
|
* data-one="%{name} is typing…" data-many="%{names} are typing…"></p>
|
|
218
238
|
* </div>
|
|
219
239
|
*
|
|
@@ -224,6 +244,14 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
224
244
|
* { name: data["name"] })
|
|
225
245
|
* end
|
|
226
246
|
*
|
|
247
|
+
* The `status` target is a plain visible slot, not a live region: assistive tech is
|
|
248
|
+
* reached through the page's shared announcer instead, so a set that settles is sent
|
|
249
|
+
* there as `announceOneText` / `announceManyText` (`{name}` / `{names}` / `{count}`,
|
|
250
|
+
* debounced). Both default to empty, and an empty message announces nothing — a page
|
|
251
|
+
* that wants the indicator seen but not heard simply leaves them off.
|
|
252
|
+
*
|
|
253
|
+
* `change` dispatches `{ names }`.
|
|
254
|
+
*
|
|
227
255
|
* @remarks
|
|
228
256
|
* Behavior only — the indicator's look is the consumer's CSS, keyed off the
|
|
229
257
|
* `data-typing` hook; the copy is localizable through the `data-one` /
|
|
@@ -237,7 +265,7 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
237
265
|
* subscription publishes the `data-typing-indicator-rejected` hook (cleared on
|
|
238
266
|
* `connect()` — rejection is transient server state), mirroring
|
|
239
267
|
* `data-live-counter-rejected`. Typing state is transient by nature:
|
|
240
|
-
* `connect()` resets the hook and the
|
|
268
|
+
* `connect()` resets the hook and the status slot (a Turbo cache snapshot must
|
|
241
269
|
* not resurrect a stale "X is typing…"), and re-population happens naturally
|
|
242
270
|
* from the stream. The subscription, the per-typer timers, and the delegated
|
|
243
271
|
* `input` listener are all released on `disconnect()` (Turbo navigation
|
|
@@ -252,8 +280,8 @@ declare class TypingIndicatorController extends Controller<HTMLElement> {
|
|
|
252
280
|
default: string;
|
|
253
281
|
};
|
|
254
282
|
params: {
|
|
255
|
-
type:
|
|
256
|
-
default:
|
|
283
|
+
type: StringConstructor;
|
|
284
|
+
default: string;
|
|
257
285
|
};
|
|
258
286
|
name: {
|
|
259
287
|
type: StringConstructor;
|
|
@@ -267,15 +295,41 @@ declare class TypingIndicatorController extends Controller<HTMLElement> {
|
|
|
267
295
|
type: NumberConstructor;
|
|
268
296
|
default: number;
|
|
269
297
|
};
|
|
298
|
+
announceOneText: {
|
|
299
|
+
type: StringConstructor;
|
|
300
|
+
default: string;
|
|
301
|
+
};
|
|
302
|
+
announceManyText: {
|
|
303
|
+
type: StringConstructor;
|
|
304
|
+
default: string;
|
|
305
|
+
};
|
|
270
306
|
};
|
|
271
307
|
static events: readonly ["change"];
|
|
272
308
|
readonly hasStatusTarget: boolean;
|
|
273
309
|
readonly statusTarget: HTMLElement;
|
|
274
310
|
channelValue: string;
|
|
275
|
-
paramsValue:
|
|
311
|
+
paramsValue: string;
|
|
276
312
|
nameValue: string;
|
|
277
313
|
timeoutValue: number;
|
|
278
314
|
throttleValue: number;
|
|
315
|
+
announceOneTextValue: string;
|
|
316
|
+
announceManyTextValue: string;
|
|
317
|
+
/**
|
|
318
|
+
* Re-parses the identifier parameters when the declaration changes.
|
|
319
|
+
*
|
|
320
|
+
* A malformed declaration falls back to no parameters, so the identifier keeps
|
|
321
|
+
* naming the channel instead of the subscription never being created at all.
|
|
322
|
+
*/
|
|
323
|
+
paramsValueChanged(): void;
|
|
324
|
+
/**
|
|
325
|
+
* Paints the current copy into a `status` target that arrived at runtime.
|
|
326
|
+
*
|
|
327
|
+
* No event: the set of typers did not change, only the element that displays it.
|
|
328
|
+
* Without this a region swapped in mid-conversation stays empty while `data-typing`
|
|
329
|
+
* still says someone is typing, leaving the state in the visual hook alone. An empty
|
|
330
|
+
* set needs no paint — a fresh region already shows it.
|
|
331
|
+
*/
|
|
332
|
+
statusTargetConnected(): void;
|
|
279
333
|
connect(): void;
|
|
280
334
|
disconnect(): void;
|
|
281
335
|
}
|
|
@@ -346,6 +400,17 @@ interface ConfirmedCableSubscription extends CableSubscription {
|
|
|
346
400
|
* caller's own handler runs (so a handler reading `subscription.confirmed`
|
|
347
401
|
* sees the post-transition state), and `received` passes straight through.
|
|
348
402
|
*
|
|
403
|
+
* **Callers with the same identifier (channel + params) share one wire
|
|
404
|
+
* subscription.** The server confirms an identifier once and silently ignores a
|
|
405
|
+
* repeated `subscribe` for it, so a second wire subscription would never be
|
|
406
|
+
* confirmed — its sends would stay gated and the client would keep re-sending
|
|
407
|
+
* `subscribe` until the next reconnect. Instead every caller is a member of the
|
|
408
|
+
* identifier's one subscription: lifecycle callbacks and broadcasts fan out to all
|
|
409
|
+
* members, a member joining an already confirmed (or refused) identifier is told
|
|
410
|
+
* so on the next microtask — after its caller has stored the returned
|
|
411
|
+
* subscription, the way a callback from the wire would arrive — and the wire is
|
|
412
|
+
* unsubscribed when the last member leaves.
|
|
413
|
+
*
|
|
349
414
|
* This is deliberately a *tracker*, not an automatic `perform()` gate: the
|
|
350
415
|
* controllers must skip the local side effects that surround a send (an
|
|
351
416
|
* optimistic DOM bump, a throttle timestamp) together with the send itself,
|