From 2e9aeb5f05e94d63ea453c4f07a3e84ee2a02773 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 26 Nov 2024 16:24:20 +0500 Subject: [PATCH] feat(Calendar): implement component (#2618) Co-authored-by: Benjamin Canac --- docs/app/components/content/ComponentCode.vue | 2 + .../calendar/CalendarDatePickerExample.vue | 21 + .../CalendarDateRangePickerExample.vue | 35 + .../calendar/CalendarDisabledDatesExample.vue | 17 + .../calendar/CalendarEventsExample.vue | 30 + .../calendar/CalendarMinMaxDatesExample.vue | 11 + .../CalendarUnavailableDatesExample.vue | 17 + docs/content/3.components/calendar.md | 210 + docs/content/3.components/input-menu.md | 2 +- docs/content/3.components/input-number.md | 4 + docs/content/3.components/select-menu.md | 2 +- package.json | 1 + playground/app/app.vue | 1 + playground/app/pages/components/calendar.vue | 20 + pnpm-lock.yaml | 11 +- src/runtime/components/Calendar.vue | 165 + src/runtime/components/InputMenu.vue | 9 +- src/runtime/components/SelectMenu.vue | 9 +- src/runtime/locale/ar.ts | 6 + src/runtime/locale/cs.ts | 6 + src/runtime/locale/de.ts | 6 + src/runtime/locale/en.ts | 6 + src/runtime/locale/es.ts | 6 + src/runtime/locale/fa_ir.ts | 6 + src/runtime/locale/fr.ts | 6 + src/runtime/locale/it.ts | 6 + src/runtime/locale/ko.ts | 6 + src/runtime/locale/nl.ts | 6 + src/runtime/locale/pl.ts | 6 + src/runtime/locale/ru.ts | 6 + src/runtime/locale/tr.ts | 6 + src/runtime/locale/zh_hans.ts | 6 + src/runtime/locale/zh_hant.ts | 6 + src/runtime/types/index.ts | 1 + src/runtime/types/locale.ts | 6 + src/theme/calendar.ts | 64 + src/theme/index.ts | 1 + test/components/Calendar.spec.ts | 65 + .../__snapshots__/Calendar-vue.spec.ts.snap | 4751 +++++++++++++++++ .../__snapshots__/Calendar.spec.ts.snap | 4751 +++++++++++++++++ 40 files changed, 10278 insertions(+), 18 deletions(-) create mode 100644 docs/app/components/content/examples/calendar/CalendarDatePickerExample.vue create mode 100644 docs/app/components/content/examples/calendar/CalendarDateRangePickerExample.vue create mode 100644 docs/app/components/content/examples/calendar/CalendarDisabledDatesExample.vue create mode 100644 docs/app/components/content/examples/calendar/CalendarEventsExample.vue create mode 100644 docs/app/components/content/examples/calendar/CalendarMinMaxDatesExample.vue create mode 100644 docs/app/components/content/examples/calendar/CalendarUnavailableDatesExample.vue create mode 100644 docs/content/3.components/calendar.md create mode 100644 playground/app/pages/components/calendar.vue create mode 100644 src/runtime/components/Calendar.vue create mode 100644 src/theme/calendar.ts create mode 100644 test/components/Calendar.spec.ts create mode 100644 test/components/__snapshots__/Calendar-vue.spec.ts.snap create mode 100644 test/components/__snapshots__/Calendar.spec.ts.snap diff --git a/docs/app/components/content/ComponentCode.vue b/docs/app/components/content/ComponentCode.vue index c92ab9db49..08746c809e 100644 --- a/docs/app/components/content/ComponentCode.vue +++ b/docs/app/components/content/ComponentCode.vue @@ -93,6 +93,8 @@ const options = computed(() => { chip: key.toLowerCase().endsWith('color') ? { color: variant } : undefined })) + // TODO: process "undefined | Date | DateRange", https://github.com/nuxt/ui/issues/2651 + return { name: key, label: key, diff --git a/docs/app/components/content/examples/calendar/CalendarDatePickerExample.vue b/docs/app/components/content/examples/calendar/CalendarDatePickerExample.vue new file mode 100644 index 0000000000..c60583b213 --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarDatePickerExample.vue @@ -0,0 +1,21 @@ + + + diff --git a/docs/app/components/content/examples/calendar/CalendarDateRangePickerExample.vue b/docs/app/components/content/examples/calendar/CalendarDateRangePickerExample.vue new file mode 100644 index 0000000000..37804cb250 --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarDateRangePickerExample.vue @@ -0,0 +1,35 @@ + + + diff --git a/docs/app/components/content/examples/calendar/CalendarDisabledDatesExample.vue b/docs/app/components/content/examples/calendar/CalendarDisabledDatesExample.vue new file mode 100644 index 0000000000..78b6ea2884 --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarDisabledDatesExample.vue @@ -0,0 +1,17 @@ + + + diff --git a/docs/app/components/content/examples/calendar/CalendarEventsExample.vue b/docs/app/components/content/examples/calendar/CalendarEventsExample.vue new file mode 100644 index 0000000000..998bf3b008 --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarEventsExample.vue @@ -0,0 +1,30 @@ + + + diff --git a/docs/app/components/content/examples/calendar/CalendarMinMaxDatesExample.vue b/docs/app/components/content/examples/calendar/CalendarMinMaxDatesExample.vue new file mode 100644 index 0000000000..6caef84106 --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarMinMaxDatesExample.vue @@ -0,0 +1,11 @@ + + + diff --git a/docs/app/components/content/examples/calendar/CalendarUnavailableDatesExample.vue b/docs/app/components/content/examples/calendar/CalendarUnavailableDatesExample.vue new file mode 100644 index 0000000000..49c21f461f --- /dev/null +++ b/docs/app/components/content/examples/calendar/CalendarUnavailableDatesExample.vue @@ -0,0 +1,17 @@ + + + diff --git a/docs/content/3.components/calendar.md b/docs/content/3.components/calendar.md new file mode 100644 index 0000000000..0a9edcdd44 --- /dev/null +++ b/docs/content/3.components/calendar.md @@ -0,0 +1,210 @@ +--- +title: Calendar +description: A calendar component for selecting single dates, multiple dates or date ranges. +links: + - label: Calendar + icon: i-custom-radix-vue + to: https://www.radix-vue.com/components/calendar.html + - label: GitHub + icon: i-simple-icons-github + to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Calendar.vue +navigation.badge: New +--- + +::note +This component relies on the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/index.html) package which provides objects and functions for representing and manipulating dates and times in a locale-aware manner. +:: + +## Usage + +Use the `v-model` directive to control the selected date. + +::component-code +--- +--- +:: + + + +### Multiple + +Use the `multiple` prop to allow multiple selections. + +::component-code +--- +ignore: + - multiple +props: + multiple: true +--- +:: + +### Range + +Use the `range` prop to select a range of dates. + +::component-code +--- +ignore: + - range +props: + range: true +--- +:: + +### Color + +Use the `color` prop to change the color of the calendar. + +::component-code +--- +props: + color: neutral +--- +:: + +### Size + +Use the `size` prop to change the size of the calendar. + +::component-code +--- +props: + size: xl +--- +:: + +### Disabled + +Use the `disabled` prop to disable the calendar. + +::component-code +--- +props: + disabled: true +--- +:: + +### Number Of Months + +Use the `numberOfMonths` prop to change the number of months in the calendar. + +::component-code +--- +props: + numberOfMonths: 3 +--- +:: + +### Month Controls + +Use the `month-controls` prop to show the month controls. Defaults to `true`. + +::component-code +--- +props: + monthControls: false +--- +:: + +### Year Controls + +Use the `year-controls` prop to show the year controls. Defaults to `true`. + +::component-code +--- +props: + yearControls: false +--- +:: + +### Fixed Weeks + +Use the `fixed-weeks` prop to display the calendar with fixed weeks. + +::component-code +--- +props: + fixedWeeks: false +--- +:: + +## Examples + +### With chip events + +Use the [Chip](/components/chip) component to add events to specific days. + +::component-example +--- +name: 'calendar-events-example' +--- +:: + +### With disabled dates + +Use the `is-date-disabled` prop with a function to mark specific dates as disabled. + +::component-example +--- +name: 'calendar-disabled-dates-example' +--- +:: + +### With unavailable dates + +Use the `is-date-unavailable` prop with a function to mark specific dates as unavailable. + +::component-example +--- +name: 'calendar-unavailable-dates-example' +--- +:: + +### With min/max dates + +Use the `min-value` and `max-value` props to limit the dates. + +::component-example +--- +name: 'calendar-min-max-dates-example' +--- +:: + +### As a DatePicker + +Use a [Button](/components/button) and a [Popover](/components/popover) component to create a date picker. + +::component-example +--- +name: 'calendar-date-picker-example' +--- +:: + +### As a DateRangePicker + +Use a [Button](/components/button) and a [Popover](/components/popover) component to create a date range picker. + +::component-example +--- +name: 'calendar-date-range-picker-example' +--- +:: + +## API + +### Props + +:component-props + +### Slots + +:component-slots + +### Emits + +:component-emits + +## Theme + +:component-theme diff --git a/docs/content/3.components/input-menu.md b/docs/content/3.components/input-menu.md index 5254414b62..37e3d88287 100644 --- a/docs/content/3.components/input-menu.md +++ b/docs/content/3.components/input-menu.md @@ -771,7 +771,7 @@ name: 'input-menu-filter-fields-example' --- :: -### As a country picker +### As a CountryPicker This example demonstrates using the InputMenu as a country picker with lazy loading - countries are only fetched when the menu is opened. diff --git a/docs/content/3.components/input-number.md b/docs/content/3.components/input-number.md index ca8e5d8146..65f5837b5c 100644 --- a/docs/content/3.components/input-number.md +++ b/docs/content/3.components/input-number.md @@ -11,6 +11,10 @@ links: navigation.badge: New --- +::note +This component relies on the [@internationalized/number](https://react-spectrum.adobe.com/internationalized/number/index.html) package which provides utilities for formatting and parsing numbers across locales and numbering systems. +:: + ## Usage Use the `v-model` directive to control the value of the InputNumber. diff --git a/docs/content/3.components/select-menu.md b/docs/content/3.components/select-menu.md index 1de5a7cf5e..3430b5a9d9 100644 --- a/docs/content/3.components/select-menu.md +++ b/docs/content/3.components/select-menu.md @@ -806,7 +806,7 @@ name: 'select-menu-filter-fields-example' --- :: -### As a country picker +### As a CountryPicker This example demonstrates using the SelectMenu as a country picker with lazy loading - countries are only fetched when the menu is opened. diff --git a/package.json b/package.json index b8db7ae2e9..fdec411ae4 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ }, "dependencies": { "@iconify/vue": "^4.1.2", + "@internationalized/date": "^3.6.0", "@internationalized/number": "^3.6.0", "@nuxt/devtools-kit": "^1.6.1", "@nuxt/fonts": "^0.10.2", diff --git a/playground/app/app.vue b/playground/app/app.vue index 2f10354c6d..172a3ab9b8 100644 --- a/playground/app/app.vue +++ b/playground/app/app.vue @@ -24,6 +24,7 @@ const components = [ 'button', 'button-group', 'card', + 'calendar', 'carousel', 'checkbox', 'chip', diff --git a/playground/app/pages/components/calendar.vue b/playground/app/pages/components/calendar.vue new file mode 100644 index 0000000000..cd05cb4e3f --- /dev/null +++ b/playground/app/pages/components/calendar.vue @@ -0,0 +1,20 @@ + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a158125a2..ad870da713 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@iconify/vue': specifier: ^4.1.2 version: 4.1.2(vue@3.5.13(typescript@5.6.3)) + '@internationalized/date': + specifier: ^3.6.0 + version: 3.6.0 '@internationalized/number': specifier: ^3.6.0 version: 3.6.0 @@ -1281,8 +1284,8 @@ packages: resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==} engines: {node: '>=18'} - '@internationalized/date@3.5.6': - resolution: {integrity: sha512-jLxQjefH9VI5P9UQuqB6qNKnvFt1Ky1TPIzHGsIlCi7sZZoMR8SdYbBGRvM0y+Jtb+ez4ieBzmiAUcpmPYpyOw==} + '@internationalized/date@3.6.0': + resolution: {integrity: sha512-+z6ti+CcJnRlLHok/emGEsWQhe7kfSmEW+/6qCzvKY67YPh7YOBfvc7+/+NXq+zJlbArg30tYpqLjNgcAYv2YQ==} '@internationalized/number@3.6.0': resolution: {integrity: sha512-PtrRcJVy7nw++wn4W2OuePQQfTqDzfusSuY1QTtui4wa7r+rGVtR75pO8CyKvHvzyQYi3Q1uO5sY0AsB4e65Bw==} @@ -7887,7 +7890,7 @@ snapshots: '@inquirer/figures@1.0.8': {} - '@internationalized/date@3.5.6': + '@internationalized/date@3.6.0': dependencies: '@swc/helpers': 0.5.15 @@ -13914,7 +13917,7 @@ snapshots: dependencies: '@floating-ui/dom': 1.6.12 '@floating-ui/vue': 1.1.5(vue@3.5.13(typescript@5.6.3)) - '@internationalized/date': 3.5.6 + '@internationalized/date': 3.6.0 '@internationalized/number': 3.6.0 '@tanstack/vue-virtual': 3.10.9(vue@3.5.13(typescript@5.6.3)) '@vueuse/core': 10.11.1(vue@3.5.13(typescript@5.6.3)) diff --git a/src/runtime/components/Calendar.vue b/src/runtime/components/Calendar.vue new file mode 100644 index 0000000000..1a9b944448 --- /dev/null +++ b/src/runtime/components/Calendar.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/src/runtime/components/InputMenu.vue b/src/runtime/components/InputMenu.vue index b59d40bc12..617b246c2d 100644 --- a/src/runtime/components/InputMenu.vue +++ b/src/runtime/components/InputMenu.vue @@ -107,7 +107,7 @@ export interface InputMenuProps, I extends Ma /** The controlled value of the Combobox. Can be binded-with with `v-model`. */ modelValue?: SelectModelValue /** Whether multiple options can be selected or not. */ - multiple?: M + multiple?: M & boolean } export type InputMenuEmits = Omit, 'update:modelValue'> & { @@ -167,11 +167,9 @@ const searchTerm = defineModel('searchTerm', { default: '' }) const appConfig = useAppConfig() const { t } = useLocale() -const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits) +const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits) const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps) const arrowProps = toRef(() => props.arrow as ComboboxArrowProps) -// This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541) -const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple) const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled } = useFormField(props) const { orientation, size: buttonGroupSize } = useButtonGroup(props) @@ -189,7 +187,7 @@ const ui = computed(() => inputMenu({ highlight: highlight.value, leading: isLeading.value || !!props.avatar || !!slots.leading, trailing: isTrailing.value || !!slots.trailing, - multiple: multiple.value, + multiple: props.multiple, buttonGroup: orientation.value })) @@ -336,7 +334,6 @@ defineExpose({ v-model:search-term="searchTerm" :name="name" :disabled="disabled" - :multiple="multiple" :display-value="displayValue" :filter-function="() => rootItems" :class="ui.root({ class: [props.class, props.ui?.root] })" diff --git a/src/runtime/components/SelectMenu.vue b/src/runtime/components/SelectMenu.vue index f675d91b03..a222c230bc 100644 --- a/src/runtime/components/SelectMenu.vue +++ b/src/runtime/components/SelectMenu.vue @@ -99,7 +99,7 @@ export interface SelectMenuProps, I extends M /** The controlled value of the Combobox. Can be binded-with with `v-model`. */ modelValue?: SelectModelValue /** Whether multiple options can be selected or not. */ - multiple?: M + multiple?: M & boolean } export type SelectMenuEmits = Omit, 'update:modelValue'> & { @@ -160,12 +160,10 @@ const searchTerm = defineModel('searchTerm', { default: '' }) const appConfig = useAppConfig() const { t } = useLocale() -const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits) +const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits) const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps) const arrowProps = toRef(() => props.arrow as ComboboxArrowProps) const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: 'Search...', variant: 'none' }) as InputProps) -// This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541) -const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple) const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate() @@ -187,7 +185,7 @@ const ui = computed(() => selectMenu({ })) function displayValue(value: T | T[]): string { - if (multiple.value && Array.isArray(value)) { + if (props.multiple && Array.isArray(value)) { return value.map(v => displayValue(v)).filter(Boolean).join(', ') } @@ -307,7 +305,6 @@ function onUpdateOpen(value: boolean) { as-child :name="name" :disabled="disabled" - :multiple="multiple" :display-value="() => searchTerm" :filter-function="() => rootItems" @update:model-value="onUpdate" diff --git a/src/runtime/locale/ar.ts b/src/runtime/locale/ar.ts index c1fb6ed5a8..6b86aee2d0 100644 --- a/src/runtime/locale/ar.ts +++ b/src/runtime/locale/ar.ts @@ -10,6 +10,12 @@ export default defineLocale({ noData: 'لا توجد بيانات', create: 'إنشاء "{label}"' }, + calendar: { + prevYear: 'السنة السابقة', + nextYear: 'السنة المقبلة', + prevMonth: 'الشهر السابق', + nextMonth: 'الشهر المقبل' + }, inputNumber: { increment: 'زيادة', decrement: 'تقليل' diff --git a/src/runtime/locale/cs.ts b/src/runtime/locale/cs.ts index b9296d33fd..ab1da24f66 100644 --- a/src/runtime/locale/cs.ts +++ b/src/runtime/locale/cs.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Žádná data', create: 'Vytvořit "{label}"' }, + calendar: { + prevYear: 'Předchozí rok', + nextYear: 'Další rok', + prevMonth: 'Předchozí měsíc', + nextMonth: 'Další měsíc' + }, inputNumber: { increment: 'Zvýšit', decrement: 'Snížit' diff --git a/src/runtime/locale/de.ts b/src/runtime/locale/de.ts index e60b3f7eac..a0583dd649 100644 --- a/src/runtime/locale/de.ts +++ b/src/runtime/locale/de.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Keine Daten', create: '"{label}" erstellen' }, + calendar: { + prevYear: 'Vorheriges Jahr', + nextYear: 'Nächstes Jahr', + prevMonth: 'Vorheriger Monat', + nextMonth: 'Nächster Monat' + }, inputNumber: { increment: 'Erhöhen', decrement: 'Verringern' diff --git a/src/runtime/locale/en.ts b/src/runtime/locale/en.ts index 4be5a9c824..74e669b5ce 100644 --- a/src/runtime/locale/en.ts +++ b/src/runtime/locale/en.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'No data', create: 'Create "{label}"' }, + calendar: { + prevYear: 'Previous year', + nextYear: 'Next year', + prevMonth: 'Previous month', + nextMonth: 'Next month' + }, inputNumber: { increment: 'Increment', decrement: 'Decrement' diff --git a/src/runtime/locale/es.ts b/src/runtime/locale/es.ts index f3579f4e8d..bd24c608ac 100644 --- a/src/runtime/locale/es.ts +++ b/src/runtime/locale/es.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Sin datos', create: 'Crear "{label}"' }, + calendar: { + prevYear: 'A o anterior', + nextYear: 'A o siguiente', + prevMonth: 'Mes anterior', + nextMonth: 'Mes siguiente' + }, inputNumber: { increment: 'Incremento', decrement: 'Decremento' diff --git a/src/runtime/locale/fa_ir.ts b/src/runtime/locale/fa_ir.ts index 8a047305eb..6d1548902c 100644 --- a/src/runtime/locale/fa_ir.ts +++ b/src/runtime/locale/fa_ir.ts @@ -10,6 +10,12 @@ export default defineLocale({ noData: 'داده‌ای موجود نیست', create: 'ایجاد "{label}"' }, + calendar: { + prevYear: 'سال گذشته', + nextYear: 'سال آینده', + prevMonth: 'ماه گذشته', + nextMonth: 'ماه آینده' + }, inputNumber: { increment: 'افزایش', decrement: 'کاهش' diff --git a/src/runtime/locale/fr.ts b/src/runtime/locale/fr.ts index 19086796f1..111c863b91 100644 --- a/src/runtime/locale/fr.ts +++ b/src/runtime/locale/fr.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Aucune donnée', create: 'Créer "{label}"' }, + calendar: { + prevYear: 'Année précédente', + nextYear: 'Année suivante', + prevMonth: 'Mois précédent', + nextMonth: 'Mois suivant' + }, inputNumber: { increment: 'Augmenter', decrement: 'Diminuer' diff --git a/src/runtime/locale/it.ts b/src/runtime/locale/it.ts index cd0eb32b05..c7f70a3444 100644 --- a/src/runtime/locale/it.ts +++ b/src/runtime/locale/it.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Nessun dato', create: 'Crea "{label}"' }, + calendar: { + prevYear: 'Anno precedente', + nextYear: 'Anno successivo', + prevMonth: 'Mese precedente', + nextMonth: 'Mese successivo' + }, inputNumber: { increment: 'Aumenta', decrement: 'Diminuisci' diff --git a/src/runtime/locale/ko.ts b/src/runtime/locale/ko.ts index 5fe4a3a0f6..b7d78e1c60 100644 --- a/src/runtime/locale/ko.ts +++ b/src/runtime/locale/ko.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: '데이터가 없습니다.', create: '"{label}" 생성' }, + calendar: { + prevYear: '이전 해', + nextYear: '다음 해', + prevMonth: '이전 달', + nextMonth: '다음 달' + }, inputNumber: { increment: '증가', decrement: '감소' diff --git a/src/runtime/locale/nl.ts b/src/runtime/locale/nl.ts index a7198ab1ca..5a3e3f9e40 100644 --- a/src/runtime/locale/nl.ts +++ b/src/runtime/locale/nl.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Geen gegevens', create: '"{label}" creëren' }, + calendar: { + prevYear: 'Vorig jaar', + nextYear: 'Volgend jaar', + prevMonth: 'Vorige maand', + nextMonth: 'Volgende maand' + }, inputNumber: { increment: 'Verhogen', decrement: 'Verlagen' diff --git a/src/runtime/locale/pl.ts b/src/runtime/locale/pl.ts index 033ee61c11..923af69736 100644 --- a/src/runtime/locale/pl.ts +++ b/src/runtime/locale/pl.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Brak danych', create: 'Utwórz "{label}"' }, + calendar: { + prevYear: 'Poprzedni rok', + nextYear: 'Przyszły rok', + prevMonth: 'Poprzedni miesiąc', + nextMonth: 'Przyszły miesiąc' + }, inputNumber: { increment: 'Zwiększ', decrement: 'Zmniejsz' diff --git a/src/runtime/locale/ru.ts b/src/runtime/locale/ru.ts index 85135db5f3..f3d98d849e 100644 --- a/src/runtime/locale/ru.ts +++ b/src/runtime/locale/ru.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Нет данных', create: 'Создать "{label}"' }, + calendar: { + prevYear: 'Предыдущий год', + nextYear: 'Следующий год', + prevMonth: 'Предыдущий месяц', + nextMonth: 'Следующий месяц' + }, inputNumber: { increment: 'Увеличить', decrement: 'Уменьшить' diff --git a/src/runtime/locale/tr.ts b/src/runtime/locale/tr.ts index 4e475e2662..882788dcd8 100644 --- a/src/runtime/locale/tr.ts +++ b/src/runtime/locale/tr.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: 'Veri yok', create: '"{label}" oluştur' }, + calendar: { + prevYear: 'Önceki yıl', + nextYear: 'Sonraki yıl', + prevMonth: 'Önceki ay', + nextMonth: 'Sonraki ay' + }, inputNumber: { increment: 'Arttır', decrement: 'Azalt' diff --git a/src/runtime/locale/zh_hans.ts b/src/runtime/locale/zh_hans.ts index c829c64164..0a9c2213ae 100644 --- a/src/runtime/locale/zh_hans.ts +++ b/src/runtime/locale/zh_hans.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: '没有数据', create: '创建 "{label}"' }, + calendar: { + prevYear: '去年', + nextYear: '明年', + prevMonth: '上个月', + nextMonth: '下个月' + }, inputNumber: { increment: '增加', decrement: '减少' diff --git a/src/runtime/locale/zh_hant.ts b/src/runtime/locale/zh_hant.ts index 1671051c28..556d237a6e 100644 --- a/src/runtime/locale/zh_hant.ts +++ b/src/runtime/locale/zh_hant.ts @@ -9,6 +9,12 @@ export default defineLocale({ noData: '沒有資料', create: '創建 "{label}"' }, + calendar: { + prevYear: '去年', + nextYear: '明年', + prevMonth: '上个月', + nextMonth: '下个月' + }, inputNumber: { increment: '增加', decrement: '减少' diff --git a/src/runtime/types/index.ts b/src/runtime/types/index.ts index 072e3e8db8..aa067d6b7d 100644 --- a/src/runtime/types/index.ts +++ b/src/runtime/types/index.ts @@ -6,6 +6,7 @@ export * from '../components/AvatarGroup.vue' export * from '../components/Badge.vue' export * from '../components/Breadcrumb.vue' export * from '../components/Button.vue' +export * from '../components/Calendar.vue' export * from '../components/Card.vue' export * from '../components/Carousel.vue' export * from '../components/Checkbox.vue' diff --git a/src/runtime/types/locale.ts b/src/runtime/types/locale.ts index b5b3ed02bb..4148874b97 100644 --- a/src/runtime/types/locale.ts +++ b/src/runtime/types/locale.ts @@ -4,6 +4,12 @@ export type Messages = { noData: string create: string } + calendar: { + prevYear: string + nextYear: string + prevMonth: string + nextMonth: string + } inputNumber: { increment: string decrement: string diff --git a/src/theme/calendar.ts b/src/theme/calendar.ts new file mode 100644 index 0000000000..800e9e81f2 --- /dev/null +++ b/src/theme/calendar.ts @@ -0,0 +1,64 @@ +import type { ModuleOptions } from '../module' + +export default (options: Required) => ({ + slots: { + root: '', + header: 'flex items-center justify-between', + body: 'flex flex-col space-y-4 pt-4 sm:flex-row sm:space-x-4 sm:space-y-0', + heading: 'text-center font-medium truncate mx-auto', + grid: 'w-full border-collapse select-none space-y-1 focus:outline-none', + gridRow: 'grid grid-cols-7', + gridWeekDaysRow: 'mb-1 grid w-full grid-cols-7', + gridBody: 'grid', + headCell: 'rounded-[calc(var(--ui-radius)*1.5)]', + cell: 'relative text-center', + cellTrigger: ['m-0.5 relative flex items-center justify-center rounded-full whitespace-nowrap focus-visible:ring-2 focus:outline-none data-disabled:text-[var(--ui-text-muted)] data-unavailable:line-through data-unavailable:text-[var(--ui-text-muted)] data-unavailable:pointer-events-none data-[selected]:text-[var(--ui-bg)] data-today:font-semibold', options.theme.transitions && 'transition'] + }, + variants: { + color: { + ...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, { + headCell: `text-[var(--ui-${color})]`, + cellTrigger: `focus-visible:ring-[var(--ui-${color})] data-[selected]:bg-[var(--ui-${color})] data-today:not-data-[selected]:text-[var(--ui-${color})] data-[highlighted]:bg-[var(--ui-${color})]/20 hover:not-data-[selected]:bg-[var(--ui-${color})]/20` + }])), + neutral: { + headCell: 'text-[var(--ui-bg-inverted)]', + cellTrigger: 'focus-visible:ring-[var(--ui-border-inverted)] data-[selected]:bg-[var(--ui-bg-inverted)] data-today:not-data-[selected]:text-[var(--ui-bg-inverted)] data-[highlighted]:bg-[var(--ui-bg-inverted)]/20 hover:not-data-[selected]:bg-[var(--ui-bg-inverted)]/10' + } + }, + size: { + xs: { + heading: 'text-xs', + cell: 'text-xs', + headCell: 'text-[10px]', + cellTrigger: 'size-7', + body: 'space-y-2 pt-2' + }, + sm: { + heading: 'text-xs', + headCell: 'text-xs', + cell: 'text-xs', + cellTrigger: 'size-7' + }, + md: { + heading: 'text-sm', + headCell: 'text-xs', + cell: 'text-sm', + cellTrigger: 'size-8' + }, + lg: { + heading: 'text-md', + headCell: 'text-md', + cellTrigger: 'size-9 text-md' + }, + xl: { + heading: 'text-lg', + headCell: 'text-lg', + cellTrigger: 'size-10 text-lg' + } + } + }, + defaultVariants: { + size: 'md', + color: 'primary' + } +}) diff --git a/src/theme/index.ts b/src/theme/index.ts index 90d2af7156..7bbbdf938b 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -6,6 +6,7 @@ export { default as badge } from './badge' export { default as breadcrumb } from './breadcrumb' export { default as button } from './button' export { default as buttonGroup } from './button-group' +export { default as calendar } from './calendar' export { default as card } from './card' export { default as carousel } from './carousel' export { default as checkbox } from './checkbox' diff --git a/test/components/Calendar.spec.ts b/test/components/Calendar.spec.ts new file mode 100644 index 0000000000..7549019ea1 --- /dev/null +++ b/test/components/Calendar.spec.ts @@ -0,0 +1,65 @@ +import { describe, it, expect, vi, afterAll, test } from 'vitest' +import { mountSuspended } from '@nuxt/test-utils/runtime' +import Calendar, { type CalendarProps, type CalendarSlots } from '../../src/runtime/components/Calendar.vue' +import ComponentRender from '../component-render' +import theme from '#build/ui/calendar' +import { CalendarDate } from '@internationalized/date' + +describe('Calendar', () => { + const sizes = Object.keys(theme.variants.size) as any + const date = new Date('2025-01-01') + + vi.setSystemTime(date) + + afterAll(() => { + vi.useRealTimers() + }) + + it.each([ + // Props + ['with modelValue', { props: { modelValue: new CalendarDate(2025, 1, 1) } }], + ['with default value', { props: { defaultValue: new CalendarDate(2025, 1, 1) } }], + ['with range', { props: { range: true } }], + ['with multiple', { props: { multiple: true } }], + ['with disabled', { props: { disabled: true } }], + ['with readonly', { props: { readonly: true } }], + ['with isDateDisabled', { props: { isDateDisabled: () => true } }], + ['with isDateUnavailable', { props: { isDateUnavailable: () => true } }], + ['with weekStartsOn', { props: { weekStartsOn: 1 } }], + ['with weekdayFormat', { props: { weekdayFormat: 'short' } }], + ['with numberOfMonths', { props: { numberOfMonths: 2 } }], + ['without fixedWeeks', { props: { fixedWeeks: false } }], + ['without monthControls', { props: { monthControls: false } }], + ['without yearControls', { props: { yearControls: false } }], + ...sizes.map((size: string) => [`with size ${size}`, { props: { size } }]), + ['with color neutral', { props: { color: 'neutral' } }], + ['with as', { props: { as: 'section' } }], + ['with class', { props: { class: 'max-w-sm' } }], + ['with ui', { props: { ui: { header: 'gap-4' } } }], + // Slots + ['with heading slot', { slots: { heading: () => 'Heading' } }], + ['with day slot', { slots: { day: ({ day }: Parameters[0]) => day.day } }], + ['with week-day slot', { slots: { 'week-day': ({ day }: Parameters[0]) => day } }] + ])('renders %s correctly', async (nameOrHtml: string, options: { props?: CalendarProps, slots?: Partial }) => { + const html = await ComponentRender(nameOrHtml, options, Calendar) + expect(html).toMatchSnapshot() + }) + + describe('emits', () => { + test('update:modelValue event single', async () => { + const wrapper = await mountSuspended(Calendar) + const date = new CalendarDate(2025, 1, 1) + + await wrapper.setValue(date) + expect(wrapper.emitted()).toMatchObject({ 'update:modelValue': [[date]] }) + }) + + test('update:modelValue event range', async () => { + const wrapper = await mountSuspended(Calendar, { props: { range: true } }) + const date = [new CalendarDate(2025, 1, 1), new CalendarDate(2025, 1, 2)] + + await wrapper.setValue(date) + expect(wrapper.emitted()).toMatchObject({ 'update:modelValue': [[date]] }) + }) + }) +}) diff --git a/test/components/__snapshots__/Calendar-vue.spec.ts.snap b/test/components/__snapshots__/Calendar-vue.spec.ts.snap new file mode 100644 index 0000000000..08c9c7823e --- /dev/null +++ b/test/components/__snapshots__/Calendar-vue.spec.ts.snap @@ -0,0 +1,4751 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Calendar > renders with as correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with class correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with color neutral correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with day slot correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with default value correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with disabled correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with heading slot correctly 1`] = ` +"
+
+
Heading
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with isDateDisabled correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with isDateUnavailable correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with modelValue correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with multiple correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with numberOfMonths correctly 1`] = ` +"
+
+
January - February 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January - February 2025
+
+
" +`; + +exports[`Calendar > renders with range correctly 1`] = ` +"
+
+
Event Date, January 2025
+
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
" +`; + +exports[`Calendar > renders with readonly correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size lg correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size md correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size sm correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size xl correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size xs correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with ui correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with week-day slot correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with weekStartsOn correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with weekdayFormat correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without fixedWeeks correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without monthControls correctly 1`] = ` +"
+
+ +
January 2025
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without yearControls correctly 1`] = ` +"
+
+ +
January 2025
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; diff --git a/test/components/__snapshots__/Calendar.spec.ts.snap b/test/components/__snapshots__/Calendar.spec.ts.snap new file mode 100644 index 0000000000..a7be8df9dc --- /dev/null +++ b/test/components/__snapshots__/Calendar.spec.ts.snap @@ -0,0 +1,4751 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Calendar > renders with as correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with class correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with color neutral correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with day slot correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with default value correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with disabled correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with heading slot correctly 1`] = ` +"
+
+
Heading
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with isDateDisabled correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with isDateUnavailable correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with modelValue correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with multiple correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with numberOfMonths correctly 1`] = ` +"
+
+
January - February 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January - February 2025
+
+
" +`; + +exports[`Calendar > renders with range correctly 1`] = ` +"
+
+
Event Date, January 2025
+
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
" +`; + +exports[`Calendar > renders with readonly correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size lg correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size md correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size sm correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size xl correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with size xs correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with ui correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with week-day slot correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with weekStartsOn correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders with weekdayFormat correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without fixedWeeks correctly 1`] = ` +"
+
+
January 2025
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without monthControls correctly 1`] = ` +"
+
+ +
January 2025
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`; + +exports[`Calendar > renders without yearControls correctly 1`] = ` +"
+
+ +
January 2025
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
9
+
+
10
+
+
11
+
+
12
+
+
13
+
+
14
+
+
15
+
+
16
+
+
17
+
+
18
+
+
19
+
+
20
+
+
21
+
+
22
+
+
23
+
+
24
+
+
25
+
+
26
+
+
27
+
+
28
+
+
29
+
+
30
+
+
31
+
+
1
+
+
2
+
+
3
+
+
4
+
+
5
+
+
6
+
+
7
+
+
8
+
+
+
+
Event Date, January 2025
+
+
" +`;