Calendar
Accessible, unstyled calendar compound primitive with a timezone-free date model.
|
|
| Package |
@vizejs/ui/calendar |
| Maturity |
stable |
| Own the source |
vize lib pull calendar |
| Requires |
context, controllable-state, id, locale |
| Aliases |
calendar, date grid, month view, mini calendar, day picker |
| Covers |
WAI-ARIA APG date picker dialog grid, React Aria Calendar, Reka UI Calendar, Radix-style calendar composition |
Usage
import { Calendar, CalendarRoot, CalendarGrid, CalendarMultipleRoot, MultipleCalendar, CalendarHeading, CalendarMonthSelect, CalendarNext, CalendarPrev, CalendarYearSelect } from "@vizejs/ui/calendar";
Or copy the source into your project with vize lib pull calendar (see Source Distribution).
API
Calendar
Source: src/families/date-time/calendar/calendar-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
PlainDate | null | undefined |
undefined |
Controlled selected date; undefined selects uncontrolled mode and null clears. |
defaultValue |
PlainDate | null | undefined |
null |
Initial uncontrolled selected date. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name that submits the ISO date with forms. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: PlainDate | null] |
Fired when the calendar requests a new controlled value. |
change |
[value: PlainDate | null, previous: PlainDate | null, nativeEvent: Event | null] |
Fired after a distinct selection with the previous value and triggering event. |
select |
[value: PlainDate, nativeEvent: Event] |
Fired for every user activation of a selectable date, even when the value is unchanged. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Calendar composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
value |
— |
|
setValue |
— |
|
CalendarRoot
Source: src/families/date-time/calendar/calendar-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
PlainDate | null | undefined |
undefined |
Controlled selected date; undefined selects uncontrolled mode and null clears. |
defaultValue |
PlainDate | null | undefined |
null |
Initial uncontrolled selected date. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name that submits the ISO date with forms. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: PlainDate | null] |
Fired when the calendar requests a new controlled value. |
change |
[value: PlainDate | null, previous: PlainDate | null, nativeEvent: Event | null] |
Fired after a distinct selection with the previous value and triggering event. |
select |
[value: PlainDate, nativeEvent: Event] |
Fired for every user activation of a selectable date, even when the value is unchanged. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Calendar composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
mode |
CalendarSelectionMode |
Selection model of the root. |
months |
readonly CalendarMonthState[] |
Visible month grids; empty while pending. |
weekdays |
readonly CalendarWeekdayLabel[] |
Localized weekday labels in column order. |
heading |
string |
Localized heading for the visible months. |
focusedDate |
PlainDate | null |
Keyboard focus target, or null while pending. |
today |
PlainDate | null |
Resolved current date, or null before a clock is available. |
locale |
string |
Resolved BCP 47 locale. |
direction |
CalendarDirection |
Resolved text direction. |
weekStartsOn |
Weekday |
Resolved first day of week. |
disabled |
boolean |
Whether every control is disabled. |
readOnly |
boolean |
Whether selection is blocked while navigation works. |
pending |
boolean |
Whether no date is known yet: no value, focused date, today, or now was supplied, so the grid waits for the client clock after mount. |
state |
CalendarState |
Stable root state token. |
root |
HTMLDivElement | null |
Rendered root element. |
focus |
(options?: FocusOptions) => boolean |
Focus the roving day button; returns whether focus moved. |
setFocusedDate |
(date: PlainDate) => void |
Move the keyboard focus target (and visible months) to a date, clamped to min/max. |
setVisibleMonth |
(month: PlainYearMonth) => void |
Show a month as the first visible month. |
navigate |
(unit: CalendarNavigationUnit, direction: -1 | 1) => boolean |
Navigate by one page of months or years; returns whether the view moved. |
value |
PlainDate | null |
Current selected date. |
setValue |
(value: PlainDate | null) => boolean |
Request a new value; returns whether it differs. |
CalendarGrid
Source: src/families/date-time/calendar/calendar-grid.vue
Props
| Prop |
Type |
Default |
Description |
monthIndex |
number |
0 |
Zero-based index of the visible month this grid renders. |
showWeekNumbers |
boolean |
false |
Render a leading row header with the ISO 8601 week number of each row. |
weekNumberLabel |
string |
"Wk" |
Visible week-number column header. |
weekNumberHeader |
string |
"Week" |
Full week-number column header used as abbr. |
Slots
| Slot |
Slot props |
Description |
weekday |
CalendarWeekdaySlotState |
Weekday column header content. Receives the weekday, its labels, and column index. |
weekNumber |
CalendarWeekNumberSlotState |
Week-number row header content. Receives the ISO week and the row's days. |
day |
CalendarDayState |
Day button content. Receives the complete day state; defaults to the localized day number. |
CalendarMultipleRoot
Source: src/families/date-time/calendar/calendar-multiple-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
readonly PlainDate[] | undefined |
undefined |
Controlled selected dates; undefined selects uncontrolled mode. |
defaultValue |
readonly PlainDate[] | undefined |
[] |
Initial uncontrolled selected dates. |
maxSelections |
number | undefined |
undefined |
Largest number of selected dates; activating another unselected date is ignored. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name; one input per selected ISO date is submitted. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: readonly PlainDate[]] |
Fired when the calendar requests new controlled dates (sorted, unique). |
change |
[value: readonly PlainDate[], previous: readonly PlainDate[], nativeEvent: Event | null] |
Fired after a distinct selection with the previous dates and triggering event. |
toggle |
[date: PlainDate, selected: boolean, nativeEvent: Event] |
Fired after a user activation toggles a date, with its new selected state. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Calendar composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
mode |
CalendarSelectionMode |
Selection model of the root. |
months |
readonly CalendarMonthState[] |
Visible month grids; empty while pending. |
weekdays |
readonly CalendarWeekdayLabel[] |
Localized weekday labels in column order. |
heading |
string |
Localized heading for the visible months. |
focusedDate |
PlainDate | null |
Keyboard focus target, or null while pending. |
today |
PlainDate | null |
Resolved current date, or null before a clock is available. |
locale |
string |
Resolved BCP 47 locale. |
direction |
CalendarDirection |
Resolved text direction. |
weekStartsOn |
Weekday |
Resolved first day of week. |
disabled |
boolean |
Whether every control is disabled. |
readOnly |
boolean |
Whether selection is blocked while navigation works. |
pending |
boolean |
Whether no date is known yet: no value, focused date, today, or now was supplied, so the grid waits for the client clock after mount. |
state |
CalendarState |
Stable root state token. |
root |
HTMLDivElement | null |
Rendered root element. |
focus |
(options?: FocusOptions) => boolean |
Focus the roving day button; returns whether focus moved. |
setFocusedDate |
(date: PlainDate) => void |
Move the keyboard focus target (and visible months) to a date, clamped to min/max. |
setVisibleMonth |
(month: PlainYearMonth) => void |
Show a month as the first visible month. |
navigate |
(unit: CalendarNavigationUnit, direction: -1 | 1) => boolean |
Navigate by one page of months or years; returns whether the view moved. |
value |
readonly PlainDate[] |
Selected dates, sorted and unique. |
setValue |
(value: readonly PlainDate[]) => boolean |
Replace the selection; returns whether it differs. |
toggle |
(date: PlainDate) => boolean |
Toggle one date; returns whether the selection changed. |
MultipleCalendar
Source: src/families/date-time/calendar/calendar-multiple-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null | undefined |
undefined |
Consumer-owned base id; nullish values use a deterministic fallback. |
modelValue |
readonly PlainDate[] | undefined |
undefined |
Controlled selected dates; undefined selects uncontrolled mode. |
defaultValue |
readonly PlainDate[] | undefined |
[] |
Initial uncontrolled selected dates. |
maxSelections |
number | undefined |
undefined |
Largest number of selected dates; activating another unselected date is ignored. |
focusedDate |
PlainDate | null | undefined |
undefined |
Controlled keyboard focus date; also decides which months are visible. |
min |
PlainDate | null | undefined |
undefined |
Earliest selectable date, inclusive. |
max |
PlainDate | null | undefined |
undefined |
Latest selectable date, inclusive. |
isDateUnavailable |
DateMatcher | undefined |
undefined |
Predicate for dates that stay focusable but cannot be selected. |
locale |
string | undefined |
undefined |
BCP 47 locale; defaults to the nearest LocaleProvider. |
calendar |
string | undefined |
undefined |
Intl calendar used for display labels only, for example japanese. |
numberingSystem |
string | undefined |
undefined |
Intl numbering system for labels. |
dir |
CalendarDirection | undefined |
undefined |
Text direction; defaults to the nearest LocaleProvider. |
weekStartsOn |
Weekday | undefined |
undefined |
First day of week (0 = Sunday); defaults to the locale preference. |
weekdayFormat |
CalendarWeekdayFormat | undefined |
"short" |
Weekday column label width. |
numberOfMonths |
number | undefined |
1 |
Number of consecutive months rendered. |
pagedNavigation |
boolean | undefined |
false |
Move month controls by numberOfMonths instead of one month. |
fixedWeeks |
boolean | undefined |
false |
Always render six week rows per month. |
today |
PlainDate | null | undefined |
undefined |
Explicit current date; the SSR-safe way to mark today. |
now |
DateTimeNow | undefined |
undefined |
Injectable clock evaluated during setup on server and client. |
timeZone |
string | undefined |
undefined |
IANA time zone used with now and the post-mount host clock. |
disabled |
boolean | undefined |
false |
Disable navigation, focus, and selection. |
readOnly |
boolean | undefined |
false |
Allow navigation while blocking selection. |
name |
string | undefined |
undefined |
Hidden input name; one input per selected ISO date is submitted. |
ariaLabel |
string | undefined |
undefined |
Accessible name for the calendar group. |
ariaLabelledby |
string | undefined |
undefined |
Ids that label the calendar group; defaults to the heading. |
ariaDescribedby |
string | undefined |
undefined |
Ids that describe the calendar group. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: readonly PlainDate[]] |
Fired when the calendar requests new controlled dates (sorted, unique). |
change |
[value: readonly PlainDate[], previous: readonly PlainDate[], nativeEvent: Event | null] |
Fired after a distinct selection with the previous dates and triggering event. |
toggle |
[date: PlainDate, selected: boolean, nativeEvent: Event] |
Fired after a user activation toggles a date, with its new selected state. |
update:focusedDate |
[date: PlainDate] |
Fired when keyboard or navigation moves the focus date. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarSlotState |
Calendar composition. Receives months, weekdays, heading, and state; defaults to a header plus one grid per month. |
Exposed
| Member |
Type |
Description |
value |
— |
|
setValue |
— |
|
toggle |
— |
|
CalendarHeading
Source: src/families/date-time/calendar/calendar-heading.vue
Slots
| Slot |
Slot props |
Description |
default |
CalendarHeadingSlotState |
Heading content. Receives the localized heading and visible months. |
CalendarMonthSelect
Source: src/families/date-time/calendar/calendar-month-select.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string |
"Month" |
Accessible name of the native select. |
Events
| Event |
Payload |
Description |
change |
[month: number, nativeEvent: Event] |
Fired after the user picks a month, with the ISO month number. |
CalendarNext
Source: src/families/date-time/calendar/calendar-next.vue
Props
| Prop |
Type |
Default |
Description |
unit |
CalendarNavigationUnit |
"month" |
Whether the control pages by month (or numberOfMonths when paged) or by year. |
ariaLabel |
string |
undefined |
Accessible name; defaults to "Next month" or "Next year". |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before navigation. Call preventDefault() to keep the view unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarNavigationSlotState |
Control content. Receives the unit and whether navigation is possible. |
CalendarPrev
Source: src/families/date-time/calendar/calendar-prev.vue
Props
| Prop |
Type |
Default |
Description |
unit |
CalendarNavigationUnit |
"month" |
Whether the control pages by month (or numberOfMonths when paged) or by year. |
ariaLabel |
string |
undefined |
Accessible name; defaults to "Previous month" or "Previous year". |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before navigation. Call preventDefault() to keep the view unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
CalendarNavigationSlotState |
Control content. Receives the unit and whether navigation is possible. |
CalendarYearSelect
Source: src/families/date-time/calendar/calendar-year-select.vue
Props
| Prop |
Type |
Default |
Description |
from |
number |
undefined |
First listed year; defaults to the min year or ten years before the view. |
to |
number |
undefined |
Last listed year; defaults to the max year or ten years after the view. |
ariaLabel |
string |
"Year" |
Accessible name of the native select. |
Events
| Event |
Payload |
Description |
change |
[year: number, nativeEvent: Event] |
Fired after the user picks a year. |
Behavior
Normative state x input -> outcome table for the Calendar compound
(@vizejs/ui/calendar): calendar-root.vue, calendar-grid.vue,
calendar-heading.vue, calendar-prev.vue, calendar-next.vue,
calendar-month-select.vue, calendar-year-select.vue, and calendar-multiple-root.vue, plus the
timezone-free date model in plain-date.ts. Every row is proven by the named
mounted-DOM, SSR, or unit test; a row without a passing test is a contract
violation.
| # |
State |
Input |
Outcome |
Proven by |
| C1 |
known date |
render |
root role="group" labelled by the heading; each month is a <table role="grid"> named by its month; weekday headers carry abbr; one roving tabindex=0 day; today has aria-current="date"; outside days are inert |
renders an APG date grid with locale weekdays, roving focus, and today |
| C2 |
uncontrolled |
day activation |
emits update:modelValue then change(value, previous, event); selection, data-*, and the hidden ISO input update |
uncontrolled selection emits update and change with the previous date |
| C3 |
controlled |
day activation |
emits the request; rendered selection follows modelValue until the parent accepts it |
controlled value wins until the parent accepts the request |
| C4 |
focused day |
Arrow / Home / End / PageUp / PageDown |
±1 day, ±1 week, week start/end, ±1 month, Shift ±1 year; focus follows into new months; update:focusedDate fires; Tab is not intercepted |
keyboard moves focus by day, week, week edge, month, and year across months |
| C5 |
RTL / locale |
render / ArrowLeft / ArrowRight |
dir flips horizontal arrows; week start comes from CLDR region data (or -u-fw-, or weekStartsOn); labels come from Intl |
RTL flips horizontal arrows and locale week start follows the region |
| C6 |
min / max / predicate |
render / keyboard / activation |
out-of-range days are disabled and focus clamps to the window; unavailable days stay focusable with aria-disabled and never select; prev/next disable at the bounds |
min, max, and unavailable dates constrain focus, navigation, and selection |
| C7 |
multiple months |
prev / next / keyboard |
numberOfMonths grids render side by side; paged navigation moves by the page; moving focus past the window scrolls it by one month; moving back inside does not scroll |
previous and next controls page by month or year and keep focus date in view |
| C8 |
month / year selects |
native change |
the chosen month or year becomes the first visible month; focus date keeps its day clamped to the month; out-of-range months are disabled options |
month and year selects jump the view and respect bounds |
| C9 |
disabled / read-only |
render / activation |
disabled removes every day and control from interaction; read-only keeps navigation and focus but blocks selection with aria-readonly/aria-disabled |
disabled and read-only calendars keep availability semantics |
| C10 |
no value, no clock |
mount |
the grid is pending until mount, then reads the host clock in timeZone, the nearest LocaleProvider zone, or the host zone |
without today or now the calendar is pending until mount reads the injected time zone clock |
| C11 |
LocaleProvider |
render |
locale, direction, display calendar (japanese, buddhist, …), and numbering system are inherited |
LocaleProvider supplies locale, direction, calendar display, and numbering |
| C12 |
imperative |
expose |
focus(), setValue(), setFocusedDate(), setVisibleMonth(), navigate() plus normalized slot state |
exposes focus, setValue, setFocusedDate, setVisibleMonth, and navigate |
| C13 |
custom composition |
default slot |
typed CalendarSlotState drives consumer-rendered grids; fixedWeeks renders six rows; day/weekday slots replace cell content |
custom composition receives typed slot state and renders fixed weeks |
| C14 |
SSR, explicit today |
isolated requests / hydration |
markup is byte-identical, selected <option>s carry selected, and hydration reuses the root with no warnings |
renders byte-identical calendar markup across isolated SSR requests, hydrates a calendar with an explicit today without mismatches |
| C15 |
SSR, no clock |
isolated requests / hydration |
the server renders a deterministic data-state="pending" shell without days; hydration is silent and the client fills the grid after mount |
without today or now SSR renders a pending shell and the client fills it after mount |
| C16 |
SSR, injected now |
server + client |
the injected instant resolves in timeZone identically on both sides |
an injected now renders the same today on server and client |
| D1 |
date model |
arithmetic |
epoch-day math matches UTC across eras and leap rules; month/year arithmetic clamps days |
epoch-day arithmetic matches UTC Date math across eras and leap rules, month, year, and week arithmetic clamps to real calendar days |
| D2 |
date model |
adapters |
Temporal-like records are copied; ISO strings round-trip; Date adapters never shift days; instants resolve per IANA zone |
validation rejects impossible dates and copies Temporal-like records, ISO strings round-trip including extended years, Date adapters read local or UTC fields and never shift days, instants resolve to calendar dates per IANA time zone |
| D3 |
date model |
ranges / locale data |
ranges are ordered; week start and formatters are deterministic |
ranges are ordered, normalized, and compared by day, week start follows CLDR regions, the fw extension, and explicit overrides, formatters render UTC-anchored labels with calendar and numbering overrides |
Multiple selection (calendar-multiple-root.vue)
| # |
State |
Input |
Outcome |
Proven by |
| M1 |
uncontrolled |
day activation |
toggles the date; the value stays sorted and unique; grids are aria-multiselectable; name submits one input per date |
multiple mode toggles dates, keeps them sorted, and submits one input per date |
| M2 |
any |
activation / maxSelections |
emits update:modelValue, change, then toggle(date, selected); unavailable dates and additions beyond maxSelections are ignored |
multiple mode emits update, change, and toggle and honors maxSelections |
| M3 |
controlled |
keyboard / expose / prop |
Enter toggles the focused date; toggle and setValue are exposed; an external value outside the view scrolls it into view |
controlled multiple selection, keyboard toggling, and the exposed API |
| M4 |
SSR |
isolated requests / hydration |
byte-identical markup and silent hydration |
renders byte-identical multiple-date calendar markup across isolated SSR requests, hydrates multiple-date calendar markup without mismatches |
CalendarGrid also accepts showWeekNumbers (with weekNumberLabel,
weekNumberHeader, and a weekNumber slot) to render a leading
<th scope="row"> holding each row's ISO 8601 week number; see
week-picker.behavior.md row W1.
SSR determinism
"Today" is never read from the wall clock during server rendering or
hydration. Resolution order:
today — an explicit PlainDate; deterministic everywhere.
now — an injected clock (for example the request timestamp) resolved in
timeZone, else the nearest LocaleProvider time zone, else UTC. Inject
the same instant on the server and the client.
- Otherwise the calendar renders a
pending shell (data-state="pending",
empty grid body) until mount, then reads Date.now() once in timeZone,
the provided locale zone, or the host zone.
A modelValue, defaultValue, or focusedDate also decides which month is
visible, so a calendar with a value never waits for the clock. Week start uses
an embedded CLDR region table instead of Intl.Locale#getWeekInfo() so the
server and every browser agree. All labels format UTC midnight with
timeZone: "UTC".
Date model
PlainDate is { year, month, day } in the ISO calendar. Temporal.PlainDate
(ISO calendar) satisfies it structurally; call Temporal.PlainDate.from(value)
to convert back. Adapters: parseIsoDate / formatIsoDate, fromLocalDate /
toLocalDate, fromUtcDate / toUtcDate, and fromEpochMilliseconds(ms, timeZone). Non-Gregorian calendars are supported for display only
(calendar prop or LocaleProvider): grid months stay ISO months, which is
exact for gregory, iso8601, japanese, roc, and buddhist.
Public props (CalendarRoot)
| Prop |
Type |
Default |
Contract |
modelValue / defaultValue |
PlainDate | null |
undefined |
Controlled / uncontrolled selection. |
focusedDate |
PlainDate | null |
undefined |
Controlled roving focus date; decides the visible months. |
min / max |
PlainDate | null |
undefined |
Inclusive selectable window; swapped when reversed. |
isDateUnavailable |
(date) => boolean |
undefined |
Focusable but unselectable dates. |
locale / dir |
string / "ltr" | "rtl" |
provider |
Defaults to the nearest LocaleProvider. |
calendar / numberingSystem |
string |
provider |
Display-only Intl overrides. |
weekStartsOn |
0–6 |
locale |
First column; 0 is Sunday. |
weekdayFormat |
"narrow" | "short" | "long" |
"short" |
Column label width. |
numberOfMonths |
number |
1 |
Consecutive months, clamped to 1–12. |
pagedNavigation |
boolean |
false |
Month controls move by the page. |
fixedWeeks |
boolean |
false |
Always six rows. |
today / now / timeZone |
see SSR determinism |
undefined |
Clock injection. |
disabled / readOnly |
boolean |
false |
Availability. |
name |
string |
undefined |
Hidden input submitting YYYY-MM-DD. |
Extension hooks
| Hook |
Values |
| parts |
root, header, heading, prev, next, month-select, month-option, year-select, year-option, grid, grid-head, weekdays, weekday, grid-body, week, cell, day |
| root data |
data-vize-ui="calendar", data-mode, data-state, data-dir, data-months, data-value, data-disabled, data-readonly, data-pending |
| cell / day data |
data-date, data-state, data-weekday, data-today, data-focused, data-outside-month, data-selected, data-in-range, data-range-start, data-range-end, data-preview, data-disabled, data-unavailable |