Defines a filterable field — its type, allowed operators, label, and options.
The struct intentionally aggregates per-field knobs across every filter type (text, select, async, datetime, etc.). Splitting into smaller structs would force callers to know the type before constructing.
Summary
Types
@type icon_fn() :: (map() -> Phoenix.LiveView.Rendered.t()) | nil
@type t() :: %LiveFilter.FilterConfig{ always_on: boolean(), any_label: String.t(), custom_param: String.t() | nil, date_presets: [atom()] | nil, debounce: non_neg_integer(), default_operator: LiveFilter.Types.operator(), default_value: LiveFilter.Types.filter_value(), default_visible: term(), empty_message: String.t(), false_label: String.t(), field: atom(), hide_label: boolean(), icon: icon_fn(), inline_threshold: non_neg_integer(), input_component: module() | nil, label: String.t(), load_label_fn: (String.t(), map() -> {:ok, String.t()} | :error) | nil, min_chars: non_neg_integer(), minute_step: pos_integer(), mode: :basic | :command | nil, nullable: boolean(), operators: [LiveFilter.Types.operator()], options: [String.t() | {String.t(), String.t()}] | nil, options_fn: (-> [String.t() | {String.t(), String.t()}]) | nil, placeholder: String.t() | nil, query_field: atom() | nil, removable: boolean(), search_fn: (String.t(), map() -> [{String.t(), String.t()}]) | nil, search_threshold: non_neg_integer() | nil, style: :pills | :radios, theme: atom() | nil, time_format: :twelve_hour | :twenty_four_hour, true_label: String.t(), type: LiveFilter.Types.filter_type() }