( props: AriaCalendarCellProps, state: CalendarState<CalendarSelectionMode> | RangeCalendarState, ref: RefObject<HTMLElement | null> )
| 87 | * A calendar cell displays a date cell within a calendar grid which can be selected by the user. |
| 88 | */ |
| 89 | export function useCalendarCell( |
| 90 | props: AriaCalendarCellProps, |
| 91 | state: CalendarState<CalendarSelectionMode> | RangeCalendarState, |
| 92 | ref: RefObject<HTMLElement | null> |
| 93 | ): CalendarCellAria { |
| 94 | let {date, isDisabled} = props; |
| 95 | let {errorMessageId, selectedDateDescription} = hookData.get(state)!; |
| 96 | let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/calendar'); |
| 97 | let dateFormatter = useDateFormatter({ |
| 98 | weekday: 'long', |
| 99 | day: 'numeric', |
| 100 | month: 'long', |
| 101 | year: 'numeric', |
| 102 | era: getEraFormat(date), |
| 103 | timeZone: state.timeZone |
| 104 | }); |
| 105 | let isFocused = state.isCellFocused(date) && !props.isOutsideMonth; |
| 106 | isDisabled = isDisabled || state.isCellDisabled(date) || !!props.isOutsideMonth; |
| 107 | let isUnavailable = state.isCellUnavailable(date); |
| 108 | let isSelectable = !isDisabled && !isUnavailable; |
| 109 | let isSelected = state.isSelected(date) && isSelectable; |
| 110 | let isInvalid = false; |
| 111 | if (state.isValueInvalid) { |
| 112 | if ('highlightedRange' in state) { |
| 113 | isInvalid = |
| 114 | !state.anchorDate && |
| 115 | state.highlightedRange != null && |
| 116 | date.compare(state.highlightedRange.start) >= 0 && |
| 117 | date.compare(state.highlightedRange.end) <= 0; |
| 118 | } else if (Array.isArray(state.value)) { |
| 119 | isInvalid = state.value.some(value => isSameDay(value, date)); |
| 120 | } else if (state.value) { |
| 121 | isInvalid = isSameDay(state.value as CalendarDate, date); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | if (isInvalid && !isDisabled) { |
| 126 | isSelected = true; |
| 127 | } |
| 128 | |
| 129 | // For performance, reuse the same date object as before if the new date prop is the same. |
| 130 | // This allows subsequent useMemo results to be reused. |
| 131 | date = useDeepMemo<CalendarDate>(date, isEqualDay); |
| 132 | let nativeDate = useMemo(() => date.toDate(state.timeZone), [date, state.timeZone]); |
| 133 | |
| 134 | // aria-label should be localize Day of week, Month, Day and Year without Time. |
| 135 | let isDateToday = isToday(date, state.timeZone); |
| 136 | let label = useMemo(() => { |
| 137 | let label = ''; |
| 138 | |
| 139 | // If this is a range calendar, add a description of the full selected range |
| 140 | // to the first and last selected date. |
| 141 | if ( |
| 142 | 'highlightedRange' in state && |
| 143 | state.value && |
| 144 | !state.anchorDate && |
| 145 | (isSameDay(date, state.value.start) || isSameDay(date, state.value.end)) |
| 146 | ) { |
no test coverage detected