# `StarView.Component`
[🔗](https://github.com/Neophen/star_view/blob/v0.7.0/lib/star_view/component.ex#L1)

Shared UI + its event handlers in one module — for drawers, pickers,
and other components used across many pages.

    defmodule MyAppWeb.DetailDrawer do
      use StarView.Component

      def drawer(assigns) do
        ~H"""
        <div id="detail-drawer">
          <input data-on:change={event("change_title:#{@item.id}")} />
        </div>
        """
      end

      def handle_event("change_title:" <> _id, _signals, %{method: "POST"} = conn) do
        # ... update, then patch (SSE is already started by the dispatcher)
        patch_signals(conn, %{saved: true})
      end
    end

Pages embed the UI as plain function components and need no
`handle_event` clauses for it — events route to this module through
`StarView.Dispatch`. `use StarView.Component` marks the module
dispatchable (the same marker as `use StarView` controllers), so the
dispatch route is the allowlist. Wire it with `StarView.Router`:

    star_view_components "/ds"

which defaults to POST. Declare extra unsafe `:event_methods` explicitly;
read-only GET requires a `get_events: [Module]` allowlist. A plain
`post "/ds/:module/:event", StarView.Dispatch, [], alias: false` route
(the installer default) also works, but only for the default POST
events.

Unlike `StarView.Page`, `event/2` here targets the component's dispatch
URL: `<base>/<encoded-module>/<event>`. The base defaults to `/ds` and
is read client-side from `<body data-ds-base="...">`, so it must match
the base you give `star_view_components/1`. Two common setups:

    # Router: star_view_components "/ds"   (the default — no layout
    # attribute needed)

    # Custom base and/or app path prefix — declare it once in the root
    # layout, including the dispatch segment:
    #   Router: scope "/:workspace_slug" do star_view_components "/ds" end
    <Layout.app conn={@conn}
      body_attrs={%{"data-ds-base" => workspace_path(@current_scope.workspace.slug) <> "/ds"}}>
      ...
    </Layout.app>

Colocation only: no server-side component state, no lifecycle. State
lives in signals, the DOM, and the database.

Pass `checked_events: true` to derive an event contract from the actual
handler clauses and check literal local `event/1,2` references in `~STAR`.
See `StarView.Events`.

