# Find The API You Need

Most LivePanels application code uses a focused set of public modules.

Start with `LivePanels.Canvas`, render with the toolkit helpers, then reach for
graph, drawing, persistence, shared, or manual integration APIs only when that canvas
needs them.

```mermaid
flowchart TD
  App["Application LiveView"]
  Canvas["LivePanels.Canvas\nmounts the runtime"]
  Toolkit["LivePanels.Toolkit.*\ncomponents and DOM attrs"]
  Items["LivePanels.Canvas.Item\nitem lifecycle and placement"]
  Data["LivePanels.Canvas.Item\nitem props"]
  Selection["LivePanels.Canvas.Selection\nselection and bulk actions"]
  Layout["LivePanels.Canvas.Layout\nplan item layouts"]
  History["LivePanels.Canvas.History\nundo and redo"]
  Clipboard["LivePanels.Canvas.Clipboard\ncopy and paste"]
  Read["LivePanels.Canvas.Read\nread current projection"]
  Graph["LivePanels.Graph\nports, connectors, graph layout"]
  Drawing["LivePanels.Drawing\nvector items and elements"]
  Shared["LivePanels.Canvas.Shared.*\nshared canvas coordination"]
  Manual["LivePanels.Toolkit.Integration.*\nescape hatches"]

  App --> Canvas
  App --> Toolkit
  App --> Items
  App --> Data
  App --> Selection
  App --> Layout
  App --> History
  App --> Clipboard
  App --> Read
  App --> Graph
  App --> Drawing
  Canvas --> Shared
  App --> Manual
```

## Start Here

Use `LivePanels.Canvas` in the LiveView that owns the canvas route:

```elixir
defmodule MyAppWeb.BoardLive do
  use MyAppWeb, :live_view

  use LivePanels.Canvas,
    pubsub: MyApp.PubSub

  use LivePanels.Toolkit.Canvas

  def render(assigns) do
    ~H"""
    <.canvas_runtime {canvas_runtime_attrs(assigns)}>
      <:item id="note-1" type="note" at={{120, 80}} size={{520, 320}}>
        <article class="note-card">Write ordinary HEEx here.</article>
      </:item>
    </.canvas_runtime>
    """
  end
end
```

`use LivePanels.Canvas` attaches the runtime. Add `use LivePanels.Toolkit.Canvas`,
`Graph`, or `Drawing` when the LiveView renders toolkit helper components or attrs.

## Toolkit Imports

Toolkit modules are `use` presets. They do not change the state model.

| Toolkit | Use when |
|---|---|
| `LivePanels.Toolkit.Canvas` | You need runtime helpers, item frame helpers, item controls, selection, layout, history, clipboard, and viewport JS. |
| `LivePanels.Toolkit.Graph` | You need canvas controls plus graph ports, connectors, selection, and fit helpers. |
| `LivePanels.Toolkit.Drawing` | You need canvas controls plus drawing modes, vector item controls, and point editing helpers. |

Most apps should use a toolkit preset instead of hand-writing protocol attrs.

## Command Owners

Commands stay on the module that owns the vocabulary:

| Work | Module |
|---|---|
| Add, remove, present, place, move, resize, focus, attach, detach | `LivePanels.Canvas.Item` |
| Replace, merge, delete, or clear item props | `LivePanels.Canvas.Item` |
| Select, clear, align, distribute, z-order selected items | `LivePanels.Canvas.Selection` |
| Layout commands and reserved layout space | `LivePanels.Canvas.Arrange` |
| Layout planning contracts and adapters | `LivePanels.Canvas.Layout` |
| Undo and redo | `LivePanels.Canvas.History` |
| Copy and paste | `LivePanels.Canvas.Clipboard` |
| Store and navigate viewport anchors | `LivePanels.Canvas.Viewport` |
| Connect, disconnect, reconnect, fit, and lay out graph connectors | `LivePanels.Graph` |
| Create and edit vector items or drawing-owned elements | `LivePanels.Drawing` |

Every command module accepts either a canvas LiveView socket or a
`LivePanels.Canvas.Transaction` context:

```elixir
socket =
  LivePanels.Canvas.transaction!(socket, fn tx ->
    tx
    |> LivePanels.Canvas.Item.move_by!("panel-a", {24, 0})
    |> LivePanels.Canvas.Item.merge_props!("panel-a", %{accent: "red"})
    |> LivePanels.Graph.connect!(from: {"panel-a", "out"}, to: {"panel-b", "in"})
  end)
```

Use transactions when several changes should become one command history step.

## Browser Controls

Application-rendered controls should use toolkit attrs:

```heex
<button {add_item_attrs(:note)}>New note</button>
<button {remove_item_attrs(context)}>Close</button>
<button {layout_attrs(:grid)}>Layout</button>
<button {undo_attrs()}>Undo</button>
```

Those attrs emit the LivePanels protocol payloads expected by the runtime. They
also keep your visible markup free to change.

## Read Side

Use `LivePanels.Canvas.Read` when application code needs current runtime information:

```elixir
items = LivePanels.Canvas.Read.items(socket)
selection = LivePanels.Canvas.Read.selection(socket)
last = LivePanels.Canvas.Read.last_command(socket)
trace = LivePanels.Canvas.Read.command_trace(socket)
```

Use root helpers for runtime identity and subscriptions:

```elixir
canvas_id = LivePanels.canvas_id(socket)
client_id = LivePanels.client_id(socket)
mode = LivePanels.mode(socket)

:ok = LivePanels.subscribe(socket, :events)
```

## Escape Hatches

Reach for these only when the normal path is not enough:

| Need | API |
|---|---|
| Mount the canvas runtime without the `use` macro | `LivePanels.Canvas.mount_runtime/4` |
| Add runtime items after mount | `LivePanels.Canvas.Item.add/3` |
| Render runtime-created item bodies | id-less `<:item :let={context}>` slot |
| Authorize app-specific commands | `LivePanels.Canvas.Policy` |
| Persist layouts outside the default store | `LivePanels.Canvas.LayoutStore` |
| Refresh rendered item streams without mutating canvas state | `LivePanels.Canvas.Render` |
| Run shared canvases in a cluster | `LivePanels.Canvas.Shared.Backend` and `LivePanels.Canvas.Shared.Adapter` |
| Build manual protocol attrs or render loops | `LivePanels.Toolkit.Integration.ProtocolAttrs`, `LivePanels.Toolkit.Integration.Render` |

If an app can use a toolkit helper or owner module, prefer that over an escape
hatch.
