diff --git a/packages/core/src/useCalendar/index.ts b/packages/core/src/useCalendar/index.ts index 86a2a2fd..84e2a208 100644 --- a/packages/core/src/useCalendar/index.ts +++ b/packages/core/src/useCalendar/index.ts @@ -1,4 +1,4 @@ export * from './useCalendar'; export * from './types'; export * from './useCalendarCell'; -export * from './useCalendarPanel'; +export * from './useCalendarView'; diff --git a/packages/core/src/useCalendar/types.ts b/packages/core/src/useCalendar/types.ts index b5cb0683..6dc7082b 100644 --- a/packages/core/src/useCalendar/types.ts +++ b/packages/core/src/useCalendar/types.ts @@ -37,7 +37,7 @@ export interface CalendarYearCell { export type CalendarCellProps = CalendarDayCell | CalendarMonthCell | CalendarYearCell; -export type CalendarPanelType = 'weeks' | 'months' | 'years'; +export type CalendarViewType = 'weeks' | 'months' | 'years'; export interface CalendarContext { locale: Ref; @@ -49,5 +49,5 @@ export interface CalendarContext { getMaxDate: () => Maybe; getFocusedDate: () => ZonedDateTime; setFocusedDate: (date: ZonedDateTime) => void; - setDate: (date: ZonedDateTime, panel?: CalendarPanelType) => void; + setDate: (date: ZonedDateTime, view?: CalendarViewType) => void; } diff --git a/packages/core/src/useCalendar/useCalendar.spec.ts b/packages/core/src/useCalendar/useCalendar.spec.ts index d8520809..19cd0765 100644 --- a/packages/core/src/useCalendar/useCalendar.spec.ts +++ b/packages/core/src/useCalendar/useCalendar.spec.ts @@ -9,11 +9,11 @@ describe('useCalendar', () => { test('calendar should not have accessibility violations', async () => { await render({ setup() { - const { pickerProps, gridProps, buttonProps, gridLabelProps, nextButtonProps, previousButtonProps } = + const { calendarProps, gridProps, buttonProps, gridLabelProps, nextButtonProps, previousButtonProps } = useCalendar({ label: 'Calendar' }); return { - pickerProps, + calendarProps, gridProps, buttonProps, gridLabelProps, @@ -23,7 +23,7 @@ describe('useCalendar', () => { }, template: `
-
+
Month Year
@@ -71,10 +71,10 @@ describe('useCalendar', () => { test('closes calendar when Escape is pressed', async () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps } = useCalendar({ label: 'Calendar' }); + const { calendarProps, isOpen, buttonProps } = useCalendar({ label: 'Calendar' }); return { - pickerProps, + calendarProps, isOpen, buttonProps, }; @@ -82,7 +82,7 @@ describe('useCalendar', () => { template: `
-
Calendar Content
+
Calendar Content
`, }); @@ -97,10 +97,10 @@ describe('useCalendar', () => { test('closes calendar when Tab is pressed', async () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, gridProps } = useCalendar({ label: 'Calendar' }); + const { calendarProps, isOpen, buttonProps, gridProps } = useCalendar({ label: 'Calendar' }); return { - pickerProps, + calendarProps, isOpen, buttonProps, gridProps, @@ -109,7 +109,7 @@ describe('useCalendar', () => { template: `
-
+
Calendar Content
@@ -126,22 +126,21 @@ describe('useCalendar', () => { describe('date selection', () => { test('calls onUpdateModelValue when a date is selected', async () => { - const onUpdateModelValue = vi.fn(); const currentDate = now('UTC'); - await render({ + const vm = await render({ components: { CalendarCell, }, setup() { - const { pickerProps, buttonProps } = useCalendar({ + const { calendarProps, buttonProps } = useCalendar({ label: 'Calendar', - onUpdateModelValue, - modelValue: currentDate, + timeZone: 'UTC', + modelValue: currentDate.toDate(), }); return { - pickerProps, + calendarProps, buttonProps, currentDate, }; @@ -149,7 +148,7 @@ describe('useCalendar', () => { template: `
-
+
@@ -159,7 +158,7 @@ describe('useCalendar', () => { await flush(); await fireEvent.click(screen.getByText('Select Date')); await flush(); - expect(onUpdateModelValue).toHaveBeenCalledWith(currentDate); + expect(vm.emitted('update:modelValue')[0]).toEqual([currentDate.toDate()]); }); test('uses provided calendar type', async () => { @@ -188,22 +187,21 @@ describe('useCalendar', () => { }); test('handles Enter key on calendar cell', async () => { - const onUpdateModelValue = vi.fn(); const currentDate = now('UTC'); - await render({ + const vm = await render({ components: { CalendarCell, }, setup() { - const { pickerProps, buttonProps, isOpen, focusedDate } = useCalendar({ + const { calendarProps, buttonProps, isOpen, focusedDate } = useCalendar({ label: 'Calendar', - onUpdateModelValue, - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, buttonProps, isOpen, focusedDate, @@ -213,7 +211,7 @@ describe('useCalendar', () => { template: `
-
+
{ // Test Enter key selects the date await fireEvent.keyDown(cell, { code: 'Enter' }); - expect(onUpdateModelValue).toHaveBeenCalledWith(currentDate); + expect(vm.emitted('update:modelValue')[0]).toEqual([currentDate.toDate()]); expect(screen.queryByText(currentDate.toString())).not.toBeInTheDocument(); // Calendar should close after selection }); test('handles Enter key in different panels', async () => { - const onUpdateModelValue = vi.fn(); const currentDate = now('UTC'); - await render({ + const vm = await render({ setup() { - const { pickerProps, buttonProps, isOpen, focusedDate, gridLabelProps, currentPanel } = useCalendar({ + const { calendarProps, buttonProps, isOpen, focusedDate, gridLabelProps, currentView } = useCalendar({ label: 'Calendar', - onUpdateModelValue, - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, buttonProps, isOpen, focusedDate, gridLabelProps, - currentPanel, + currentView, }; }, template: `
-
{{ currentPanel.type }}
-
+
{{ currentView.type }}
+
{{ focusedDate?.toString() }}
@@ -276,7 +273,7 @@ describe('useCalendar', () => { // Test Enter in day panel await fireEvent.keyDown(calendar, { code: 'Enter' }); - expect(onUpdateModelValue).toHaveBeenCalledWith(currentDate); + expect(vm.emitted('update:modelValue')[0]).toEqual([currentDate.toDate()]); // Switch to month panel await fireEvent.click(panelLabel); @@ -295,16 +292,16 @@ describe('useCalendar', () => { test('switches between day, month, and year panels', async () => { await render({ setup() { - const { gridLabelProps, currentPanel } = useCalendar({ label: 'Calendar' }); + const { gridLabelProps, currentView } = useCalendar({ label: 'Calendar' }); return { gridLabelProps, - currentPanel, + currentView, }; }, template: `
-
{{ currentPanel.type }}
+
{{ currentView.type }}
`, }); @@ -321,25 +318,22 @@ describe('useCalendar', () => { }); test('navigates to next/previous panels', async () => { - const onUpdateModelValue = vi.fn(); - await render({ setup() { - const { nextButtonProps, previousButtonProps, currentPanel } = useCalendar({ + const { nextButtonProps, previousButtonProps, currentView } = useCalendar({ label: 'Calendar', - onUpdateModelValue, }); return { nextButtonProps, previousButtonProps, - currentPanel, + currentView, }; }, template: `
-
{{ currentPanel.type }}
+
{{ currentView.type }}
`, @@ -363,12 +357,13 @@ describe('useCalendar', () => { previousButtonProps, gridLabelProps, focusedDate, - pickerProps, + calendarProps, isOpen, buttonProps, } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { @@ -376,7 +371,7 @@ describe('useCalendar', () => { previousButtonProps, gridLabelProps, focusedDate, - pickerProps, + calendarProps, isOpen, buttonProps, }; @@ -384,7 +379,7 @@ describe('useCalendar', () => { template: `
-
+
Month Panel
@@ -428,12 +423,13 @@ describe('useCalendar', () => { previousButtonProps, gridLabelProps, focusedDate, - pickerProps, + calendarProps, isOpen, buttonProps, } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { @@ -441,7 +437,7 @@ describe('useCalendar', () => { previousButtonProps, gridLabelProps, focusedDate, - pickerProps, + calendarProps, isOpen, buttonProps, }; @@ -449,7 +445,7 @@ describe('useCalendar', () => { template: `
-
+
Year Panel
@@ -495,13 +491,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, selectedDate, focusedDate } = useCalendar({ + const { calendarProps, isOpen, buttonProps, selectedDate, focusedDate } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, selectedDate, @@ -511,7 +508,7 @@ describe('useCalendar', () => { template: `
-
+
{{ focusedDate?.toString() }}
@@ -562,13 +559,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, selectedDate, focusedDate, gridLabelProps } = useCalendar({ + const { calendarProps, isOpen, buttonProps, selectedDate, focusedDate, gridLabelProps } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, selectedDate, @@ -579,7 +577,7 @@ describe('useCalendar', () => { template: `
-
+
Month Panel
{{ focusedDate?.toString() }}
@@ -635,13 +633,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, selectedDate, focusedDate, gridLabelProps } = useCalendar({ + const { calendarProps, isOpen, buttonProps, selectedDate, focusedDate, gridLabelProps } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, selectedDate, @@ -652,7 +651,7 @@ describe('useCalendar', () => { template: `
-
+
Year Panel
{{ focusedDate?.toString() }}
@@ -709,15 +708,16 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, selectedDate, focusedDate } = useCalendar({ + const { calendarProps, isOpen, buttonProps, selectedDate, focusedDate } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', minDate, maxDate, }); return { - pickerProps, + calendarProps, isOpen, buttonProps, selectedDate, @@ -727,7 +727,7 @@ describe('useCalendar', () => { template: `
-
+
{{ focusedDate?.toString() }}
@@ -753,13 +753,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, focusedDate } = useCalendar({ + const { calendarProps, isOpen, buttonProps, focusedDate } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, focusedDate, @@ -768,7 +769,7 @@ describe('useCalendar', () => { template: `
-
+
{{ focusedDate?.toString() }}
@@ -807,13 +808,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, focusedDate, gridLabelProps } = useCalendar({ + const { calendarProps, isOpen, buttonProps, focusedDate, gridLabelProps } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, focusedDate, @@ -823,7 +825,7 @@ describe('useCalendar', () => { template: `
-
+
Month Panel
{{ focusedDate?.toString() }}
@@ -853,13 +855,14 @@ describe('useCalendar', () => { await render({ setup() { - const { pickerProps, isOpen, buttonProps, focusedDate, gridLabelProps } = useCalendar({ + const { calendarProps, isOpen, buttonProps, focusedDate, gridLabelProps } = useCalendar({ label: 'Calendar', - modelValue: currentDate, + modelValue: currentDate.toDate(), + timeZone: 'UTC', }); return { - pickerProps, + calendarProps, isOpen, buttonProps, focusedDate, @@ -869,7 +872,7 @@ describe('useCalendar', () => { template: `
-
+
Month Panel
{{ focusedDate?.toString() }}
diff --git a/packages/core/src/useCalendar/useCalendar.ts b/packages/core/src/useCalendar/useCalendar.ts index 3c4318c8..7a3393e6 100644 --- a/packages/core/src/useCalendar/useCalendar.ts +++ b/packages/core/src/useCalendar/useCalendar.ts @@ -1,7 +1,7 @@ import { computed, nextTick, provide, Ref, ref, shallowRef, toValue, watch } from 'vue'; -import { CalendarContext, CalendarPanelType } from './types'; +import { CalendarContext, CalendarViewType } from './types'; import { hasKeyCode, normalizeProps, useUniqId, withRefCapture } from '../utils/common'; -import { Maybe, Reactivify } from '../types'; +import { Maybe, Reactivify, StandardSchema } from '../types'; import { useLocale } from '../i18n'; import { FieldTypePrefixes } from '../constants'; import { usePopoverController } from '../helpers/usePopoverController'; @@ -9,8 +9,12 @@ import { blockEvent } from '../utils/events'; import { useLabel } from '../a11y'; import { useControlButtonProps } from '../helpers/useControlButtonProps'; import { CalendarContextKey, YEAR_CELLS_COUNT } from './constants'; -import { CalendarPanel, useCalendarPanel } from './useCalendarPanel'; +import { CalendarView, useCalendarView } from './useCalendarView'; import { Calendar, ZonedDateTime, now, toCalendar } from '@internationalized/date'; +import { createDisabledContext } from '../helpers/createDisabledContext'; +import { exposeField, FormField, useFormField } from '../useFormField'; +import { useInputValidity } from '../validation'; +import { useTemporalStore } from '../useDateTimeField/useTemporalStore'; export interface CalendarProps { /** @@ -31,23 +35,33 @@ export interface CalendarProps { /** * The current date to use for the calendar. */ - modelValue?: ZonedDateTime; + modelValue?: Date; /** * The initial value to use for the calendar. */ - value?: ZonedDateTime; + value?: Date; /** * The calendar type to use for the calendar, e.g. `gregory`, `islamic-umalqura`, etc. */ calendar?: Calendar; + /** + * The time zone to use for the calendar. + */ + timeZone?: string; + /** * Whether the calendar is disabled. */ disabled?: boolean; + /** + * Whether the calendar is readonly. + */ + readonly?: boolean; + /** * The label for the next month button. */ @@ -84,30 +98,60 @@ export interface CalendarProps { yearFormat?: Intl.DateTimeFormatOptions['year']; /** - * The available panels to switch to and from in the calendar. + * The available views to switch to and from in the calendar. */ - allowedPanels?: CalendarPanelType[]; + allowedViews?: CalendarViewType[]; /** - * The callback to call when the calendar value is updated. + * The form field to use for the calendar. */ - onUpdateModelValue?: (value: ZonedDateTime) => void; + field?: FormField; + + /** + * The schema to use for the calendar. + */ + schema?: StandardSchema; } -export function useCalendar(_props: Reactivify) { - const props = normalizeProps(_props, ['onUpdateModelValue']); +export function useCalendar(_props: Reactivify) { + const props = normalizeProps(_props, ['field', 'schema']); + const { weekInfo, locale, calendar, timeZone } = useLocale(props.locale, { + calendar: () => toValue(props.calendar), + timeZone: () => toValue(props.timeZone), + }); const calendarId = useUniqId(FieldTypePrefixes.Calendar); const gridId = `${calendarId}-g`; - const pickerEl = ref(); + const calendarEl = ref(); const gridEl = ref(); const calendarLabelEl = ref(); - const { weekInfo, locale, calendar, timeZone } = useLocale(props.locale, { - calendar: () => toValue(props.calendar), + const field = + props.field ?? + useFormField>({ + path: props.name, + disabled: props.disabled, + initialValue: toValue(props.modelValue) ?? toValue(props.value), + schema: props.schema, + }); + + const temporalValue = useTemporalStore({ + calendar: calendar, + timeZone: timeZone, + locale: locale, + model: { + get: () => field.fieldValue.value, + set: value => field.setValue(value), + }, }); - const selectedDate = computed(() => toValue(props.modelValue) ?? toCalendar(now(toValue(timeZone)), calendar.value)); + // If no controlling field is provided, we should hook up the required hooks to promote the calender to a full form field. + if (!props.field) { + useInputValidity({ field }); + } + + const isDisabled = createDisabledContext(props.disabled); + const selectedDate = computed(() => temporalValue.value ?? toCalendar(now(toValue(timeZone)), calendar.value)); const focusedDay = shallowRef(); - const { isOpen } = usePopoverController(pickerEl, { disabled: props.disabled }); + const { isOpen } = usePopoverController(calendarEl, { disabled: props.disabled }); function getFocusedOrSelected() { if (focusedDay.value) { @@ -124,15 +168,7 @@ export function useCalendar(_props: Reactivify selectedDate.value, getFocusedDate: getFocusedOrSelected, - setDate: (date: ZonedDateTime, panel?: CalendarPanelType) => { - props.onUpdateModelValue?.(date); - if (panel) { - switchPanel(panel); - } else if (currentPanel.value.type === 'weeks') { - // Automatically close the calendar when a day is selected - isOpen.value = false; - } - }, + setDate, setFocusedDate: async (date: ZonedDateTime) => { focusedDay.value = date; await nextTick(); @@ -145,10 +181,10 @@ export function useCalendar(_props: Reactivify ({ onClick: () => { isOpen.value = true; @@ -195,7 +241,7 @@ export function useCalendar(_props: Reactivify { if (!value) { focusedDay.value = undefined; - switchPanel('weeks'); + setView('weeks'); return; } @@ -207,49 +253,51 @@ export function useCalendar(_props: Reactivify { + const calendarProps = computed(() => { return withRefCapture( { id: calendarId, ...pickerHandlers, }, - pickerEl, + calendarEl, ); }); const nextButtonProps = useControlButtonProps(() => ({ id: `${calendarId}-next`, 'aria-label': 'Next', + disabled: isDisabled.value, onClick: () => { - if (currentPanel.value.type === 'weeks') { + if (currentView.value.type === 'weeks') { context.setFocusedDate(context.getFocusedDate().add({ months: 1 })); return; } - if (currentPanel.value.type === 'months') { + if (currentView.value.type === 'months') { context.setFocusedDate(context.getFocusedDate().add({ years: 1 })); return; } - context.setFocusedDate(currentPanel.value.years[currentPanel.value.years.length - 1].value.add({ years: 1 })); + context.setFocusedDate(currentView.value.years[currentView.value.years.length - 1].value.add({ years: 1 })); }, })); const previousButtonProps = useControlButtonProps(() => ({ id: `${calendarId}-previous`, 'aria-label': 'Previous', + disabled: isDisabled.value, onClick: () => { - if (currentPanel.value.type === 'weeks') { + if (currentView.value.type === 'weeks') { context.setFocusedDate(context.getFocusedDate().subtract({ months: 1 })); return; } - if (currentPanel.value.type === 'months') { + if (currentView.value.type === 'months') { context.setFocusedDate(context.getFocusedDate().subtract({ years: 1 })); return; } - context.setFocusedDate(currentPanel.value.years[0].value.subtract({ years: 1 })); + context.setFocusedDate(currentView.value.years[0].value.subtract({ years: 1 })); }, })); @@ -259,8 +307,8 @@ export function useCalendar(_props: Reactivify { @@ -270,17 +318,21 @@ export function useCalendar(_props: Reactivify { - if (currentPanel.value.type === 'weeks') { - if (isAllowedPanel('months')) { - switchPanel('months'); + if (isDisabled.value) { + return; + } + + if (currentView.value.type === 'weeks') { + if (isAllowedView('months')) { + setView('months'); } return; } - if (currentPanel.value.type === 'months') { - if (isAllowedPanel('years')) { - switchPanel('years'); + if (currentView.value.type === 'months') { + if (isAllowedView('years')) { + setView('years'); } return; @@ -302,56 +354,59 @@ export function useCalendar(_props: Reactivify) { +export function useCalendarKeyboard(context: CalendarContext, currentPanel: Ref) { function withCheckedBounds(fn: () => ZonedDateTime | undefined) { const date = fn(); if (!date) { diff --git a/packages/core/src/useCalendar/useCalendarPanel.ts b/packages/core/src/useCalendar/useCalendarView.ts similarity index 83% rename from packages/core/src/useCalendar/useCalendarPanel.ts rename to packages/core/src/useCalendar/useCalendarView.ts index 650e6c06..4f141fdf 100644 --- a/packages/core/src/useCalendar/useCalendarPanel.ts +++ b/packages/core/src/useCalendar/useCalendarView.ts @@ -1,30 +1,30 @@ import { computed, MaybeRefOrGetter, shallowRef, toValue } from 'vue'; -import { CalendarContext, CalendarDayCell, CalendarMonthCell, CalendarPanelType, CalendarYearCell } from './types'; +import { CalendarContext, CalendarDayCell, CalendarMonthCell, CalendarViewType, CalendarYearCell } from './types'; import { useDateFormatter } from '../i18n'; import { Reactivify } from '../types'; import { normalizeProps } from '../utils/common'; import { YEAR_CELLS_COUNT } from './constants'; import { now, toCalendar } from '@internationalized/date'; -export interface CalendarWeeksPanel { +export interface CalendarWeeksView { type: 'weeks'; days: CalendarDayCell[]; weekDays: string[]; } -export interface CalendarMonthsPanel { +export interface CalendarMonthsView { type: 'months'; months: CalendarMonthCell[]; } -export interface CalendarYearsPanel { +export interface CalendarYearsView { type: 'years'; years: CalendarYearCell[]; } -export type CalendarPanel = CalendarWeeksPanel | CalendarMonthsPanel | CalendarYearsPanel; +export type CalendarView = CalendarWeeksView | CalendarMonthsView | CalendarYearsView; -export interface CalendarPanelProps { +export interface CalendarViewProps { /** * The format option for the days of the week. */ @@ -41,55 +41,55 @@ export interface CalendarPanelProps { yearFormat?: Intl.DateTimeFormatOptions['year']; } -export function useCalendarPanel(_props: Reactivify, context: CalendarContext) { +export function useCalendarView(_props: Reactivify, context: CalendarContext) { const props = normalizeProps(_props); - const panelType = shallowRef('weeks'); - const { days, weekDays } = useCalendarDaysPanel(context, props.weekDayFormat); - const { months, monthFormatter } = useCalendarMonthsPanel(context, props.monthFormat); - const { years, yearFormatter } = useCalendarYearsPanel(context, props.yearFormat); + const viewType = shallowRef('weeks'); + const { days, weekDays } = useCalendarDaysView(context, props.weekDayFormat); + const { months, monthFormatter } = useCalendarMonthsView(context, props.monthFormat); + const { years, yearFormatter } = useCalendarYearsView(context, props.yearFormat); - const currentPanel = computed(() => { - if (panelType.value === 'weeks') { + const currentView = computed(() => { + if (viewType.value === 'weeks') { return { type: 'weeks', days: days.value, weekDays: weekDays.value, - } as CalendarWeeksPanel; + } as CalendarWeeksView; } - if (panelType.value === 'months') { + if (viewType.value === 'months') { return { type: 'months', months: months.value, - } as CalendarMonthsPanel; + } as CalendarMonthsView; } return { type: 'years', years: years.value, - } as CalendarYearsPanel; + } as CalendarYearsView; }); - function switchPanel(type: CalendarPanelType) { - panelType.value = type; + function setView(type: CalendarViewType) { + viewType.value = type; } - const panelLabel = computed(() => { - if (panelType.value === 'weeks') { + const viewLabel = computed(() => { + if (viewType.value === 'weeks') { return `${monthFormatter.value.format(context.getFocusedDate().toDate())} ${yearFormatter.value.format(context.getFocusedDate().toDate())}`; } - if (panelType.value === 'months') { + if (viewType.value === 'months') { return yearFormatter.value.format(context.getFocusedDate().toDate()); } return `${yearFormatter.value.format(years.value[0].value.toDate())} - ${yearFormatter.value.format(years.value[years.value.length - 1].value.toDate())}`; }); - return { currentPanel, switchPanel, panelLabel }; + return { currentView, setView, viewLabel }; } -function useCalendarDaysPanel( +function useCalendarDaysView( { weekInfo, getFocusedDate, getSelectedDate, locale, timeZone, calendar, getMinDate, getMaxDate }: CalendarContext, daysOfWeekFormat?: MaybeRefOrGetter, ) { @@ -163,7 +163,7 @@ function useCalendarDaysPanel( return { days, weekDays, dayFormatter }; } -function useCalendarMonthsPanel( +function useCalendarMonthsView( { getFocusedDate, locale, getSelectedDate, getMinDate, getMaxDate }: CalendarContext, monthFormat?: MaybeRefOrGetter, ) { @@ -204,7 +204,7 @@ function useCalendarMonthsPanel( return { months, monthFormatter }; } -function useCalendarYearsPanel( +function useCalendarYearsView( { getFocusedDate, locale, getSelectedDate, getMinDate, getMaxDate }: CalendarContext, yearFormat?: MaybeRefOrGetter, ) { diff --git a/packages/core/src/useDateTimeField/useDateTimeField.ts b/packages/core/src/useDateTimeField/useDateTimeField.ts index 95b55dc8..5763402f 100644 --- a/packages/core/src/useDateTimeField/useDateTimeField.ts +++ b/packages/core/src/useDateTimeField/useDateTimeField.ts @@ -167,15 +167,14 @@ export function useDateTimeField(_props: Reactivify = { + const calendarProps: Reactivify = { label: props.label, locale: () => locale.value, name: undefined, - modelValue: temporalValue, calendar: calendar, - onUpdateModelValue: onValueChange, minDate: () => (isTemporalPartial(minDate.value) ? undefined : minDate.value), maxDate: () => (isTemporalPartial(maxDate.value) ? undefined : maxDate.value), + field, }; const controlProps = computed(() => {