# `Cardbox.Koyomi`
[🔗](https://github.com/hattoriai/cardbox/blob/v0.1.0/lib/cardbox/koyomi.ex#L2)

A collection as a Koyomi calendar: each record on the day of the view's
date field, a mark for each, and the records of the day a person picks.

    <Cardbox.Koyomi.calendar id="due" view={@view} on_change="day" months={2} />

    def handle_event("koyomi:days", %{"id" => "due"} = params, socket),
      do: Cardbox.Koyomi.handle_days(socket, params, MyApp.Cardbox, socket.assigns.collection, socket.assigns.view)

    def handle_event("day", %{"value" => day}, socket) do
      {:ok, records} = Cardbox.Koyomi.on_day(MyApp.Cardbox, socket.assigns.collection, socket.assigns.view, day)
      {:noreply, assign(socket, day_records: records)}
    end

The view is a saved `Cardbox.View` of type `calendar`: its `date_field`
names the date field (a day, or a moment), and its query which records.
The calendar asks for the days it shows a month or a few at a time, and
the database reads only the records of those days.

A day's marks are a dot for each record (four at most), toned by the
group of the record's status when the collection has one: to do muted,
doing in the accent, done in green. Its title, read by screen readers
and shown on hover, has the records' titles.

When records change (`Cardbox.Event`), `Koyomi.Live.refresh_days/2`
asks the calendar for its days again (Koyomi 0.2.1 and later, which
Cardbox requires: before it, a refresh emptied the calendar).

# `calendar`

A calendar of a view's records, on the days of its date field.
## Attributes

* `id` (`:string`) (required)
* `view` (`Cardbox.View`) (required) - a view of type `calendar`.
* `on_change` (`:string`) - the event of a day picked: `%{"value" => "2026-10-25"}`. Defaults to `nil`.
* `months` (`:integer`) - Defaults to `1`.
* `label` (`:string`) - Defaults to `nil`.
* Global attributes are accepted. Supports all globals plus: `["value", "locale", "first_day", "week_numbers", "holidays", "class"]`.

# `days`

```elixir
@spec days(
  module(),
  Cardbox.Collection.t(),
  Cardbox.View.t(),
  Date.Range.t(),
  keyword()
) :: %{
  required(Date.t()) =&gt; keyword()
}
```

The content of the days of a range: for each day with records, their
marks and their titles, as `Koyomi.Live.handle_days/4` takes them.

# `handle_days`

```elixir
@spec handle_days(
  Phoenix.LiveView.Socket.t(),
  map(),
  module(),
  Cardbox.Collection.t(),
  Cardbox.View.t(),
  keyword()
) :: {:reply, map(), Phoenix.LiveView.Socket.t()}
```

Answers the calendar's `koyomi:days` event with the days of the view's
records (`Koyomi.Live.handle_days/4`). `opts` are those of a query
(`:me`, `:time_zone`, `:now`).

# `on_day`

```elixir
@spec on_day(
  module(),
  Cardbox.Collection.t(),
  Cardbox.View.t(),
  Date.t() | String.t(),
  keyword()
) ::
  {:ok, [Cardbox.Record.t()]} | {:error, Cardbox.Error.t()}
```

The records of a view on a day (a `Date` or `"YYYY-MM-DD"`), in the view's order.

---

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