@react-aria/calendar 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,16 +12,15 @@
12
12
 
13
13
  import {announce} from '@react-aria/live-announcer';
14
14
  import {AriaButtonProps} from '@react-types/button';
15
- import {AriaLabelingProps, DOMAttributes} from '@react-types/shared';
15
+ import {AriaLabelingProps, DOMAttributes, DOMProps} from '@react-types/shared';
16
16
  import {CalendarPropsBase} from '@react-types/calendar';
17
17
  import {CalendarState, RangeCalendarState} from '@react-stately/calendar';
18
- import {DOMProps} from '@react-types/shared';
19
18
  import {filterDOMProps, mergeProps, useLabels, useSlotId, useUpdateEffect} from '@react-aria/utils';
20
19
  import {hookData, useSelectedDateDescription, useVisibleRangeDescription} from './utils';
21
20
  // @ts-ignore
22
21
  import intlMessages from '../intl/*.json';
23
22
  import {useLocalizedStringFormatter} from '@react-aria/i18n';
24
- import {useRef} from 'react';
23
+ import {useState} from 'react';
25
24
 
26
25
  export interface CalendarAria {
27
26
  /** Props for the calendar grouping element. */
@@ -71,17 +70,17 @@ export function useCalendarBase(props: CalendarPropsBase & DOMProps & AriaLabeli
71
70
  });
72
71
 
73
72
  // If the next or previous buttons become disabled while they are focused, move focus to the calendar body.
74
- let nextFocused = useRef(false);
73
+ let [nextFocused, setNextFocused] = useState(false);
75
74
  let nextDisabled = props.isDisabled || state.isNextVisibleRangeInvalid();
76
- if (nextDisabled && nextFocused.current) {
77
- nextFocused.current = false;
75
+ if (nextDisabled && nextFocused) {
76
+ setNextFocused(false);
78
77
  state.setFocused(true);
79
78
  }
80
79
 
81
- let previousFocused = useRef(false);
80
+ let [previousFocused, setPreviousFocused] = useState(false);
82
81
  let previousDisabled = props.isDisabled || state.isPreviousVisibleRangeInvalid();
83
- if (previousDisabled && previousFocused.current) {
84
- previousFocused.current = false;
82
+ if (previousDisabled && previousFocused) {
83
+ setPreviousFocused(false);
85
84
  state.setFocused(true);
86
85
  }
87
86
 
@@ -93,22 +92,20 @@ export function useCalendarBase(props: CalendarPropsBase & DOMProps & AriaLabeli
93
92
 
94
93
  return {
95
94
  calendarProps: mergeProps(domProps, labelProps, {
96
- role: 'group',
95
+ role: 'application',
97
96
  'aria-describedby': props['aria-describedby'] || undefined
98
97
  }),
99
98
  nextButtonProps: {
100
99
  onPress: () => state.focusNextPage(),
101
100
  'aria-label': stringFormatter.format('next'),
102
101
  isDisabled: nextDisabled,
103
- onFocus: () => nextFocused.current = true,
104
- onBlur: () => nextFocused.current = false
102
+ onFocusChange: setNextFocused
105
103
  },
106
104
  prevButtonProps: {
107
105
  onPress: () => state.focusPreviousPage(),
108
106
  'aria-label': stringFormatter.format('previous'),
109
107
  isDisabled: previousDisabled,
110
- onFocus: () => previousFocused.current = true,
111
- onBlur: () => previousFocused.current = false
108
+ onFocusChange: setPreviousFocused
112
109
  },
113
110
  errorMessageProps: {
114
111
  id: errorMessageId
@@ -13,12 +13,11 @@
13
13
  import {CalendarDate, isEqualDay, isSameDay, isToday} from '@internationalized/date';
14
14
  import {CalendarState, RangeCalendarState} from '@react-stately/calendar';
15
15
  import {DOMAttributes} from '@react-types/shared';
16
- import {focusWithoutScrolling, getScrollParent, scrollIntoViewport, useDescription} from '@react-aria/utils';
16
+ import {focusWithoutScrolling, getScrollParent, mergeProps, scrollIntoViewport, useDeepMemo, useDescription} from '@react-aria/utils';
17
17
  import {getEraFormat, hookData} from './utils';
18
18
  import {getInteractionModality, usePress} from '@react-aria/interactions';
19
19
  // @ts-ignore
20
20
  import intlMessages from '../intl/*.json';
21
- import {mergeProps} from '@react-aria/utils';
22
21
  import {RefObject, useEffect, useMemo, useRef} from 'react';
23
22
  import {useDateFormatter, useLocalizedStringFormatter} from '@react-aria/i18n';
24
23
 
@@ -102,13 +101,7 @@ export function useCalendarCell(props: AriaCalendarCellProps, state: CalendarSta
102
101
 
103
102
  // For performance, reuse the same date object as before if the new date prop is the same.
104
103
  // This allows subsequent useMemo results to be reused.
105
- let lastDate = useRef(null);
106
- if (lastDate.current && isEqualDay(date, lastDate.current)) {
107
- date = lastDate.current;
108
- }
109
-
110
- lastDate.current = date;
111
-
104
+ date = useDeepMemo<CalendarDate>(date, isEqualDay);
112
105
  let nativeDate = useMemo(() => date.toDate(state.timeZone), [date, state.timeZone]);
113
106
 
114
107
  // aria-label should be localize Day of week, Month, Day and Year without Time.
@@ -289,8 +282,11 @@ export function useCalendarCell(props: AriaCalendarCellProps, state: CalendarSta
289
282
  // Scroll into view if navigating with a keyboard, otherwise
290
283
  // try not to shift the view under the user's mouse/finger.
291
284
  // If in a overlay, scrollIntoViewport will only cause scrolling
292
- // up to the overlay scroll body to prevent overlay shifting
293
- if (getInteractionModality() !== 'pointer') {
285
+ // up to the overlay scroll body to prevent overlay shifting.
286
+ // Also only scroll into view if the cell actually got focused.
287
+ // There are some cases where the cell might be disabled or inside,
288
+ // an inert container and we don't want to scroll then.
289
+ if (getInteractionModality() !== 'pointer' && document.activeElement === ref.current) {
294
290
  scrollIntoViewport(ref.current, {containingElement: getScrollParent(ref.current)});
295
291
  }
296
292
  }