# `MishkaGervaz.Table.Behaviours.Template`
[🔗](https://github.com/mishka-group/mishka_gervaz/blob/v0.0.1-alpha.3/lib/mishka_gervaz/table/behaviours/template.ex#L1)

Behaviour for layout templates.

Templates define HOW data is structured and arranged:
- Table: Traditional rows and columns
- MediaGallery: Image/file gallery with thumbnails
- Kanban: Column-based board layout
- List: Simple list layout

Templates work together with UIAdapters:
- Template = WHERE things go (structure/layout)
- UIAdapter = HOW things look (styling/CSS)

## Creating a Custom Template

    defmodule MyApp.Templates.CustomTable do
      @behaviour MishkaGervaz.Table.Behaviours.Template
      use Phoenix.Component

      @impl true
      def name, do: :custom_table

      @impl true
      def label, do: "Custom Table"

      @impl true
      def icon, do: "hero-table-cells"

      @impl true
      def features, do: [:sort, :filter, :select, :paginate]

      @impl true
      def render(assigns) do
        ~H"""
        <div class="my-custom-wrapper">
          {render_slot(@inner_block)}
        </div>
        """
      end

      # ... implement other callbacks
    end

## Using in DSL

    mishka_gervaz do
      table do
        presentation do
          template MyApp.Templates.CustomTable
          switchable_templates [
            MishkaGervaz.Table.Templates.Table,
            MyApp.Templates.CustomTable
          ]
        end
      end
    end

See `MishkaGervaz.Table.Templates.Table` (default),
`MishkaGervaz.Table.Templates.MediaGallery`,
`MishkaGervaz.Table.Templates.Shared` (rendering helpers),
`MishkaGervaz.Behaviours.UIAdapter`, and the form-side counterpart
`MishkaGervaz.Form.Behaviours.Template`.

# `assigns`

```elixir
@type assigns() :: map()
```

# `feature`

```elixir
@type feature() ::
  :sort
  | :filter
  | :select
  | :bulk_actions
  | :paginate
  | :export
  | :expand
  | :reorder
  | :inline_edit
```

# `features`

```elixir
@type features() :: :all | [feature()]
```

# `rendered`

```elixir
@type rendered() :: Phoenix.LiveView.Rendered.t()
```

# `default_options`

```elixir
@callback default_options() :: keyword()
```

Default options for this template.

Can include things like:
- `:columns` - Number of grid columns
- `:card_size` - Card size for grid
- `:show_header` - Whether to show header

# `description`

```elixir
@callback description() :: String.t()
```

Description of what this template is best used for.

# `features`

```elixir
@callback features() :: features()
```

Features supported by this template.

Can return `:all` for all features or a list of specific features.

Possible features:
- `:sort` - Column sorting
- `:filter` - Filtering
- `:select` - Row/item selection
- `:bulk_actions` - Bulk actions on selected items
- `:paginate` - Pagination
- `:export` - Export to CSV/Excel
- `:expand` - Expandable rows/cards
- `:reorder` - Drag and drop reordering
- `:inline_edit` - Inline editing

## Examples

    # All features
    def features, do: :all

    # Specific features
    def features, do: [:sort, :filter, :paginate]

# `icon`

```elixir
@callback icon() :: String.t()
```

Icon identifier for template switcher UI.

Examples: "hero-table-cells", "hero-squares-2x2", "hero-photo"

# `label`

```elixir
@callback label() :: String.t()
```

Human-readable label for UI display.

Examples: "Table", "Grid View", "Media Gallery"

# `name`

```elixir
@callback name() :: atom()
```

Unique template identifier atom.

Examples: `:table`, `:grid`, `:media_gallery`, `:kanban`

# `render`

```elixir
@callback render(assigns()) :: rendered()
```

Render the complete template wrapper.

This is the main entry point. It should render:
- Filters (if enabled)
- The main content area (table/grid/etc.)
- Pagination (if enabled)

Assigns include:
- `@state` - The table state
- `@ui_adapter` - The UI adapter module
- `@stream` - The data stream
- `@columns` - Column configurations
- `@filters` - Filter configurations
- And more...

# `render_bulk_actions`
*optional* 

```elixir
@callback render_bulk_actions(assigns()) :: rendered()
```

Render bulk actions bar. Optional - has default implementation.

# `render_empty`

```elixir
@callback render_empty(assigns()) :: rendered()
```

Render the empty state when no records exist.

# `render_error`

```elixir
@callback render_error(assigns()) :: rendered()
```

Render the error state.

# `render_filters`
*optional* 

```elixir
@callback render_filters(assigns()) :: rendered()
```

Render filters section. Optional - has default implementation.

# `render_header`

```elixir
@callback render_header(assigns()) :: rendered()
```

Render the header section (for tables: thead, for grids: toolbar, etc.)

# `render_item`

```elixir
@callback render_item(assigns()) :: rendered()
```

Render a single item (row for table, card for grid, etc.)

Assigns include:
- `@record` - The data record
- `@id` - The stream item ID
- `@columns` - Column configurations
- `@actions` - Available actions

# `render_loading`
*optional* 

```elixir
@callback render_loading(assigns()) :: rendered()
```

Render the loading state.

# `render_pagination`

```elixir
@callback render_pagination(assigns()) :: rendered()
```

Render pagination controls.

# `render_template_switcher`
*optional* 

```elixir
@callback render_template_switcher(assigns()) :: rendered()
```

Render the template switcher UI. Optional - has default implementation.

# `__using__`
*macro* 

Use this module to get default implementations for optional callbacks.

    defmodule MyTemplate do
      use MishkaGervaz.Table.Behaviours.Template

      # Now you only need to implement required callbacks
    end

# `all_features`

```elixir
@spec all_features() :: [feature()]
```

Returns the list of all valid features.

# `feature_enabled?`

```elixir
@spec feature_enabled?(features(), feature()) :: boolean()
```

Checks if a specific feature is enabled.

## Examples

    iex> feature_enabled?(:all, :sort)
    true

    iex> feature_enabled?([:filter, :paginate], :sort)
    false

# `get_cell_value`

```elixir
@spec get_cell_value(map(), map() | atom()) :: any()
```

Extract cell value from a record based on column source.

Handles various source formats:
- Atom: Direct field access
- List: Multiple fields joined
- Tuple: Relationship field access

# `normalize_features`

```elixir
@spec normalize_features(features()) :: [feature()]
```

Normalizes features to a list.

Converts `:all` to the full list of features, validates feature atoms.

## Examples

    iex> normalize_features(:all)
    [:sort, :filter, :select, :bulk_actions, :paginate, :export, :expand, :reorder, :inline_edit]

    iex> normalize_features([:sort, :filter])
    [:sort, :filter]

---

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