# Commit Vector Items To Canvas State

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:

| Kind | Shape |
|---|---|
| `:freehand` | Point-backed freehand stroke. |
| `:polyline` | Point-backed line with editable vertices. |
| `:arrow` | Point-backed line with arrow presentation. |
| `:line` | Point-backed straight or routed line. |
| `:rectangle` | Box-backed rectangle. |
| `:ellipse` | Box-backed ellipse. |
| `:diamond` | Box-backed diamond. |
| `:triangle` | Box-backed triangle. |
| `:text` | Text 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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

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

Check one item:

```elixir
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.
