Skip to content

createGroup

ts
createGroup<T extends GroupMember = GroupMember>(): Group<T>

A membership set whose members list is a reactive value.

ts
interface Group<T extends GroupMember = GroupMember> {
  readonly members: Signal<readonly T[]>;
  join(member: T): () => void;
}

A GroupMember is anything with a readonly $el: Element — which every Base instance is.

Usage

The coordinator owns the membership and gives out the ways in:

ts
class 
DisclosureGroup
extends
Base
{
static
config
= {
name
: 'DisclosureGroup' };
#peers =
createGroup
<
Base
>();
api
= this.
$provide
(
DisclosureGroupContext
, {
members
: this.#peers.
members
, // the members to read, in document order
join
: (
peer
:
Base
) => this.#peers.
join
(
peer
), // returns the leave function
open
: (
peer
:
Base
) => this.
open
(
peer
), // the invariant stays here
});
mounted
() {
// The membership is a value: re-check the invariant on each change. return this.#peers.
members
.
subscribe
((
members
) => this.
enforce
(
members
));
}
open
(
peer
:
Base
) {}
enforce
(
members
: readonly
Base
[]) {}
}

A member joins the nearest group whenever that group appears — see subscribeContext().

What it does, and what it does not

  • join() returns its own leave, so a member that moves to a nearer group leaves the old one first.
  • The membership is a value. A coordinator subscribes to it and re-checks its invariant on each change, rather than being called back on a mutation.
  • Document order is the tie-breaker, so the markup decides which peer keeps its state.
  • Nothing sweeps disconnected members. The teardown of the member removes it.
  • It names no group and resolves no scope. Scope comes from nearest-provider-wins, so a nested group takes its own members only.

The helper holds a Set and a Signal, and nothing else. That is the whole implementation.

It replaces withGroup

withGroup is not ported. A group is a provided value now, so its scope is the provider's subtree rather than a name in a global table — and a nested group is a nested provider, with nothing to configure.

MIT Licensed