Blame view

天文台pc/tianwentai-ui/node_modules/react-day-picker/src/hooks/useDayRender/useDayRender.tsx 3.72 KB
bc518174   王天杨   提交两个项目文件
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  import { RefObject, useEffect } from 'react';
  
  import { isSameDay } from 'date-fns';
  
  import { ButtonProps } from 'components/Button';
  import { DayContent } from 'components/DayContent';
  import { useDayPicker } from 'contexts/DayPicker';
  import { useFocusContext } from 'contexts/Focus';
  import { useActiveModifiers } from 'hooks/useActiveModifiers';
  import {
    DayEventHandlers,
    useDayEventHandlers
  } from 'hooks/useDayEventHandlers';
  import { SelectedDays, useSelectedDays } from 'hooks/useSelectedDays';
  import { ActiveModifiers } from 'types/Modifiers';
  import { StyledComponent } from 'types/Styles';
  
  import { getDayClassNames } from './utils/getDayClassNames';
  import { getDayStyle } from './utils/getDayStyle';
  
  export type DayRender = {
    /** Whether the day should be rendered a `button` instead of a `div` */
    isButton: boolean;
    /** Whether the day should be hidden. */
    isHidden: boolean;
    /** The modifiers active for the given day. */
    activeModifiers: ActiveModifiers;
    /** The props to apply to the button element (when `isButton` is true). */
    buttonProps: StyledComponent &
      Pick<ButtonProps, 'disabled' | 'aria-selected' | 'tabIndex'> &
      DayEventHandlers;
    /** The props to apply to the div element (when `isButton` is false). */
    divProps: StyledComponent;
    selectedDays: SelectedDays;
  };
  
  /**
   * Return props and data used to render the {@link Day} component.
   *
   * Use this hook when creating a component to replace the built-in `Day`
   * component.
   */
  export function useDayRender(
    /** The date to render. */
    day: Date,
    /** The month where the date is displayed (if not the same as `date`, it means it is an "outside" day). */
    displayMonth: Date,
    /** A ref to the button element that will be target of focus when rendered (if required). */
    buttonRef: RefObject<HTMLButtonElement>
  ): DayRender {
    const dayPicker = useDayPicker();
    const focusContext = useFocusContext();
    const activeModifiers = useActiveModifiers(day, displayMonth);
    const eventHandlers = useDayEventHandlers(day, activeModifiers);
    const selectedDays = useSelectedDays();
    const isButton = Boolean(
      dayPicker.onDayClick || dayPicker.mode !== 'default'
    );
  
    // Focus the button if the day is focused according to the focus context
    useEffect(() => {
      if (activeModifiers.outside) return;
      if (!focusContext.focusedDay) return;
      if (!isButton) return;
      if (isSameDay(focusContext.focusedDay, day)) {
        buttonRef.current?.focus();
      }
    }, [
      focusContext.focusedDay,
      day,
      buttonRef,
      isButton,
      activeModifiers.outside
    ]);
  
    const className = getDayClassNames(dayPicker, activeModifiers).join(' ');
    const style = getDayStyle(dayPicker, activeModifiers);
    const isHidden = Boolean(
      (activeModifiers.outside && !dayPicker.showOutsideDays) ||
        activeModifiers.hidden
    );
  
    const DayContentComponent = dayPicker.components?.DayContent ?? DayContent;
    const children = (
      <DayContentComponent
        date={day}
        displayMonth={displayMonth}
        activeModifiers={activeModifiers}
      />
    );
  
    const divProps = {
      style,
      className,
      children,
      role: 'gridcell'
    };
  
    const isFocusTarget =
      focusContext.focusTarget &&
      isSameDay(focusContext.focusTarget, day) &&
      !activeModifiers.outside;
  
    const isFocused =
      focusContext.focusedDay && isSameDay(focusContext.focusedDay, day);
  
    const buttonProps = {
      ...divProps,
      disabled: activeModifiers.disabled,
      role: 'gridcell',
      ['aria-selected']: activeModifiers.selected,
      tabIndex: isFocused || isFocusTarget ? 0 : -1,
      ...eventHandlers
    };
  
    const dayRender: DayRender = {
      isButton,
      isHidden,
      activeModifiers: activeModifiers,
      selectedDays,
      buttonProps,
      divProps
    };
  
    return dayRender;
  }