# `PhoenixKitDocumentCreator.Variable`
[🔗](https://github.com/BeamLabEU/phoenix_kit_document_creator/blob/0.4.8/lib/phoenix_kit_document_creator/variable.ex#L1)

Variable definitions for document templates.

Variables are `{{ variable_name }}` placeholders in Google Docs templates that
get substituted with actual values via the Google Docs `replaceAllText` API.

`default_image_config/1` returns the default render config for image variables,
including `opacity` and `z_index` fields introduced in the composition pipeline.

# `t`

```elixir
@type t() :: %PhoenixKitDocumentCreator.Variable{
  config: map(),
  default: String.t() | nil,
  label: String.t(),
  name: String.t(),
  required: boolean(),
  type: variable_type()
}
```

# `variable_type`

```elixir
@type variable_type() :: :text | :date | :currency | :multiline | :image | :image_list
```

# `build_definitions`

```elixir
@spec build_definitions(%{
  text: [String.t()],
  image: [%{name: String.t(), kind: :image | :image_list}]
}) ::
  [t()]
```

Builds Variable structs from a forked detection map. Text variables come first
(sorted), then image variables (sorted by name).

# `default_image_config`

```elixir
@spec default_image_config(:image | :image_list) :: map()
```

Returns the default render config for an image variable.

For `:image`: `%{default_width_px: 400, opacity: 1.0, z_index: 0, annotated: true}`
For `:image_list`: adds `separator: :newline, max_count: nil, columns: 1`.

`:annotated` — when `true` (default), the host app should flatten drawn
annotations into the image before inserting it into the document. Set to
`false` per-slot in the template editor to use the raw photo instead.

Note: `:opacity` is currently a no-op in the inline path; positioned objects
(`z_index > 0`) also skip it pending a follow-up two-pass batchUpdate.
Values stored in the DB are preserved for future activation.

# `extract_image_variables`

```elixir
@spec extract_image_variables(term()) :: [
  %{name: String.t(), kind: :image | :image_list}
]
```

Extracts image variable definitions from `{{ image: name }}` /
`{{ images: name }}` placeholders.

Returns a list of `%{name: String.t(), kind: :image | :image_list}` maps,
deduplicated by name, sorted by name.

Note: if both `{{ image: foo }}` and `{{ images: foo }}` appear with the same name, the first occurrence (by document order) wins.

# `extract_string_variables`

```elixir
@spec extract_string_variables(term()) :: [String.t()]
```

Extracts text variable names from `{{ name }}` placeholders.

Deliberately ignores `{{ image: name }}` and `{{ images: name }}` via a negative
lookahead — those are handled by `extract_image_variables/1`.

Returns a sorted list of unique names.

# `extract_variables`

```elixir
@spec extract_variables(term()) :: %{
  text: [String.t()],
  image: [%{name: String.t(), kind: :image | :image_list}]
}
```

Convenience entry point that runs both detectors and returns a forked map.

Returns `%{text: [String.t()], image: [%{name, kind}]}`.

# `guess_type`

```elixir
@spec guess_type(String.t()) :: variable_type()
```

Guesses the variable type from its name.

# `humanize`

```elixir
@spec humanize(String.t()) :: String.t()
```

Converts an underscore_name to a human-readable label.

# `image_config_annotated?`

```elixir
@spec image_config_annotated?(map()) :: boolean()
```

Returns the effective `annotated` value for an image variable config map.

Handles both atom (`:annotated`) and string (`"annotated"`) keys, defaulting
to `true` when the key is missing or explicitly `nil`. This is the canonical
accessor host apps should use so they don't need to know the config's key
shape or the default value.

---

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