# `MishkaGervaz.Resource.Info.Table`
[🔗](https://github.com/mishka-group/mishka_gervaz/blob/v0.0.1-alpha.3/lib/mishka_gervaz/_resource/info/table.ex#L1)

Table-specific introspection for resources using `MishkaGervaz.Resource`.

## Usage

    # Get full table config
    config = MishkaGervaz.Resource.Info.Table.config(MyResource)

    # Get columns
    columns = MishkaGervaz.Resource.Info.Table.columns(MyResource)

    # Get filters
    filters = MishkaGervaz.Resource.Info.Table.filters(MyResource)

# `action_for`

```elixir
@spec action_for(module(), :read | :get | :destroy, boolean()) :: atom()
```

Get the appropriate action for the current user type.

For non-multi-tenant resources, returns the same (tenant) action for both
master and tenant users, since there's no need for differentiation.

# `all_preloads`

```elixir
@spec all_preloads(module(), boolean()) :: [atom()]
```

Get all preloads needed (always + detected + master/tenant specific).

Preload items can be atoms or `{source, alias}` tuples. This function
extracts just the source atoms for the actual preload query.

# `archive_action_for`

```elixir
@spec archive_action_for(module(), :read | :get | :restore | :destroy, boolean()) ::
  atom() | nil
```

Get the appropriate archive action for the current user type.

Returns the archive action for `:read`, `:get`, `:restore`, or `:destroy`.
Returns `nil` if archive is not configured for the resource.

# `archive_enabled?`

```elixir
@spec archive_enabled?(module()) :: boolean()
```

Check if archive is enabled for a resource.

# `builtins`

```elixir
@spec builtins(module()) :: map() | nil
```

Get the built-in state-transition rules map, or `nil` if none are configured.

# `bulk_actions`

```elixir
@spec bulk_actions(module()) :: [struct()]
```

Get all bulk actions for a resource.

# `column`

```elixir
@spec column(module(), atom()) :: struct() | nil
```

Get a specific column by name.

# `column_order`

```elixir
@spec column_order(module()) :: [atom()]
```

Get the column order for a resource.

# `columns`

```elixir
@spec columns(module()) :: [struct()]
```

Get all columns for a resource.

# `config`

```elixir
@spec config(module()) :: map() | nil
```

Get the full compiled table configuration for a resource.

Returns the pre-built configuration map merged with domain defaults.

# `data_loader`

```elixir
@spec data_loader(module()) :: map()
```

Get the data_loader configuration.

Returns a map with any configured data_loader module overrides.
Keys can include: `:module`, `:query`, `:filter_parser`, `:pagination`, `:tenant`, `:hooks`

# `detected_preloads`

```elixir
@spec detected_preloads(module()) :: [atom()]
```

Get detected preloads from column sources.

# `events`

```elixir
@spec events(module()) :: map()
```

Get the events configuration from the resource.

Returns a map with optional keys for sub-builder overrides:
- `:sanitization` - Custom sanitization handler module
- `:record` - Custom record handler module
- `:selection` - Custom selection handler module
- `:bulk_action` - Custom bulk action handler module
- `:hooks` - Custom hook runner module
- `:module` - Complete events module override

Returns an empty map if no events configuration is set.

# `feature_enabled?`

```elixir
@spec feature_enabled?(module(), MishkaGervaz.Table.Behaviours.Template.feature()) ::
  boolean()
```

Check if a specific feature is enabled for a resource.

## Examples

    feature_enabled?(MyResource, :sort) #=> true
    feature_enabled?(MyResource, :export) #=> false

# `features`

```elixir
@spec features(module()) :: [MishkaGervaz.Table.Behaviours.Template.feature()]
```

Get enabled features for a resource.

Returns a normalized list of enabled features (never `:all`).

## How Features Work

- DSL default is `:all` - uses template's `features()` as the source of truth
- `:all` → calls template's `features()` callback to get supported features
- `[:sort, :filter]` → uses the explicit list directly

Each template defines which features it supports via its `features()` callback.
Setting `:all` means "use all features this template supports".

## Examples

    # DSL: features [:filter, :paginate]
    features(MyResource) #=> [:filter, :paginate]

    # DSL: features :all (or not set, since :all is default)
    features(MyResource) #=> [:sort, :filter, :select, ...] (from template)

# `filter`

```elixir
@spec filter(module(), atom()) :: struct() | nil
```

Get a specific filter by name.

# `filter_group`

```elixir
@spec filter_group(module(), atom()) :: map() | nil
```

Get a specific filter group by name.

# `filter_groups`

```elixir
@spec filter_groups(module()) :: [map()]
```

Get all filter groups for a resource.

# `filter_mode`

```elixir
@spec filter_mode(module()) :: atom()
```

Get the filter mode for a resource.

# `filters`

```elixir
@spec filters(module()) :: [struct()]
```

Get all filters for a resource.

# `footer`

```elixir
@spec footer(module()) :: map() | nil
```

Get the table footer configuration. Returns nil when no footer is declared.

# `get_hook`

```elixir
@spec get_hook(module(), atom() | {atom(), atom()}) :: term() | nil
```

Get a single hook entry by key.

The key may be a global atom (e.g. `:on_load`) or a per-action tuple
(e.g. `{:before_row_action, :unarchive}`).

# `header`

```elixir
@spec header(module()) :: map() | nil
```

Get the table header configuration. Returns nil when no header is declared.

# `hooks`

```elixir
@spec hooks(module()) :: map()
```

Get all hooks as a map.

Returns globals (`:on_load`, `:before_delete`, …), per-action observer hooks
keyed as `{:before_row_action, :unarchive}`, and the `:__builtins__` map of
state-transition flags.

# `layout`

```elixir
@spec layout(module()) :: map() | nil
```

Get the table layout configuration (chrome). Returns nil when no `layout`
block is declared.

# `max_page_size`

```elixir
@spec max_page_size(module()) :: pos_integer() | nil
```

Get the max page size for a resource.

# `mishka_gervaz_form`

```elixir
@spec mishka_gervaz_form(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form DSL entities

# `mishka_gervaz_form_fields`

```elixir
@spec mishka_gervaz_form_fields(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form.fields DSL entities

# `mishka_gervaz_form_fields_field_order`

```elixir
@spec mishka_gervaz_form_fields_field_order(dsl_or_extended :: module() | map()) ::
  {:ok, [atom()]} | :error
```

Field display order. Fields not in list appear at end.

# `mishka_gervaz_form_fields_field_order!`

```elixir
@spec mishka_gervaz_form_fields_field_order!(dsl_or_extended :: module() | map()) ::
  [atom()] | no_return()
```

Field display order. Fields not in list appear at end.

# `mishka_gervaz_form_fields_options`

```elixir
@spec mishka_gervaz_form_fields_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.fields DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_groups`

```elixir
@spec mishka_gervaz_form_groups(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form.groups DSL entities

# `mishka_gervaz_form_hooks_after_save`

```elixir
@spec mishka_gervaz_form_hooks_after_save(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn result, state -> state` - After successful save.

# `mishka_gervaz_form_hooks_after_save!`

```elixir
@spec mishka_gervaz_form_hooks_after_save!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn result, state -> state` - After successful save.

# `mishka_gervaz_form_hooks_before_save`

```elixir
@spec mishka_gervaz_form_hooks_before_save(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn params, state -> params | {:halt, state}` - Before save. Return {:halt, state} to cancel.

# `mishka_gervaz_form_hooks_before_save!`

```elixir
@spec mishka_gervaz_form_hooks_before_save!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn params, state -> params | {:halt, state}` - Before save. Return {:halt, state} to cancel.

# `mishka_gervaz_form_hooks_js_after_save`

```elixir
@spec mishka_gervaz_form_hooks_js_after_save(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

`fn record_id -> %JS{}` - JS commands after successful save. Receives saved record ID.

# `mishka_gervaz_form_hooks_js_after_save!`

```elixir
@spec mishka_gervaz_form_hooks_js_after_save!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

`fn record_id -> %JS{}` - JS commands after successful save. Receives saved record ID.

# `mishka_gervaz_form_hooks_js_on_cancel`

```elixir
@spec mishka_gervaz_form_hooks_js_on_cancel(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

`fn record_id -> %JS{}` - JS commands when form is cancelled. Receives record ID or nil (create).

# `mishka_gervaz_form_hooks_js_on_cancel!`

```elixir
@spec mishka_gervaz_form_hooks_js_on_cancel!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

`fn record_id -> %JS{}` - JS commands when form is cancelled. Receives record ID or nil (create).

# `mishka_gervaz_form_hooks_js_on_error`

```elixir
@spec mishka_gervaz_form_hooks_js_on_error(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

`fn record_id -> %JS{}` - JS commands on save error. Receives record ID or nil (create).

# `mishka_gervaz_form_hooks_js_on_error!`

```elixir
@spec mishka_gervaz_form_hooks_js_on_error!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

`fn record_id -> %JS{}` - JS commands on save error. Receives record ID or nil (create).

# `mishka_gervaz_form_hooks_js_on_init`

```elixir
@spec mishka_gervaz_form_hooks_js_on_init(dsl_or_extended :: module() | map()) ::
  {:ok, (-&gt; any())} | :error
```

`fn -> %JS{}` - JS commands for phx-mounted on form container.

# `mishka_gervaz_form_hooks_js_on_init!`

```elixir
@spec mishka_gervaz_form_hooks_js_on_init!(dsl_or_extended :: module() | map()) ::
  (-&gt; any()) | no_return()
```

`fn -> %JS{}` - JS commands for phx-mounted on form container.

# `mishka_gervaz_form_hooks_js_options`

```elixir
@spec mishka_gervaz_form_hooks_js_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.hooks.js DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_hooks_on_cancel`

```elixir
@spec mishka_gervaz_form_hooks_on_cancel(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

`fn state -> state` - When form is cancelled.

# `mishka_gervaz_form_hooks_on_cancel!`

```elixir
@spec mishka_gervaz_form_hooks_on_cancel!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

`fn state -> state` - When form is cancelled.

# `mishka_gervaz_form_hooks_on_change`

```elixir
@spec mishka_gervaz_form_hooks_on_change(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any(), any() -&gt; any())} | :error
```

`fn field, value, state -> state | {:halt, state}` - On individual field change.

# `mishka_gervaz_form_hooks_on_change!`

```elixir
@spec mishka_gervaz_form_hooks_on_change!(dsl_or_extended :: module() | map()) ::
  (any(), any(), any() -&gt; any()) | no_return()
```

`fn field, value, state -> state | {:halt, state}` - On individual field change.

# `mishka_gervaz_form_hooks_on_error`

```elixir
@spec mishka_gervaz_form_hooks_on_error(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn form, state -> state` - On save error.

# `mishka_gervaz_form_hooks_on_error!`

```elixir
@spec mishka_gervaz_form_hooks_on_error!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn form, state -> state` - On save error.

# `mishka_gervaz_form_hooks_on_init`

```elixir
@spec mishka_gervaz_form_hooks_on_init(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn form, state -> form` - After form initialization.

# `mishka_gervaz_form_hooks_on_init!`

```elixir
@spec mishka_gervaz_form_hooks_on_init!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn form, state -> form` - After form initialization.

# `mishka_gervaz_form_hooks_on_validate`

```elixir
@spec mishka_gervaz_form_hooks_on_validate(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn params, state -> params` - On form validate event.

# `mishka_gervaz_form_hooks_on_validate!`

```elixir
@spec mishka_gervaz_form_hooks_on_validate!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn params, state -> params` - On form validate event.

# `mishka_gervaz_form_hooks_options`

```elixir
@spec mishka_gervaz_form_hooks_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.hooks DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_hooks_transform_errors`

```elixir
@spec mishka_gervaz_form_hooks_transform_errors(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn changeset, errors -> errors` - Transform error messages.

# `mishka_gervaz_form_hooks_transform_errors!`

```elixir
@spec mishka_gervaz_form_hooks_transform_errors!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn changeset, errors -> errors` - Transform error messages.

# `mishka_gervaz_form_hooks_transform_params`

```elixir
@spec mishka_gervaz_form_hooks_transform_params(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

`fn params -> params` - Transform params before action.

# `mishka_gervaz_form_hooks_transform_params!`

```elixir
@spec mishka_gervaz_form_hooks_transform_params!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

`fn params -> params` - Transform params before action.

# `mishka_gervaz_form_identity_name`

```elixir
@spec mishka_gervaz_form_identity_name(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Unique form identifier.

# `mishka_gervaz_form_identity_name!`

```elixir
@spec mishka_gervaz_form_identity_name!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Unique form identifier.

# `mishka_gervaz_form_identity_options`

```elixir
@spec mishka_gervaz_form_identity_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.identity DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_identity_route`

```elixir
@spec mishka_gervaz_form_identity_route(dsl_or_extended :: module() | map()) ::
  {:ok, String.t()} | :error
```

Base route for redirects after save.

# `mishka_gervaz_form_identity_route!`

```elixir
@spec mishka_gervaz_form_identity_route!(dsl_or_extended :: module() | map()) ::
  String.t() | no_return()
```

Base route for redirects after save.

# `mishka_gervaz_form_identity_stream_name`

```elixir
@spec mishka_gervaz_form_identity_stream_name(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Phoenix stream name. Auto-generated if not set.

# `mishka_gervaz_form_identity_stream_name!`

```elixir
@spec mishka_gervaz_form_identity_stream_name!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Phoenix stream name. Auto-generated if not set.

# `mishka_gervaz_form_layout`

```elixir
@spec mishka_gervaz_form_layout(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form.layout DSL entities

# `mishka_gervaz_form_layout_columns`

```elixir
@spec mishka_gervaz_form_layout_columns(dsl_or_extended :: module() | map()) ::
  {:ok, 4 | 3 | 2 | 1} | :error
```

Number of grid columns (1-4).

# `mishka_gervaz_form_layout_columns!`

```elixir
@spec mishka_gervaz_form_layout_columns!(dsl_or_extended :: module() | map()) ::
  (4 | 3 | 2 | 1) | no_return()
```

Number of grid columns (1-4).

# `mishka_gervaz_form_layout_mode`

```elixir
@spec mishka_gervaz_form_layout_mode(dsl_or_extended :: module() | map()) ::
  {:ok, :tabs | :wizard | :standard} | :error
```

Form layout mode.

# `mishka_gervaz_form_layout_mode!`

```elixir
@spec mishka_gervaz_form_layout_mode!(dsl_or_extended :: module() | map()) ::
  (:tabs | :wizard | :standard) | no_return()
```

Form layout mode.

# `mishka_gervaz_form_layout_navigation`

```elixir
@spec mishka_gervaz_form_layout_navigation(dsl_or_extended :: module() | map()) ::
  {:ok, :free | :sequential} | :error
```

Step navigation strategy. `:sequential` enforces order, `:free` allows jumping.

# `mishka_gervaz_form_layout_navigation!`

```elixir
@spec mishka_gervaz_form_layout_navigation!(dsl_or_extended :: module() | map()) ::
  (:free | :sequential) | no_return()
```

Step navigation strategy. `:sequential` enforces order, `:free` allows jumping.

# `mishka_gervaz_form_layout_options`

```elixir
@spec mishka_gervaz_form_layout_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.layout DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_layout_persistence`

```elixir
@spec mishka_gervaz_form_layout_persistence(dsl_or_extended :: module() | map()) ::
  {:ok, :client_token | :ets | :none} | :error
```

Where to persist step data between navigations.

# `mishka_gervaz_form_layout_persistence!`

```elixir
@spec mishka_gervaz_form_layout_persistence!(dsl_or_extended :: module() | map()) ::
  (:client_token | :ets | :none) | no_return()
```

Where to persist step data between navigations.

# `mishka_gervaz_form_layout_responsive`

```elixir
@spec mishka_gervaz_form_layout_responsive(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable responsive layout adjustments.

# `mishka_gervaz_form_layout_responsive!`

```elixir
@spec mishka_gervaz_form_layout_responsive!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable responsive layout adjustments.

# `mishka_gervaz_form_presentation_debounce`

```elixir
@spec mishka_gervaz_form_presentation_debounce(dsl_or_extended :: module() | map()) ::
  {:ok, integer()} | :error
```

Default debounce milliseconds for all fields. Overridden per-field via `ui do debounce end`.

# `mishka_gervaz_form_presentation_debounce!`

```elixir
@spec mishka_gervaz_form_presentation_debounce!(dsl_or_extended :: module() | map()) ::
  integer() | no_return()
```

Default debounce milliseconds for all fields. Overridden per-field via `ui do debounce end`.

# `mishka_gervaz_form_presentation_features`

```elixir
@spec mishka_gervaz_form_presentation_features(dsl_or_extended :: module() | map()) ::
  {:ok,
   :all
   | [:inline_errors | :autosave | :wizard | :groups | :uploads | :validation]}
  | :error
```

Features to enable for this form.

# `mishka_gervaz_form_presentation_features!`

```elixir
@spec mishka_gervaz_form_presentation_features!(dsl_or_extended :: module() | map()) ::
  (:all
   | [:inline_errors | :autosave | :wizard | :groups | :uploads | :validation])
  | no_return()
```

Features to enable for this form.

# `mishka_gervaz_form_presentation_options`

```elixir
@spec mishka_gervaz_form_presentation_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.form.presentation DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_presentation_template`

```elixir
@spec mishka_gervaz_form_presentation_template(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Template module for form layout.

# `mishka_gervaz_form_presentation_template!`

```elixir
@spec mishka_gervaz_form_presentation_template!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Template module for form layout.

# `mishka_gervaz_form_presentation_theme_error_class`

```elixir
@spec mishka_gervaz_form_presentation_theme_error_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Error message CSS classes.

# `mishka_gervaz_form_presentation_theme_error_class!`

```elixir
@spec mishka_gervaz_form_presentation_theme_error_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Error message CSS classes.

# `mishka_gervaz_form_presentation_theme_extra`

```elixir
@spec mishka_gervaz_form_presentation_theme_extra(dsl_or_extended :: module() | map()) ::
  {:ok, map()} | :error
```

Template-specific theming options.

# `mishka_gervaz_form_presentation_theme_extra!`

```elixir
@spec mishka_gervaz_form_presentation_theme_extra!(
  dsl_or_extended :: module() | map()
) ::
  map() | no_return()
```

Template-specific theming options.

# `mishka_gervaz_form_presentation_theme_field_class`

```elixir
@spec mishka_gervaz_form_presentation_theme_field_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Default field CSS classes.

# `mishka_gervaz_form_presentation_theme_field_class!`

```elixir
@spec mishka_gervaz_form_presentation_theme_field_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Default field CSS classes.

# `mishka_gervaz_form_presentation_theme_form_class`

```elixir
@spec mishka_gervaz_form_presentation_theme_form_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Form element CSS classes.

# `mishka_gervaz_form_presentation_theme_form_class!`

```elixir
@spec mishka_gervaz_form_presentation_theme_form_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Form element CSS classes.

# `mishka_gervaz_form_presentation_theme_label_class`

```elixir
@spec mishka_gervaz_form_presentation_theme_label_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Default label CSS classes.

# `mishka_gervaz_form_presentation_theme_label_class!`

```elixir
@spec mishka_gervaz_form_presentation_theme_label_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Default label CSS classes.

# `mishka_gervaz_form_presentation_theme_options`

```elixir
@spec mishka_gervaz_form_presentation_theme_options(
  dsl_or_extended :: module() | map()
) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.presentation.theme DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_presentation_ui_adapter`

```elixir
@spec mishka_gervaz_form_presentation_ui_adapter(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

UI adapter module for rendering components.

# `mishka_gervaz_form_presentation_ui_adapter!`

```elixir
@spec mishka_gervaz_form_presentation_ui_adapter!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

UI adapter module for rendering components.

# `mishka_gervaz_form_presentation_ui_adapter_opts`

```elixir
@spec mishka_gervaz_form_presentation_ui_adapter_opts(
  dsl_or_extended :: module() | map()
) ::
  {:ok, keyword()} | :error
```

Options for UI adapter configuration.

# `mishka_gervaz_form_presentation_ui_adapter_opts!`

```elixir
@spec mishka_gervaz_form_presentation_ui_adapter_opts!(
  dsl_or_extended :: module() | map()
) ::
  keyword() | no_return()
```

Options for UI adapter configuration.

# `mishka_gervaz_form_source`

```elixir
@spec mishka_gervaz_form_source(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form.source DSL entities

# `mishka_gervaz_form_source_actions_create`

```elixir
@spec mishka_gervaz_form_source_actions_create(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Create action. Atom (used for both master and tenant) or tuple `{master_action, tenant_action}`. Required either here or on the domain — compile fails otherwise.

# `mishka_gervaz_form_source_actions_create!`

```elixir
@spec mishka_gervaz_form_source_actions_create!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Create action. Atom (used for both master and tenant) or tuple `{master_action, tenant_action}`. Required either here or on the domain — compile fails otherwise.

# `mishka_gervaz_form_source_actions_options`

```elixir
@spec mishka_gervaz_form_source_actions_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.form.source.actions DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_source_actions_read`

```elixir
@spec mishka_gervaz_form_source_actions_read(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Read/get action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_form_source_actions_read!`

```elixir
@spec mishka_gervaz_form_source_actions_read!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Read/get action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_form_source_actions_update`

```elixir
@spec mishka_gervaz_form_source_actions_update(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Update action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_form_source_actions_update!`

```elixir
@spec mishka_gervaz_form_source_actions_update!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Update action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_form_source_actor_key`

```elixir
@spec mishka_gervaz_form_source_actor_key(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Assigns key for current user.

# `mishka_gervaz_form_source_actor_key!`

```elixir
@spec mishka_gervaz_form_source_actor_key!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Assigns key for current user.

# `mishka_gervaz_form_source_master_check`

```elixir
@spec mishka_gervaz_form_source_master_check(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

Function returning true for master users. `fn user -> boolean`

# `mishka_gervaz_form_source_master_check!`

```elixir
@spec mishka_gervaz_form_source_master_check!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

Function returning true for master users. `fn user -> boolean`

# `mishka_gervaz_form_source_options`

```elixir
@spec mishka_gervaz_form_source_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.source DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_source_preload_always`

```elixir
@spec mishka_gervaz_form_source_preload_always(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Always preload these relationships.

Supports atoms or `{source, alias}` tuples:
- `:category` - preload `:category` relationship
- `{:category, :cat}` or `category: :cat` - preload `:category`, alias as `:cat`

> ### Pagination Warning {: .warning}
>
> The relationship's read action must NOT have `pagination required?: true`.
> Preloads do not pass pagination params, so required pagination will cause
> `LimitRequired` errors at runtime. Use `required?: false` on the action:
>
>     read :my_action do
>       pagination offset?: true, required?: false, default_limit: 20
>     end

# `mishka_gervaz_form_source_preload_always!`

```elixir
@spec mishka_gervaz_form_source_preload_always!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Always preload these relationships.

Supports atoms or `{source, alias}` tuples:
- `:category` - preload `:category` relationship
- `{:category, :cat}` or `category: :cat` - preload `:category`, alias as `:cat`

> ### Pagination Warning {: .warning}
>
> The relationship's read action must NOT have `pagination required?: true`.
> Preloads do not pass pagination params, so required pagination will cause
> `LimitRequired` errors at runtime. Use `required?: false` on the action:
>
>     read :my_action do
>       pagination offset?: true, required?: false, default_limit: 20
>     end

# `mishka_gervaz_form_source_preload_master`

```elixir
@spec mishka_gervaz_form_source_preload_master(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Additional preloads for master users.

Supports atoms or `{source, alias}` tuples.
See `always` for pagination requirements.

# `mishka_gervaz_form_source_preload_master!`

```elixir
@spec mishka_gervaz_form_source_preload_master!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Additional preloads for master users.

Supports atoms or `{source, alias}` tuples.
See `always` for pagination requirements.

# `mishka_gervaz_form_source_preload_options`

```elixir
@spec mishka_gervaz_form_source_preload_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.form.source.preload DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_source_preload_tenant`

```elixir
@spec mishka_gervaz_form_source_preload_tenant(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Additional preloads for tenant users.

Supports atoms or `{source, alias}` tuples.
See `always` for pagination requirements.

# `mishka_gervaz_form_source_preload_tenant!`

```elixir
@spec mishka_gervaz_form_source_preload_tenant!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Additional preloads for tenant users.

Supports atoms or `{source, alias}` tuples.
See `always` for pagination requirements.

# `mishka_gervaz_form_source_restricted`

```elixir
@spec mishka_gervaz_form_source_restricted(dsl_or_extended :: module() | map()) ::
  {:ok, boolean() | (any() -&gt; any())} | :error
```

Restrict all form modes to master users. Boolean or `fn state -> boolean end`.

# `mishka_gervaz_form_source_restricted!`

```elixir
@spec mishka_gervaz_form_source_restricted!(dsl_or_extended :: module() | map()) ::
  (boolean() | (any() -&gt; any())) | no_return()
```

Restrict all form modes to master users. Boolean or `fn state -> boolean end`.

# `mishka_gervaz_form_state_access`

```elixir
@spec mishka_gervaz_form_state_access(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Access module. Must `use MishkaGervaz.Form.Web.State.Access`.
Handles access control for form actions.

# `mishka_gervaz_form_state_access!`

```elixir
@spec mishka_gervaz_form_state_access!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Access module. Must `use MishkaGervaz.Form.Web.State.Access`.
Handles access control for form actions.

# `mishka_gervaz_form_state_field`

```elixir
@spec mishka_gervaz_form_state_field(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Field builder module. Must `use MishkaGervaz.Form.Web.State.FieldBuilder`.
Builds field configs from DSL and resource configuration.

# `mishka_gervaz_form_state_field!`

```elixir
@spec mishka_gervaz_form_state_field!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Field builder module. Must `use MishkaGervaz.Form.Web.State.FieldBuilder`.
Builds field configs from DSL and resource configuration.

# `mishka_gervaz_form_state_group`

```elixir
@spec mishka_gervaz_form_state_group(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Group builder module. Must `use MishkaGervaz.Form.Web.State.GroupBuilder`.
Builds group layout from DSL configuration.

# `mishka_gervaz_form_state_group!`

```elixir
@spec mishka_gervaz_form_state_group!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Group builder module. Must `use MishkaGervaz.Form.Web.State.GroupBuilder`.
Builds group layout from DSL configuration.

# `mishka_gervaz_form_state_module`

```elixir
@spec mishka_gervaz_form_state_module(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Override the entire state module. When set, all other options are ignored.
The module must `use MishkaGervaz.Form.Web.State`.

# `mishka_gervaz_form_state_module!`

```elixir
@spec mishka_gervaz_form_state_module!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Override the entire state module. When set, all other options are ignored.
The module must `use MishkaGervaz.Form.Web.State`.

# `mishka_gervaz_form_state_options`

```elixir
@spec mishka_gervaz_form_state_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.form.state DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_form_state_presentation`

```elixir
@spec mishka_gervaz_form_state_presentation(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Presentation module. Must `use MishkaGervaz.Form.Web.State.Presentation`.
Resolves UI adapter, templates, and presentation options.

# `mishka_gervaz_form_state_presentation!`

```elixir
@spec mishka_gervaz_form_state_presentation!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Presentation module. Must `use MishkaGervaz.Form.Web.State.Presentation`.
Resolves UI adapter, templates, and presentation options.

# `mishka_gervaz_form_state_step`

```elixir
@spec mishka_gervaz_form_state_step(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Step builder module. Must `use MishkaGervaz.Form.Web.State.StepBuilder`.
Builds wizard/tab steps from DSL configuration.

# `mishka_gervaz_form_state_step!`

```elixir
@spec mishka_gervaz_form_state_step!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Step builder module. Must `use MishkaGervaz.Form.Web.State.StepBuilder`.
Builds wizard/tab steps from DSL configuration.

# `mishka_gervaz_form_uploads`

```elixir
@spec mishka_gervaz_form_uploads(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.form.uploads DSL entities

# `mishka_gervaz_table`

```elixir
@spec mishka_gervaz_table(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table DSL entities

# `mishka_gervaz_table_bulk_actions`

```elixir
@spec mishka_gervaz_table_bulk_actions(dsl_or_extended :: module() | map()) :: [
  struct()
]
```

mishka_gervaz.table.bulk_actions DSL entities

# `mishka_gervaz_table_bulk_actions_enabled`

```elixir
@spec mishka_gervaz_table_bulk_actions_enabled(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable bulk actions.

# `mishka_gervaz_table_bulk_actions_enabled!`

```elixir
@spec mishka_gervaz_table_bulk_actions_enabled!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable bulk actions.

# `mishka_gervaz_table_bulk_actions_options`

```elixir
@spec mishka_gervaz_table_bulk_actions_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.table.bulk_actions DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_columns`

```elixir
@spec mishka_gervaz_table_columns(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table.columns DSL entities

# `mishka_gervaz_table_columns_column_order`

```elixir
@spec mishka_gervaz_table_columns_column_order(dsl_or_extended :: module() | map()) ::
  {:ok, [atom()]} | :error
```

Column display order. Columns not in list appear at end.

# `mishka_gervaz_table_columns_column_order!`

```elixir
@spec mishka_gervaz_table_columns_column_order!(dsl_or_extended :: module() | map()) ::
  [atom()] | no_return()
```

Column display order. Columns not in list appear at end.

# `mishka_gervaz_table_columns_default_sort`

```elixir
@spec mishka_gervaz_table_columns_default_sort(dsl_or_extended :: module() | map()) ::
  {:ok, any()} | :error
```

Default sort. Atom, tuple, or list of tuples.

# `mishka_gervaz_table_columns_default_sort!`

```elixir
@spec mishka_gervaz_table_columns_default_sort!(dsl_or_extended :: module() | map()) ::
  any() | no_return()
```

Default sort. Atom, tuple, or list of tuples.

# `mishka_gervaz_table_columns_options`

```elixir
@spec mishka_gervaz_table_columns_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.columns DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_filter_groups`

```elixir
@spec mishka_gervaz_table_filter_groups(dsl_or_extended :: module() | map()) :: [
  struct()
]
```

mishka_gervaz.table.filter_groups DSL entities

# `mishka_gervaz_table_filters`

```elixir
@spec mishka_gervaz_table_filters(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table.filters DSL entities

# `mishka_gervaz_table_hooks`

```elixir
@spec mishka_gervaz_table_hooks(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table.hooks DSL entities

# `mishka_gervaz_table_hooks_after_delete`

```elixir
@spec mishka_gervaz_table_hooks_after_delete(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn record, state -> any` - After delete (side effects only).

# `mishka_gervaz_table_hooks_after_delete!`

```elixir
@spec mishka_gervaz_table_hooks_after_delete!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn record, state -> any` - After delete (side effects only).

# `mishka_gervaz_table_hooks_before_delete`

```elixir
@spec mishka_gervaz_table_hooks_before_delete(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn record, state -> {:ok, state} | {:halt, {:error, msg}}` - Before delete.

# `mishka_gervaz_table_hooks_before_delete!`

```elixir
@spec mishka_gervaz_table_hooks_before_delete!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn record, state -> {:ok, state} | {:halt, {:error, msg}}` - Before delete.

# `mishka_gervaz_table_hooks_clear_selection_after_bulk`

```elixir
@spec mishka_gervaz_table_hooks_clear_selection_after_bulk(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Clear `selected_ids` / `excluded_ids` / `select_all?` after a successful bulk action.

# `mishka_gervaz_table_hooks_clear_selection_after_bulk!`

```elixir
@spec mishka_gervaz_table_hooks_clear_selection_after_bulk!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Clear `selected_ids` / `excluded_ids` / `select_all?` after a successful bulk action.

# `mishka_gervaz_table_hooks_on_event`

```elixir
@spec mishka_gervaz_table_hooks_on_event(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any(), any() -&gt; any())} | :error
```

`fn event_name, params, socket -> {:ok, socket} | {:halt, socket}` - Custom event handler.

# `mishka_gervaz_table_hooks_on_event!`

```elixir
@spec mishka_gervaz_table_hooks_on_event!(dsl_or_extended :: module() | map()) ::
  (any(), any(), any() -&gt; any()) | no_return()
```

`fn event_name, params, socket -> {:ok, socket} | {:halt, socket}` - Custom event handler.

# `mishka_gervaz_table_hooks_on_expand`

```elixir
@spec mishka_gervaz_table_hooks_on_expand(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn record_id, socket -> socket | {:cont, socket} | {:halt, socket}` - Row expanded. Return {:halt, socket} to cancel.

# `mishka_gervaz_table_hooks_on_expand!`

```elixir
@spec mishka_gervaz_table_hooks_on_expand!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn record_id, socket -> socket | {:cont, socket} | {:halt, socket}` - Row expanded. Return {:halt, socket} to cancel.

# `mishka_gervaz_table_hooks_on_filter`

```elixir
@spec mishka_gervaz_table_hooks_on_filter(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn filter_values, socket -> socket | {:cont, socket} | {:halt, socket}` - Filter changed.

# `mishka_gervaz_table_hooks_on_filter!`

```elixir
@spec mishka_gervaz_table_hooks_on_filter!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn filter_values, socket -> socket | {:cont, socket} | {:halt, socket}` - Filter changed.

# `mishka_gervaz_table_hooks_on_load`

```elixir
@spec mishka_gervaz_table_hooks_on_load(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn query, state -> {:cont, query} | query` - Before data loaded. Modify query.

# `mishka_gervaz_table_hooks_on_load!`

```elixir
@spec mishka_gervaz_table_hooks_on_load!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn query, state -> {:cont, query} | query` - Before data loaded. Modify query.

# `mishka_gervaz_table_hooks_on_realtime`

```elixir
@spec mishka_gervaz_table_hooks_on_realtime(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn notification, socket -> socket | {:cont, socket} | {:halt, socket}` - PubSub received. Return {:halt, socket} to skip update.

# `mishka_gervaz_table_hooks_on_realtime!`

```elixir
@spec mishka_gervaz_table_hooks_on_realtime!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn notification, socket -> socket | {:cont, socket} | {:halt, socket}` - PubSub received. Return {:halt, socket} to skip update.

# `mishka_gervaz_table_hooks_on_select`

```elixir
@spec mishka_gervaz_table_hooks_on_select(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn selected_ids, socket -> socket | {:cont, socket} | {:halt, socket}` - Selection changed.

# `mishka_gervaz_table_hooks_on_select!`

```elixir
@spec mishka_gervaz_table_hooks_on_select!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn selected_ids, socket -> socket | {:cont, socket} | {:halt, socket}` - Selection changed.

# `mishka_gervaz_table_hooks_on_sort`

```elixir
@spec mishka_gervaz_table_hooks_on_sort(dsl_or_extended :: module() | map()) ::
  {:ok, (any(), any() -&gt; any())} | :error
```

`fn {field, direction}, socket -> socket | {:cont, socket} | {:halt, socket}` - Sort changed.

# `mishka_gervaz_table_hooks_on_sort!`

```elixir
@spec mishka_gervaz_table_hooks_on_sort!(dsl_or_extended :: module() | map()) ::
  (any(), any() -&gt; any()) | no_return()
```

`fn {field, direction}, socket -> socket | {:cont, socket} | {:halt, socket}` - Sort changed.

# `mishka_gervaz_table_hooks_options`

```elixir
@spec mishka_gervaz_table_hooks_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.hooks DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_hooks_redirect_on_empty`

```elixir
@spec mishka_gervaz_table_hooks_redirect_on_empty(dsl_or_extended :: module() | map()) ::
  {:ok, String.t() | (any() -&gt; any())} | :error
```

Redirect path (string or `fn state -> path end`) when `total_count == 0` after a load.

# `mishka_gervaz_table_hooks_redirect_on_empty!`

```elixir
@spec mishka_gervaz_table_hooks_redirect_on_empty!(
  dsl_or_extended :: module() | map()
) ::
  (String.t() | (any() -&gt; any())) | no_return()
```

Redirect path (string or `fn state -> path end`) when `total_count == 0` after a load.

# `mishka_gervaz_table_hooks_reset_page_on_empty_current_page`

```elixir
@spec mishka_gervaz_table_hooks_reset_page_on_empty_current_page(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Reload page 1 if the current page becomes empty after an action.

# `mishka_gervaz_table_hooks_reset_page_on_empty_current_page!`

```elixir
@spec mishka_gervaz_table_hooks_reset_page_on_empty_current_page!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Reload page 1 if the current page becomes empty after an action.

# `mishka_gervaz_table_hooks_switch_to_active_on_empty_archive`

```elixir
@spec mishka_gervaz_table_hooks_switch_to_active_on_empty_archive(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Switch to active mode after a successful unarchive/permanent_destroy if the archive list is now empty.

# `mishka_gervaz_table_hooks_switch_to_active_on_empty_archive!`

```elixir
@spec mishka_gervaz_table_hooks_switch_to_active_on_empty_archive!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Switch to active mode after a successful unarchive/permanent_destroy if the archive list is now empty.

# `mishka_gervaz_table_hooks_switch_to_archive_on_empty_active`

```elixir
@spec mishka_gervaz_table_hooks_switch_to_archive_on_empty_active(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Symmetric: switch to archive mode after a successful destroy if the active list is now empty.

# `mishka_gervaz_table_hooks_switch_to_archive_on_empty_active!`

```elixir
@spec mishka_gervaz_table_hooks_switch_to_archive_on_empty_active!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Symmetric: switch to archive mode after a successful destroy if the active list is now empty.

# `mishka_gervaz_table_identity_name`

```elixir
@spec mishka_gervaz_table_identity_name(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Unique table identifier.

# `mishka_gervaz_table_identity_name!`

```elixir
@spec mishka_gervaz_table_identity_name!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Unique table identifier.

# `mishka_gervaz_table_identity_options`

```elixir
@spec mishka_gervaz_table_identity_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.identity DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_identity_route`

```elixir
@spec mishka_gervaz_table_identity_route(dsl_or_extended :: module() | map()) ::
  {:ok, String.t()} | :error
```

Base route for links (used in row actions).

# `mishka_gervaz_table_identity_route!`

```elixir
@spec mishka_gervaz_table_identity_route!(dsl_or_extended :: module() | map()) ::
  String.t() | no_return()
```

Base route for links (used in row actions).

# `mishka_gervaz_table_identity_stream_name`

```elixir
@spec mishka_gervaz_table_identity_stream_name(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Phoenix stream name. Auto-generated if not set.

# `mishka_gervaz_table_identity_stream_name!`

```elixir
@spec mishka_gervaz_table_identity_stream_name!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Phoenix stream name. Auto-generated if not set.

# `mishka_gervaz_table_layout`

```elixir
@spec mishka_gervaz_table_layout(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table.layout DSL entities

# `mishka_gervaz_table_presentation_features`

```elixir
@spec mishka_gervaz_table_presentation_features(dsl_or_extended :: module() | map()) ::
  {:ok,
   :all
   | [
       :inline_edit
       | :reorder
       | :expand
       | :export
       | :paginate
       | :bulk_actions
       | :select
       | :filter
       | :sort
     ]}
  | :error
```

Features to enable for this table.

Can be `:all` (default - uses template's features) or a list of specific features.

Available 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

    # Use all template features (default)
    features :all

    # Only specific features
    features [:filter, :paginate]

    # Disable all features
    features []

# `mishka_gervaz_table_presentation_features!`

```elixir
@spec mishka_gervaz_table_presentation_features!(dsl_or_extended :: module() | map()) ::
  (:all
   | [
       :inline_edit
       | :reorder
       | :expand
       | :export
       | :paginate
       | :bulk_actions
       | :select
       | :filter
       | :sort
     ])
  | no_return()
```

Features to enable for this table.

Can be `:all` (default - uses template's features) or a list of specific features.

Available 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

    # Use all template features (default)
    features :all

    # Only specific features
    features [:filter, :paginate]

    # Disable all features
    features []

# `mishka_gervaz_table_presentation_filter_mode`

```elixir
@spec mishka_gervaz_table_presentation_filter_mode(
  dsl_or_extended :: module() | map()
) ::
  {:ok, :drawer | :modal | :sidebar | :inline} | :error
```

Filter display mode: :inline (default), :sidebar, :modal, or :drawer.

# `mishka_gervaz_table_presentation_filter_mode!`

```elixir
@spec mishka_gervaz_table_presentation_filter_mode!(
  dsl_or_extended :: module() | map()
) ::
  (:drawer | :modal | :sidebar | :inline) | no_return()
```

Filter display mode: :inline (default), :sidebar, :modal, or :drawer.

# `mishka_gervaz_table_presentation_options`

```elixir
@spec mishka_gervaz_table_presentation_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.table.presentation DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_presentation_responsive_hide_on_mobile`

```elixir
@spec mishka_gervaz_table_presentation_responsive_hide_on_mobile(
  dsl_or_extended :: module() | map()
) ::
  {:ok, [atom()]} | :error
```

Columns to hide on mobile.

# `mishka_gervaz_table_presentation_responsive_hide_on_mobile!`

```elixir
@spec mishka_gervaz_table_presentation_responsive_hide_on_mobile!(
  dsl_or_extended :: module() | map()
) ::
  [atom()] | no_return()
```

Columns to hide on mobile.

# `mishka_gervaz_table_presentation_responsive_hide_on_tablet`

```elixir
@spec mishka_gervaz_table_presentation_responsive_hide_on_tablet(
  dsl_or_extended :: module() | map()
) ::
  {:ok, [atom()]} | :error
```

Columns to hide on tablet.

# `mishka_gervaz_table_presentation_responsive_hide_on_tablet!`

```elixir
@spec mishka_gervaz_table_presentation_responsive_hide_on_tablet!(
  dsl_or_extended :: module() | map()
) ::
  [atom()] | no_return()
```

Columns to hide on tablet.

# `mishka_gervaz_table_presentation_responsive_mobile_layout`

```elixir
@spec mishka_gervaz_table_presentation_responsive_mobile_layout(
  dsl_or_extended :: module() | map()
) ::
  {:ok, :stacked | :cards} | :error
```

Layout mode on mobile.

# `mishka_gervaz_table_presentation_responsive_mobile_layout!`

```elixir
@spec mishka_gervaz_table_presentation_responsive_mobile_layout!(
  dsl_or_extended :: module() | map()
) ::
  (:stacked | :cards) | no_return()
```

Layout mode on mobile.

# `mishka_gervaz_table_presentation_responsive_options`

```elixir
@spec mishka_gervaz_table_presentation_responsive_options(
  dsl_or_extended :: module() | map()
) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.presentation.responsive DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_presentation_switchable_templates`

```elixir
@spec mishka_gervaz_table_presentation_switchable_templates(
  dsl_or_extended :: module() | map()
) ::
  {:ok, [atom() | module()]} | :error
```

List of template modules users can switch between at runtime.
If empty, template switching is disabled.
Example: [MishkaGervaz.Table.Templates.Table, MishkaGervaz.Table.Templates.MediaGallery]

# `mishka_gervaz_table_presentation_switchable_templates!`

```elixir
@spec mishka_gervaz_table_presentation_switchable_templates!(
  dsl_or_extended :: module() | map()
) ::
  [atom() | module()] | no_return()
```

List of template modules users can switch between at runtime.
If empty, template switching is disabled.
Example: [MishkaGervaz.Table.Templates.Table, MishkaGervaz.Table.Templates.MediaGallery]

# `mishka_gervaz_table_presentation_template`

```elixir
@spec mishka_gervaz_table_presentation_template(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | module()} | :error
```

Default template module for layout structure.
Built-in templates:
- `MishkaGervaz.Table.Templates.Table` - Traditional rows/columns (default)
- `MishkaGervaz.Table.Templates.MediaGallery` - Image/file gallery

# `mishka_gervaz_table_presentation_template!`

```elixir
@spec mishka_gervaz_table_presentation_template!(dsl_or_extended :: module() | map()) ::
  (atom() | module()) | no_return()
```

Default template module for layout structure.
Built-in templates:
- `MishkaGervaz.Table.Templates.Table` - Traditional rows/columns (default)
- `MishkaGervaz.Table.Templates.MediaGallery` - Image/file gallery

# `mishka_gervaz_table_presentation_template_options`

```elixir
@spec mishka_gervaz_table_presentation_template_options(
  dsl_or_extended :: module() | map()
) ::
  {:ok, keyword()} | :error
```

Options passed to the template.
Common options vary by template:
- Table: [:striped, :bordered, :compact, :hoverable]
- MediaGallery: [:thumbnail_size, :aspect_ratio, :columns]

# `mishka_gervaz_table_presentation_template_options!`

```elixir
@spec mishka_gervaz_table_presentation_template_options!(
  dsl_or_extended :: module() | map()
) ::
  keyword() | no_return()
```

Options passed to the template.
Common options vary by template:
- Table: [:striped, :bordered, :compact, :hoverable]
- MediaGallery: [:thumbnail_size, :aspect_ratio, :columns]

# `mishka_gervaz_table_presentation_theme_border_class`

```elixir
@spec mishka_gervaz_table_presentation_theme_border_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Border CSS classes.

# `mishka_gervaz_table_presentation_theme_border_class!`

```elixir
@spec mishka_gervaz_table_presentation_theme_border_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Border CSS classes.

# `mishka_gervaz_table_presentation_theme_extra`

```elixir
@spec mishka_gervaz_table_presentation_theme_extra(
  dsl_or_extended :: module() | map()
) ::
  {:ok, map()} | :error
```

Template-specific theming options.

# `mishka_gervaz_table_presentation_theme_extra!`

```elixir
@spec mishka_gervaz_table_presentation_theme_extra!(
  dsl_or_extended :: module() | map()
) ::
  map() | no_return()
```

Template-specific theming options.

# `mishka_gervaz_table_presentation_theme_header_class`

```elixir
@spec mishka_gervaz_table_presentation_theme_header_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Header row CSS classes.

# `mishka_gervaz_table_presentation_theme_header_class!`

```elixir
@spec mishka_gervaz_table_presentation_theme_header_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Header row CSS classes.

# `mishka_gervaz_table_presentation_theme_options`

```elixir
@spec mishka_gervaz_table_presentation_theme_options(
  dsl_or_extended :: module() | map()
) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.presentation.theme DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_presentation_theme_row_class`

```elixir
@spec mishka_gervaz_table_presentation_theme_row_class(
  dsl_or_extended :: module() | map()
) ::
  {:ok, String.t()} | :error
```

Data row CSS classes.

# `mishka_gervaz_table_presentation_theme_row_class!`

```elixir
@spec mishka_gervaz_table_presentation_theme_row_class!(
  dsl_or_extended :: module() | map()
) ::
  String.t() | no_return()
```

Data row CSS classes.

# `mishka_gervaz_table_presentation_ui_adapter`

```elixir
@spec mishka_gervaz_table_presentation_ui_adapter(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | module()} | :error
```

UI adapter module for rendering components.

Built-in adapters:
- `MishkaGervaz.UIAdapters.Tailwind` - Plain Tailwind CSS (default)

Create custom adapter with `use MishkaGervaz.Behaviours.UIAdapter`:

    defmodule MyAppWeb.UIAdapter do
      use MishkaGervaz.Behaviours.UIAdapter,
        components: MyAppWeb.Components  # Auto-override from your components

      # Or manually override specific functions:
      # def button(assigns), do: MyAppWeb.Components.Button.button(assigns)
    end

Options for `use`:
- `:fallback` - Fallback module (default: Tailwind)
- `:components` - Module to auto-generate overrides from

# `mishka_gervaz_table_presentation_ui_adapter!`

```elixir
@spec mishka_gervaz_table_presentation_ui_adapter!(
  dsl_or_extended :: module() | map()
) ::
  (atom() | module()) | no_return()
```

UI adapter module for rendering components.

Built-in adapters:
- `MishkaGervaz.UIAdapters.Tailwind` - Plain Tailwind CSS (default)

Create custom adapter with `use MishkaGervaz.Behaviours.UIAdapter`:

    defmodule MyAppWeb.UIAdapter do
      use MishkaGervaz.Behaviours.UIAdapter,
        components: MyAppWeb.Components  # Auto-override from your components

      # Or manually override specific functions:
      # def button(assigns), do: MyAppWeb.Components.Button.button(assigns)
    end

Options for `use`:
- `:fallback` - Fallback module (default: Tailwind)
- `:components` - Module to auto-generate overrides from

# `mishka_gervaz_table_presentation_ui_adapter_opts`

```elixir
@spec mishka_gervaz_table_presentation_ui_adapter_opts(
  dsl_or_extended :: module() | map()
) ::
  {:ok, keyword()} | :error
```

Options for UI adapter configuration.

## Available Options

  * `:component_module` - Your components module (e.g., `MyAppWeb.Components`).
    When specified together with `MishkaGervaz.UIAdapters.Dynamic`, generates
    a dynamic adapter at compile time that uses your components with Tailwind
    as fallback.

  * `:fallback` - Fallback adapter module. Defaults to `MishkaGervaz.UIAdapters.Tailwind`.

  * `:nested_components` - If true, uses nested module pattern (e.g., `Components.Button.button/1`).

  * `:module_prefix` - Prefix for module names (e.g., `"Mishka"` → `Components.MishkaButton`).

  * `:component_prefix` - Prefix for function names (e.g., `"mc_"` → `mc_button/1`).

## Examples

    # Basic dynamic adapter usage
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components
    end
    # Calls: MyAppWeb.Components.Button.button/1

    # With module prefix
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components, module_prefix: "Mishka"
    end
    # Calls: MyAppWeb.Components.MishkaButton.button/1

    # With component prefix
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components, component_prefix: "mc_"
    end
    # Calls: MyAppWeb.Components.Button.mc_button/1

    # With both prefixes
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components,
                      module_prefix: "Mishka",
                      component_prefix: "mc_"
    end
    # Calls: MyAppWeb.Components.MishkaButton.mc_button/1

This auto-generates an adapter module `YourResource.GervazUIAdapter` that:
- Delegates to your declared components if they exist
- Falls back to Tailwind for any missing components
- All resolved at compile time with zero runtime overhead

# `mishka_gervaz_table_presentation_ui_adapter_opts!`

```elixir
@spec mishka_gervaz_table_presentation_ui_adapter_opts!(
  dsl_or_extended :: module() | map()
) ::
  keyword() | no_return()
```

Options for UI adapter configuration.

## Available Options

  * `:component_module` - Your components module (e.g., `MyAppWeb.Components`).
    When specified together with `MishkaGervaz.UIAdapters.Dynamic`, generates
    a dynamic adapter at compile time that uses your components with Tailwind
    as fallback.

  * `:fallback` - Fallback adapter module. Defaults to `MishkaGervaz.UIAdapters.Tailwind`.

  * `:nested_components` - If true, uses nested module pattern (e.g., `Components.Button.button/1`).

  * `:module_prefix` - Prefix for module names (e.g., `"Mishka"` → `Components.MishkaButton`).

  * `:component_prefix` - Prefix for function names (e.g., `"mc_"` → `mc_button/1`).

## Examples

    # Basic dynamic adapter usage
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components
    end
    # Calls: MyAppWeb.Components.Button.button/1

    # With module prefix
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components, module_prefix: "Mishka"
    end
    # Calls: MyAppWeb.Components.MishkaButton.button/1

    # With component prefix
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components, component_prefix: "mc_"
    end
    # Calls: MyAppWeb.Components.Button.mc_button/1

    # With both prefixes
    presentation do
      ui_adapter MishkaGervaz.UIAdapters.Dynamic
      ui_adapter_opts component_module: MyAppWeb.Components,
                      module_prefix: "Mishka",
                      component_prefix: "mc_"
    end
    # Calls: MyAppWeb.Components.MishkaButton.mc_button/1

This auto-generates an adapter module `YourResource.GervazUIAdapter` that:
- Delegates to your declared components if they exist
- Falls back to Tailwind for any missing components
- All resolved at compile time with zero runtime overhead

# `mishka_gervaz_table_refresh_enabled`

```elixir
@spec mishka_gervaz_table_refresh_enabled(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable auto-refresh for this resource. Overrides domain default.

# `mishka_gervaz_table_refresh_enabled!`

```elixir
@spec mishka_gervaz_table_refresh_enabled!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable auto-refresh for this resource. Overrides domain default.

# `mishka_gervaz_table_refresh_interval`

```elixir
@spec mishka_gervaz_table_refresh_interval(dsl_or_extended :: module() | map()) ::
  {:ok, pos_integer()} | :error
```

Refresh interval in milliseconds. Overrides domain default.

# `mishka_gervaz_table_refresh_interval!`

```elixir
@spec mishka_gervaz_table_refresh_interval!(dsl_or_extended :: module() | map()) ::
  pos_integer() | no_return()
```

Refresh interval in milliseconds. Overrides domain default.

# `mishka_gervaz_table_refresh_options`

```elixir
@spec mishka_gervaz_table_refresh_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.refresh DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_refresh_pause_on_blur`

```elixir
@spec mishka_gervaz_table_refresh_pause_on_blur(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Pause auto-refresh when browser tab loses focus. Overrides domain default.

# `mishka_gervaz_table_refresh_pause_on_blur!`

```elixir
@spec mishka_gervaz_table_refresh_pause_on_blur!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Pause auto-refresh when browser tab loses focus. Overrides domain default.

# `mishka_gervaz_table_refresh_pause_on_interaction`

```elixir
@spec mishka_gervaz_table_refresh_pause_on_interaction(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Pause auto-refresh when user is interacting. Overrides domain default.

# `mishka_gervaz_table_refresh_pause_on_interaction!`

```elixir
@spec mishka_gervaz_table_refresh_pause_on_interaction!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Pause auto-refresh when user is interacting. Overrides domain default.

# `mishka_gervaz_table_refresh_show_indicator`

```elixir
@spec mishka_gervaz_table_refresh_show_indicator(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Show visual indicator when auto-refresh is active. Overrides domain default.

# `mishka_gervaz_table_refresh_show_indicator!`

```elixir
@spec mishka_gervaz_table_refresh_show_indicator!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Show visual indicator when auto-refresh is active. Overrides domain default.

# `mishka_gervaz_table_row`

```elixir
@spec mishka_gervaz_table_row(dsl_or_extended :: module() | map()) :: [struct()]
```

mishka_gervaz.table.row DSL entities

# `mishka_gervaz_table_row_actions`

```elixir
@spec mishka_gervaz_table_row_actions(dsl_or_extended :: module() | map()) :: [
  struct()
]
```

mishka_gervaz.table.row_actions DSL entities

# `mishka_gervaz_table_row_actions_actions_layout_auto_collapse_after`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_auto_collapse_after(
  dsl_or_extended :: module() | map()
) :: {:ok, integer()} | :error
```

Auto-collapse after N actions.

# `mishka_gervaz_table_row_actions_actions_layout_auto_collapse_after!`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_auto_collapse_after!(
  dsl_or_extended :: module() | map()
) :: integer() | no_return()
```

Auto-collapse after N actions.

# `mishka_gervaz_table_row_actions_actions_layout_dropdown`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_dropdown(
  dsl_or_extended :: module() | map()
) ::
  {:ok, [atom()]} | :error
```

Actions in dropdown menu.

# `mishka_gervaz_table_row_actions_actions_layout_dropdown!`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_dropdown!(
  dsl_or_extended :: module() | map()
) ::
  [atom()] | no_return()
```

Actions in dropdown menu.

# `mishka_gervaz_table_row_actions_actions_layout_inline`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_inline(
  dsl_or_extended :: module() | map()
) ::
  {:ok, [atom()]} | :error
```

Actions shown as buttons.

# `mishka_gervaz_table_row_actions_actions_layout_inline!`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_inline!(
  dsl_or_extended :: module() | map()
) ::
  [atom()] | no_return()
```

Actions shown as buttons.

# `mishka_gervaz_table_row_actions_actions_layout_options`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_options(
  dsl_or_extended :: module() | map()
) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.row_actions.actions_layout DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_row_actions_actions_layout_position`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_position(
  dsl_or_extended :: module() | map()
) ::
  {:ok, :end | :start} | :error
```

Which side of row.

# `mishka_gervaz_table_row_actions_actions_layout_position!`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_position!(
  dsl_or_extended :: module() | map()
) ::
  (:end | :start) | no_return()
```

Which side of row.

# `mishka_gervaz_table_row_actions_actions_layout_sticky`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_sticky(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Stick on horizontal scroll.

# `mishka_gervaz_table_row_actions_actions_layout_sticky!`

```elixir
@spec mishka_gervaz_table_row_actions_actions_layout_sticky!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Stick on horizontal scroll.

# `mishka_gervaz_table_row_class_apply`

```elixir
@spec mishka_gervaz_table_row_class_apply(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

Function `fn record -> [class | nil]`.

# `mishka_gervaz_table_row_class_apply!`

```elixir
@spec mishka_gervaz_table_row_class_apply!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

Function `fn record -> [class | nil]`.

# `mishka_gervaz_table_row_class_options`

```elixir
@spec mishka_gervaz_table_row_class_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.row.class DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_row_class_possible`

```elixir
@spec mishka_gervaz_table_row_class_possible(dsl_or_extended :: module() | map()) ::
  {:ok, [String.t()]} | :error
```

Possible classes for Tailwind JIT extraction.

# `mishka_gervaz_table_row_class_possible!`

```elixir
@spec mishka_gervaz_table_row_class_possible!(dsl_or_extended :: module() | map()) ::
  [String.t()] | no_return()
```

Possible classes for Tailwind JIT extraction.

# `mishka_gervaz_table_row_event`

```elixir
@spec mishka_gervaz_table_row_event(dsl_or_extended :: module() | map()) ::
  {:ok, String.t()} | :error
```

Event name triggered on row click.

# `mishka_gervaz_table_row_event!`

```elixir
@spec mishka_gervaz_table_row_event!(dsl_or_extended :: module() | map()) ::
  String.t() | no_return()
```

Event name triggered on row click.

# `mishka_gervaz_table_row_options`

```elixir
@spec mishka_gervaz_table_row_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.row DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_row_payload`

```elixir
@spec mishka_gervaz_table_row_payload(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any()) | map()} | :error
```

Payload for row click. Map or `fn record -> map`.

# `mishka_gervaz_table_row_payload!`

```elixir
@spec mishka_gervaz_table_row_payload!(dsl_or_extended :: module() | map()) ::
  ((any() -&gt; any()) | map()) | no_return()
```

Payload for row click. Map or `fn record -> map`.

# `mishka_gervaz_table_row_selectable`

```elixir
@spec mishka_gervaz_table_row_selectable(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable row selection checkboxes.

# `mishka_gervaz_table_row_selectable!`

```elixir
@spec mishka_gervaz_table_row_selectable!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable row selection checkboxes.

# `mishka_gervaz_table_source_actions_destroy`

```elixir
@spec mishka_gervaz_table_source_actions_destroy(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Destroy action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_table_source_actions_destroy!`

```elixir
@spec mishka_gervaz_table_source_actions_destroy!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Destroy action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_table_source_actions_get`

```elixir
@spec mishka_gervaz_table_source_actions_get(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Get action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_table_source_actions_get!`

```elixir
@spec mishka_gervaz_table_source_actions_get!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Get action. Atom or tuple `{master_action, tenant_action}`. Required either here or on the domain.

# `mishka_gervaz_table_source_actions_options`

```elixir
@spec mishka_gervaz_table_source_actions_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.table.source.actions DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_source_actions_read`

```elixir
@spec mishka_gervaz_table_source_actions_read(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Read action. Atom (used for both master and tenant) or tuple `{master_action, tenant_action}`. Required either here or on the domain — compile fails otherwise.

# `mishka_gervaz_table_source_actions_read!`

```elixir
@spec mishka_gervaz_table_source_actions_read!(dsl_or_extended :: module() | map()) ::
  (atom() | {atom(), atom()}) | no_return()
```

Read action. Atom (used for both master and tenant) or tuple `{master_action, tenant_action}`. Required either here or on the domain — compile fails otherwise.

# `mishka_gervaz_table_source_actor_key`

```elixir
@spec mishka_gervaz_table_source_actor_key(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Assigns key for current user.

# `mishka_gervaz_table_source_actor_key!`

```elixir
@spec mishka_gervaz_table_source_actor_key!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Assigns key for current user.

# `mishka_gervaz_table_source_archive_destroy_action`

```elixir
@spec mishka_gervaz_table_source_archive_destroy_action(
  dsl_or_extended :: module() | map()
) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Permanent destroy action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_destroy_action!`

```elixir
@spec mishka_gervaz_table_source_archive_destroy_action!(
  dsl_or_extended :: module() | map()
) ::
  (atom() | {atom(), atom()}) | no_return()
```

Permanent destroy action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_enabled`

```elixir
@spec mishka_gervaz_table_source_archive_enabled(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable archive support. Set `false` to disable without removing the block.

# `mishka_gervaz_table_source_archive_enabled!`

```elixir
@spec mishka_gervaz_table_source_archive_enabled!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable archive support. Set `false` to disable without removing the block.

# `mishka_gervaz_table_source_archive_get_action`

```elixir
@spec mishka_gervaz_table_source_archive_get_action(
  dsl_or_extended :: module() | map()
) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Get archived action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_get_action!`

```elixir
@spec mishka_gervaz_table_source_archive_get_action!(
  dsl_or_extended :: module() | map()
) ::
  (atom() | {atom(), atom()}) | no_return()
```

Get archived action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_options`

```elixir
@spec mishka_gervaz_table_source_archive_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.table.source.archive DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_source_archive_read_action`

```elixir
@spec mishka_gervaz_table_source_archive_read_action(
  dsl_or_extended :: module() | map()
) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Read archived action. Can be single atom or tuple `{master_action, tenant_action}`.

# `mishka_gervaz_table_source_archive_read_action!`

```elixir
@spec mishka_gervaz_table_source_archive_read_action!(
  dsl_or_extended :: module() | map()
) ::
  (atom() | {atom(), atom()}) | no_return()
```

Read archived action. Can be single atom or tuple `{master_action, tenant_action}`.

# `mishka_gervaz_table_source_archive_restore_action`

```elixir
@spec mishka_gervaz_table_source_archive_restore_action(
  dsl_or_extended :: module() | map()
) ::
  {:ok, atom() | {atom(), atom()}} | :error
```

Restore action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_restore_action!`

```elixir
@spec mishka_gervaz_table_source_archive_restore_action!(
  dsl_or_extended :: module() | map()
) ::
  (atom() | {atom(), atom()}) | no_return()
```

Restore action. Can be single atom or tuple.

# `mishka_gervaz_table_source_archive_restricted`

```elixir
@spec mishka_gervaz_table_source_archive_restricted(
  dsl_or_extended :: module() | map()
) ::
  {:ok, boolean()} | :error
```

Restrict archive UI to master users only. When `true`, tenant users cannot see archive toggle.

# `mishka_gervaz_table_source_archive_restricted!`

```elixir
@spec mishka_gervaz_table_source_archive_restricted!(
  dsl_or_extended :: module() | map()
) ::
  boolean() | no_return()
```

Restrict archive UI to master users only. When `true`, tenant users cannot see archive toggle.

# `mishka_gervaz_table_source_archive_visible`

```elixir
@spec mishka_gervaz_table_source_archive_visible(dsl_or_extended :: module() | map()) ::
  {:ok, boolean() | tuple()} | :error
```

Control archive toggle visibility. Boolean or `fn state -> boolean` for dynamic control.

# `mishka_gervaz_table_source_archive_visible!`

```elixir
@spec mishka_gervaz_table_source_archive_visible!(dsl_or_extended :: module() | map()) ::
  (boolean() | tuple()) | no_return()
```

Control archive toggle visibility. Boolean or `fn state -> boolean` for dynamic control.

# `mishka_gervaz_table_source_master_check`

```elixir
@spec mishka_gervaz_table_source_master_check(dsl_or_extended :: module() | map()) ::
  {:ok, (any() -&gt; any())} | :error
```

Function returning true for master users. `fn user -> boolean`

# `mishka_gervaz_table_source_master_check!`

```elixir
@spec mishka_gervaz_table_source_master_check!(dsl_or_extended :: module() | map()) ::
  (any() -&gt; any()) | no_return()
```

Function returning true for master users. `fn user -> boolean`

# `mishka_gervaz_table_source_options`

```elixir
@spec mishka_gervaz_table_source_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.source DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_source_preload_always`

```elixir
@spec mishka_gervaz_table_source_preload_always(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Always preload these relationships.

Supports atoms or `{source, alias}` tuples:
- `:site` - preload `:site` relationship
- `{:site, :site_info}` or `site: :site_info` - preload `:site`, alias as `:site_info`

# `mishka_gervaz_table_source_preload_always!`

```elixir
@spec mishka_gervaz_table_source_preload_always!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Always preload these relationships.

Supports atoms or `{source, alias}` tuples:
- `:site` - preload `:site` relationship
- `{:site, :site_info}` or `site: :site_info` - preload `:site`, alias as `:site_info`

# `mishka_gervaz_table_source_preload_master`

```elixir
@spec mishka_gervaz_table_source_preload_master(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Additional preloads for master users.

Supports atoms or `{source, alias}` tuples:
- `:layout` - preload `:layout` relationship
- `{:layout, :page_layout}` or `layout: :page_layout` - preload `:layout`, alias as `:page_layout`

# `mishka_gervaz_table_source_preload_master!`

```elixir
@spec mishka_gervaz_table_source_preload_master!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Additional preloads for master users.

Supports atoms or `{source, alias}` tuples:
- `:layout` - preload `:layout` relationship
- `{:layout, :page_layout}` or `layout: :page_layout` - preload `:layout`, alias as `:page_layout`

# `mishka_gervaz_table_source_preload_options`

```elixir
@spec mishka_gervaz_table_source_preload_options(dsl_or_extended :: module() | map()) ::
  %{
    required(atom()) =&gt; any()
  }
```

mishka_gervaz.table.source.preload DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_source_preload_tenant`

```elixir
@spec mishka_gervaz_table_source_preload_tenant(dsl_or_extended :: module() | map()) ::
  {:ok, [atom() | {atom(), atom()}]} | :error
```

Additional preloads for tenant users.

Supports atoms or `{source, alias}` tuples:
- `:tenant_layout` - preload `:tenant_layout` relationship
- `{:tenant_layout, :layout}` or `tenant_layout: :layout` - preload `:tenant_layout`, alias as `:layout`

This allows master/tenant to expose different relationships under the same alias key.

# `mishka_gervaz_table_source_preload_tenant!`

```elixir
@spec mishka_gervaz_table_source_preload_tenant!(dsl_or_extended :: module() | map()) ::
  [atom() | {atom(), atom()}] | no_return()
```

Additional preloads for tenant users.

Supports atoms or `{source, alias}` tuples:
- `:tenant_layout` - preload `:tenant_layout` relationship
- `{:tenant_layout, :layout}` or `tenant_layout: :layout` - preload `:tenant_layout`, alias as `:layout`

This allows master/tenant to expose different relationships under the same alias key.

# `mishka_gervaz_table_state_access`

```elixir
@spec mishka_gervaz_table_state_access(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Access module. Must `use MishkaGervaz.Table.Web.State.Access`.
Handles access control for records and actions.

# `mishka_gervaz_table_state_access!`

```elixir
@spec mishka_gervaz_table_state_access!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Access module. Must `use MishkaGervaz.Table.Web.State.Access`.
Handles access control for records and actions.

# `mishka_gervaz_table_state_action`

```elixir
@spec mishka_gervaz_table_state_action(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Action builder module. Must `use MishkaGervaz.Table.Web.State.ActionBuilder`.
Builds row actions and bulk actions from configuration.

# `mishka_gervaz_table_state_action!`

```elixir
@spec mishka_gervaz_table_state_action!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Action builder module. Must `use MishkaGervaz.Table.Web.State.ActionBuilder`.
Builds row actions and bulk actions from configuration.

# `mishka_gervaz_table_state_column`

```elixir
@spec mishka_gervaz_table_state_column(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Column builder module. Must `use MishkaGervaz.Table.Web.State.ColumnBuilder`.
Builds columns from DSL and resource configuration.

# `mishka_gervaz_table_state_column!`

```elixir
@spec mishka_gervaz_table_state_column!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Column builder module. Must `use MishkaGervaz.Table.Web.State.ColumnBuilder`.
Builds columns from DSL and resource configuration.

# `mishka_gervaz_table_state_filter`

```elixir
@spec mishka_gervaz_table_state_filter(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Filter builder module. Must `use MishkaGervaz.Table.Web.State.FilterBuilder`.
Builds filters from DSL and resource configuration.

# `mishka_gervaz_table_state_filter!`

```elixir
@spec mishka_gervaz_table_state_filter!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Filter builder module. Must `use MishkaGervaz.Table.Web.State.FilterBuilder`.
Builds filters from DSL and resource configuration.

# `mishka_gervaz_table_state_module`

```elixir
@spec mishka_gervaz_table_state_module(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Override the entire state module. When set, all other options are ignored.
The module must `use MishkaGervaz.Table.Web.State`.

# `mishka_gervaz_table_state_module!`

```elixir
@spec mishka_gervaz_table_state_module!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Override the entire state module. When set, all other options are ignored.
The module must `use MishkaGervaz.Table.Web.State`.

# `mishka_gervaz_table_state_options`

```elixir
@spec mishka_gervaz_table_state_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.state DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_state_presentation`

```elixir
@spec mishka_gervaz_table_state_presentation(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

Presentation module. Must `use MishkaGervaz.Table.Web.State.Presentation`.
Resolves UI adapter, templates, and presentation options.

# `mishka_gervaz_table_state_presentation!`

```elixir
@spec mishka_gervaz_table_state_presentation!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

Presentation module. Must `use MishkaGervaz.Table.Web.State.Presentation`.
Resolves UI adapter, templates, and presentation options.

# `mishka_gervaz_table_state_url_sync`

```elixir
@spec mishka_gervaz_table_state_url_sync(dsl_or_extended :: module() | map()) ::
  {:ok, atom()} | :error
```

URL sync module. Must `use MishkaGervaz.Table.Web.State.UrlSync`.
Handles URL state synchronization.

# `mishka_gervaz_table_state_url_sync!`

```elixir
@spec mishka_gervaz_table_state_url_sync!(dsl_or_extended :: module() | map()) ::
  atom() | no_return()
```

URL sync module. Must `use MishkaGervaz.Table.Web.State.UrlSync`.
Handles URL state synchronization.

# `mishka_gervaz_table_url_sync_enabled`

```elixir
@spec mishka_gervaz_table_url_sync_enabled(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Enable URL state synchronization. Overrides domain default.

# `mishka_gervaz_table_url_sync_enabled!`

```elixir
@spec mishka_gervaz_table_url_sync_enabled!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Enable URL state synchronization. Overrides domain default.

# `mishka_gervaz_table_url_sync_max_filter_length`

```elixir
@spec mishka_gervaz_table_url_sync_max_filter_length(
  dsl_or_extended :: module() | map()
) ::
  {:ok, pos_integer()} | :error
```

Maximum length for filter values. Values exceeding this are ignored. Default: 500.

# `mishka_gervaz_table_url_sync_max_filter_length!`

```elixir
@spec mishka_gervaz_table_url_sync_max_filter_length!(
  dsl_or_extended :: module() | map()
) ::
  pos_integer() | no_return()
```

Maximum length for filter values. Values exceeding this are ignored. Default: 500.

# `mishka_gervaz_table_url_sync_mode`

```elixir
@spec mishka_gervaz_table_url_sync_mode(dsl_or_extended :: module() | map()) ::
  {:ok, :bidirectional | :read_only} | :error
```

URL sync mode:
- `:read_only` - Only read from URL on initial load (default)
- `:bidirectional` - Sync URL when filters/sort/page change

# `mishka_gervaz_table_url_sync_mode!`

```elixir
@spec mishka_gervaz_table_url_sync_mode!(dsl_or_extended :: module() | map()) ::
  (:bidirectional | :read_only) | no_return()
```

URL sync mode:
- `:read_only` - Only read from URL on initial load (default)
- `:bidirectional` - Sync URL when filters/sort/page change

# `mishka_gervaz_table_url_sync_options`

```elixir
@spec mishka_gervaz_table_url_sync_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

mishka_gervaz.table.url_sync DSL options

Returns a map containing the and any configured or default values.

# `mishka_gervaz_table_url_sync_params`

```elixir
@spec mishka_gervaz_table_url_sync_params(dsl_or_extended :: module() | map()) ::
  {:ok, [:template | :search | :page_size | :page | :sort | :filters]} | :error
```

Which state to sync to URL params. Overrides domain default.

# `mishka_gervaz_table_url_sync_params!`

```elixir
@spec mishka_gervaz_table_url_sync_params!(dsl_or_extended :: module() | map()) ::
  [:template | :search | :page_size | :page | :sort | :filters] | no_return()
```

Which state to sync to URL params. Overrides domain default.

# `mishka_gervaz_table_url_sync_prefix`

```elixir
@spec mishka_gervaz_table_url_sync_prefix(dsl_or_extended :: module() | map()) ::
  {:ok, String.t()} | :error
```

Prefix for URL params. Overrides domain default.

# `mishka_gervaz_table_url_sync_prefix!`

```elixir
@spec mishka_gervaz_table_url_sync_prefix!(dsl_or_extended :: module() | map()) ::
  String.t() | no_return()
```

Prefix for URL params. Overrides domain default.

# `mishka_gervaz_table_url_sync_preserve_params`

```elixir
@spec mishka_gervaz_table_url_sync_preserve_params(
  dsl_or_extended :: module() | map()
) ::
  {:ok, :all | [atom()]} | :error
```

Params to preserve in URL across re-encoding. :all keeps all unknown params, or provide a list of specific param names. Preserved params are NOT stored in table state. max_filter_length applies to values.

# `mishka_gervaz_table_url_sync_preserve_params!`

```elixir
@spec mishka_gervaz_table_url_sync_preserve_params!(
  dsl_or_extended :: module() | map()
) ::
  (:all | [atom()]) | no_return()
```

Params to preserve in URL across re-encoding. :all keeps all unknown params, or provide a list of specific param names. Preserved params are NOT stored in table state. max_filter_length applies to values.

# `notice`

```elixir
@spec notice(module(), atom()) :: map() | nil
```

Get a specific notice by name.

# `notices`

```elixir
@spec notices(module()) :: [map()]
```

Get all notices declared in the table layout.

# `notices_at`

```elixir
@spec notices_at(module(), term()) :: [map()]
```

Get notices targeting the given position. Position can be an atom or a
`{:before_column, name}` / `{:after_column, name}` tuple.

# `page_size`

```elixir
@spec page_size(module()) :: pos_integer() | nil
```

Get the page size for a resource.

# `page_size_options`

```elixir
@spec page_size_options(module()) :: [pos_integer()] | nil
```

Get the page size options for a resource.
Returns nil when no options are configured (no dropdown shown).

# `pagination`

```elixir
@spec pagination(module()) :: map() | nil
```

Get the full pagination configuration for a resource.
Returns nil when pagination is disabled or not configured.

# `pagination_enabled?`

```elixir
@spec pagination_enabled?(module()) :: boolean()
```

Check if pagination is enabled for a resource.

# `pagination_type`

```elixir
@spec pagination_type(module()) :: :numbered | :infinite | :load_more | nil
```

Get the pagination type for a resource.

# `pagination_ui`

```elixir
@spec pagination_ui(module()) :: struct()
```

Get the pagination UI configuration for a resource.

# `preload_aliases`

```elixir
@spec preload_aliases(module(), boolean()) :: %{required(atom()) =&gt; atom()}
```

Get preload aliases for master/tenant context.

Returns a map of `%{alias_key => source_key}` for resolving aliased preloads.
Only includes entries where source != alias (actual aliases).

## Example

    # Given: master [layout: :layout], tenant [tenant_layout: :layout]
    preload_aliases(MyResource, true)   # => %{}  (no aliasing for master)
    preload_aliases(MyResource, false)  # => %{layout: :tenant_layout}

# `refresh`

```elixir
@spec refresh(module()) :: map() | nil
```

Get the refresh configuration.

# `route`

```elixir
@spec route(module()) :: String.t() | nil
```

Get the route for a resource.

# `row_action`

```elixir
@spec row_action(module(), atom()) :: struct() | nil
```

Get a specific row action by name.

# `row_actions`

```elixir
@spec row_actions(module()) :: [struct()]
```

Get all row actions for a resource.

# `state`

```elixir
@spec state(module()) :: map()
```

Get the state configuration.

Returns a map with any configured state module overrides.
Keys can include: `:module`, `:column`, `:filter`, `:action`, `:presentation`, `:url_sync`, `:access`

# `stream_name`

```elixir
@spec stream_name(module()) :: atom() | nil
```

Get the stream name for a resource.

# `url_sync`

```elixir
@spec url_sync(module()) :: map() | nil
```

Get the URL sync configuration.

---

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