# date-picker

Calendar date selection with single/range modes, min/max constraints, locale support, and floating panel.

## Markup

```html
<div data-c42-datepicker>
  <button data-c42-datepicker-trigger>
    <span data-c42-datepicker-value></span>
  </button>
  <div data-c42-datepicker-panel>
    <div>
      <button data-c42-datepicker-prev aria-label="Previous month">‹</button>
      <span data-c42-datepicker-label></span>
      <button data-c42-datepicker-next aria-label="Next month">›</button>
    </div>
    <div data-c42-datepicker-grid></div>
  </div>
</div>
```

The controller renders the calendar grid into `[data-c42-datepicker-grid]` automatically.

## Options

```ts
import { DatePicker } from '@42/core/date-picker';

new DatePicker(root, {
  mode: 'single',              // 'single' | 'range'
  defaultValue: null,          // ISO 'YYYY-MM-DD' or Date
  defaultRange: null,          // { start, end } for range mode
  min: undefined,              // earliest selectable date
  max: undefined,              // latest selectable date
  weekStartsOn: 0,            // 0=Sun, 1=Mon, ..., 6=Sat
  locale: 'en-US',            // BCP-47 locale for month/day names
  formatLabel: undefined,      // (date: Date) => string
  placeholder: 'Select a date',
  closeOnSelect: true,
  placement: 'bottom-start',   // floating-ui Placement
  offset: 4,
});
```

## Events

| Event | Detail |
|-------|--------|
| `datepicker:change` | `{ value: string \| null, date: Date \| null, range: { start, end } \| null }` |
| `datepicker:open` | — |
| `datepicker:close` | — |

## Range mode

Set `mode: 'range'`. The user clicks a start date, then an end date. The change event fires with `range: { start: 'YYYY-MM-DD', end: 'YYYY-MM-DD' }`.

## Accessibility

- Grid cells have `aria-label` with the full date.
- Arrow keys navigate days, PageUp/PageDown navigate months.
- Escape closes the panel.
- `aria-selected` marks the current selection.
