# `LivePanels.Drawing`
[🔗](https://github.com/livepanels/livepanels/blob/v0.1.0/lib/livepanels/drawing.ex#L1)

Drawing subsystem for persistent vector items.

Drawing commands still flow through the canonical canvas reducer. This module
is the app-facing command/query front door for vector item creation, mutation,
removal, and inspection.

# `command_result`

```elixir
@type command_result() :: LivePanels.Canvas.Command.result()
```

# `item_ref`

```elixir
@type item_ref() :: LivePanels.Item.ref()
```

# `socket`

```elixir
@type socket() :: Phoenix.LiveView.Socket.t()
```

# `target`

```elixir
@type target() :: LivePanels.Canvas.command_target()
```

First argument accepted by drawing command helpers.

Pass a LiveView socket for a standalone command, or a
`LivePanels.Canvas.Transaction` context inside `LivePanels.Canvas.transaction/2`.

# `vector_kind`

```elixir
@type vector_kind() ::
  :freehand
  | :polyline
  | :arrow
  | :line
  | :rectangle
  | :ellipse
  | :diamond
  | :triangle
  | :text
```

# `vector_source`

```elixir
@type vector_source() ::
  LivePanels.Canvas.State.t()
  | %{items: %{optional(String.t()) =&gt; LivePanels.Item.t()}}
  | %{optional(String.t()) =&gt; LivePanels.Item.t()}
```

# `add`

```elixir
@spec add(target(), vector_kind(), map(), keyword()) :: command_result()
```

Creates a persistent vector item and returns the command result.

# `add!`

```elixir
@spec add!(target(), vector_kind(), map(), keyword()) :: target()
```

Creates a persistent vector item through the canvas command path.

# `arrow`

```elixir
@spec arrow(target(), map(), keyword()) :: command_result()
```

Creates a persistent arrow vector item and returns the command result.

# `arrow!`

```elixir
@spec arrow!(target(), map(), keyword()) :: target()
```

Creates a persistent arrow vector item.

# `box_kinds`

```elixir
@spec box_kinds() :: [vector_kind()]
```

Returns vector kinds backed by a placement box.

# `diamond`

```elixir
@spec diamond(target(), map(), keyword()) :: command_result()
```

Creates a persistent diamond vector item and returns the command result.

# `diamond!`

```elixir
@spec diamond!(target(), map(), keyword()) :: target()
```

Creates a persistent diamond vector item.

# `edit`

```elixir
@spec edit(target(), item_ref(), map() | keyword()) :: command_result()
```

Edits a committed vector item and returns the command result.

# `edit!`

```elixir
@spec edit!(target(), item_ref(), map() | keyword()) :: target()
```

Edits committed vector item style, text, label, route, arrowheads, or bends.

# `ellipse`

```elixir
@spec ellipse(target(), map(), keyword()) :: command_result()
```

Creates a persistent ellipse vector item and returns the command result.

# `ellipse!`

```elixir
@spec ellipse!(target(), map(), keyword()) :: target()
```

Creates a persistent ellipse vector item.

# `excalidraw_commands`

```elixir
@spec excalidraw_commands(
  map(),
  keyword()
) :: {:ok, [tuple()]} | {:error, term()}
```

Converts an external drawing document into canonical LivePanels commands.

Drawn shapes become vector item commands, and arrows with both endpoints bound
become graph connector commands with ports on the bound items.

# `flatten`

```elixir
@spec flatten(target(), [item_ref()] | item_ref(), keyword() | map()) ::
  command_result()
```

Flattens committed vector items and returns the command result.

# `flatten!`

```elixir
@spec flatten!(target(), [item_ref()] | item_ref(), keyword() | map()) :: target()
```

Flattens committed vector items into one persistent drawing item.

The flattened item renders as one unit and stores the source vector items as
serialized source item records in the flattened item's local coordinate space.

Options:

  * `:id` - explicit id for the flattened item.
  * `:owner_client_id` - only flatten vector items owned by that client.

# `flatten_over_limit`

```elixir
@spec flatten_over_limit(target(), pos_integer(), keyword() | map()) ::
  command_result()
```

Automatically flattens vector items over a threshold and returns the command result.

# `flatten_over_limit!`

```elixir
@spec flatten_over_limit!(target(), pos_integer(), keyword() | map()) :: target()
```

Automatically flattens vector items when a count threshold is exceeded.

Applications can call this after drawing commits, on a timer, or from their own
workflow hooks. `scope` may be `:all`, `:owner`, `:viewport`, or `:selection`.
`:viewport` uses the current actor viewport when available; `:owner` uses the
current actor unless `:owner_client_id` is supplied.

# `freehand`

```elixir
@spec freehand(target(), map(), keyword()) :: command_result()
```

Creates a persistent freehand vector item and returns the command result.

# `freehand!`

```elixir
@spec freehand!(target(), map(), keyword()) :: target()
```

Creates a persistent freehand vector item.

# `from_excalidraw`

```elixir
@spec from_excalidraw(
  map(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}
```

Converts an external drawing document map into normalized drawing payloads.

Unsupported or malformed elements are ignored. Applications should create the
returned payloads through `vector_item/4` so authorization, broadcasts, history, and
persistence stay on the normal canvas command path.

# `import_excalidraw`

```elixir
@spec import_excalidraw(target(), map(), keyword()) :: command_result()
```

Imports an external drawing document and returns the command result.

# `import_excalidraw!`

```elixir
@spec import_excalidraw!(target(), map(), keyword()) :: target()
```

Imports an external drawing document through the normal canvas command path.

# `line`

```elixir
@spec line(target(), map(), keyword()) :: command_result()
```

Creates a persistent line vector item and returns the command result.

# `line!`

```elixir
@spec line!(target(), map(), keyword()) :: target()
```

Creates a persistent line vector item.

# `point_kinds`

```elixir
@spec point_kinds() :: [vector_kind()]
```

Returns vector kinds backed by editable points.

# `point_vector_item?`

```elixir
@spec point_vector_item?(
  LivePanels.Canvas.State.t(),
  String.t() | LivePanels.Item.t()
) :: boolean()
```

Returns true when the item id or item value is a committed point-backed vector item.

# `polyline`

```elixir
@spec polyline(target(), map(), keyword()) :: command_result()
```

Creates a persistent polyline vector item and returns the command result.

# `polyline!`

```elixir
@spec polyline!(target(), map(), keyword()) :: target()
```

Creates a persistent polyline vector item.

# `rectangle`

```elixir
@spec rectangle(target(), map(), keyword()) :: command_result()
```

Creates a persistent rectangle vector item and returns the command result.

# `rectangle!`

```elixir
@spec rectangle!(target(), map(), keyword()) :: target()
```

Creates a persistent rectangle vector item.

# `remove`

```elixir
@spec remove(target(), item_ref()) :: command_result()
```

Removes a committed vector item and returns the command result.

# `remove!`

```elixir
@spec remove!(target(), item_ref()) :: target()
```

Removes a committed vector item through drawing authorization.

# `text`

```elixir
@spec text(target(), map(), String.t(), keyword()) :: command_result()
```

Creates a persistent text vector item and returns the command result.

# `text!`

```elixir
@spec text!(target(), map(), String.t(), keyword()) :: target()
```

Creates a persistent text vector item.

# `to_excalidraw`

```elixir
@spec to_excalidraw(
  vector_source(),
  keyword()
) :: map()
```

Exports committed vector items as an external drawing document map.

The returned map is intentionally not JSON-encoded here; applications can choose how
they want to persist or download it without making the drawing subsystem
depend on a JSON library.

# `triangle`

```elixir
@spec triangle(target(), map(), keyword()) :: command_result()
```

Creates a persistent triangle vector item and returns the command result.

# `triangle!`

```elixir
@spec triangle!(target(), map(), keyword()) :: target()
```

Creates a persistent triangle vector item.

# `unflatten`

```elixir
@spec unflatten(target(), item_ref()) :: command_result()
```

Restores a flattened vector item and returns the command result.

# `unflatten!`

```elixir
@spec unflatten!(target(), item_ref()) :: target()
```

Restores a flattened vector item back into its source vector items.

Flattened vector items retain their source item records and can be restored later.

# `vector_item`

```elixir
@spec vector_item(target(), vector_kind(), map(), keyword()) :: command_result()
```

Creates a persistent vector item and returns the command result.

# `vector_item!`

```elixir
@spec vector_item!(target(), vector_kind(), map(), keyword()) :: target()
```

Creates a persistent vector item through the canvas command path.

`kind` is one of `vector_kinds/0`. `placement` accepts the app-facing
placement frame shape:

    %{
      x: 120,
      y: 80,
      w: 320,
      h: 180
    }

`:space` and `:anchor` may be included and default to `:world` and
`:top_left`:

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

`opts` accepts `:style`, `:points`, optional `:id`, text state (`:text`,
`:font`, `:align`, `:vertical_align`), bound `:label`, and linear vector
presentation (`:arrowheads`, `:route`).

# `vector_item?`

```elixir
@spec vector_item?(LivePanels.Canvas.State.t(), String.t() | LivePanels.Item.t()) ::
  boolean()
```

Returns true when the item id or item value is a committed vector item.

# `vector_items`

```elixir
@spec vector_items(vector_source()) :: [LivePanels.Item.t()]
```

Returns committed vector items from assigned items or a canvas state.

# `vector_kinds`

```elixir
@spec vector_kinds() :: [vector_kind()]
```

Returns every supported vector kind.

# `vector_state`

```elixir
@spec vector_state(LivePanels.Item.t() | map()) :: {:ok, map()} | :error
```

Returns canonical vector state for a committed vector item.

Application-owned drawing renderers use this to add hit areas, point handles,
and editing controls while keeping geometry normalization in LivePanels.

---

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