# `PhoenixKitEntities.FieldTypes`
[🔗](https://github.com/BeamLabEU/phoenix_kit_entities/blob/v0.4.6/lib/phoenix_kit_entities/field_types.ex#L1)

Field type definitions and utilities for the Entities system.

This module defines all supported field types for entity definitions,
including their properties, validation rules, and rendering information.

## Supported Field Types

### Basic Text Types
- **text**: Single-line text input
- **textarea**: Multi-line text area
- **email**: Email address with validation
- **url**: URL with validation
- **rich_text**: Rich HTML editor (TinyMCE/CKEditor-like)
- **heading**: Display-only section heading (no data), category `:basic`

### Numeric Types
- **number**: Numeric input (integer or decimal)

### Boolean Types
- **boolean**: True/false toggle or checkbox

### Date/Time Types
- **date**: Date picker (YYYY-MM-DD format)

### Choice Types
- **select**: Dropdown selection (single choice)
- **radio**: Radio button group (single choice)
- **checkbox**: Checkbox group (multiple choices)

## Usage Examples

    # Get all field types
    field_types = PhoenixKitEntities.FieldTypes.all()

    # Get field type info
    text_info = PhoenixKitEntities.FieldTypes.get_type("text")

    # Get field types by category
    basic_types = PhoenixKitEntities.FieldTypes.by_category(:basic)

    # Check if field type requires options
    PhoenixKitEntities.FieldTypes.requires_options?("select") # => true

# `field_category`

```elixir
@type field_category() ::
  :basic | :numeric | :boolean | :datetime | :choice | :advanced
```

# `field_type`

```elixir
@type field_type() :: String.t()
```

# `all`

```elixir
@spec all() :: %{required(String.t()) =&gt; PhoenixKitEntities.FieldType.t()}
```

Returns all field types as a map of `%FieldType{}` structs.

## Examples

    iex> PhoenixKitEntities.FieldTypes.all()
    %{"text" => %FieldType{name: "text", ...}, ...}

# `allow_other?`

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

Checks whether a field definition has the `allow_other` ("Muu" custom
option) flag set — tolerant of both the boolean `true` and the string
`"true"`.

Field definition flags in this codebase are submitted from HTML forms
(where checkbox values arrive as strings) and persisted as-is into the
`fields_definition` JSONB column, so callers must never compare against
the literal boolean `true` — that only matches definitions built by hand
in Elixir, not ones created through the admin field editor.

## Examples

    iex> PhoenixKitEntities.FieldTypes.allow_other?(%{"allow_other" => true})
    true

    iex> PhoenixKitEntities.FieldTypes.allow_other?(%{"allow_other" => "true"})
    true

    iex> PhoenixKitEntities.FieldTypes.allow_other?(%{})
    false

# `boolean_field`

Helper to create a boolean field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.boolean_field("active", "Is Active", default: true)
    %{"type" => "boolean", "key" => "active", "label" => "Is Active", "default" => true, ...}

# `by_category`

```elixir
@spec by_category(field_category()) :: [PhoenixKitEntities.FieldType.t()]
```

Returns field types grouped by category.

## Examples

    iex> PhoenixKitEntities.FieldTypes.by_category(:basic)
    [%FieldType{name: "text", ...}, %FieldType{name: "textarea", ...}, ...]

# `categories`

Returns all categories with their field types.

## Examples

    iex> PhoenixKitEntities.FieldTypes.categories()
    %{
      basic: [%{name: "text", ...}, ...],
      numeric: [%{name: "number", ...}],
      ...
    }

# `category_list`

Returns a list of category names with labels.

## Examples

    iex> PhoenixKitEntities.FieldTypes.category_list()
    [
      {:basic, "Basic"},
      {:numeric, "Numeric"},
      ...
    ]

# `checkbox_field`

Helper to create a checkbox field with options.

## Examples

    iex> PhoenixKitEntities.FieldTypes.checkbox_field("tags", "Tags", ["Featured", "Popular", "New"])
    %{"type" => "checkbox", "key" => "tags", "label" => "Tags", "options" => ["Featured", "Popular", "New"], ...}

# `decimal_field`

Helper to create a decimal field — exact numeric, for money and
anything else that must not round.

## Examples

    iex> PhoenixKitEntities.FieldTypes.decimal_field("unit_cost", "Unit cost")
    %{"type" => "decimal", "key" => "unit_cost", "label" => "Unit cost", ...}

# `decimal_input_value`

```elixir
@spec decimal_input_value(term()) :: String.t() | nil
```

Renders a stored decimal for an input's `value`. Values arrive as a
`%Decimal{}` (freshly cast) or the canonical string (round-tripped
through JSONB); both must render without exponent notation, which an
`<input type="number">` will not accept.

# `decimal_step`

```elixir
@spec decimal_step(map()) :: String.t()
```

The `step` for a decimal field's numeric input, derived from its
declared `scale`. Without this the browser rejects the extra decimal
places the type exists to preserve, because `<input type="number">`
defaults to `step="1"`.

# `default_props`

Gets the default properties for a field type.

## Examples

    iex> PhoenixKitEntities.FieldTypes.default_props("text")
    %{"placeholder" => "", "max_length" => 255}

# `description_for`

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

Translated short description for a field type.

Each clause is a literal `gettext(...)` call so `mix gettext.extract` picks
the strings up; calling `gettext(type.description)` over the raw map value
would feed a variable into the extractor and the descriptions would never
be translated.

# `email_field`

Helper to create an email field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.email_field("email", "Email Address", required: true)
    %{"type" => "email", "key" => "email", "label" => "Email Address", "required" => true, ...}

# `file_field`

Helper to create a file upload field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.file_field("attachments", "Attachments")
    %{"type" => "file", "key" => "attachments", "label" => "Attachments", ...}

    iex> PhoenixKitEntities.FieldTypes.file_field("docs", "Documents",
         max_entries: 10, max_file_size: 52428800, accept: [".pdf", ".docx"])
    %{"type" => "file", "key" => "docs", "label" => "Documents",
      "max_entries" => 10, "max_file_size" => 52428800, "accept" => [".pdf", ".docx"], ...}

# `for_picker`

Returns field types suitable for a field picker UI.

Formats the data for use in select dropdowns or type choosers. Grouped by
category in `category_list/0` order (Basic, Numeric, Boolean, Date & Time,
Choice, Advanced) — sorting by the translated category *label* instead
would reorder the picker per-locale (en groups "Date & Time" before
"Choice"; et's "Kuupäev ja aeg" sorts after "Valik").

## Examples

    iex> PhoenixKitEntities.FieldTypes.for_picker()
    [
      %{value: "text", label: "Text", category: "Basic", icon: "hero-pencil"},
      ...
      %{value: "file", label: "File Upload", category: "Advanced", icon: "hero-document-arrow-up"}
    ]

# `get_type`

```elixir
@spec get_type(String.t()) :: PhoenixKitEntities.FieldType.t() | nil
```

Gets information about a specific field type.

Returns nil if the type doesn't exist.

## Examples

    iex> PhoenixKitEntities.FieldTypes.get_type("text")
    %FieldType{name: "text", label: "Text", ...}

    iex> PhoenixKitEntities.FieldTypes.get_type("invalid")
    nil

# `label_for`

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

Translated display label for a field type.

Same reasoning as `description_for/1`: each clause is a literal
`gettext(...)` call so `mix gettext.extract` picks the strings up —
calling `gettext(type.label)` over the raw `@field_types` map value
would feed a variable into the extractor and the labels would never be
translated.

# `list_types`

Returns a list of all field type names.

## Examples

    iex> PhoenixKitEntities.FieldTypes.list_types()
    ["text", "textarea", "number", ...]

# `new_field`

Creates a new field definition with default values.

## Examples

    iex> PhoenixKitEntities.FieldTypes.new_field("text", "my_field", "My Field")
    %{
      "type" => "text",
      "key" => "my_field",
      "label" => "My Field",
      "required" => false,
      "default" => "",
      "validation" => %{},
      "placeholder" => "",
      "max_length" => 255
    }

    # With options for choice fields
    iex> PhoenixKitEntities.FieldTypes.new_field("select", "category", "Category", options: ["Tech", "Business"])
    %{
      "type" => "select",
      "key" => "category",
      "label" => "Category",
      "required" => false,
      "options" => ["Tech", "Business"],
      ...
    }

    # With required flag
    iex> PhoenixKitEntities.FieldTypes.new_field("text", "name", "Name", required: true)
    %{"type" => "text", "key" => "name", "label" => "Name", "required" => true, ...}

# `number_field`

Helper to create a number field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.number_field("age", "Age")
    %{"type" => "number", "key" => "age", "label" => "Age", ...}

# `radio_field`

Helper to create a radio button field with options.

## Examples

    iex> PhoenixKitEntities.FieldTypes.radio_field("priority", "Priority", ["Low", "Medium", "High"])
    %{"type" => "radio", "key" => "priority", "label" => "Priority", "options" => ["Low", "Medium", "High"], ...}

# `requires_options?`

Checks if a field type requires options to be defined.

## Examples

    iex> PhoenixKitEntities.FieldTypes.requires_options?("select")
    true

    iex> PhoenixKitEntities.FieldTypes.requires_options?("text")
    false

# `rich_text_field`

Helper to create a rich text field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.rich_text_field("content", "Content", required: true)
    %{"type" => "rich_text", "key" => "content", "label" => "Content", "required" => true, ...}

# `select_field`

Helper to create a select field with options.

## Examples

    iex> PhoenixKitEntities.FieldTypes.select_field("category", "Category", ["Tech", "Business", "Other"])
    %{"type" => "select", "key" => "category", "label" => "Category", "options" => ["Tech", "Business", "Other"], ...}

    iex> PhoenixKitEntities.FieldTypes.select_field("status", "Status", ["Active", "Inactive"], required: true)
    %{"type" => "select", "key" => "status", "label" => "Status", "options" => ["Active", "Inactive"], "required" => true, ...}

# `text_field`

Helper to create a text field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.text_field("name", "Full Name", required: true)
    %{"type" => "text", "key" => "name", "label" => "Full Name", "required" => true, ...}

# `textarea_field`

Helper to create a textarea field.

## Examples

    iex> PhoenixKitEntities.FieldTypes.textarea_field("bio", "Biography")
    %{"type" => "textarea", "key" => "bio", "label" => "Biography", ...}

# `valid_type?`

Checks if a field type exists.

## Examples

    iex> PhoenixKitEntities.FieldTypes.valid_type?("text")
    true

    iex> PhoenixKitEntities.FieldTypes.valid_type?("invalid")
    false

# `validate_field`

Validates a field definition map.

Checks that the field has all required properties and valid values.

## Examples

    iex> field = %{"type" => "text", "key" => "title", "label" => "Title"}
    iex> PhoenixKitEntities.FieldTypes.validate_field(field)
    {:ok, field}

    iex> invalid_field = %{"type" => "invalid", "key" => "test"}
    iex> PhoenixKitEntities.FieldTypes.validate_field(invalid_field)
    {:error, {:invalid_field_type, "invalid"}}

Error tuples flow through `PhoenixKitEntities.Errors.message/1` for
user-facing strings.

---

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