react-day-picker 9.2.1 → 9.3.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 (67) hide show
  1. package/dist/cjs/DayPicker.js +1 -0
  2. package/dist/cjs/DayPicker.js.map +1 -1
  3. package/dist/cjs/selection/useRange.js +5 -13
  4. package/dist/cjs/selection/useRange.js.map +1 -1
  5. package/dist/cjs/types/props.d.ts +7 -0
  6. package/dist/cjs/useDayPicker.d.ts +8 -1
  7. package/dist/cjs/useDayPicker.js +1 -1
  8. package/dist/cjs/useDayPicker.js.map +1 -1
  9. package/dist/cjs/utils/dateMatchModifiers.d.ts +7 -7
  10. package/dist/cjs/utils/dateMatchModifiers.js +7 -7
  11. package/dist/cjs/utils/index.d.ts +3 -0
  12. package/dist/cjs/utils/index.js +3 -0
  13. package/dist/cjs/utils/index.js.map +1 -1
  14. package/dist/cjs/utils/rangeContainsDayOfWeek.d.ts +19 -0
  15. package/dist/cjs/utils/rangeContainsDayOfWeek.js +33 -0
  16. package/dist/cjs/utils/rangeContainsDayOfWeek.js.map +1 -0
  17. package/dist/cjs/utils/rangeContainsModifiers.d.ts +25 -0
  18. package/dist/cjs/utils/rangeContainsModifiers.js +84 -0
  19. package/dist/cjs/utils/rangeContainsModifiers.js.map +1 -0
  20. package/dist/cjs/utils/rangeOverlaps.d.ts +13 -0
  21. package/dist/cjs/utils/rangeOverlaps.js +18 -0
  22. package/dist/cjs/utils/rangeOverlaps.js.map +1 -0
  23. package/dist/esm/DayPicker.js +1 -0
  24. package/dist/esm/DayPicker.js.map +1 -1
  25. package/dist/esm/selection/useRange.js +6 -14
  26. package/dist/esm/selection/useRange.js.map +1 -1
  27. package/dist/esm/types/props.d.ts +7 -0
  28. package/dist/esm/useDayPicker.d.ts +8 -1
  29. package/dist/esm/useDayPicker.js +1 -1
  30. package/dist/esm/useDayPicker.js.map +1 -1
  31. package/dist/esm/utils/dateMatchModifiers.d.ts +7 -7
  32. package/dist/esm/utils/dateMatchModifiers.js +7 -7
  33. package/dist/esm/utils/index.d.ts +3 -0
  34. package/dist/esm/utils/index.js +3 -0
  35. package/dist/esm/utils/index.js.map +1 -1
  36. package/dist/esm/utils/rangeContainsDayOfWeek.d.ts +19 -0
  37. package/dist/esm/utils/rangeContainsDayOfWeek.js +30 -0
  38. package/dist/esm/utils/rangeContainsDayOfWeek.js.map +1 -0
  39. package/dist/esm/utils/rangeContainsModifiers.d.ts +25 -0
  40. package/dist/esm/utils/rangeContainsModifiers.js +81 -0
  41. package/dist/esm/utils/rangeContainsModifiers.js.map +1 -0
  42. package/dist/esm/utils/rangeOverlaps.d.ts +13 -0
  43. package/dist/esm/utils/rangeOverlaps.js +15 -0
  44. package/dist/esm/utils/rangeOverlaps.js.map +1 -0
  45. package/examples/ItalianLabels.tsx +1 -1
  46. package/examples/RangeLong.tsx +1 -3
  47. package/examples/RangeLongExcludeDisabled.tsx +22 -0
  48. package/examples/index.ts +2 -0
  49. package/package.json +1 -1
  50. package/src/DayPicker.tsx +1 -0
  51. package/src/selection/useRange.tsx +12 -18
  52. package/src/style.css +10 -14
  53. package/src/style.module.css +12 -16
  54. package/src/types/props.ts +7 -0
  55. package/src/useDayPicker.test.tsx +134 -0
  56. package/src/useDayPicker.ts +8 -1
  57. package/src/utils/dateMatchModifiers.ts +7 -7
  58. package/src/utils/index.ts +3 -0
  59. package/src/utils/rangeContainsDayOfWeek.test.ts +48 -0
  60. package/src/utils/rangeContainsDayOfWeek.ts +35 -0
  61. package/src/utils/rangeContainsModifiers.test.ts +230 -0
  62. package/src/utils/rangeContainsModifiers.ts +125 -0
  63. package/src/utils/rangeOverlaps.test.ts +60 -0
  64. package/src/utils/rangeOverlaps.ts +22 -0
  65. package/website/docs/docs/styling.mdx +36 -43
  66. package/website/docs/docs/translation.mdx +1 -1
  67. package/website/docs/guides/custom-components.mdx +16 -15
