# `Etcher.Layer`
[🔗](https://github.com/alexdont/etcher/blob/v0.1.0/lib/etcher/layer.ex#L1)

Phoenix LiveView function component that attaches Etcher's annotation
overlay to a named [Fresco](https://hex.pm/packages/fresco) viewer.

The component renders a hidden host `<div>` with
`phx-hook="EtcherLayer"`. The client-side hook:

  * Looks up the named Fresco viewer via `window.Fresco.onViewerReady/2`
  * Appends a pencil button to Fresco's nav column via
    `handle.appendNavButton/3` (added in Fresco 0.2)
  * On pencil click, opens a bottom toolbar with the configured
    drawing tools and toggles annotation mode
  * Draws shapes as SVG overlays locked to image coordinates
  * Fires LiveView events on each lifecycle moment (`etcher:created`,
    `:updated`, `:deleted`, `:selected`)

## Usage

    <Fresco.viewer id="photo" src={~p"/uploads/photo.jpg"} />

    <Etcher.layer
      fresco_id="photo"
      target_type="file"
      target_uuid={@file.uuid}
      initial_annotations={@annotations}
      tools={[:rectangle, :circle, :polygon, :freehand]}
    />

## Events the consumer's LiveView handles

Required (Etcher always emits these on user interaction):

    def handle_event("etcher:created", %{
      "target_type" => t,
      "target_uuid" => u,
      "kind" => kind,
      "geometry" => geometry,
      "tmp_id" => tmp_id     # client-side stand-in until you confirm save
    }, socket) do
      {:ok, ann} = Etcher.create_annotation(%{
        target_type: t, target_uuid: u, kind: kind, geometry: geometry,
        creator_uuid: socket.assigns.current_user.uuid
      })
      # Reflect the persisted UUID back to the client so the shape
      # element gets re-keyed for subsequent updates / deletes.
      {:noreply, push_event(socket, "etcher:annotation-saved",
        %{tmp_id: tmp_id, uuid: ann.uuid})}
    end

    def handle_event("etcher:updated", %{"uuid" => uuid, "geometry" => geometry}, socket), do: ...
    def handle_event("etcher:deleted", %{"uuid" => uuid}, socket), do: ...
    def handle_event("etcher:selected", %{"uuid" => uuid}, socket), do: ...

## Initial annotations

The `:initial_annotations` attr is a list of maps with at least
`:uuid`, `:kind`, `:geometry`. Any extra fields are passed through to
the client untouched. The hook renders each as an SVG overlay on
mount.

## Tools

Configure which drawing tools appear in the bottom toolbar. Defaults
to all four:

    tools={[:rectangle, :circle, :polygon, :freehand]}

Subsetting hides specific tools (e.g. only `:rectangle, :freehand`).

# `layer`

Mounts an Etcher annotation layer onto a named Fresco viewer.

Renders a hidden `<div phx-hook="EtcherLayer">` that hosts the JS
engine; the visible UI (pencil nav button + bottom toolbar + SVG
shapes) is created by the hook on top of the Fresco viewer.

## Attributes

* `fresco_id` (`:string`) (required) - DOM id of the `<Fresco.viewer>` this layer attaches to.
* `target_type` (`:string`) (required) - The kind of resource the annotation is on (e.g. `"file"`,
  `"document"`, `"product"`). Echoed back in every event payload
  so the consumer's event handler knows what's being annotated.

* `target_uuid` (`:string`) (required) - UUID of the resource being annotated.
* `initial_annotations` (`:list`) - Pre-existing annotations to render on mount. Each entry needs at least `:uuid`, `:kind`, and `:geometry`. Defaults to `[]`.
* `tools` (`:list`) - Subset of drawing tools to show in the toolbar. Defaults to `[:rectangle, :circle, :polygon, :freehand]`.
* `id` (`:string`) - Optional DOM id for the layer host element; defaults to `"etcher-layer-<fresco_id>"`. Defaults to `nil`.
* Global attributes are accepted.

---

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