Flicker.Providers.Static (Flicker v0.1.0)

Copy Markdown View Source

A small in-memory Flicker.Provider backed by a fixed list of results.

This is Flicker's reference pure-Elixir provider: it proves the Flicker.Provider contract stands alone with no Ash dependency, and it doubles as the test double for component tests (Spec 001 onward). It is also the worked example for third parties writing their own provider from the docs alone.

Configure it with {Flicker.Providers.Static, results: [...]}:

results = [
  %Flicker.Result{value: 1, label: "Casey Cassidy", sublabel: "Bass"},
  %Flicker.Result{value: 2, label: "Alex Rivers", sublabel: "Drums"}
]

Flicker.Provider.run_search(
  {Flicker.Providers.Static, results: results},
  %Flicker.Query{text: "cas"}
)
#=> {:ok, [%Flicker.Result{value: 1, label: "Casey Cassidy", sublabel: "Bass"}]}

search/2 matches query.text case-insensitively against :label and :sublabel; a blank query returns the full (optionally :limit-ed) list, mirroring how a real provider shows a default listing when the picker opens with nothing typed yet. fetch/2 resolves all matching :values in one pass, silently omitting any that aren't present in :results — the same "partial results are normal" behaviour ADR-003 requires of every provider.

search/2 matches text only and ignores query.facets entirely — a fixed in-memory list has no type system for Flicker.Providers.AshResource-style facet derivation to introspect, so faceted filtering isn't something this provider can meaningfully support. A facets:-configured Flicker.select/1 backed by Static still gets facet-key/value autocomplete over a hand-built Flicker.Facet registry (Spec 003), it just won't narrow :results by them — write a custom provider (or use AshResource) if that's needed.

Summary

Functions

Resolves values against opts[:results] in one pass, returning only the ones present — unresolvable values are simply absent, not an error (ADR-003).

Returns results whose :label or :sublabel contains query.text (case-insensitively), windowed by opts[:offset] (default 0) and opts[:limit] (default: no limit) via Enum.slice/3 (Spec 010).

Functions

fetch(values, opts)

@spec fetch([term()], keyword()) :: {:ok, [Flicker.Result.t()]} | {:error, term()}

Resolves values against opts[:results] in one pass, returning only the ones present — unresolvable values are simply absent, not an error (ADR-003).

Matches by to_string/1, not strict term equality: form-field mode's field.value always arrives as a string (from params, or a LiveSocket reconnect), while a result's :value is commonly an integer or atom — the same string-normalised comparison Flicker.Components.Select itself uses everywhere (reorder_like/2, matches_values?/2, filter_selected/2).

search(query, opts)

@spec search(Flicker.Query.t(), keyword()) ::
  {:ok, [Flicker.Result.t()]} | {:error, term()}

Returns results whose :label or :sublabel contains query.text (case-insensitively), windowed by opts[:offset] (default 0) and opts[:limit] (default: no limit) via Enum.slice/3 (Spec 010).

A blank query.text matches everything, so callers get a listing rather than an empty set when the picker opens with no input yet. Omitting :offset (the default 0) is byte-identical to the pre-windowing behaviour.