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

Item tracked by the LivePanels runtime.

Every placeable canvas object is an item. Content-bearing items, graph
nodes, viewport readouts, and other item shapes all share this struct. Extra
behavior hangs off capability buckets rather than separate top-level runtime
structs.

The struct is the runtime's canonical record. Applications that need placement,
identity, or type checks may read and pattern match on item fields directly;
item props and metadata should use `LivePanels.Canvas.Item` commands.
Mutations still belong to owner modules such as `LivePanels.Canvas.Item`,
`LivePanels.Graph`, and `LivePanels.Drawing` so commands, authorization,
persistence, and shared-canvas coordination stay on the same path.

# `item_kind`

```elixir
@type item_kind() :: atom() | String.t() | nil
```

# `item_type`

```elixir
@type item_type() :: atom() | String.t()
```

# `ref`

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

An item id or an app-facing item value that carries an `:id`.

# `t`

```elixir
@type t() :: %LivePanels.Item{
  added_at: integer() | nil,
  attachment: %{
    children: [String.t()],
    edge: :left | :right | :top | :bottom | nil,
    mode: :flyout | :anchored | :tiling | nil,
    offset_x: integer(),
    offset_y: integer(),
    constrain_to: :canvas | :parent | :none | nil,
    dismiss_on_focus_loss: boolean()
  },
  authority_scope: :canvas | :owner,
  capabilities: map(),
  group_id: String.t() | nil,
  h: integer(),
  icon: String.t() | nil,
  id: String.t(),
  interaction: %{owner: String.t() | nil, state: map() | nil},
  kind: item_kind(),
  label: String.t() | nil,
  opts: map(),
  owner_client_id: String.t() | nil,
  parent_id: String.t() | nil,
  persistent: boolean(),
  placement_anchor: LivePanels.Canvas.Placement.anchor(),
  placement_space: LivePanels.Canvas.Placement.space(),
  props: map(),
  type: item_type(),
  visible: boolean(),
  visible_to: :all | [String.t()],
  w: integer(),
  x: integer(),
  y: integer(),
  z_index: number() | nil
}
```

Canonical canvas item state.

Identity lives in `:id`, `:type`, `:kind`, `:label`, and `:icon`.
Host-owned item props live in `:props`. Runtime behavior state lives in
`:capabilities`, including vector geometry/style and connector endpoints.
Geometry lives in `:placement_space`, `:placement_anchor`, `:x`, `:y`, `:w`,
`:h`, and `:z_index`.

Runtime coordination fields are explicit as well: `:interaction` is
`%{owner: client_id | nil, state: map | nil}`, `:attachment` records
attached placement, and `:capabilities` carries normalized behavior buckets.

# `attached?`

```elixir
@spec attached?(t()) :: boolean()
```

Returns true when the item is attached to a parent item.

# `attachment_dismiss_on_focus_loss?`

```elixir
@spec attachment_dismiss_on_focus_loss?(t()) :: boolean()
```

Returns true when an attached item dismisses on focus loss.

# `normalize_type`

```elixir
@spec normalize_type(term()) :: item_type() | nil
```

Normalizes item type values to the canonical runtime shape.

# `prop`

```elixir
@spec prop(t() | map() | term(), atom() | String.t(), term()) :: term()
```

Returns one app-owned prop by atom or string key.

`prop(item, :body)` reads both `:body` and `"body"` from `item.props`, and
`prop(item, "body")` does the reverse lookup against existing atoms.

# `props`

```elixir
@spec props(t() | map() | term()) :: map()
```

Returns an item's app-owned props map.

Use `prop/3` when reading one value from application render code. It accepts
atom or string keys and checks both key shapes without creating new atoms.

# `type?`

```elixir
@spec type?(t(), item_type()) :: boolean()
```

Returns true when the item has the requested type.

# `valid_type?`

```elixir
@spec valid_type?(term()) :: boolean()
```

Returns true when a value can be used as a runtime item type.

# `viewport?`

```elixir
@spec viewport?(t()) :: boolean()
```

Returns true when an item is placed in viewport space.

# `visible_to_client?`

```elixir
@spec visible_to_client?(t(), String.t()) :: boolean()
```

Returns true when the item is visible to a client id.

# `world?`

```elixir
@spec world?(t()) :: boolean()
```

Returns true when an item is placed in world space.

---

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