# `Toddy.Iced.Widget.Canvas`
[🔗](https://github.com/toddy-ui/toddy-elixir/blob/v0.3.0/lib/toddy/iced/widget/canvas.ex#L1)

Canvas for drawing shapes, organized into named layers.

Layers are a map of layer names to shape lists. Each layer maps to an iced
`Cache` on the Rust side -- only changed layers are re-tessellated. This
prevents performance footguns when rendering thousands of shapes in a stable
layer.

Shape descriptors are plain maps with string keys. Use `Toddy.Canvas.Shape`
for convenience builders, or construct maps directly.

## Props

- `layers` (map of string => list of maps) -- named layers of shape
  descriptors. Each layer is independently cached. Shapes within a layer
  are drawn in order. Layers are drawn in alphabetical order by name.
- `width` (length) -- canvas width. Default: fill. See `Toddy.Iced.Length`.
- `height` (length) -- canvas height. Default: 200px.
- `background` (color) -- canvas background color. See `Toddy.Iced.Color`.
- `interactive` (boolean) -- enables all mouse event handlers. Default: false.
- `on_press` (boolean) -- enable mouse press events. Default: false.
- `on_release` (boolean) -- enable mouse release events. Default: false.
- `on_move` (boolean) -- enable mouse move events. Default: false.
- `on_scroll` (boolean) -- enable mouse scroll events. Default: false.
- `a11y` (map) -- accessibility overrides. See `Toddy.Iced.A11y`.

## Shape types

Shapes are plain maps. See `Toddy.Canvas.Shape` for builder functions.

- `%{"type" => "rect", "x" => x, "y" => y, "w" => w, "h" => h}` -- rectangle.
- `%{"type" => "circle", "x" => x, "y" => y, "r" => r}` -- circle.
- `%{"type" => "line", "x1" => x1, "y1" => y1, "x2" => x2, "y2" => y2}` -- line.
- `%{"type" => "text", "x" => x, "y" => y, "content" => text}` -- text.
- `%{"type" => "path", "commands" => [...]}` -- arbitrary path.
- `%{"type" => "image", "source" => path, "x" => x, "y" => y, "w" => w, "h" => h}` -- image.
- `%{"type" => "svg", "source" => path, "x" => x, "y" => y, "w" => w, "h" => h}` -- SVG.

All shapes accept optional `fill` (hex color or gradient) and `stroke` fields.

## Events

- `%Canvas{type: :press, id: id, x: x, y: y, button: button}`
- `%Canvas{type: :release, id: id, x: x, y: y, button: button}`
- `%Canvas{type: :move, id: id, x: x, y: y}`
- `%Canvas{type: :scroll, id: id, x: x, y: y, delta_x: dx, delta_y: dy}`

# `option`

```elixir
@type option() ::
  {:layers, %{required(String.t()) =&gt; [map()]}}
  | {:width, Toddy.Iced.Length.t()}
  | {:height, Toddy.Iced.Length.t()}
  | {:background, Toddy.Iced.Color.input()}
  | {:interactive, boolean()}
  | {:on_press, boolean()}
  | {:on_release, boolean()}
  | {:on_move, boolean()}
  | {:on_scroll, boolean()}
  | {:a11y, Toddy.Iced.A11y.t()}
```

# `t`

```elixir
@type t() :: %Toddy.Iced.Widget.Canvas{
  a11y: Toddy.Iced.A11y.t() | nil,
  background: Toddy.Iced.Color.t() | nil,
  height: Toddy.Iced.Length.t() | nil,
  id: String.t(),
  interactive: boolean() | nil,
  layers: %{required(String.t()) =&gt; [map()]} | nil,
  on_move: boolean() | nil,
  on_press: boolean() | nil,
  on_release: boolean() | nil,
  on_scroll: boolean() | nil,
  width: Toddy.Iced.Length.t() | nil
}
```

# `a11y`

```elixir
@spec a11y(canvas :: t(), a11y :: Toddy.Iced.A11y.t()) :: t()
```

Sets accessibility annotations.

# `background`

```elixir
@spec background(canvas :: t(), background :: Toddy.Iced.Color.input()) :: t()
```

Sets the canvas background color. Accepts a hex string or named color atom.

# `build`

```elixir
@spec build(canvas :: t()) :: Toddy.Iced.ui_node()
```

Converts this canvas struct to a `ui_node()` map via the `Toddy.Iced.Widget` protocol.

# `height`

```elixir
@spec height(canvas :: t(), height :: Toddy.Iced.Length.t()) :: t()
```

Sets the canvas height.

# `interactive`

```elixir
@spec interactive(canvas :: t(), interactive :: boolean()) :: t()
```

Sets whether all mouse event handlers are enabled.

# `layer`

```elixir
@spec layer(canvas :: t(), name :: String.t(), shapes :: [map()]) :: t()
```

Adds a single named layer to the canvas. Merges with existing layers.

# `layers`

```elixir
@spec layers(canvas :: t(), layers :: %{required(String.t()) =&gt; [map()]}) :: t()
```

Sets the layers map (layer name => list of shape descriptors).

# `new`

```elixir
@spec new(id :: String.t(), opts :: [option()]) :: t()
```

Creates a new canvas struct with optional keyword opts.

# `on_move`

```elixir
@spec on_move(canvas :: t(), on_move :: boolean()) :: t()
```

Sets whether mouse move events are enabled.

# `on_press`

```elixir
@spec on_press(canvas :: t(), on_press :: boolean()) :: t()
```

Sets whether mouse press events are enabled.

# `on_release`

```elixir
@spec on_release(canvas :: t(), on_release :: boolean()) :: t()
```

Sets whether mouse release events are enabled.

# `on_scroll`

```elixir
@spec on_scroll(canvas :: t(), on_scroll :: boolean()) :: t()
```

Sets whether mouse scroll events are enabled.

# `width`

```elixir
@spec width(canvas :: t(), width :: Toddy.Iced.Length.t()) :: t()
```

Sets the canvas width.

# `with_options`

```elixir
@spec with_options(canvas :: t(), opts :: [option()]) :: t()
```

Applies keyword options to an existing canvas struct.

---

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