@@ -3,26 +3,22 @@
3
3
  .root {
4
4
  --rdp-accent-color: blue; /* The accent color used for selected days and UI elements. */
5
5
  --rdp-accent-background-color: #f0f0ff; /* The accent background color used for selected days and UI elements. */
6
- --rdp-font-family: system-ui; /* The font family used by the calendar. Note that `inherit`does not work here. */
7
6
 
8
- --rdp-day-font: inherit; /* The font used for the day cells. */
9
7
  --rdp-day-height: 2.75rem; /* The height of the day cells. */
10
8
  --rdp-day-width: 2.75rem; /* The width of the day cells. */
11
9
 
12
10
  --rdp-day_button-border-radius: 100%; /* The border radius of the day cells. */
13
11
  --rdp-day_button-border: 2px solid transparent; /* The border of the day cells. */
14
- --rdp-day_button-height: var(--rdp-day-width); /* The height of the day cells. */
15
- --rdp-day_button-width: var(--rdp-day-height); /* The width of the day cells. */
12
+ --rdp-day_button-height: var(--rdp-day-height); /* The height of the day cells. */
13
+ --rdp-day_button-width: var(--rdp-day-width); /* The width of the day cells. */
16
14
 
17
15
  --rdp-selected-border: 2px solid var(--rdp-accent-color); /* The border of the selected days. */
18
- --rdp-selected-font: bold large var(--rdp-font-family); /* The font of the selected days. */
19
16
  --rdp-disabled-opacity: 0.5; /* The opacity of the disabled days. */
20
17
  --rdp-outside-opacity: 0.75; /* The opacity of the days outside the current month. */
21
18
  --rdp-today-color: var(--rdp-accent-color); /* The color of the today's date. */
22
19
 
23
20
  --rdp-dropdown-gap: 0.5rem;/* The gap between the dropdowns used in the month captons. */
24
21
 
25
- --rdp-month_caption-font: bold larger var(--rdp-font-family); /* The font of the month caption. */
26
22
  --rdp-months-gap: 2rem; /* The gap between the months in the multi-month view. */
27
23
 
28
24
  --rdp-nav_button-disabled-opacity: 0.5; /* The opacity of the disabled navigation buttons. */
@@ -31,8 +27,7 @@
31
27
  --rdp-nav-height: 2.75rem; /* The height of the navigation bar. */
32
28
 
33
29
  --rdp-range_middle-background-color: var(--rdp-accent-background-color); /* The color of the background for days in the middle of a range. */
34
- --rdp-range_middle-font: normal medium var(--rdp-font-family); /* The font for days in the middle of a range. */
35
- --rdp-range_middle-foreground-color: white; /* The font for days in the middle of a range. */
30
+ --rdp-range_middle-foreground-color: white; /* The foregraound color for days in the middle of a range. */
36
31
  --rdp-range_middle-color: inherit;/* The color of the range text. */
37
32
 
38
33
  --rdp-range_start-color: white; /* The color of the range text. */
@@ -45,13 +40,12 @@
45
40
 
46
41
  --rdp-week_number-border-radius: 100%; /* The border radius of the week number. */
47
42
  --rdp-week_number-border: 2px solid transparent; /* The border of the week number. */
48
- --rdp-week_number-font: 400 small var(--rdp-font-family); /* The font of the week number cells. */
43
+
49
44
  --rdp-week_number-height: var(--rdp-day-height); /* The height of the week number cells. */
50
45
  --rdp-week_number-opacity: 0.75; /* The opacity of the week number. */
51
46
  --rdp-week_number-width: var(--rdp-day-width); /* The width of the week number cells. */
52
47
  --rdp-weeknumber-text-align: center; /* The text alignment of the weekday cells. */
53
48
 
54
- --rdp-weekday-font: 500 smaller var(--rdp-font-family); /* The font of the weekday. */
55
49
  --rdp-weekday-opacity: 0.75; /* The opacity of the weekday. */
56
50
  --rdp-weekday-padding: 0.5rem 0rem; /* The padding of the weekday. */
57
51
  --rdp-weekday-text-align: center; /* The text alignment of the weekday cells. */
@@ -76,7 +70,6 @@
76
70
  .day {
77
71
  width: var(--rdp-day-width);
78
72
  height: var(--rdp-day-height);
79
- font: var(--rdp-day-font);
80
73
  text-align: center;
81
74
  }
82
75
 
@@ -192,7 +185,8 @@
192
185
  display: flex;
193
186
  align-content: center;
194
187
  height: var(--rdp-nav-height);
195
- font: var(--rdp-month_caption-font);
188
+ font-weight: bold;
189
+ font-size: large;
196
190
  }
