---
## DateRangePicker
Date range picker with a calendar popup for selecting a start and end date — min/max constraints, disabled dates, and native form submission via paired hidden inputs.
**Import:** `import { DateRangePicker } from '@urbicon-ui/blocks';`
### Examples
```svelte
booked.has(toIso(d))}
/>
```
### Api
| Prop | Type | Required | Default | Description |
| --- | --- | :---: | --- | --- |
| ...HTMLAttributes | `HTMLAttributes` | no | | HTML attributes (excluding: 'children') |
| calendarVariant | `'default' | 'bordered' | 'ghost'` | no | 'default' | Visual style of the calendar popup. |
| class | `string` | no | | Extra classes merged onto the positioning wrapper, the `base` slot. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. |
| clearable | `boolean` | no | true | Allow clearing the selected range: a clear button appears in the field while it holds a range. |
| closeOnClickOutside | `boolean` | no | true | Whether the popover closes on outside click. |
| closeOnEscape | `boolean` | no | true | Whether the popover closes on Escape key. |
| closeOnSelect | `boolean` | no | true | Close popover after selecting both dates. |
| defaultMonth | `MonthIndex` | no | | Default month shown when the picker opens without a value. `0`–`11`. |
| defaultYear | `number` | no | | Default year shown when the picker opens without a value. |
| disabled | `boolean` | no | false | Disable the entire picker. |
| displayFormat | `DateFormatOptions` | no | | Intl.DateTimeFormat options for displayed dates. |
| error | `string` | no | | Error message shown below the input. While set, it takes the place of the picker's own message for a range it cannot parse or that falls outside the allowed dates. |
| fixedWeeks | `boolean` | no | true | Always show 6 week rows, so the overlay keeps its height while paging months. Set `false` to let it shrink to 4 or 5 rows. |
| helper | `string` | no | | Helper text shown below the input. |
| inputVariant | `'outlined' | 'filled' | 'ghost' | 'underline'` | no | 'outlined' | Input variant. |
| isDateDisabled | `(date: Date) => boolean` | no | | Disables every day it returns `true` for, on top of `minDate`/`maxDate` — the one way to disable single days, whether a rule (weekends) or a list (holidays). Only a range's two ends are checked: the calendar cannot start or end a range on a disabled day, and a typed range with a disabled end is rejected as out of range, but a range may span disabled days. It receives a `Date` of its own for each day — read only its calendar day. It runs again when `$state` it reads changes. Compare calendar days, not `Date` objects (`list.includes(d)` matches nothing): keep a list as a `Set` of `toIso` keys from `@urbicon-ui/blocks/date` and pass `(d) => blocked.has(toIso(d))`. It must not throw; the calendar does not catch it. |
| label | `string` | no | | Label above the input. |
| locale | `string` | no | 'auto' | BCP 47 locale tag for date formatting — month names, weekday names and the header title. Defaults to `'auto'`, which follows the active `` locale, so an app that already declares its language does not have to repeat it here. SSR-safe: the locale comes from context, so the server and the client resolve the same tag (`Intl` with `undefined` would follow the runtime and disagree across hydration). Falls back to the base locale (`en`) when no provider is mounted. Pass an explicit tag (e.g. `'de-DE'`, `'ja-JP'`) to override. |
| maxDate | `Date` | no | | Latest selectable date. |
| minDate | `Date` | no | | Earliest selectable date. |
| mint | `MintProp` | no | 'none' | Micro-interaction preset forwarded to the inner Input. |
| name | `string` | no | | Shared base `name` for native form submission. When set, two hidden inputs are rendered — `{name}_start` and `{name}_end` — each carrying the serialized date, so the visible input's locale-formatted display string is never submitted instead. Empty range submits both halves as `""`. The `_start` / `_end` convention reflects the picker's domain language — date ranges read naturally as start/end rather than min/max. |
| onClickOutside | `() => void` | no | | Notification only — does NOT govern close behavior. |
| onEscape | `() => void` | no | | Notification only — does NOT govern close behavior. |
| onOpenChange | `(open: boolean) => void` | no | | Fires when the popover opens or closes. |
| onValueChange | `(value: DateRange | undefined) => void` | no | | Fires when the selected range changes. In the calendar the user clicks twice, once for the start and once for the end, and it fires on the second click, once the range is complete (start ≠ end). The intermediate `{ start: d, end: d }` state after the first click is not reported; use `bind:value` if you need it. |
| placeholder | `string` | no | | Placeholder when no range is selected. |
| preset | `string` | no | | Apply a named preset registered on ``. |
| required | `boolean` | no | false | Mark input as required: the label gets an asterisk and the text field the native `required` attribute. |
| showOutsideDays | `boolean` | no | true | Show days from adjacent months. |
| showWeekNumbers | `boolean` | no | false | Show ISO week numbers. |
| size | `'xs' | 'sm' | 'md' | 'lg' | 'xl'` | no | 'md' | Component size. |
| slotClasses | `Partial>` | no | | Per-slot class overrides. `base` is the positioning wrapper the field and the popover anchor sit in, `iconButton` the clear / open-calendar buttons in the field's right-icon area. The field itself is an `Input` and the overlay a `Calendar`; restyle those under their own names. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. |
| unstyled | `boolean` | no | | Strip the default tv() classes of the wrapper AND of the Input, Popover and Calendar it renders; `slotClasses` and `class` then stand alone. |
| value | `DateRange` | no | | Currently selected date range. Supports bind:value. |
| valueFormat | `'date' | 'iso'` | no | 'date' | Format used to serialise both range halves for the hidden form inputs. - `'date'` (default): `YYYY-MM-DD` in the local timezone — matches the native `` payload and Zod schemas like `z.string().regex(/^\d{4}-\d{2}-\d{2}$/).transform((v) => new Date(v))`. - `'iso'`: full ISO-8601 with `Z` suffix (UTC). Use this when the downstream schema expects a parseable timestamp string (e.g. a Drizzle `timestamp({ withTimezone: true, mode: 'date' })` column). Only relevant when `DateRangePickerProps.name` is set. |
| weekStartsOn | `WeekdayIndex` | no | 1 | First day of the week. 0 = Sunday, 1 = Monday. |
Inherited from:
- Omit, 'children'> (omit-pattern)
### Types
```ts
interface DatePickerPreset {
label: string;
value: Date;
}
```
```ts
interface DateRangePreset {
label: string;
value: DateRange;
}
```
```ts
type MintProp = | MintName
| { name: MintName; config?: MintConfig & Record }
| Array
| Array }>
```
```ts
type MonthIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11
```
```ts
type WeekdayIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6
```
```ts
interface DateRange {
start: Date;
end: Date;
}
```
```ts
type DateFormatOptions = Intl.DateTimeFormatOptions
```
```ts
type MintName = BuiltinMintName | 'none' | (string & {})
```
```ts
interface MintConfig {
/**
* `hover` and `focus` hold the effect while the pointer/visible focus stays
* on the element; `click` and `load` run it once.
*/
trigger?: 'hover' | 'click' | 'focus' | 'load';
/**
* Effect duration in ms. Written as an inline per-effect custom property
* (`--blocks-mint--duration`), so the CSS transition/animation
* actually runs at this speed; unset, the theme duration tokens apply.
*/
duration?: number;
/** Delay in ms before the effect applies. */
delay?: number;
/**
* CSS easing for the effect (`--blocks-mint--easing` inline);
* unset, the per-effect theme default applies.
*/
easing?: string;
disabled?: boolean;
}
```
```ts
type SlotNames = keyof ReturnType & string
```
```ts
type BuiltinMintName = (typeof BUILTIN_MINT_NAMES)[number]
```