# `PhoenixKitCatalogue.Web.ComponentRelay`
[🔗](https://github.com/BeamLabEU/phoenix_kit_catalogue/blob/v0.31.3/lib/phoenix_kit_catalogue/web/component_relay.ex#L1)

Delivers catalogue PubSub events to a LiveComponent as `send_update/3`
refreshes, so a component embedded in ANY host LiveView follows the
catalogue live without the host forwarding a single message.

A LiveComponent cannot receive PubSub itself — subscribing from one
subscribes the host LiveView process, and every host would then need
a `handle_info/2` clause for each catalogue event or crash on the
first broadcast. The relay is a small process of its own: it holds the
subscription, decides which events concern the component (its scope's
catalogues), collapses a burst of writes into one refresh, and hands
that refresh to the component through `Phoenix.LiveView.send_update/3`
— the one door into a component that is open from another process.

## Lifetime

The relay monitors the host LiveView and exits when it does, and the
component stops it (`stop/1`) when it closes. A component the host
unmounted some other way is detected by the ack: each refresh carries
a reference the component acknowledges from `update/2`; a refresh
still unacknowledged 15000 ms later means nobody is
listening and the relay exits on its own — it does not wait for a
second event to notice. (LiveView itself only logs a debug line for a
`send_update` to a component that is gone, so even that one refresh
costs nothing visible.)

## Events that trigger a refresh

Every `{:catalogue_data_changed, kind, uuid, parent}` whose parent is
one of the component's catalogues, every catalogue-level event (a
reorder names only its first row), or any event at all when the
component browses without a catalogue restriction — plus the position events (`:catalogue_category_reorder`,
`:catalogue_card_refresh`, `:catalogue_bulk_change`) for those
catalogues, and every shared-sort change. Events are collapsed with a
250 ms trailing debounce, so one drag that writes a dozen
rows refreshes once.

# `refresh`

```elixir
@type refresh() :: {reference(), pid()}
```

What the component receives in `update/2`: `live_refresh: {ref, relay_pid}`.

# `ack`

```elixir
@spec ack(refresh()) :: :ok
```

Acknowledges a refresh from the component's `update/2`.

# `start`

```elixir
@spec start(module(), String.t(), keyword()) :: pid()
```

Starts a relay for the component `module` with `id` mounted in the
calling LiveView process. Returns the relay pid, to pass to `ack/1`
and `stop/1`.

`opts`:

  * `:catalogue_uuids` — the component's catalogues (string uuids);
    `nil` or `[]` means every catalogue event is relevant.
  * `:debounce_ms` — override the trailing debounce (tests).
  * `:ack_timeout_ms` — override the abandonment timeout (tests).

# `stop`

```elixir
@spec stop(pid() | nil) :: :ok
```

Stops the relay. Safe on `nil` and on a relay that already exited.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
