PhoenixKitOG.Canvas (PhoenixKitOG v0.1.1)

Copy Markdown View Source

Pure helpers for manipulating a template's canvas JSON. The editor LV calls these on the in-memory canvas map; persistence is a separate Templates.update/2 step.

Canvas shape:

%{
  "width" => 1200,
  "height" => 630,
  "background" => %{"type" => "color", "value" => "#0b1220"},
  "elements" => [%{"id" => "abc", "type" => "text", }, ]
}

Element ids are short random strings — stable across reorders/edits so the editor can refer to them, but ephemeral (regenerated on duplication).

Summary

Functions

Adds a new element at the end of the z-stack (rendered on top).

The canonical empty canvas. Used when a new template is created.

Moves the given element to the top of the z-stack.

Builds a fresh element struct for the given insert kind. Kinds

Removes the given element ids.

Reads the elements list, defaulting to [] for legacy canvases.

Looks up a single element by id.

Bulk-applies {x, y} deltas to a list of element ids — fast path for drag operations that move several elements at once.

Finds an unused slot name with the given prefix. Returns the bare prefix if it's free, otherwise appends the lowest unused numeric suffix — so a fresh canvas gets Text, a second Text insert gets Text2, and so on.

Replaces the elements list.

Substitutes {{slot}} tokens in a text/stamp element. Unknown slots pass through unchanged ({{name}} stays visible), matching the workspace convention.

Moves the given element to the bottom of the z-stack.

Updates a top-level canvas field (width, height, background). Values are coerced to their expected shape.

Updates one field on a single element. Coordinate + size fields (x/y/width/height) are coerced to numbers and clamped inside the canvas; everything else passes through.

Functions

add_element(canvas, attrs)

@spec add_element(map(), map()) :: {map(), map()}

Adds a new element at the end of the z-stack (rendered on top).

Returns {updated_canvas, new_element} so the caller can immediately select the new id without recomputing it.

blank()

@spec blank() :: map()

The canonical empty canvas. Used when a new template is created.

bring_to_front(canvas, id)

@spec bring_to_front(map(), String.t()) :: map()

Moves the given element to the top of the z-stack.

default_element(kind, canvas \\ %{})

@spec default_element(String.t(), map()) :: map()

Builds a fresh element struct for the given insert kind. Kinds:

  • "text" / "text_var" — text element, static content vs. an auto-named {{TextN}} slot placeholder.
  • "image" / "image_var" — image element, empty src vs. {{ImageN}}.
  • "rect" — rectangle.

The caller passes the current canvas so the helper can pick a slot name that doesn't collide with existing slots.

delete_elements(canvas, ids)

@spec delete_elements(map(), [String.t()]) :: map()

Removes the given element ids.

elements(canvas)

@spec elements(map()) :: [map()]

Reads the elements list, defaulting to [] for legacy canvases.

get_element(canvas, id)

@spec get_element(map(), String.t()) :: map() | nil

Looks up a single element by id.

move_elements(canvas, ids, dx, dy)

@spec move_elements(map(), [String.t()], number(), number()) :: map()

Bulk-applies {x, y} deltas to a list of element ids — fast path for drag operations that move several elements at once.

next_slot_name(canvas, prefix)

@spec next_slot_name(map(), String.t()) :: String.t()

Finds an unused slot name with the given prefix. Returns the bare prefix if it's free, otherwise appends the lowest unused numeric suffix — so a fresh canvas gets Text, a second Text insert gets Text2, and so on.

Names stay descriptive rather than always carrying a numeric suffix, which reads better in the "Wire slots" list on the Assignments page.

put_elements(canvas, elements)

@spec put_elements(map(), [map()]) :: map()

Replaces the elements list.

resolve_text(arg1, values)

@spec resolve_text(map(), map()) :: String.t()

Substitutes {{slot}} tokens in a text/stamp element. Unknown slots pass through unchanged ({{name}} stays visible), matching the workspace convention.

Used by the editor preview; the SVG renderer calls Slots.substitute directly.

send_to_back(canvas, id)

@spec send_to_back(map(), String.t()) :: map()

Moves the given element to the bottom of the z-stack.

update_canvas_field(canvas, arg2, value)

@spec update_canvas_field(map(), String.t(), any()) :: map()

Updates a top-level canvas field (width, height, background). Values are coerced to their expected shape.

update_element(canvas, id, field, value)

@spec update_element(map(), String.t(), String.t(), any()) :: map()

Updates one field on a single element. Coordinate + size fields (x/y/width/height) are coerced to numbers and clamped inside the canvas; everything else passes through.