/* * Copyright 2020 Adobe. All rights reserved. * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ import {ActionButton} from '@react-spectrum/button'; import {AriaButtonProps} from '@react-types/button'; import {CalendarDate} from '@internationalized/date'; import {CalendarMonth} from './CalendarMonth'; import {CalendarPropsBase} from '@react-types/calendar'; import {CalendarState, RangeCalendarState} from '@react-stately/calendar'; import ChevronLeft from '@spectrum-icons/ui/ChevronLeftLarge'; import ChevronRight from '@spectrum-icons/ui/ChevronRightLarge'; import {classNames, useStyleProps} from '@react-spectrum/utils'; import {DOMProps, RefObject, StyleProps} from '@react-types/shared'; import {HelpText} from '@react-spectrum/label'; // @ts-ignore import intlMessages from '../intl/*.json'; import React, {HTMLAttributes, JSX} from 'react'; import styles from '@adobe/spectrum-css-temp/components/calendar/vars.css'; import {useDateFormatter, useLocale, useLocalizedStringFormatter} from '@react-aria/i18n'; import {VisuallyHidden} from '@react-aria/visually-hidden'; interface CalendarBaseProps extends CalendarPropsBase, DOMProps, StyleProps { state: T, visibleMonths?: number, calendarProps: HTMLAttributes, nextButtonProps: AriaButtonProps, prevButtonProps: AriaButtonProps, errorMessageProps: HTMLAttributes, calendarRef: RefObject } export function CalendarBase(props: CalendarBaseProps): JSX.Element { let { state, calendarProps, nextButtonProps, prevButtonProps, errorMessageProps, calendarRef: ref, visibleMonths = 1, firstDayOfWeek } = props; let {styleProps} = useStyleProps(props); let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/calendar'); let {direction} = useLocale(); let currentMonth = state.visibleRange.start; let monthDateFormatter = useDateFormatter({ month: 'long', year: 'numeric', era: currentMonth.calendar.identifier === 'gregory' && currentMonth.era === 'BC' ? 'short' : undefined, calendar: currentMonth.calendar.identifier, timeZone: state.timeZone }); let titles: JSX.Element[] = []; let calendars: JSX.Element[] = []; for (let i = 0; i < visibleMonths; i++) { let d = currentMonth.add({months: i}); titles.push(
{i === 0 && {direction === 'rtl' ? : } } {i === visibleMonths - 1 && {direction === 'rtl' ? : } }
); calendars.push( ); } return (
{/* Add a screen reader only description of the entire visible range rather than * a separate heading above each month grid. This is placed first in the DOM order * so that it is the first thing a touch screen reader user encounters. * In addition, VoiceOver on iOS does not announce the aria-label of the grid * elements, so the aria-label of the Calendar is included here as well. */}

{calendarProps['aria-label']}

{titles}
{calendars}
{/* For touch screen readers, add a visually hidden next button after the month grid * so it's easy to navigate after reaching the end without going all the way * back to the start of the month. */}
); } function getCurrentMonthName(date: CalendarDate, timezone: string, monthDateFormatter: ReturnType): string { if (date.calendar.getFormattableMonth) { date = date.calendar.getFormattableMonth(date); } return monthDateFormatter.format(date.toDate(timezone)); }