197
191
 
198
192
  .months {
@@ -221,14 +215,16 @@
221
215
  .weekday {
222
216
  opacity: var(--rdp-weekday-opacity);
223
217
  padding: var(--rdp-weekday-padding);
224
- font: var(--rdp-weekday-font);
218
+ font-weight: 500;
219
+ font-size: smaller;
225
220
  text-align: var(--rdp-weekday-text-align);
226
221
  text-transform: var(--rdp-weekday-text-transform);
227
222
  }
228
223
 
229
224
  .week_number {
230
225
  opacity: var(--rdp-week_number-opacity);
231
- font: var(--rdp-week_number-font);
226
+ font-weight: 400;
227
+ font-size: small;
232
228
  height: var(--rdp-week_number-height);
233
229
  width: var(--rdp-week_number-width);
234
230
  border: var(--rdp-week_number-border);
@@ -242,7 +238,8 @@
242
238
  }
243
239
 
244
240
  .selected {
245
- font: var(--rdp-selected-font);
241
+ font-weight: bold;
242
+ font-size: large;
246
243
  }
247
244
 
248
245
  .selected .day_button {
@@ -273,7 +270,6 @@
273
270
 
274
271
  .range_middle {
275
272
  background-color: var(--rdp-range_middle-background-color);
276
- font: var(--rdp-range_middle-font);
277
273
  }
278
274
 
279
275
  .range_middle .day_button {
@@ -490,6 +490,7 @@ export interface PropsBase {
490
490
  * @param {Date} triggerDate - The date when the event was triggered.
491
491
  * @param {Modifiers} modifiers - The modifiers associated with the event.
492
492
  * @param {React.MouseEvent | React.KeyboardEvent} e - The event object.
493
+ * @group DayPicker
493
494
  */
494
495
  export type OnSelectHandler<T> = (
495
496
  selected: T,
@@ -501,6 +502,7 @@ export type OnSelectHandler<T> = (
501
502
  /**
502
503
  * The props when the single selection is required.
503
504
  *
505
+ * @group DayPicker
504
506
  * @see https://daypicker.dev/docs/selection-modes#single-mode
505
507
  */
506
508
  export interface PropsSingleRequired {
@@ -515,6 +517,7 @@ export interface PropsSingleRequired {
515
517
  /**
516
518
  * The props when the single selection is optional.
517
519
  *
520
+ * @group DayPicker
518
521
  * @see https://daypicker.dev/docs/selection-modes#single-mode
519
522
  */
520
523
  export interface PropsSingle {
@@ -529,6 +532,7 @@ export interface PropsSingle {
529
532
  /**
530
533
  * The props when the multiple selection is required.
531
534
  *
535
+ * @group DayPicker
532
536
  * @see https://daypicker.dev/docs/selection-modes#multiple-mode
533
537
  */
534
538
  export interface PropsMultiRequired {
@@ -547,6 +551,7 @@ export interface PropsMultiRequired {
547
551
  /**
548
552
  * The props when the multiple selection is optional.
549
553
  *
554
+ * @group DayPicker
550
555
  * @see https://daypicker.dev/docs/selection-modes#multiple-mode
551
556
  */
552
557
  export interface PropsMulti {
@@ -564,6 +569,7 @@ export interface PropsMulti {
564
569
  /**
565
570
  * The props when the range selection is required.
566
571
  *
572
+ * @group DayPicker
567
573
  * @see https://daypicker.dev/docs/selection-modes#range-mode
568
574
  */
569
575
  export interface PropsRangeRequired {
@@ -588,6 +594,7 @@ export interface PropsRangeRequired {
588
594
  /**
589
595
  * The props when the range selection is optional.
590
596
  *
597
+ * @group DayPicker
591
598
  * @see https://daypicker.dev/docs/selection-modes#range-mode
592
599
  */
593
600
  export interface PropsRange {
@@ -0,0 +1,134 @@
1
+ import React from "react";
2
+
3
+ import { renderHook } from "@testing-library/react";
4
+
5
+ import { DayFlag, SelectionState, UI } from "./UI";
6
+ import { CalendarDay } from "./classes/CalendarDay";
7
+ import { CalendarMonth } from "./classes/CalendarMonth";
8
+ import { DayPickerProps } from "./types/props";
9
+ import { Modifiers } from "./types/shared";
10
+ import {
11
+ DayPickerContext,
12
+ dayPickerContext,
13
+ useDayPicker
14
+ } from "./useDayPicker";
15
+
16
+ describe("useDayPicker", () => {
17
+ const mockContextValue: DayPickerContext<{
18
+ required: false;
19
+ mode: "single";
20
+ }> = {
21
+ months: [new CalendarMonth(new Date(), [])],
22
+ nextMonth: new Date(),
23
+ previousMonth: new Date(),
24
+ goToMonth: jest.fn(),
25
+ getModifiers: jest.fn((day: CalendarDay) => ({}) as Modifiers),
26
+ selected: undefined,
27
+ select: jest.fn(),
28
+ isSelected: jest.fn((date: Date) => false),
29
+ components: {
30
+ Button: jest.fn(),
31
+ Chevron: jest.fn(),
32
+ CaptionLabel: jest.fn(),
33
+ Day: jest.fn(),
34
+ DayButton: jest.fn(),
35
+ Dropdown: jest.fn(),
36
+ DropdownNav: jest.fn(),
37
+ Footer: jest.fn(),
38
+ Month: jest.fn(),
39
+ MonthCaption: jest.fn(),
40
+ MonthGrid: jest.fn(),
41
+ Months: jest.fn(),
42
+ Nav: jest.fn(),
43
+ Option: jest.fn(),
44
+ PreviousMonthButton: jest.fn(),
45
+ NextMonthButton: jest.fn(),
46
+ Root: jest.fn(),
47
+ Select: jest.fn(),
48
+ Weeks: jest.fn(),
49
+ Week: jest.fn(),
50
+ Weekday: jest.fn(),
51
+ Weekdays: jest.fn(),
52
+ WeekNumber: jest.fn(),
53
+ WeekNumberHeader: jest.fn(),
54
+ MonthsDropdown: jest.fn(),
55
+ YearsDropdown: jest.fn()
56
+ },
57
+ classNames: {
58
+ [UI.Root]: "",
59
+ [UI.Chevron]: "",
60
+ [UI.Day]: "",
61
+ [UI.DayButton]: "",
62
+ [UI.CaptionLabel]: "",
63
+ [UI.Dropdowns]: "",
64
+ [UI.Dropdown]: "",
65
+ [UI.DropdownRoot]: "",
66
+ [UI.Footer]: "",
67
+ [UI.MonthGrid]: "",
68
+ [UI.MonthCaption]: "",
69
+ [UI.MonthsDropdown]: "",
70
+ [UI.Month]: "",
71
+ [UI.Months]: "",
72
+ [UI.Nav]: "",
73
+ [UI.NextMonthButton]: "",
74
+ [UI.PreviousMonthButton]: "",
75
+ [UI.Week]: "",
76
+ [UI.Weeks]: "",
77
+ [UI.Weekday]: "",
78
+ [UI.Weekdays]: "",
79
+ [UI.WeekNumber]: "",
80
+ [UI.WeekNumberHeader]: "",
81
+ [UI.YearsDropdown]: "",
82
+ [SelectionState.range_end]: "",
83
+ [SelectionState.range_middle]: "",
84
+ [SelectionState.range_start]: "",
85
+ [SelectionState.selected]: "",
86
+ [DayFlag.disabled]: "",
87
+ [DayFlag.hidden]: "",
88
+ [DayFlag.outside]: "",
89
+ [DayFlag.focused]: "",
90
+ [DayFlag.today]: ""
91
+ },
92
+ styles: {},
93
+ labels: {
94
+ labelNav: jest.fn(),
95
+ labelGrid: jest.fn(),
96
+ labelGridcell: jest.fn(),
97
+ labelMonthDropdown: jest.fn(),
98
+ labelYearDropdown: jest.fn(),
99
+ labelNext: jest.fn(),
100
+ labelPrevious: jest.fn(),
101
+ labelDayButton: jest.fn(),
102
+ labelDay: jest.fn(),
103
+ labelWeekday: jest.fn(),
104
+ labelWeekNumber: jest.fn(),
105
+ labelWeekNumberHeader: jest.fn()
106
+ },
107
+ formatters: {
108
+ formatCaption: jest.fn(),
109
+ formatDay: jest.fn(),
110
+ formatMonthDropdown: jest.fn(),
111
+ formatMonthCaption: jest.fn(),
112
+ formatWeekNumber: jest.fn(),
113
+ formatWeekNumberHeader: jest.fn(),
114
+ formatWeekdayName: jest.fn(),
115
+ formatYearDropdown: jest.fn(),
116
+ formatYearCaption: jest.fn()
117
+ },
118
+ dayPickerProps: {
119
+ mode: "single",
120
+ required: false
121
+ } as DayPickerProps
122
+ };
123
+
124
+ it("should return the context value when used within a DayPicker provider", () => {
125
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
126
+ <dayPickerContext.Provider value={mockContextValue}>
127
+ {children}
128
+ </dayPickerContext.Provider>
129
+ );
130
+
131
+ const { result } = renderHook(() => useDayPicker(), { wrapper });
132
+ expect(result.current).toEqual(mockContextValue);
133
+ });
134
+ });
@@ -2,6 +2,7 @@ import { createContext, useContext } from "react";
2
2
 
3
3
  import { CalendarDay } from "./classes/CalendarDay.js";
4
4
  import { CalendarMonth } from "./classes/CalendarMonth.js";
5
+ import { DayPickerProps } from "./types/props.js";
5
6
  import type { SelectedValue, SelectHandler } from "./types/selection.js";
6
7
  import {
7
8
  ClassNames,
@@ -13,7 +14,7 @@ import {
13
14
  Styles
14
15
  } from "./types/shared.js";
15
16
 
16
- /** @private */
17
+ /** @ignore */
17
18
  export const dayPickerContext = createContext<
18
19
  | DayPickerContext<{
19
20
  mode?: Mode | undefined;
@@ -59,6 +60,12 @@ export type DayPickerContext<
59
60
  labels: Labels;
60
61
  /** The formatters used to format the UI elements. */
61
62
  formatters: Formatters;
63
+ /**
64
+ * The props as passed to the DayPicker component.
65
+ *
66
+ * @since 9.3.0
67
+ */
68
+ dayPickerProps: DayPickerProps;
62
69
  };
63
70
 
64
71
  /**
@@ -18,14 +18,14 @@ import {
18
18
  * ```tsx
19
19
  * const date = new Date(2022, 5, 19);
20
20
  * const matcher1: DateRange = {
21
- * from: new Date(2021, 12, 21),
22
- * to: new Date(2021, 12, 30)
23
- * }
21
+ * from: new Date(2021, 12, 21),
22
+ * to: new Date(2021, 12, 30)
23
+ * };
24
24
  * const matcher2: DateRange = {
25
- * from: new Date(2022, 5, 1),
26
- * to: new Date(2022, 5, 23)
27
- * }
28
- * const dateMatchModifiers(date, [matcher1, matcher2]); // true, since day is in the matcher1 range.
25
+ * from: new Date(2022, 5, 1),
26
+ * to: new Date(2022, 5, 23)
27
+ * };
28
+ * dateMatchModifiers(date, [matcher1, matcher2]); // true, since day is in the matcher1 range.
29
29
  * ```
30
30
  *
31
31
  * @group Utilities
@@ -1,4 +1,7 @@
1
1
  export * from "./addToRange.js";
2
2
  export * from "./dateMatchModifiers.js";
3
+ export * from "./rangeContainsDayOfWeek.js";
4
+ export * from "./rangeContainsModifiers.js";
3
5
  export * from "./rangeIncludesDate.js";
6
+ export * from "./rangeOverlaps.js";
4
7
  export * from "./typeguards.js";
@@ -0,0 +1,48 @@
1
+ import { defaultDateLib } from "../classes/DateLib";
2
+
3
+ import { rangeContainsDayOfWeek } from "./rangeContainsDayOfWeek";
4
+
5
+ const sunday = new Date(2024, 8, 1); // day of the week 0
6
+ const monday = new Date(2024, 8, 2); // day of the week 1
7
+ const friday = new Date(2024, 8, 6); // day of the week 5
8
+ const saturday = new Date(2024, 8, 7); // day of the week 6
9
+ const nextWeekSunday = new Date(2024, 8, 8); // day of the week 0
10
+
11
+ describe("should return false", () => {
12
+ const testCases: Array<[{ from: Date; to: Date }, number | number[]]> = [
13
+ [{ from: monday, to: saturday }, 0],
14
+ [{ from: monday, to: friday }, [0, 6]],
15
+ [{ from: sunday, to: friday }, 6]
16
+ ];
17
+
18
+ for (const [range, dayOfWeek] of testCases) {
19
+ it(`range from ${range.from} to ${range.to} should not contain ${JSON.stringify(dayOfWeek)}`, () => {
20
+ expect(rangeContainsDayOfWeek(range, dayOfWeek, defaultDateLib)).toBe(
21
+ false
22
+ );
23
+ });
24
+ }
25
+ });
26
+
27
+ describe("should return true", () => {
28
+ const testCases: Array<[{ from: Date; to: Date }, number | number[]]> = [
29
+ [{ from: sunday, to: saturday }, 0],
30
+ [{ from: monday, to: friday }, 1],
31
+ [{ from: monday, to: friday }, 2],
32
+ [{ from: monday, to: friday }, 3],
33
+ [{ from: monday, to: friday }, 4],
34
+ [{ from: monday, to: friday }, 5],
35
+ [{ from: monday, to: saturday }, 6],
36
+ [{ from: monday, to: saturday }, [0, 6]],
37
+ [{ from: monday, to: nextWeekSunday }, 0],
38
+ [{ from: monday, to: nextWeekSunday }, 6]
39
+ ];
40
+
41
+ for (const [range, dayOfWeek] of testCases) {
42
+ it(`range from ${range.from} to ${range.to} should contain ${JSON.stringify(dayOfWeek)}`, () => {
43
+ expect(rangeContainsDayOfWeek(range, dayOfWeek, defaultDateLib)).toBe(
44
+ true
45
+ );
46
+ });
47
+ }
48
+ });
@@ -0,0 +1,35 @@
1
+ import { defaultDateLib, type DateLib } from "../classes/DateLib.js";
2
+
3
+ /**
4
+ * Returns whether a date range contains one or more days of the week.
5
+ *
6
+ * ```tsx
7
+ * const range: DateRange = {
8
+ * from: new Date(2024, 8, 1), // Sunday
9
+ * to: new Date(2024, 8, 6) // Thursday
10
+ * };
11
+ * rangeContainsDayOfWeek(date, 1); // true: contains range contains Monday
12
+ * ```
13
+ *
14
+ * @since 9.2.2
15
+ * @group Utilities
16
+ */
17
+ export function rangeContainsDayOfWeek(
18
+ range: { from: Date; to: Date },
19
+ dayOfWeek: number | number[],
20
+ dateLib: DateLib = defaultDateLib
21
+ ) {
22
+ const dayOfWeekArr = !Array.isArray(dayOfWeek) ? [dayOfWeek] : dayOfWeek;
23
+ let date = range.from;
24
+ const totalDays = dateLib.differenceInCalendarDays(range.to, range.from);
25
+
26
+ // iterate at maximum one week or the total days if the range is shorter than one week
27
+ const totalDaysLimit = Math.min(totalDays, 6);
28
+ for (let i = 0; i <= totalDaysLimit; i++) {
29
+ if (dayOfWeekArr.includes(date.getDay())) {
30
+ return true;
31
+ }
32
+ date = dateLib.addDays(date, 1);
33
+ }
34
+ return false;
35
+ }
@@ -0,0 +1,230 @@
1
+ import { defaultDateLib } from "../classes/DateLib";
2
+ import { DayOfWeek } from "../types";
3
+
4
+ import { rangeContainsModifiers } from "./rangeContainsModifiers";
5
+
6
+ const sunday = new Date(2024, 8, 1); // day of the week 0
7
+ const monday = new Date(2024, 8, 2); // day of the week 1
8
+ const tuesday = new Date(2024, 8, 3); // day of the week 1
9
+ const wednesday = new Date(2024, 8, 4); // day of the week 1
10
+ const thursday = new Date(2024, 8, 5); // day of the week 1
11
+ const friday = new Date(2024, 8, 6); // day of the week 5
12
+ const saturday = new Date(2024, 8, 7); // day of the week 6
13
+ const nextWeekSunday = new Date(2024, 8, 8); // day of the week 0
14
+
15
+ const testRange = { from: monday, to: saturday };
16
+
17
+ describe("when the matcher is a boolean", () => {
18
+ const matcher = true;
19
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
20
+ test("should return the boolean", () => {
21
+ expect(result).toBe(matcher);
22
+ });
23
+ });
24
+
25
+ describe("when matching a single date", () => {
26
+ test("should return true when matching a date in the range", () => {
27
+ const matcher = thursday;
28
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
29
+ expect(result).toBe(true);
30
+ });
31
+ test('should return true when matching the "from" date', () => {
32
+ const matcher = monday;
33
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
34
+ expect(result).toBe(true);
35
+ });
36
+ test('should return true when matching the "to" date', () => {
37
+ const matcher = saturday;
38
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
39
+ expect(result).toBe(true);
40
+ });
41
+ test('should return false on the edge of the "from" date', () => {
42
+ const matcher = sunday;
43
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
44
+ expect(result).toBe(false);
45
+ });
46
+ test('should return false on the edge of the "to" date', () => {
47
+ const matcher = nextWeekSunday;
48
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
49
+ expect(result).toBe(false);
50
+ });
51
+ });
52
+
53
+ describe("when matching an array of dates", () => {
54
+ test("should return true", () => {
55
+ const matcher = [sunday, wednesday, nextWeekSunday];
56
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
57
+ expect(result).toBe(true);
58
+ });
59
+ test("should return false", () => {
60
+ const matcher = [sunday, nextWeekSunday];
61
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
62
+ expect(result).toBe(false);
63
+ });
64
+ });
65
+
66
+ describe("when matching date range", () => {
67
+ test('should return true when matching the "from" date', () => {
68
+ const matcher = { from: sunday, to: monday };
69
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
70
+ expect(result).toBe(true);
71
+ });
72
+ test('should return true when matching the "to" date', () => {
73
+ const matcher = { from: saturday, to: nextWeekSunday };
74
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
75
+ expect(result).toBe(true);
76
+ });
77
+
78
+ test("should return true when date range contains matcher", () => {
79
+ const matcher = { from: tuesday, to: thursday };
80
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
81
+ expect(result).toBe(true);
82
+ });
83
+ test("should return true when matcher contains date range", () => {
84
+ const matcher = { from: sunday, to: nextWeekSunday };
85
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
86
+ expect(result).toBe(true);
87
+ });
88
+
89
+ test('should return false on the edge of the "from" date', () => {
90
+ const matcher = { from: new Date(2000, 1, 1), to: sunday };
91
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
92
+ expect(result).toBe(false);
93
+ });
94
+ test('should return false on the edge of the "to" date', () => {
95
+ const matcher = { from: nextWeekSunday, to: new Date(2077, 1, 1) };
96
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
97
+ expect(result).toBe(false);
98
+ });
99
+ test("should return false if matcher is an incomplete date range", () => {
100
+ const matcher = { from: monday };
101
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
102
+ expect(result).toBe(false);
103
+ });
104
+ });
105
+
106
+ describe("when matching the day of week", () => {
107
+ test("should return true", () => {
108
+ const matcher: DayOfWeek = {
109
+ dayOfWeek: [monday.getDay()]
110
+ };
111
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
112
+ expect(result).toBe(true);
113
+ });
114
+ test("should return false", () => {
115
+ const matcher: DayOfWeek = {
116
+ dayOfWeek: [sunday.getDay()]
117
+ };
118
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
119
+ expect(result).toBe(false);
120
+ });
121
+ });
122
+
123
+ describe("when matching date interval (closed)", () => {
124
+ test('should return true when matching the "from" date', () => {
125
+ const matcher = { after: sunday, before: tuesday };
126
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
127
+ expect(result).toBe(true);
128
+ });
129
+ test('should return true when matching the "to" date', () => {
130
+ const matcher = { after: friday, before: nextWeekSunday };
131
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
132
+ expect(result).toBe(true);
133
+ });
134
+
135
+ test("should return true when date range contains matcher", () => {
136
+ const matcher = { after: tuesday, before: thursday };
137
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
138
+ expect(result).toBe(true);
139
+ });
140
+ test("should return true when matcher contains date range", () => {
141
+ const matcher = { after: sunday, before: nextWeekSunday };
142
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
143
+ expect(result).toBe(true);
144
+ });
145
+
146
+ test('should return false on the edge of the "from" date', () => {
147
+ const matcher = { after: new Date(2000, 1, 1), before: monday };
148
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
149
+ expect(result).toBe(false);
150
+ });
151
+ test('should return false on the edge of the "to" date', () => {
152
+ const matcher = { after: saturday, before: new Date(2077, 1, 1) };
153
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
154
+ expect(result).toBe(false);
155
+ });
156
+ });
157
+
158
+ describe("when matching date interval (open)", () => {
159
+ test('should return true when matching the "from" date', () => {
160
+ const matcher = { before: tuesday, after: saturday };
161
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
162
+ expect(result).toBe(true);
163
+ });
164
+ test('should return true when matching the "to" date', () => {
165
+ const matcher = { before: monday, after: friday };
166
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
167
+ expect(result).toBe(true);
168
+ });
169
+ test("should return false when date range is not part of the matcher", () => {
170
+ const matcher = { before: monday, after: saturday };
171
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
172
+ expect(result).toBe(false);
173
+ });
174
+ });
175
+
176
+ describe("when matching the date after", () => {
177
+ test('should return true when matching the "from" date', () => {
178
+ const matcher = { after: sunday };
179
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
180
+ expect(result).toBe(true);
181
+ });
182
+ test('should return true when matching the "to" date', () => {
183
+ const matcher = { after: friday };
184
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
185
+ expect(result).toBe(true);
186
+ });
187
+
188
+ test("should return false", () => {
189
+ const matcher = { after: saturday };
190
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
191
+ expect(result).toBe(false);
192
+ });
193
+ });
194
+
195
+ describe("when matching the date before", () => {
196
+ test('should return true when matching the "from" date', () => {
197
+ const matcher = { before: tuesday };
198
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
199
+ expect(result).toBe(true);
200
+ });
201
+ test('should return true when matching the "to" date', () => {
202
+ const matcher = { before: nextWeekSunday };
203
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
204
+ expect(result).toBe(true);
205
+ });
206
+
207
+ test("should return false", () => {
208
+ const matcher = { before: monday };
209
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
210
+ expect(result).toBe(false);
211
+ });
212
+ });
213
+
214
+ describe("when the matcher is a function", () => {
215
+ test('should return true when matching the "from" date', () => {
216
+ const matcher = (date: Date) => date.getTime() === monday.getTime();
217
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
218
+ expect(result).toBe(true);
219
+ });
220
+ test('should return true when matching the "to" date', () => {
221
+ const matcher = (date: Date) => date.getTime() === saturday.getTime();
222
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
223
+ expect(result).toBe(true);
224
+ });
225
+ test("should return false", () => {
226
+ const matcher = (date: Date) => date.getTime() === nextWeekSunday.getTime();
227
+ const result = rangeContainsModifiers(testRange, [matcher], defaultDateLib);
228
+ expect(result).toBe(false);
229
+ });
230
+ });