Etcher.Layer (etcher v0.1.0)

Copy Markdown View Source

Phoenix LiveView function component that attaches Etcher's annotation overlay to a named 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).

Summary

Functions

Mounts an Etcher annotation layer onto a named Fresco viewer.

Functions

layer(assigns)

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.