Studio
2

Range Calendar

Installation

pnpm dlx @mielui/svelte add range-calendar

Usage

Bind an object with start and end DateValue properties. An incomplete selection has an undefined end. The default view uses the same Header, Month, Cell and Day parts you can compose yourself.

import * as RangeCalendar from '$lib/mielui/components/range-calendar';

<RangeCalendar.Root bind:value calendarLabel="Travel dates" />

Use CalendarDate from @internationalized/date for date-only values, or parseDate for ISO date strings. Bind placeholder to control the visible month. An explicit locale and placeholder keep server and client formatting predictable. Avoid converting a date-only selection through a UTC JavaScript Date to store it. Save each endpoint with value.start?.toString() and value.end?.toString().

Examples

Across months

numberOfMonths controls the visible months. pagedNavigation advances a page at a time. This example has no range-length limit. Optional minDays and maxDays count both endpoints; an out-of-range second selection becomes a new start date.

Composition and accessibility

Root exposes a children snippet with months and weekdays. Keep the default Month, or compose Grid, GridHead, GridBody, GridRow, HeadCell, Cell and Day to restyle individual regions. Month also accepts a day(date) snippet. Header, Heading, PrevButton, NextButton, MonthSelect and YearSelect can be omitted, reordered or replaced with another documented composition.

Styled parts forward native attributes and expose bind:ref for their underlying element. Arrow keys move between days, Page Up and Page Down change the visible month, and Enter or Space selects. Focus and selection are distinct. Disabled dates cannot be selected; readonly calendars remain navigable. The today indicator and unavailable strike-through provide cues beyond color.

The standalone calendar does not create a form field. Add a named hidden input when it participates in a form, or use the corresponding date picker for editable fields and form serialization. The calendar grid stays still during navigation; only state feedback changes.

Bounds and custom composition

Choose two to seven days within September. This composition omits navigation buttons because dates outside the month are unavailable.

API reference

RangeCalendar.Root

Prop Type Default
children Snippet<[RangeCalendarRootSnippetProps]> | undefined —
id string | undefined —
placeholder Bindable DateValue | undefined

The placeholder date, used to control the view of the calendar when no value is present.

—
style string | StyleProperties | null | undefined —
disabled boolean | undefined

Whether or not the calendar is disabled.

—
value Bindable DateRange | undefined

The value of the selected date range.

—
readonly boolean | undefined

Whether the calendar is readonly. When true, the user will be able to focus and navigate the calendar, but will not be able to select dates.

—
ref Bindable HTMLElement | null | undefined null
onValueChange OnChangeFn<DateRange> | undefined

A callback function called when the value changes.

—
onPlaceholderChange OnChangeFn<DateValue> | undefined

A callback function called when the placeholder value changes.

—
preventDeselect boolean | undefined

Whether or not users can deselect a date once selected without selecting another date.

—
minValue DateValue | undefined

The minimum date that can be selected in the calendar.

—
maxValue DateValue | undefined

The maximum date that can be selected in the calendar.

—
pagedNavigation boolean | undefined

Applicable only when `numberOfMonths` is greater than 1.

—
weekStartsOn 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined

The day of the week to start the calendar on, which must be a number between 0 and 6, where 0 is Sunday and 6 is Saturday.

—
weekdayFormat "long" | "short" | "narrow" | undefined

How the string representation of the weekdays provided via the `weekdays` state store should be formatted.

'short'
isDateDisabled DateMatcher | undefined

A function that receives a date and returns `true` or `false` to indicate whether the date is disabled.

—
isDateUnavailable DateMatcher | undefined

Dates matching the provided matchers are marked as "unavailable." Unlike disabled dates, users can still focus and select unavailable dates. However, selecting an unavailable date renders the date picker as invalid.

—
fixedWeeks boolean | undefined

Display 6 weeks per month, regardless the month's number of weeks. This is useful for displaying a consistent calendar, where the size of the calendar doesn't change month to month.

true
numberOfMonths number | undefined

Determines the number of months to display on the calendar simultaneously. For navigation between months, refer to the `pagedNavigation` prop.

—
calendarLabel string | undefined

This label is exclusively used for accessibility, remaining hidden from the page. It's read by screen readers when the calendar is opened. The current month and year are automatically appended to the label, so you only need to provide the base label.

—
locale string | undefined

The default locale setting.

'en-US'
disableDaysOutsideMonth boolean | undefined

Whether to disable the selection of days outside the current month. By default, days outside the current month are rendered to fill the calendar grid, but they are not selectable. Setting this prop to `true` will disable this behavior.

—
maxDays number | undefined

The maximum number of days that can be selected in a range.

—
monthFormat "numeric" | "long" | "short" | "narrow" | "2-digit" | ((month: number) => string) | undefined

The format of the month names in the calendar.

—
yearFormat "numeric" | "2-digit" | ((year: number) => string) | undefined

The format of the year names in the calendar.

—
onStartValueChange OnChangeFn<DateValue | undefined> | undefined

A callback function called when the start value changes. This doesn't necessarily mean the `value` has updated and should be used to apply cosmetic changes to the calendar when only part of the value is changed/completed.

—
onEndValueChange OnChangeFn<DateValue | undefined> | undefined

A callback function called when the end value changes. This doesn't necessarily mean the `value` has updated and should be used to apply cosmetic changes to the calendar when only part of the value is changed/completed.

—
minDays number | undefined

The minimum number of days that can be selected in a range.

—
excludeDisabled boolean | undefined

Whether to automatically reset the range if any date within the selected range becomes disabled. When true, the entire range will be cleared if a disabled date is found between the start and end dates.

—

RangeCalendar.Grid

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.GridBody

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.GridHead

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.GridRow

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.HeadCell

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.Header

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.Heading

Prop Type Default
child Snippet<[CalendarHeadingSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarHeadingSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.MonthSelect

Prop Type Default
monthFormat "numeric" | "long" | "short" | "narrow" | "2-digit" | ((month: number) => string) | undefined

How the month names should be formatted in the select options.

—
months number[] | undefined

An array of month numbers (1-12) to display in the select. This allows for flexible month selection, such as showing only specific months or seasons.

—
child Snippet<[CalendarMonthSelectSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarMonthSelectSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.NextButton

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.PrevButton

Prop Type Default
child Snippet<[{ props: Record<string, unknown>; }]> | undefined —
children Snippet<[]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.YearSelect

Prop Type Default
yearFormat "numeric" | "2-digit" | ((year: number) => string) | undefined

How the year should be formatted in the select options.

—
years number[] | undefined

An array of years to display in the select. This allows for complete control over which years appear, such as showing only years with data or excluding certain periods.

—
child Snippet<[CalendarYearSelectSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarYearSelectSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.Cell

Prop Type Default
date Required CalendarDate | CalendarDateTime | ZonedDateTime

The date value of the cell.

—
month Required CalendarDate | CalendarDateTime | ZonedDateTime

The month DateValue that this cell is being rendered in.

—
child Snippet<[CalendarCellSnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarCellSnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.Day

Prop Type Default
child Snippet<[CalendarDaySnippetProps & { props: Record<string, unknown>; }]> | undefined —
children Snippet<[CalendarDaySnippetProps]> | undefined —
style string | StyleProperties | null | undefined —
ref Bindable HTMLElement | null | undefined null
id string | undefined —

RangeCalendar.Month

Prop Type Default
class string | undefined —
month Required { value: DateValue; weeks: DateValue[][]; dates: DateValue[]; } —
weekdays Required string[] —
locale string | undefined 'en-US'
showHeading boolean | undefined false
day Snippet<[date: DateValue]> | undefined —