# `Ascii.Pieces.Calendar`
[🔗](https://github.com/houllette/ascii_art/blob/main/lib/ascii/pieces/calendar.ex#L1)

This month like cal, today bracketed, time ticking below.

This month laid out like the cal command, today in brackets, with the
weekday and the running time along the bottom: upstream's calendar,
which it is by default. Give it a `date` and it shows that month and day
instead, and is a date picker that keys and clicks move.

Reads the clock from `env.now` (see `Ascii.Kit.Clock`), for today and
the running time.

## Options

Give them to `Ascii.new/2` as `options:`, and new ones while it plays
with `Ascii.put_options/2` (or a Phoenix player's `options`): the page
is drawn anew from them.

  * `date` - a day to show, as `"2026-10-12"`: its month, the day
    bracketed as the one selected, and along the bottom its weekday (and
    the time, if `time`). `"2026-10"` shows a month with nothing
    selected. Default `""`, as is any string that is not a date: this
    month, today bracketed, as upstream.
  * `marks` - days to mark, as `["2026-10-03", "2026-10-19"]`: those in
    the month shown wear a `·` after their number (a bracketed one, only
    where its cell has room). Default `[]`.
  * `monday` - weeks start on Monday rather than Sunday. Default `false`.
  * `time` - the running time at the right of the bottom line, from the
    clock, with a `date` too. Default `true`; `false` for a plain date
    picker.
  * `months`, `weekdays` - the names to use, twelve from January and
    seven from Sunday; the heading shows each weekday's first two
    letters. English by default; a list of another length is ignored.
  * `cols`, `rows` - the frame's size, 32 to 200 by 13 to 60; 32 by 13
    by default. The days' cells widen to fill the width, and the page
    sits in the middle.

## Colours

In one ink, or a gradient, with `:ink` and `:gradient` (see
`Ascii.Ink`); part by part with `:parts` (see `Ascii.Parts`),
`parts: true` taking the colours suggested here:

  * `title` - the month and year.
  * `rule` - the rules above and below the weeks, grey.
  * `weekday` - the heading's days, grey; `weekday.weekend`, Saturday's
    and Sunday's, cyan.
  * `day` - a date; `day.weekend`, one on a weekend, cyan; and
    `day.marked`, one in `marks`, yellow.
  * `today` - today, bracketed, blue; or `selected`, the `date` given,
    blue.
  * `date`, `time` - the weekday and day, and the time, along the bottom.

## Keys and clicks

With a `date`, it is a date picker: `Ascii.handle_event/2` takes keys
and clicks, and the day chosen is the new `date`, from which the app
reads it:

  * ← and → move the selection a day, ↑ and ↓ a week.
  * Page up and page down move it a month (to that month's last day, if
    it is shorter).
  * Home and end go to the month's first and last day.
  * A click on a day selects it.
  * From a month with nothing selected (`"2026-10"`), a key selects its
    first day (end, its last), and page up and page down change the
    month.

Years stay within 1 to 9999. Without a `date`, the clock says which
month it is, so there is none to move in: it takes none, and keys and
clicks are ignored. In Phoenix, give the player `interactive` (and
`notify` to be told of each key and click); in ExRatatui,
`Ascii.ExRatatui.handle_event/3`; in a terminal,
`mix ascii.play calendar --option date=2026-10-08 --option time=false --interactive`.

## Screen readers

`Ascii.describe/1` tells the month shown, the day selected and the
days marked in it, as "calendar: october 2026, 8 selected, marked 24",
the month in the names given. Showing this month from the clock, it
gives the piece's name and note.

## Example

```elixir
options = %{date: "2026-10-08", time: false, marks: ["2026-10-24"]}
picker = Ascii.new!("calendar", options: options, parts: true)
Ascii.describe(picker)
#=> "calendar: october 2026, 8 selected, marked 24"

{:ok, picker} = Ascii.handle_event(picker, {:key, "right"})
{:ok, picker} = Ascii.handle_event(picker, {:key, "page_down"})
picker.options.date
#=> "2026-11-09"

# Upstream's: this month, at a given moment.
now = DateTime.new!(~D[2026-03-14], ~T[15:09:26], "Etc/UTC")
{frame, _} = Ascii.new!("calendar") |> Ascii.frame(0.0, now: now)
frame.text =~ "[14]"
#=> true
```

```heex
<Ascii.Phoenix.live_player id="day" piece="calendar" options={%{date: @today, time: false, marks: @deadlines}} parts interactive notify />
```

Ported from `src/pieces/calendar.ts` in bas3line/ascii (MIT).

---

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