# `Dala.Event.Bridge`
[🔗](https://github.com/manhvu/dala/blob/main/lib/dala/event/bridge.ex#L1)

Translates legacy event shapes (`{:tap, tag}`, `{:change, tag, value}`,
`{:tap, {:list, id, :select, index}}`) into the canonical
`{:dala_event, %Address{}, event, payload}` envelope.

This is a transitional helper: as long as the native NIF emits the legacy
`register_tap`-style messages, this module bridges them into the new model.
When the native side is migrated to emit the canonical envelope directly,
this module can be removed.

## Usage from a screen

    def handle_info(msg, socket) do
      case Dala.Event.Bridge.legacy_to_canonical(msg, screen_module) do
        {:ok, {:dala_event, addr, event, payload}} ->
          # Handle via the new model
          handle_event(addr, event, payload, socket)

        :passthrough ->
          # Not a recognised legacy shape — handle normally
          ...
      end
    end

## Bridge rules

| Legacy shape | Canonical envelope |
|---|---|
| `{:tap, tag}` (atom or arbitrary tag) | `{:dala_event, addr(:button, tag), :tap, nil}` |
| `{:tap, {:list, id, :select, index}}` | `{:dala_event, addr(:list, id, instance: index), :select, nil}` |
| `{:change, tag, value}` | `{:dala_event, addr(:text_field, tag), :change, value}` |
| other | `:passthrough` |

Widget kind defaults to `:button` for `:tap`, `:text_field` for `:change`,
and `:list` for the structured list-row tag. Callers that need a more
specific widget kind can extend the rule table.

# `result`

```elixir
@type result() ::
  {:ok, {:dala_event, Dala.Event.Address.t(), atom(), term()}} | :passthrough
```

Result of attempting to bridge a legacy message.

# `legacy_to_canonical`

```elixir
@spec legacy_to_canonical(term(), term(), keyword()) :: result()
```

Convert a legacy event shape to the canonical envelope.

`screen_id` is used as the `screen` field on the address; it can be the
screen module atom, the screen pid, or any term. `render_id`, if known,
bumps the address's render generation; defaults to 1 if omitted.

## Examples

    iex> Dala.Event.Bridge.legacy_to_canonical({:tap, :save}, MyScreen)
    {:ok, {:dala_event, %Dala.Event.Address{screen: MyScreen, widget: :button, id: :save, render_id: 1, component_path: [], instance: nil}, :tap, nil}}

    iex> Dala.Event.Bridge.legacy_to_canonical({:tap, {:list, :contacts, :select, 47}}, MyScreen)
    {:ok, {:dala_event, %Dala.Event.Address{screen: MyScreen, widget: :list, id: :contacts, instance: 47, render_id: 1, component_path: []}, :select, nil}}

    iex> Dala.Event.Bridge.legacy_to_canonical({:change, :email, "user@example.com"}, MyScreen)
    {:ok, {:dala_event, %Dala.Event.Address{screen: MyScreen, widget: :text_field, id: :email, render_id: 1, component_path: [], instance: nil}, :change, "user@example.com"}}

    iex> Dala.Event.Bridge.legacy_to_canonical({:not_an_event, :something}, MyScreen)
    :passthrough

# `legacy_to_canonical!`

```elixir
@spec legacy_to_canonical!(term(), term(), keyword()) ::
  {:dala_event, Dala.Event.Address.t(), atom(), term()}
```

Same as `legacy_to_canonical/3` but raises if the message is not a
recognised legacy event. Useful in tests.

---

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