react-day-picker 8.1.2 → 8.2.0

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.
Files changed (56) hide show
  1. package/dist/components/Button/Button.d.ts +1 -1
  2. package/dist/components/DayContent/DayContent.d.ts +1 -3
  3. package/dist/components/Dropdown/Dropdown.d.ts +4 -0
  4. package/dist/components/Head/Head.d.ts +1 -3
  5. package/dist/components/HeadRow/HeadRow.d.ts +4 -0
  6. package/dist/components/HeadRow/index.d.ts +1 -0
  7. package/dist/components/HeadRow/utils/getWeekdays.d.ts +8 -0
  8. package/{src/components/Head/utils/index.ts → dist/components/HeadRow/utils/index.d.ts} +0 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.esm.js +37 -27
  11. package/dist/index.esm.js.map +1 -1
  12. package/dist/index.js +37 -26
  13. package/dist/index.js.map +1 -1
  14. package/dist/react-day-picker.min.js +1 -1
  15. package/dist/style.css +14 -7
  16. package/dist/style.module.css +14 -7
  17. package/dist/types/DayPickerBase.d.ts +5 -3
  18. package/dist/types/DayPickerMultiple.d.ts +1 -1
  19. package/dist/types/DayPickerRange.d.ts +1 -1
  20. package/package.json +1 -1
  21. package/src/components/Day/Day.test.tsx +2 -1
  22. package/src/components/Day/Day.tsx +1 -1
  23. package/src/components/DayContent/DayContent.test.tsx +1 -13
  24. package/src/components/DayContent/DayContent.tsx +2 -14
  25. package/src/components/Dropdown/Dropdown.test.tsx +1 -0
  26. package/src/components/Dropdown/Dropdown.tsx +5 -0
  27. package/src/components/Head/Head.test.tsx +13 -63
  28. package/src/components/Head/Head.tsx +5 -41
  29. package/src/components/HeadRow/HeadRow.test.tsx +109 -0
  30. package/src/components/HeadRow/HeadRow.tsx +49 -0
  31. package/src/components/HeadRow/index.ts +1 -0
  32. package/src/components/{Head → HeadRow}/utils/getWeekdays.test.ts +0 -0
  33. package/src/components/{Head → HeadRow}/utils/getWeekdays.ts +0 -0
  34. package/src/components/HeadRow/utils/index.ts +1 -0
  35. package/src/components/MonthsDropdown/MonthsDropdown.test.tsx +11 -1
  36. package/src/components/MonthsDropdown/MonthsDropdown.tsx +1 -0
  37. package/src/components/MonthsDropdown/__snapshots__/MonthsDropdown.test.tsx.snap +48 -0
  38. package/src/components/Navigation/Navigation.test.tsx +6 -0
  39. package/src/components/Navigation/Navigation.tsx +2 -0
  40. package/src/components/Table/Table.test.tsx +2 -2
  41. package/src/components/Table/__snapshots__/Table.test.tsx.snap +122 -586
  42. package/src/components/WeekNumber/WeekNumber.test.tsx +9 -2
  43. package/src/components/WeekNumber/WeekNumber.tsx +1 -0
  44. package/src/components/WeekNumber/__snapshots__/WeekNumber.test.tsx.snap +10 -1
  45. package/src/components/YearsDropdown/YearsDropdown.test.tsx +11 -1
  46. package/src/components/YearsDropdown/YearsDropdown.tsx +1 -0
  47. package/src/components/YearsDropdown/__snapshots__/YearsDropdown.test.tsx.snap +43 -0
  48. package/src/hooks/useDayEventHandlers/useDayEventHandlers.test.tsx +6 -3
  49. package/src/hooks/useDayEventHandlers/useDayEventHandlers.tsx +2 -1
  50. package/src/hooks/useDayRender/useDayRender.tsx +6 -2
  51. package/src/hooks/useInput/useInput.ts +2 -2
  52. package/src/index.ts +1 -0
  53. package/src/style.css +14 -7
  54. package/src/types/DayPickerBase.ts +5 -3
  55. package/src/types/DayPickerMultiple.ts +1 -1
  56. package/src/types/DayPickerRange.ts +1 -1
