README.md

# SelectoComponents

> Alpha software. Expect API and behavior changes while the core LiveView package continues to settle.

`selecto_components` provides Phoenix LiveView components for building interactive query UIs on top of `selecto`.

It is the package you use when you want users to:

- build filters visually
- choose fields for detail and aggregate views
- switch between built-in result views
- save/export/share views
- email or schedule exports through host-app integrations

## What It Includes

- `SelectoComponents.Form` for query-building and view configuration
- `SelectoComponents.Results` for result rendering
- built-in views:
  - `Detail`
  - `Aggregate`
  - `Graph`
- extension-driven view support such as map views via `selecto_postgis`
- exported-view, email-export, and scheduled-export integration points

## Requirements

- Phoenix 1.7+
- Elixir ~> 1.18
- `selecto >= 0.4.3 and < 0.5.0`
- an adapter package such as `selecto_db_postgresql >= 0.4.2 and < 0.5.0`
- `selecto_mix >= 0.4.2 and < 0.5.0` if you want generators and installation helpers

## Installation

```elixir
def deps do
  [
    {:selecto_components, ">= 0.4.5 and < 0.5.0"},
    {:selecto, ">= 0.4.3 and < 0.5.0"},
    {:selecto_db_postgresql, ">= 0.4.2 and < 0.5.0"},
    {:selecto_mix, ">= 0.4.2 and < 0.5.0"}
  ]
end
```

Then run the recommended integration task:

```bash
mix deps.get
mix selecto.components.integrate
mix assets.build
```

That wires:

- colocated SelectoComponents hooks into your LiveSocket config
- Tailwind `@source` coverage for component templates

## Minimal Usage

```elixir
defmodule MyAppWeb.ProductLive do
  use MyAppWeb, :live_view
  use SelectoComponents.Form

  alias MyApp.SelectoDomains.ProductDomain
  alias MyApp.Repo

  def mount(_params, _session, socket) do
    selecto = ProductDomain.new(Repo)

    views = [
      {:detail, SelectoComponents.Views.Detail, "Detail", %{}},
      {:aggregate, SelectoComponents.Views.Aggregate, "Aggregate", %{}},
      {:graph, SelectoComponents.Views.Graph, "Graph", %{}}
    ]

    {:ok, assign(socket, get_initial_state(views, selecto))}
  end

  def render(assigns) do
    ~H"""
    <.live_component module={SelectoComponents.Form} id="product-form" {assigns} />
    <.live_component module={SelectoComponents.Results} id="product-results" {assigns} />
    """
  end
end
```

## Common Add-Ons

You can keep the basic `Form` + `Results` pairing and progressively add host-app integrations.

### Saved Views

Use a host module that persists saved views and assign it to the LiveView.

Typical generation path:

```bash
mix selecto.gen.saved_views MyApp.SavedView MyApp.SavedViewContext
```

### Exported Views

Use `SelectoComponents.ExportedViews` when you want signed iframe/embed snapshots of current views.

### Email And Scheduled Exports

Assign these modules when you want the Export tab to send or manage exports:

```elixir
assign(socket,
  export_delivery_module: MyApp.ExportDelivery,
  scheduled_export_module: MyApp.ScheduledExports,
  scheduled_export_context: scoped_context
)
```

The host app owns actual delivery and scheduling. `selecto_components` stays scheduler-neutral.

Recommended execution model: use Oban (or another worker system) to run due scheduled exports via `SelectoComponents.ScheduledExports.Service.run_scheduled_export/3`.

### Extension Views

Map views and other extension-provided view systems are merged from domain extensions rather than hard-coded into the package.

## Custom View Systems

`selecto_components` supports external view packages through `SelectoComponents.Views.System`.

That is the contract used when you want to publish a package like:

- `selecto_components_view_<slug>`

and register it into a host LiveView with `SelectoComponents.Views.spec/4`.

## Status

Current `0.4.x` scope:

- core query UI flows are usable but still alpha
- exported views, one-off email export, and scheduled export management are available
- custom and extension view support exists, but host apps still own persistence and delivery concerns
- advanced graph/dashboard integrations still need real-world hardening

## Demos And Tutorials

- `selecto_livebooks`
- `selecto_northwind`
- hosted demo: `testselecto.fly.dev`
- runnable example app: `selecto_example`