SubscriptionController ​
SubscriptionController holds one source object for a Lit host and keeps the host subscribed to it while the host is connected. Subscriptions are released when the host disconnects or a new source is attached, and opened again when the host reconnects.
ts
import { SubscriptionController } from "@jolly-pixel/ui";
new SubscriptionController<TSource>(
host: ReactiveControllerHost,
subscribe?: SourceSubscriber<TSource>
)
type SourceSubscriber<TSource> = (
source: TSource
) => Iterable<() => void>;ts
interface SubscriptionController<TSource> {
readonly current: TSource | null; // null before the first attach()
readonly attached: TSource; // throws before the first attach()
attach(source: TSource): void;
}attach()stores the source, releases the previous subscriptions, subscribes when the host is connected, then callshost.requestUpdate(). It does not compare sources: attaching the same one resubscribes.subscriberuns on every connect and everyattach()while connected. Each returned function is called once on release.- Without
subscribe, the controller is a plain holder that repaints the host onattach(). - The source stays attached across a disconnect.
ts
@customElement("peer-count")
export class PeerCount extends LitElement {
#presence = new SubscriptionController<PresenceSource>(this, (presence) => {
const repaint = () => this.requestUpdate();
presence.on("change", repaint);
return [
() => presence.off("change", repaint)
];
});
set presence(
presence: PresenceSource
) {
this.#presence.attach(presence);
}
override render() {
const peers = this.#presence.current?.peers.size ?? 0;
return html`${peers} peers`;
}
}Read attached in code that only runs once a source is known, such as event handlers wired by render() after the host received it.