# `LivePanels.Toolkit.Canvas`
[🔗](https://github.com/livepanels/livepanels/blob/v0.1.0/lib/livepanels/toolkit/canvas.ex#L1)

Canvas-domain runtime, DOM attr, and JS helpers for Phoenix LiveViews.

`use LivePanels.Toolkit.Canvas` imports the canonical canvas runtime
components, item controls, selection controls, layout controls, history
controls, clipboard controls, and viewport JS helpers.

The helpers in this module emit protocol attrs and browser runtime events.
They do not render application chrome, choose visual treatment, or own canvas
state.

# `item_ref`

```elixir
@type item_ref() ::
  LivePanels.Item.t()
  | LivePanels.Item.RenderContext.t()
  | LivePanels.Item.View.t()
  | %{id: String.t()}
  | String.t()
```

# `add_item_attrs`

```elixir
@spec add_item_attrs(atom() | String.t(), keyword() | map()) :: map()
```

Returns attrs for an application control that adds an item of `type`.

# `align_selection_attrs`

```elixir
@spec align_selection_attrs(
  LivePanels.Canvas.Arrange.align_mode() | String.t(),
  keyword() | map()
) ::
  map()
```

Returns attrs for an application control that aligns the actor's selected items.

# `canvas_runtime`

Renders the canonical canvas runtime root, stages, and item loop.

# `canvas_runtime_attrs`

Returns canonical runtime root attrs from canvas assigns.

# `clear_selection_attrs`

```elixir
@spec clear_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that clears the actor selection.

# `copy_item_js`

```elixir
@spec copy_item_js(String.t(), String.t(), map()) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that asks the browser runtime to copy an item to a new
placement.

`placement` must be a map. The browser resolves partial viewport placement
requests against the current canvas root before pushing `copy_item`
to the server.

# `copy_selection_attrs`

```elixir
@spec copy_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that copies the actor selection.

# `cut_selection_attrs`

```elixir
@spec cut_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that cuts the actor selection.

# `distribute_selection_attrs`

```elixir
@spec distribute_selection_attrs(
  LivePanels.Canvas.Arrange.distribute_axis() | String.t(),
  keyword() | map()
) :: map()
```

Returns attrs for an application control that distributes the actor's selected items.

# `drag_handle_attrs`

```elixir
@spec drag_handle_attrs(keyword() | map()) :: map()
```

Returns attrs for a descendant that should start item dragging.

# `fit_view_js`

```elixir
@spec fit_view_js(
  String.t(),
  keyword()
) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that asks the browser runtime to fit the world view.

Optional `:max_zoom` limits the resulting zoom level.

# `focus_exempt_attrs`

```elixir
@spec focus_exempt_attrs(keyword() | map()) :: map()
```

Returns attrs for an interactive descendant that should not focus the item.

# `group_selection_attrs`

```elixir
@spec group_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that groups the actor's selected items.

# `hide_item_attrs`

```elixir
@spec hide_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that hides an existing canvas item.

# `include_item_attrs`

```elixir
@spec include_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that includes one item in the actor selection.

# `input_attrs`

Returns runtime input-policy data attrs for the canvas root.

# `item_drop_source_attrs`

```elixir
@spec item_drop_source_attrs(
  LivePanels.Item.t() | LivePanels.Item.RenderContext.t(),
  atom() | String.t(),
  keyword() | map()
) :: map()
```

Returns attrs for a descendant that should start an existing-item drop source.

Use this for items that declare `:drag_drop` with `:move` or `:copy` actions
and need the browser runtime to produce a `drop_item` command when the pointer
crosses into another placement space.

# `keyboard_scope_attrs`

```elixir
@spec keyboard_scope_attrs(keyword() | map()) :: map()
```

Returns attrs for app-owned runtime chrome that should receive canvas
keyboard handling.

# `layout_attrs`

```elixir
@spec layout_attrs(atom() | String.t(), keyword() | map(), keyword() | map()) :: map()
```

Returns attrs for an application control that lays out world-space canvas items.

# `marquee_selection_attrs`

```elixir
@spec marquee_selection_attrs(atom() | String.t(), keyword() | map()) :: map()
@spec marquee_selection_attrs(atom() | String.t(), atom() | String.t()) :: map()
```

Returns attrs for configuring empty-canvas marquee selection on a
`canvas_runtime/1` root.

The scope controls whether the browser asks the server to marquee-select only
canvas items or graph items plus connectors. Pass a mode when containment
behavior should differ from the runtime default.

# `marquee_selection_attrs`

```elixir
@spec marquee_selection_attrs(
  atom() | String.t(),
  atom() | String.t(),
  keyword() | map()
) :: map()
```

# `minimap`

Renders the canonical minimap DOM contract for a canvas.

# `pan_to_js`

```elixir
@spec pan_to_js(String.t(), number(), number()) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that centers the canvas camera on a world-space point.

# `paste_selection_attrs`

```elixir
@spec paste_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that pastes the actor clipboard.

# `pin_js`

```elixir
@spec pin_js(String.t(), String.t()) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that asks the browser runtime to pin an item into
viewport space.

# `present_item_attrs`

```elixir
@spec present_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that presents an existing canvas item.

# `present_js`

```elixir
@spec present_js(String.t(), String.t(), keyword()) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that asks the browser runtime to present an existing item.

Supported opts are `:focus` and `:placement`.

# `redo_attrs`

```elixir
@spec redo_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that reapplies the next history entry.

# `remove_item_attrs`

```elixir
@spec remove_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that removes a canvas item.

# `remove_selected_attrs`

```elixir
@spec remove_selected_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that removes the actor selection.

# `resize_handle_attrs`

```elixir
@spec resize_handle_attrs(atom() | String.t(), keyword() | map()) :: map()
```

Returns attrs for one canonical resize handle.

# `resize_handles`

Renders canonical resize handles for a canvas item frame.

# `select_all_attrs`

```elixir
@spec select_all_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that selects every available item and connector item.

# `select_item_attrs`

```elixir
@spec select_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that replaces the actor item selection.

# `select_item_drag_handle_attrs`

```elixir
@spec select_item_drag_handle_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an app-rendered item body that should both drag and select
the item.

This is for draggable item surfaces, not nested buttons or toolbar controls.
It intentionally does not mark the element as focus-ignored; the browser
runtime treats focus-ignored descendants as interactive islands that should
not start a drag.

# `set_cursor_mode_js`

```elixir
@spec set_cursor_mode_js(String.t(), atom() | String.t(), keyword()) ::
  Phoenix.LiveView.JS.t()
```

Returns a JS command that dispatches the canonical browser cursor-mode event.

`mode` must be `:drag`, `:marquee`, `:pan`, `:draw`, `:erase`, or the matching string.
Pass `tool` must be `:pen`, `:polyline`, or a known vector item family. Pass
`style:` must include the full drawing style map: `:color`, `:width`,
`:fill_color`, `:stroke_style`, `:opacity`, and `:roundness`.

Cursor mode is browser-owned. If an application also mirrors the selected mode in
LiveView assigns, pass `push: "event_name"` to append an application `JS.push/2`.

# `show_item_attrs`

```elixir
@spec show_item_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that shows an existing canvas item.

# `toggle_item_selection_attrs`

```elixir
@spec toggle_item_selection_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that toggles one selected item.

# `toggle_item_visibility_attrs`

```elixir
@spec toggle_item_visibility_attrs(item_ref(), keyword() | map()) :: map()
```

Returns attrs for an application control that toggles item visibility.

# `undo_attrs`

```elixir
@spec undo_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that rewinds canvas history.

# `ungroup_selection_attrs`

```elixir
@spec ungroup_selection_attrs(keyword() | map()) :: map()
```

Returns attrs for an application control that ungroups grouped items in the actor selection.

# `unpin_js`

```elixir
@spec unpin_js(String.t(), String.t(), keyword()) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that asks the browser runtime to unpin an item into world
space.

Optional `:client_x` and `:client_y` opts let applications anchor the world-space
placement to a pointer location. Without them, the browser uses the item's
current screen rect.

# `z_order_selection_attrs`

```elixir
@spec z_order_selection_attrs(
  LivePanels.Canvas.Arrange.z_order_mode() | String.t(),
  keyword() | map()
) ::
  map()
```

Returns attrs for an application control that reorders the actor's selected items.

# `zoom_js`

```elixir
@spec zoom_js(
  String.t(),
  keyword()
) :: Phoenix.LiveView.JS.t()
```

Returns a JS command that applies pointer-centered canvas zoom.

Required opts are `:delta_y`, `:client_x`, and `:client_y`. Optional
`:delta_mode` follows the browser `WheelEvent` convention.

---

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