@@ -27,12 +27,19 @@ describe('without "onWeekNumberClick" prop', () => {
27
27
 
28
28
  describe('with "onWeekNumberClick" prop', () => {
29
29
  const dayPickerProps: DayPickerProps = { onWeekNumberClick: jest.fn() };
30
- const { container } = setup(props, dayPickerProps);
30
+ let container: HTMLElement;
31
+ beforeEach(() => {
32
+ container = setup(props, dayPickerProps).container;
33
+ });
31
34
  test('it should return a button element', () => {
35
+ expect(screen.getByRole('button')).toBeInTheDocument();
36
+ expect(container.firstChild).toHaveAttribute('name', 'week-number');
32
37
  expect(container.firstChild).toMatchSnapshot();
33
38
  });
34
39
  describe('when the button element is clicked', () => {
35
- userEvent.click(screen.getByRole('button'));
40
+ beforeEach(async () => {
41
+ await userEvent.click(screen.getByRole('button'));
42
+ });
36
43
  test('should call onWeekNumberClick', () => {
37
44
  expect(dayPickerProps.onWeekNumberClick).toHaveBeenCalledWith(
38
45
  props.number,
@@ -47,6 +47,7 @@ export function WeekNumber(props: WeekNumberProps): JSX.Element {
47
47
 
48
48
  return (
49
49
  <Button
50
+ name="week-number"
50
51
  aria-label={label}
51
52
  className={classNames.weeknumber}
52
53
  style={styles.weeknumber}
@@ -1,6 +1,15 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`with "onWeekNumberClick" prop it should return a button element 1`] = `null`;
3
+ exports[`with "onWeekNumberClick" prop it should return a button element 1`] = `
4
+ <button
5
+ aria-label="Week n. 10"
6
+ class="rdp-button_reset rdp-button rdp-weeknumber"
7
+ name="week-number"
8
+ type="button"
9
+ >
10
+ 10
11
+ </button>
12
+ `;
4
13
 
5
14
  exports[`without "onWeekNumberClick" prop it should return a span element 1`] = `
6
15
  <span
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  import { screen } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
5
- import { differenceInYears } from 'date-fns';
5
+ import { addMonths, differenceInYears } from 'date-fns';
6
6
  import { DayPickerProps } from 'DayPicker';
7
7
 
8
8
  import { customRender } from 'test/render';
@@ -30,6 +30,16 @@ const props: YearsDropdownProps = {
30
30
  onChange: jest.fn()
31
31
  };
32
32
 
33
+ describe('when fromDate and toDate are passed in', () => {
34
+ beforeEach(() => {
35
+ setup(props, { fromDate: new Date(), toDate: addMonths(new Date(), 1) });
36
+ });
37
+ test('should render the dropdown element', () => {
38
+ expect(root).toMatchSnapshot();
39
+ expect(select).toHaveAttribute('name', 'years');
40
+ });
41
+ });
42
+
33
43
  describe('when "fromDate" is not set', () => {
34
44
  beforeEach(() => {
35
45
  setup(props, { fromDate: undefined });
@@ -59,6 +59,7 @@ export function YearsDropdown(props: YearsDropdownProps): JSX.Element {
59
59
 
60
60
  return (
61
61
  <DropdownComponent
62
+ name="years"
62
63
  aria-label={labelYearDropdown()}
63
64
  className={classNames.dropdown_year}
64
65
  style={styles.dropdown_year}
@@ -0,0 +1,43 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`when fromDate and toDate are passed in should render the dropdown element 1`] = `
4
+ <div
5
+ class="rdp-dropdown_year"
6
+ >
7
+ <span
8
+ class="rdp-vhidden"
9
+ >
10
+ Year:
11
+ </span>
12
+ <select
13
+ aria-label="Year: "
14
+ class="rdp-dropdown"
15
+ name="years"
16
+ >
17
+ <option
18
+ value="2021"
19
+ >
20
+ 2021
21
+ </option>
22
+ </select>
23
+ <div
24
+ aria-hidden="true"
25
+ class="rdp-caption_label"
26
+ >
27
+ 2021
28
+ <svg
29
+ class="rdp-dropdown_icon"
30
+ data-testid="iconDropdown"
31
+ height="8px"
32
+ viewBox="0 0 120 120"
33
+ width="8px"
34
+ >
35
+ <path
36
+ d="M4.22182541,48.2218254 C8.44222828,44.0014225 15.2388494,43.9273804 19.5496459,47.9996989 L19.7781746,48.2218254 L60,88.443 L100.221825,48.2218254 C104.442228,44.0014225 111.238849,43.9273804 115.549646,47.9996989 L115.778175,48.2218254 C119.998577,52.4422283 120.07262,59.2388494 116.000301,63.5496459 L115.778175,63.7781746 L67.7781746,111.778175 C63.5577717,115.998577 56.7611506,116.07262 52.4503541,112.000301 L52.2218254,111.778175 L4.22182541,63.7781746 C-0.0739418023,59.4824074 -0.0739418023,52.5175926 4.22182541,48.2218254 Z"
37
+ fill="currentColor"
38
+ fill-rule="nonzero"
39
+ />
40
+ </svg>
41
+ </div>
42
+ </div>
43
+ `;
@@ -115,15 +115,18 @@ describe.each<'single' | 'multiple' | 'range'>(['single', 'multiple', 'range'])(
115
115
  'when calling "onClick" in "%s" selection mode',
116
116
  (mode) => {
117
117
  const activeModifiers: ActiveModifiers = {};
118
- const dayPickerProps = { mode, onDayClick: jest.fn() };
118
+ const dayPickerProps = {
119
+ mode,
120
+ onDayClick: mockedContexts[mode].onDayClick
121
+ };
119
122
  const mouseEvent = {} as React.MouseEvent<HTMLButtonElement, MouseEvent>;
120
123
  const date = today;
121
124
  beforeEach(() => {
122
125
  setup(date, activeModifiers, dayPickerProps);
123
126
  renderResult.current.onClick?.(mouseEvent);
124
127
  });
125
- test(`should have called "onDayClick" from the day picker props`, () => {
126
- expect(dayPickerProps.onDayClick).toHaveBeenCalled();
128
+ test(`should have called "onDayClick" from the ${mode} context`, () => {
129
+ expect(dayPickerProps.onDayClick).toHaveBeenCalledTimes(1);
127
130
  });
128
131
  }
129
132
  );
@@ -94,8 +94,9 @@ export function useDayEventHandlers(
94
94
  multiple.onDayClick?.(date, activeModifiers, e);
95
95
  } else if (isDayPickerRange(dayPicker)) {
96
96
  range.onDayClick?.(date, activeModifiers, e);
97
+ } else {
98
+ dayPicker.onDayClick?.(date, activeModifiers, e);
97
99
  }
98
- dayPicker.onDayClick?.(date, activeModifiers, e);
99
100
  };
100
101
 
101
102
  const onFocus: FocusEventHandler = (e) => {
@@ -75,7 +75,9 @@ export function useDayRender(
75
75
 
76
76
  const className = getDayClassNames(dayPicker, activeModifiers).join(' ');
77
77
  const style = getDayStyle(dayPicker, activeModifiers);
78
-
78
+ const ariaLabel = dayPicker.labels.labelDay(day, activeModifiers, {
79
+ locale: dayPicker.locale
80
+ });
79
81
  const isHidden = Boolean(
80
82
  (activeModifiers.outside && !dayPicker.showOutsideDays) ||
81
83
  activeModifiers.hidden
@@ -93,7 +95,8 @@ export function useDayRender(
93
95
  const divProps = {
94
96
  style,
95
97
  className,
96
- children
98
+ children,
99
+ 'aria-label': ariaLabel
97
100
  };
98
101
 
99
102
  const isFocusTarget = Boolean(
@@ -103,6 +106,7 @@ export function useDayRender(
103
106
  ...divProps,
104
107
  disabled: activeModifiers.disabled,
105
108
  ['aria-pressed']: activeModifiers.selected,
109
+ ['aria-label']: ariaLabel,
106
110
  tabIndex: isFocusTarget ? 0 : -1,
107
111
  ...eventHandlers
108
112
  };
@@ -158,8 +158,8 @@ export function useInput(options: UseInputOptions = {}): UseInputValue {
158
158
  onMonthChange: handleMonthChange,
159
159
  selected: selectedDay,
160
160
  locale,
161
- fromDate: options?.fromDate,
162
- toDate: options?.toDate,
161
+ fromDate,
162
+ toDate,
163
163
  today
164
164
  };
165
165
 
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ export * from 'components/DayContent';
10
10
  export * from 'components/Dropdown';
11
11
  export * from 'components/Footer';
12
12
  export * from 'components/Head';
13
+ export * from 'components/HeadRow';
13
14
  export * from 'components/IconDropdown';
14
15
  export * from 'components/IconRight';
15
16
  export * from 'components/IconLeft';
package/src/style.css CHANGED
@@ -5,7 +5,7 @@
5
5
  --rdp-accent-color-dark: #3003e1;
6
6
  --rdp-background-color-dark: #180270;
7
7
  --rdp-outline: 2px solid var(--rdp-accent-color); /* Outline border for focused elements */
8
- --rdp-outline-selected: 2px solid rgba(0, 0, 0, 0.75); /* Outline border for focused _and_ selected elements */
8
+ --rdp-outline-selected: 3px solid var(--rdp-accent-color); /* Outline border for focused _and_ selected elements */
9
9
 
10
10
  margin: 1em;
11
11
  }
@@ -38,7 +38,6 @@
38
38
  padding: 0;
39
39
  cursor: default;
40
40
  color: inherit;
41
- outline: none;
42
41
  background: none;
43
42
  font: inherit;
44
43
 
@@ -46,6 +45,11 @@
46
45
  -webkit-appearance: none;
47
46
  }
48
47
 
48
+ .rdp-button_reset:focus-visible {
49
+ /* Make sure to reset outline only when :focus-visible is supported */
50
+ outline: none;
51
+ }
52
+
49
53
  .rdp-button {
50
54
  border: 2px solid transparent;
51
55
  }
@@ -58,11 +62,11 @@
58
62
  cursor: pointer;
59
63
  }
60
64
 
61
- .rdp-button:focus:not([disabled]),
65
+ .rdp-button:focus-visible:not([disabled]),
62
66
  .rdp-button:active:not([disabled]) {
63
67
  color: inherit;
64
- border: var(--rdp-outline);
65
68
  background-color: var(--rdp-background-color);
69
+ border: var(--rdp-outline);
66
70
  }
67
71
 
68
72
  .rdp-button:hover:not([disabled]) {
@@ -194,11 +198,11 @@
194
198
  color: unset;
195
199
  }
196
200
 
197
- .rdp-dropdown:focus:not([disabled]) + .rdp-caption_label,
201
+ .rdp-dropdown:focus-visible:not([disabled]) + .rdp-caption_label,
198
202
  .rdp-dropdown:active:not([disabled]) + .rdp-caption_label {
203
+ background-color: var(--rdp-background-color);
199
204
  border: var(--rdp-outline);
200
205
  border-radius: 6px;
201
- background-color: var(--rdp-background-color);
202
206
  }
203
207
 
204
208
  .rdp-dropdown_icon {
@@ -273,7 +277,10 @@
273
277
  }
274
278
 
275
279
  .rdp-day_selected:focus:not([disabled]) {
276
- border: var(--rdp-outline-selected);
280
+ /* Since the background is the same use again the outline */
281
+ outline: var(--rdp-outline);
282
+ outline-offset: 2px;
283
+ z-index: 1;
277
284
  }
278
285
 
279
286
  .rdp:not([dir='rtl']) .rdp-day_range_start:not(.rdp-day_range_end) {
@@ -175,15 +175,15 @@ export interface DayPickerBase {
175
175
  /**
176
176
  * Apply the `disabled` modifier to the matching days.
177
177
  */
178
- disabled?: Matcher | Matcher[];
178
+ disabled?: Matcher | Matcher[] | undefined;
179
179
  /**
180
180
  * Apply the `hidden` modifier to the matching days. Will hide them from the
181
181
  * calendar.
182
182
  */
183
- hidden?: Matcher | Matcher[];
183
+ hidden?: Matcher | Matcher[] | undefined;
184
184
 
185
185
  /** Apply the `selected` modifier to the matching days. */
186
- selected?: Matcher | Matcher[];
186
+ selected?: Matcher | Matcher[] | undefined;
187
187
 
188
188
  /**
189
189
  * The today’s date. Default is the current date. This Date will get the
@@ -270,6 +270,8 @@ export interface CustomComponents {
270
270
  Footer?: () => JSX.Element | null;
271
271
  /** The component for the table’s head. */
272
272
  Head?: () => JSX.Element | null;
273
+ /** The component for the table’s head row. */
274
+ HeadRow?: () => JSX.Element | null;
273
275
  /** The component for the small icon in the drop-downs. */
274
276
  IconDropdown?: (props: StyledComponent) => JSX.Element | null;
275
277
  /** The arrow right icon (used for the Navigation buttons). */
@@ -9,7 +9,7 @@ import { SelectMultipleEventHandler } from './EventHandlers';
9
9
  export interface DayPickerMultipleProps extends DayPickerBase {
10
10
  mode: 'multiple';
11
11
  /** The selected days. */
12
- selected?: Date[];
12
+ selected?: Date[] | undefined;
13
13
  /** Event fired when a days added or removed to the selection. */
14
14
  onSelect?: SelectMultipleEventHandler;
15
15
  /** The minimum amount of days that can be selected. */
@@ -10,7 +10,7 @@ import { DateRange } from './Matchers';
10
10
  export interface DayPickerRangeProps extends DayPickerBase {
11
11
  mode: 'range';
12
12
  /** The selected range of days. */
13
- selected?: DateRange;
13
+ selected?: DateRange | undefined;
14
14
  /** Event fired when a range (or a part of the range) is selected. */
15
15
  onSelect?: SelectRangeEventHandler;
16
16
  /** The minimum amount of days that can be selected. */