# Calendar

> A month of days to pick one day or a range from. Plain YYYY-MM-DD strings in and out, never a Date, so no time zone can move the day. Today is today in the account's zone. Weekdays, months and every label come from Intl in its locale, and the week starts where the locale starts it. Built on react-day-picker with every piece replaced.

Section: Forms. Docs: https://entrepta.vercel.app/docs/components/calendar

## Install

```bash
npx @entrepta/cli@latest add calendar
```

Files: `primitives/calendar.tsx`, `lib/format.ts`, `hooks/use-format.ts`.
npm packages: `react-day-picker`, `@phosphor-icons/react`.
Comes with: `format-lib`, `use-format`.

## Usage

```tsx
import { Calendar } from "@/components/entrepta/calendar"

<Calendar value={day} onValueChange={setDay} min="2025-01-01" max={today} />

<Calendar
  mode="range"
  value={range}                 // { start, end? }
  onValueChange={setRange}
  renderDay={(day) => hasData(day) ? <Dot /> : null}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | `"single" \| "range"` | "single" | A range is { start, end? }: end is missing until the second click |
| `min / max` | `string` | - | The first and last days that can be picked |
| `isDisabled` | `(day: string) => boolean` | - | Days that cannot be picked, such as days with no data |
| `renderDay` | `(day: string) => ReactNode` | - | Something small under a day's number, such as a coverage dot |
| `locale / timeZone` | `string` | - | Fall back to the FormatProvider's. timeZone decides which day is today |
| `labels` | `{ previous?, next?, today?, selected? }` | - | The words screen readers hear, for another language |
