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.
- package/dist/cjs/DayPicker.js +1 -0
- package/dist/cjs/DayPicker.js.map +1 -1
- package/dist/cjs/selection/useRange.js +5 -13
- package/dist/cjs/selection/useRange.js.map +1 -1
- package/dist/cjs/types/props.d.ts +7 -0
- package/dist/cjs/useDayPicker.d.ts +8 -1
- package/dist/cjs/useDayPicker.js +1 -1
- package/dist/cjs/useDayPicker.js.map +1 -1
- package/dist/cjs/utils/dateMatchModifiers.d.ts +7 -7
- package/dist/cjs/utils/dateMatchModifiers.js +7 -7
- package/dist/cjs/utils/index.d.ts +3 -0
- package/dist/cjs/utils/index.js +3 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/rangeContainsDayOfWeek.d.ts +19 -0
- package/dist/cjs/utils/rangeContainsDayOfWeek.js +33 -0
- package/dist/cjs/utils/rangeContainsDayOfWeek.js.map +1 -0
- package/dist/cjs/utils/rangeContainsModifiers.d.ts +25 -0
- package/dist/cjs/utils/rangeContainsModifiers.js +84 -0
- package/dist/cjs/utils/rangeContainsModifiers.js.map +1 -0
- package/dist/cjs/utils/rangeOverlaps.d.ts +13 -0
- package/dist/cjs/utils/rangeOverlaps.js +18 -0
- package/dist/cjs/utils/rangeOverlaps.js.map +1 -0
- package/dist/esm/DayPicker.js +1 -0
- package/dist/esm/DayPicker.js.map +1 -1
- package/dist/esm/selection/useRange.js +6 -14
- package/dist/esm/selection/useRange.js.map +1 -1
- package/dist/esm/types/props.d.ts +7 -0
- package/dist/esm/useDayPicker.d.ts +8 -1
- package/dist/esm/useDayPicker.js +1 -1
- package/dist/esm/useDayPicker.js.map +1 -1
- package/dist/esm/utils/dateMatchModifiers.d.ts +7 -7
- package/dist/esm/utils/dateMatchModifiers.js +7 -7
- package/dist/esm/utils/index.d.ts +3 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/rangeContainsDayOfWeek.d.ts +19 -0
- package/dist/esm/utils/rangeContainsDayOfWeek.js +30 -0
- package/dist/esm/utils/rangeContainsDayOfWeek.js.map +1 -0
- package/dist/esm/utils/rangeContainsModifiers.d.ts +25 -0
- package/dist/esm/utils/rangeContainsModifiers.js +81 -0
- package/dist/esm/utils/rangeContainsModifiers.js.map +1 -0
- package/dist/esm/utils/rangeOverlaps.d.ts +13 -0
- package/dist/esm/utils/rangeOverlaps.js +15 -0
- package/dist/esm/utils/rangeOverlaps.js.map +1 -0
- package/examples/ItalianLabels.tsx +1 -1
- package/examples/RangeLong.tsx +1 -3
- package/examples/RangeLongExcludeDisabled.tsx +22 -0
- package/examples/index.ts +2 -0
- package/package.json +1 -1
- package/src/DayPicker.tsx +1 -0
- package/src/selection/useRange.tsx +12 -18
- package/src/style.css +10 -14
- package/src/style.module.css +12 -16
- package/src/types/props.ts +7 -0
- package/src/useDayPicker.test.tsx +134 -0
- package/src/useDayPicker.ts +8 -1
- package/src/utils/dateMatchModifiers.ts +7 -7
- package/src/utils/index.ts +3 -0
- package/src/utils/rangeContainsDayOfWeek.test.ts +48 -0
- package/src/utils/rangeContainsDayOfWeek.ts +35 -0
- package/src/utils/rangeContainsModifiers.test.ts +230 -0
- package/src/utils/rangeContainsModifiers.ts +125 -0
- package/src/utils/rangeOverlaps.test.ts +60 -0
- package/src/utils/rangeOverlaps.ts +22 -0
- package/website/docs/docs/styling.mdx +36 -43
- package/website/docs/docs/translation.mdx +1 -1
- package/website/docs/guides/custom-components.mdx +16 -15
package/src/style.module.css
CHANGED
|
@@ -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-
|
|
15
|
-
--rdp-day_button-width: var(--rdp-day-
|
|
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-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 {
|
package/src/types/props.ts
CHANGED
|
@@ -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
|
+
});
|
package/src/useDayPicker.ts
CHANGED
|
@@ -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
|
-
/** @
|
|
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
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* }
|
|
21
|
+
* from: new Date(2021, 12, 21),
|
|
22
|
+
* to: new Date(2021, 12, 30)
|
|
23
|
+
* };
|
|
24
24
|
* const matcher2: DateRange = {
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* }
|
|
28
|
-
*
|
|
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
|
package/src/utils/index.ts
CHANGED
|
@@ -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
|
+
});
|