Commit Vector Items To Canvas State

Copy Markdown View Source

A vector item becomes real canvas state only when it is committed.

Browser tools commit vector items automatically at the end of a drawing gesture. Application code can also create vector items with LivePanels.Drawing.vector_item/4.

Vector Item Kinds

Supported committed vector item kinds:

KindShape
:freehandPoint-backed freehand stroke.
:polylinePoint-backed line with editable vertices.
:arrowPoint-backed line with arrow presentation.
:linePoint-backed straight or routed line.
:rectangleBox-backed rectangle.
:ellipseBox-backed ellipse.
:diamondBox-backed diamond.
:triangleBox-backed triangle.
:textText vector item inside a placement box.

Use LivePanels.Drawing.vector_kinds/0, point_kinds/0, and box_kinds/0 when building dynamic tool palettes.

Placement

Every committed vector item is a canvas item, so it has item placement:

placement = %{
  space: :world,
  anchor: :top_left,
  x: 120,
  y: 80,
  w: 320,
  h: 180
}

space defaults to :world and anchor defaults to :top_left when omitted.

Create A Vector Item From Server Code

Use LivePanels.Drawing.vector_item/4 for server-authored vector items, imports, tests, and derived annotations:

socket =
  LivePanels.Drawing.vector_item!(socket, :rectangle, placement,
    style: %{
      color: "#2563eb",
      width: 3,
      fill_color: "#dbeafe",
      stroke_style: "solid",
      opacity: 100,
      roundness: 8
    }
  )

The command goes through the normal canvas reducer. It is not a direct DOM operation.

Point-Backed Vector Items

Point-backed vector items use points inside the placement box:

socket =
  LivePanels.Drawing.vector_item!(socket, :polyline, placement,
    points: [
      %{x: 0, y: 12},
      %{x: 120, y: 72},
      %{x: 320, y: 20}
    ],
    style: %{
      color: "#111827",
      width: 3,
      fill_color: "none",
      stroke_style: "solid",
      opacity: 100,
      roundness: 0
    }
  )

For point-backed vector items, the item placement gives the vector item a world-space frame. The points describe geometry inside that frame.

Text Vector Items

Text vector items use the same placement model:

socket =
  LivePanels.Drawing.vector_item!(socket, :text, placement,
    text: "Review this",
    font: %{size: 24, family: "Inter"},
    align: :center,
    vertical_align: :middle,
    style: %{
      color: "#111827",
      width: 1,
      fill_color: "none",
      stroke_style: "solid",
      opacity: 100,
      roundness: 0
    }
  )

Use text vector items for drawing-owned text. Use ordinary LiveView content items for rich editable app content.

Labels, Routes, And Arrowheads

Linear vector items can carry presentation state:

socket =
  LivePanels.Drawing.vector_item!(socket, :arrow, placement,
    points: [%{x: 0, y: 40}, %{x: 280, y: 40}],
    label: %{text: "approval"},
    arrowheads: %{start: false, end: true},
    route: :straight,
    style: %{
      color: "#0f172a",
      width: 2,
      fill_color: "none",
      stroke_style: "solid",
      opacity: 100,
      roundness: 0
    }
  )

Treat labels and arrowheads as drawing presentation. Store product meaning in your app when the label needs to drive behavior.

Stable Vector Item IDs

Pass :id when a vector item needs a stable identity:

LivePanels.Drawing.vector_item!(socket, :ellipse, placement,
  id: "annotation-#{annotation.id}",
  style: style
)

LivePanels rejects duplicate vector item ids. Stable ids are important when drawings mirror domain annotations or when tests need deterministic assertions.

Transactions

Use a canvas transaction when one application action should create several items or vector items as one command group:

socket =
  LivePanels.Canvas.transaction!(socket, fn tx ->
    tx
    |> LivePanels.Drawing.vector_item!(:rectangle, box, id: "callout-box", style: box_style)
    |> LivePanels.Drawing.vector_item!(:arrow, arrow, id: "callout-arrow", points: arrow_points, style: arrow_style)
    |> LivePanels.Canvas.Selection.select!(["callout-box", "callout-arrow"])
  end)

Transactions are useful for imports, templates, stamps, and generated annotations.

Query Committed Vector Items

Use drawing queries when building inspectors or empty states:

vector_items =
  socket
  |> LivePanels.Canvas.Read.state()
  |> LivePanels.Drawing.vector_items()

Check one item:

state = LivePanels.Canvas.Read.state(socket)

if LivePanels.Drawing.vector_item?(state, item_id) do
  # show vector item inspector
end

Use LivePanels.Drawing.vector_state/1 when application rendering or inspectors need the normalized vector state for a committed vector item.