@react-stately/calendar 3.0.0-alpha.3 → 3.0.0-alpha.4
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/main.js +158 -97
- package/dist/main.js.map +1 -1
- package/dist/module.js +156 -95
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +95 -20
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/types.ts +57 -13
- package/src/useCalendarState.ts +66 -36
- package/src/useRangeCalendarState.ts +82 -12
- package/src/utils.ts +6 -6
package/dist/types.d.ts
CHANGED
|
@@ -1,62 +1,137 @@
|
|
|
1
|
-
import { CalendarDate, Calendar,
|
|
1
|
+
import { CalendarDate, Calendar, DateDuration } from "@internationalized/date";
|
|
2
2
|
import { DateValue, CalendarProps, RangeCalendarProps } from "@react-types/calendar";
|
|
3
3
|
import { RangeValue } from "@react-types/shared";
|
|
4
4
|
export interface CalendarStateBase {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
/** Whether the calendar is disabled. */
|
|
6
|
+
readonly isDisabled: boolean;
|
|
7
|
+
/** Whether the calendar is in a read only state. */
|
|
8
|
+
readonly isReadOnly: boolean;
|
|
9
|
+
/** The date range that is currently visible in the calendar. */
|
|
10
|
+
readonly visibleRange: RangeValue<CalendarDate>;
|
|
11
|
+
/** The time zone of the dates currently being displayed. */
|
|
12
|
+
readonly timeZone: string;
|
|
13
|
+
/** The currently focused date. */
|
|
14
|
+
readonly focusedDate: CalendarDate;
|
|
15
|
+
/** Sets the focused date. */
|
|
10
16
|
setFocusedDate(value: CalendarDate): void;
|
|
17
|
+
/** Moves focus to the next calendar date. */
|
|
11
18
|
focusNextDay(): void;
|
|
19
|
+
/** Moves focus to the previous calendar date. */
|
|
12
20
|
focusPreviousDay(): void;
|
|
21
|
+
/** Moves focus to the next row of dates, e.g. the next week. */
|
|
13
22
|
focusNextRow(): void;
|
|
23
|
+
/** Moves focus to the previous row of dates, e.g. the previous work. */
|
|
14
24
|
focusPreviousRow(): void;
|
|
25
|
+
/** Moves focus to the next page of dates, e.g. the next month if one month is visible. */
|
|
15
26
|
focusNextPage(): void;
|
|
27
|
+
/** Moves focus to the previous page of dates, e.g. the previous month if one month is visible. */
|
|
16
28
|
focusPreviousPage(): void;
|
|
29
|
+
/** Moves focus to the start of the current page of dates, e.g. the start of the first visible month. */
|
|
17
30
|
focusPageStart(): void;
|
|
31
|
+
/** Moves focus to the end of the current page of dates, e.g. the end of the last visible month. */
|
|
18
32
|
focusPageEnd(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Moves focus to the next larger section of dates based on what is currently displayed.
|
|
35
|
+
* If days are displayed, then moves to the next visible range. If weeks are displayed, then
|
|
36
|
+
* moves to the next month. If months or years are displayed, moves to the next year.
|
|
37
|
+
*/
|
|
19
38
|
focusNextSection(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Moves focus to the previous larger section of dates based on what is currently displayed.
|
|
41
|
+
* If days are displayed, then moves to the previous visible range. If weeks are displayed, then
|
|
42
|
+
* moves to the previous month. If months or years are displayed, moves to the previous year.
|
|
43
|
+
*/
|
|
20
44
|
focusPreviousSection(): void;
|
|
21
|
-
|
|
22
|
-
focusPreviousPage(): void;
|
|
45
|
+
/** Selects the currently focused date. */
|
|
23
46
|
selectFocusedDate(): void;
|
|
47
|
+
/** Selects the given date. */
|
|
24
48
|
selectDate(date: CalendarDate): void;
|
|
25
|
-
|
|
49
|
+
/** Whether focus is currently within the calendar. */
|
|
50
|
+
readonly isFocused: boolean;
|
|
51
|
+
/** Sets whether focus is currently within the calendar. */
|
|
26
52
|
setFocused(value: boolean): void;
|
|
53
|
+
/** Returns whether the given date is invalid according to the `minValue` and `maxValue` props. */
|
|
27
54
|
isInvalid(date: CalendarDate): boolean;
|
|
55
|
+
/** Returns whether the given date is currently selected. */
|
|
28
56
|
isSelected(date: CalendarDate): boolean;
|
|
57
|
+
/** Returns whether the given date is currently focused. */
|
|
29
58
|
isCellFocused(date: CalendarDate): boolean;
|
|
59
|
+
/** Returns whether the given date is disabled according to the `minValue, `maxValue`, and `isDisabled` props. */
|
|
30
60
|
isCellDisabled(date: CalendarDate): boolean;
|
|
61
|
+
/** Returns whether the given date is unavailable according to the `isDateUnavailable` prop. */
|
|
62
|
+
isCellUnavailable(date: CalendarDate): boolean;
|
|
63
|
+
/** Returns whether the previous visible date range is allowed to be selected according to the `minValue` prop. */
|
|
31
64
|
isPreviousVisibleRangeInvalid(): boolean;
|
|
65
|
+
/** Returns whether the next visible date range is allowed to be selected according to the `maxValue` prop. */
|
|
32
66
|
isNextVisibleRangeInvalid(): boolean;
|
|
33
67
|
}
|
|
34
68
|
export interface CalendarState extends CalendarStateBase {
|
|
35
|
-
|
|
69
|
+
/** The currently selected date. */
|
|
70
|
+
readonly value: CalendarDate;
|
|
71
|
+
/** Sets the currently selected date. */
|
|
36
72
|
setValue(value: CalendarDate): void;
|
|
37
73
|
}
|
|
38
74
|
export interface RangeCalendarState extends CalendarStateBase {
|
|
39
|
-
|
|
75
|
+
/** The currently selected date range. */
|
|
76
|
+
readonly value: RangeValue<DateValue>;
|
|
77
|
+
/** Sets the currently selected date range. */
|
|
40
78
|
setValue(value: RangeValue<DateValue>): void;
|
|
79
|
+
/** Highlights the given date during selection, e.g. by hovering or dragging. */
|
|
41
80
|
highlightDate(date: CalendarDate): void;
|
|
42
|
-
|
|
81
|
+
/** The current anchor date that the user clicked on to begin range selection. */
|
|
82
|
+
readonly anchorDate: CalendarDate | null;
|
|
83
|
+
/** Sets the anchor date that the user clicked on to begin range selection. */
|
|
43
84
|
setAnchorDate(date: CalendarDate | null): void;
|
|
44
|
-
|
|
45
|
-
|
|
85
|
+
/** The currently highlighted date range. */
|
|
86
|
+
readonly highlightedRange: RangeValue<CalendarDate>;
|
|
87
|
+
/** Whether the user is currently dragging over the calendar. */
|
|
88
|
+
readonly isDragging: boolean;
|
|
89
|
+
/** Sets whether the user is dragging over the calendar. */
|
|
46
90
|
setDragging(isDragging: boolean): void;
|
|
47
91
|
}
|
|
48
|
-
interface CalendarStateOptions
|
|
92
|
+
interface CalendarStateOptions extends CalendarProps<DateValue> {
|
|
93
|
+
/** The locale to display and edit the value according to. */
|
|
49
94
|
locale: string;
|
|
95
|
+
/**
|
|
96
|
+
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
|
|
97
|
+
* object for a given calendar identifier. Such a function may be imported from the
|
|
98
|
+
* `@internationalized/date` package, or manually implemented to include support for
|
|
99
|
+
* only certain calendars.
|
|
100
|
+
*/
|
|
50
101
|
createCalendar: (name: string) => Calendar;
|
|
51
|
-
|
|
102
|
+
/**
|
|
103
|
+
* The amount of days that will be displayed at once. This affects how pagination works.
|
|
104
|
+
* @default {months: 1}
|
|
105
|
+
*/
|
|
106
|
+
visibleDuration?: DateDuration;
|
|
107
|
+
/** Determines how to align the initial selection relative to the visible date range. */
|
|
52
108
|
selectionAlignment?: 'start' | 'center' | 'end';
|
|
53
109
|
}
|
|
54
|
-
|
|
55
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Provides state management for a calendar component.
|
|
112
|
+
* A calendar displays one or more date grids and allows users to select a single date.
|
|
113
|
+
*/
|
|
114
|
+
export function useCalendarState(props: CalendarStateOptions): CalendarState;
|
|
115
|
+
interface RangeCalendarStateOptions extends RangeCalendarProps<DateValue> {
|
|
116
|
+
/** The locale to display and edit the value according to. */
|
|
56
117
|
locale: string;
|
|
118
|
+
/**
|
|
119
|
+
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
|
|
120
|
+
* object for a given calendar identifier. Such a function may be imported from the
|
|
121
|
+
* `@internationalized/date` package, or manually implemented to include support for
|
|
122
|
+
* only certain calendars.
|
|
123
|
+
*/
|
|
57
124
|
createCalendar: (name: string) => Calendar;
|
|
58
|
-
|
|
125
|
+
/**
|
|
126
|
+
* The amount of days that will be displayed at once. This affects how pagination works.
|
|
127
|
+
* @default {months: 1}
|
|
128
|
+
*/
|
|
129
|
+
visibleDuration?: DateDuration;
|
|
59
130
|
}
|
|
60
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Provides state management for a range calendar component.
|
|
133
|
+
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
|
|
134
|
+
*/
|
|
135
|
+
export function useRangeCalendarState(props: RangeCalendarStateOptions): RangeCalendarState;
|
|
61
136
|
|
|
62
137
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;AAgBA;IACE,UAAU,EAAE,OAAO,CAAC;
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-stately/calendar/src/packages/@react-stately/calendar/src/types.ts","packages/@react-stately/calendar/src/packages/@react-stately/calendar/src/utils.ts","packages/@react-stately/calendar/src/packages/@react-stately/calendar/src/useCalendarState.ts","packages/@react-stately/calendar/src/packages/@react-stately/calendar/src/useRangeCalendarState.ts","packages/@react-stately/calendar/src/packages/@react-stately/calendar/src/index.ts","packages/@react-stately/calendar/src/index.ts"],"sourcesContent":[null,null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport * from './types';\nexport * from './useCalendarState';\nexport * from './useRangeCalendarState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-stately/calendar",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.4",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@babel/runtime": "^7.6.2",
|
|
21
|
-
"@internationalized/date": "3.0.0-alpha.
|
|
22
|
-
"@react-aria/i18n": "^3.3.
|
|
21
|
+
"@internationalized/date": "3.0.0-alpha.4",
|
|
22
|
+
"@react-aria/i18n": "^3.3.8",
|
|
23
23
|
"@react-stately/utils": "^3.4.1",
|
|
24
|
-
"@react-types/calendar": "3.0.0-alpha.
|
|
25
|
-
"@react-types/datepicker": "3.0.0-alpha.
|
|
24
|
+
"@react-types/calendar": "3.0.0-alpha.4",
|
|
25
|
+
"@react-types/datepicker": "3.0.0-alpha.4",
|
|
26
26
|
"@react-types/shared": "^3.11.1",
|
|
27
27
|
"date-fns": "^1.30.1"
|
|
28
28
|
},
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "e7708349a637642a30d33a11ca4a75ad5829eaa3"
|
|
36
36
|
}
|
package/src/types.ts
CHANGED
|
@@ -15,48 +15,92 @@ import {DateValue} from '@react-types/calendar';
|
|
|
15
15
|
import {RangeValue} from '@react-types/shared';
|
|
16
16
|
|
|
17
17
|
export interface CalendarStateBase {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/** Whether the calendar is disabled. */
|
|
19
|
+
readonly isDisabled: boolean,
|
|
20
|
+
/** Whether the calendar is in a read only state. */
|
|
21
|
+
readonly isReadOnly: boolean,
|
|
22
|
+
/** The date range that is currently visible in the calendar. */
|
|
23
|
+
readonly visibleRange: RangeValue<CalendarDate>,
|
|
24
|
+
/** The time zone of the dates currently being displayed. */
|
|
25
|
+
readonly timeZone: string,
|
|
26
|
+
/** The currently focused date. */
|
|
27
|
+
readonly focusedDate: CalendarDate,
|
|
28
|
+
/** Sets the focused date. */
|
|
23
29
|
setFocusedDate(value: CalendarDate): void,
|
|
30
|
+
/** Moves focus to the next calendar date. */
|
|
24
31
|
focusNextDay(): void,
|
|
32
|
+
/** Moves focus to the previous calendar date. */
|
|
25
33
|
focusPreviousDay(): void,
|
|
34
|
+
/** Moves focus to the next row of dates, e.g. the next week. */
|
|
26
35
|
focusNextRow(): void,
|
|
36
|
+
/** Moves focus to the previous row of dates, e.g. the previous work. */
|
|
27
37
|
focusPreviousRow(): void,
|
|
38
|
+
/** Moves focus to the next page of dates, e.g. the next month if one month is visible. */
|
|
28
39
|
focusNextPage(): void,
|
|
40
|
+
/** Moves focus to the previous page of dates, e.g. the previous month if one month is visible. */
|
|
29
41
|
focusPreviousPage(): void,
|
|
42
|
+
/** Moves focus to the start of the current page of dates, e.g. the start of the first visible month. */
|
|
30
43
|
focusPageStart(): void,
|
|
44
|
+
/** Moves focus to the end of the current page of dates, e.g. the end of the last visible month. */
|
|
31
45
|
focusPageEnd(): void,
|
|
46
|
+
/**
|
|
47
|
+
* Moves focus to the next larger section of dates based on what is currently displayed.
|
|
48
|
+
* If days are displayed, then moves to the next visible range. If weeks are displayed, then
|
|
49
|
+
* moves to the next month. If months or years are displayed, moves to the next year.
|
|
50
|
+
*/
|
|
32
51
|
focusNextSection(): void,
|
|
52
|
+
/**
|
|
53
|
+
* Moves focus to the previous larger section of dates based on what is currently displayed.
|
|
54
|
+
* If days are displayed, then moves to the previous visible range. If weeks are displayed, then
|
|
55
|
+
* moves to the previous month. If months or years are displayed, moves to the previous year.
|
|
56
|
+
*/
|
|
33
57
|
focusPreviousSection(): void,
|
|
34
|
-
|
|
35
|
-
focusPreviousPage(): void,
|
|
58
|
+
/** Selects the currently focused date. */
|
|
36
59
|
selectFocusedDate(): void,
|
|
60
|
+
/** Selects the given date. */
|
|
37
61
|
selectDate(date: CalendarDate): void,
|
|
38
|
-
|
|
62
|
+
/** Whether focus is currently within the calendar. */
|
|
63
|
+
readonly isFocused: boolean,
|
|
64
|
+
/** Sets whether focus is currently within the calendar. */
|
|
39
65
|
setFocused(value: boolean): void,
|
|
66
|
+
/** Returns whether the given date is invalid according to the `minValue` and `maxValue` props. */
|
|
40
67
|
isInvalid(date: CalendarDate): boolean,
|
|
68
|
+
/** Returns whether the given date is currently selected. */
|
|
41
69
|
isSelected(date: CalendarDate): boolean,
|
|
70
|
+
/** Returns whether the given date is currently focused. */
|
|
42
71
|
isCellFocused(date: CalendarDate): boolean,
|
|
72
|
+
/** Returns whether the given date is disabled according to the `minValue, `maxValue`, and `isDisabled` props. */
|
|
43
73
|
isCellDisabled(date: CalendarDate): boolean,
|
|
74
|
+
/** Returns whether the given date is unavailable according to the `isDateUnavailable` prop. */
|
|
75
|
+
isCellUnavailable(date: CalendarDate): boolean,
|
|
76
|
+
/** Returns whether the previous visible date range is allowed to be selected according to the `minValue` prop. */
|
|
44
77
|
isPreviousVisibleRangeInvalid(): boolean,
|
|
78
|
+
/** Returns whether the next visible date range is allowed to be selected according to the `maxValue` prop. */
|
|
45
79
|
isNextVisibleRangeInvalid(): boolean
|
|
46
80
|
}
|
|
47
81
|
|
|
48
82
|
export interface CalendarState extends CalendarStateBase {
|
|
49
|
-
|
|
83
|
+
/** The currently selected date. */
|
|
84
|
+
readonly value: CalendarDate,
|
|
85
|
+
/** Sets the currently selected date. */
|
|
50
86
|
setValue(value: CalendarDate): void
|
|
51
87
|
}
|
|
52
88
|
|
|
53
89
|
export interface RangeCalendarState extends CalendarStateBase {
|
|
54
|
-
|
|
90
|
+
/** The currently selected date range. */
|
|
91
|
+
readonly value: RangeValue<DateValue>,
|
|
92
|
+
/** Sets the currently selected date range. */
|
|
55
93
|
setValue(value: RangeValue<DateValue>): void,
|
|
94
|
+
/** Highlights the given date during selection, e.g. by hovering or dragging. */
|
|
56
95
|
highlightDate(date: CalendarDate): void,
|
|
57
|
-
|
|
96
|
+
/** The current anchor date that the user clicked on to begin range selection. */
|
|
97
|
+
readonly anchorDate: CalendarDate | null,
|
|
98
|
+
/** Sets the anchor date that the user clicked on to begin range selection. */
|
|
58
99
|
setAnchorDate(date: CalendarDate | null): void,
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
/** The currently highlighted date range. */
|
|
101
|
+
readonly highlightedRange: RangeValue<CalendarDate>,
|
|
102
|
+
/** Whether the user is currently dragging over the calendar. */
|
|
103
|
+
readonly isDragging: boolean,
|
|
104
|
+
/** Sets whether the user is dragging over the calendar. */
|
|
61
105
|
setDragging(isDragging: boolean): void
|
|
62
106
|
}
|
package/src/useCalendarState.ts
CHANGED
|
@@ -14,7 +14,8 @@ import {alignCenter, alignEnd, alignStart, constrainStart, constrainValue, isInv
|
|
|
14
14
|
import {
|
|
15
15
|
Calendar,
|
|
16
16
|
CalendarDate,
|
|
17
|
-
|
|
17
|
+
DateDuration,
|
|
18
|
+
DateFormatter,
|
|
18
19
|
GregorianCalendar,
|
|
19
20
|
isSameDay,
|
|
20
21
|
toCalendar,
|
|
@@ -24,18 +25,33 @@ import {
|
|
|
24
25
|
import {CalendarProps, DateValue} from '@react-types/calendar';
|
|
25
26
|
import {CalendarState} from './types';
|
|
26
27
|
import {useControlledState} from '@react-stately/utils';
|
|
27
|
-
import {
|
|
28
|
-
import {useEffect, useMemo, useRef, useState} from 'react';
|
|
28
|
+
import {useMemo, useRef, useState} from 'react';
|
|
29
29
|
|
|
30
|
-
interface CalendarStateOptions
|
|
30
|
+
interface CalendarStateOptions extends CalendarProps<DateValue> {
|
|
31
|
+
/** The locale to display and edit the value according to. */
|
|
31
32
|
locale: string,
|
|
33
|
+
/**
|
|
34
|
+
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
|
|
35
|
+
* object for a given calendar identifier. Such a function may be imported from the
|
|
36
|
+
* `@internationalized/date` package, or manually implemented to include support for
|
|
37
|
+
* only certain calendars.
|
|
38
|
+
*/
|
|
32
39
|
createCalendar: (name: string) => Calendar,
|
|
33
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The amount of days that will be displayed at once. This affects how pagination works.
|
|
42
|
+
* @default {months: 1}
|
|
43
|
+
*/
|
|
44
|
+
visibleDuration?: DateDuration,
|
|
45
|
+
/** Determines how to align the initial selection relative to the visible date range. */
|
|
34
46
|
selectionAlignment?: 'start' | 'center' | 'end'
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Provides state management for a calendar component.
|
|
51
|
+
* A calendar displays one or more date grids and allows users to select a single date.
|
|
52
|
+
*/
|
|
53
|
+
export function useCalendarState(props: CalendarStateOptions): CalendarState {
|
|
54
|
+
let defaultFormatter = useMemo(() => new DateFormatter(props.locale), [props.locale]);
|
|
39
55
|
let resolvedOptions = useMemo(() => defaultFormatter.resolvedOptions(), [defaultFormatter]);
|
|
40
56
|
let {
|
|
41
57
|
locale,
|
|
@@ -51,46 +67,57 @@ export function useCalendarState<T extends DateValue>(props: CalendarStateOption
|
|
|
51
67
|
let [value, setControlledValue] = useControlledState<DateValue>(props.value, props.defaultValue, props.onChange);
|
|
52
68
|
let calendarDateValue = useMemo(() => value ? toCalendar(toCalendarDate(value), calendar) : null, [value, calendar]);
|
|
53
69
|
let timeZone = useMemo(() => value && 'timeZone' in value ? value.timeZone : resolvedOptions.timeZone, [value, resolvedOptions.timeZone]);
|
|
54
|
-
let
|
|
70
|
+
let focusedCalendarDate = useMemo(() => (
|
|
71
|
+
props.focusedValue
|
|
72
|
+
? constrainValue(toCalendar(toCalendarDate(props.focusedValue), calendar), minValue, maxValue)
|
|
73
|
+
: undefined
|
|
74
|
+
), [props.focusedValue, calendar, minValue, maxValue]);
|
|
75
|
+
let defaultFocusedCalendarDate = useMemo(() => (
|
|
76
|
+
constrainValue(
|
|
77
|
+
props.defaultFocusedValue
|
|
78
|
+
? toCalendar(toCalendarDate(props.defaultFocusedValue), calendar)
|
|
79
|
+
: calendarDateValue || toCalendar(today(timeZone), calendar),
|
|
80
|
+
minValue,
|
|
81
|
+
maxValue
|
|
82
|
+
)
|
|
83
|
+
), [props.defaultFocusedValue, calendarDateValue, timeZone, calendar, minValue, maxValue]);
|
|
84
|
+
let [focusedDate, setFocusedDate] = useControlledState(focusedCalendarDate, defaultFocusedCalendarDate, props.onFocusChange);
|
|
55
85
|
let [startDate, setStartDate] = useState(() => {
|
|
56
86
|
switch (selectionAlignment) {
|
|
57
87
|
case 'start':
|
|
58
|
-
return alignStart(
|
|
88
|
+
return alignStart(focusedDate, visibleDuration, locale, minValue, maxValue);
|
|
59
89
|
case 'end':
|
|
60
|
-
return alignEnd(
|
|
90
|
+
return alignEnd(focusedDate, visibleDuration, locale, minValue, maxValue);
|
|
61
91
|
case 'center':
|
|
62
92
|
default:
|
|
63
|
-
return alignCenter(
|
|
93
|
+
return alignCenter(focusedDate, visibleDuration, locale, minValue, maxValue);
|
|
64
94
|
}
|
|
65
95
|
});
|
|
66
|
-
let [focusedDate, setFocusedDate] = useState(defaultDate);
|
|
67
96
|
let [isFocused, setFocused] = useState(props.autoFocus || false);
|
|
68
97
|
|
|
69
98
|
let endDate = useMemo(() => startDate.add(visibleDuration).subtract({days: 1}), [startDate, visibleDuration]);
|
|
70
99
|
|
|
71
100
|
// Reset focused date and visible range when calendar changes.
|
|
72
101
|
let lastCalendarIdentifier = useRef(calendar.identifier);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
if (calendar.identifier !== lastCalendarIdentifier.current) {
|
|
103
|
+
let newFocusedDate = toCalendar(focusedDate, calendar);
|
|
104
|
+
setStartDate(alignCenter(newFocusedDate, visibleDuration, locale, minValue, maxValue));
|
|
105
|
+
setFocusedDate(newFocusedDate);
|
|
106
|
+
lastCalendarIdentifier.current = calendar.identifier;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (isInvalid(focusedDate, minValue, maxValue)) {
|
|
110
|
+
// If the focused date was moved to an invalid value, it can't be focused, so constrain it.
|
|
111
|
+
setFocusedDate(constrainValue(focusedDate, minValue, maxValue));
|
|
112
|
+
} else if (focusedDate.compare(startDate) < 0) {
|
|
113
|
+
setStartDate(alignEnd(focusedDate, visibleDuration, locale, minValue, maxValue));
|
|
114
|
+
} else if (focusedDate.compare(startDate.add(visibleDuration)) >= 0) {
|
|
115
|
+
setStartDate(alignStart(focusedDate, visibleDuration, locale, minValue, maxValue));
|
|
116
|
+
}
|
|
81
117
|
|
|
82
118
|
// Sets focus to a specific cell date
|
|
83
119
|
function focusCell(date: CalendarDate) {
|
|
84
|
-
// date = constrain(focusedDate, date, visibleDuration, locale, minValue, maxValue);
|
|
85
120
|
date = constrainValue(date, minValue, maxValue);
|
|
86
|
-
|
|
87
|
-
let next = startDate.add(visibleDuration);
|
|
88
|
-
if (date.compare(startDate) < 0) {
|
|
89
|
-
setStartDate(alignEnd(date, visibleDuration, locale, minValue, maxValue));
|
|
90
|
-
} else if (date.compare(next) >= 0) {
|
|
91
|
-
setStartDate(alignStart(date, visibleDuration, locale, minValue, maxValue));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
121
|
setFocusedDate(date);
|
|
95
122
|
}
|
|
96
123
|
|
|
@@ -121,7 +148,7 @@ export function useCalendarState<T extends DateValue>(props: CalendarStateOption
|
|
|
121
148
|
focusedDate,
|
|
122
149
|
timeZone,
|
|
123
150
|
setFocusedDate(date) {
|
|
124
|
-
|
|
151
|
+
focusCell(date);
|
|
125
152
|
setFocused(true);
|
|
126
153
|
},
|
|
127
154
|
focusNextDay() {
|
|
@@ -146,13 +173,13 @@ export function useCalendarState<T extends DateValue>(props: CalendarStateOption
|
|
|
146
173
|
},
|
|
147
174
|
focusNextPage() {
|
|
148
175
|
let start = startDate.add(visibleDuration);
|
|
149
|
-
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue));
|
|
150
176
|
setFocusedDate(constrainValue(focusedDate.add(visibleDuration), minValue, maxValue));
|
|
177
|
+
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue));
|
|
151
178
|
},
|
|
152
179
|
focusPreviousPage() {
|
|
153
180
|
let start = startDate.subtract(visibleDuration);
|
|
154
|
-
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue));
|
|
155
181
|
setFocusedDate(constrainValue(focusedDate.subtract(visibleDuration), minValue, maxValue));
|
|
182
|
+
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue));
|
|
156
183
|
},
|
|
157
184
|
focusPageStart() {
|
|
158
185
|
focusCell(startDate);
|
|
@@ -190,19 +217,22 @@ export function useCalendarState<T extends DateValue>(props: CalendarStateOption
|
|
|
190
217
|
return isInvalid(date, minValue, maxValue);
|
|
191
218
|
},
|
|
192
219
|
isSelected(date) {
|
|
193
|
-
return calendarDateValue != null && isSameDay(date, calendarDateValue);
|
|
220
|
+
return calendarDateValue != null && isSameDay(date, calendarDateValue) && !this.isCellDisabled(date) && !this.isCellUnavailable(date);
|
|
194
221
|
},
|
|
195
222
|
isCellFocused(date) {
|
|
196
223
|
return isFocused && focusedDate && isSameDay(date, focusedDate);
|
|
197
224
|
},
|
|
198
225
|
isCellDisabled(date) {
|
|
199
|
-
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || isInvalid(date, minValue, maxValue);
|
|
226
|
+
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || this.isInvalid(date, minValue, maxValue);
|
|
227
|
+
},
|
|
228
|
+
isCellUnavailable(date) {
|
|
229
|
+
return props.isDateUnavailable && props.isDateUnavailable(date);
|
|
200
230
|
},
|
|
201
231
|
isPreviousVisibleRangeInvalid() {
|
|
202
|
-
return isInvalid(startDate.subtract({days: 1}), minValue, maxValue);
|
|
232
|
+
return this.isInvalid(startDate.subtract({days: 1}), minValue, maxValue);
|
|
203
233
|
},
|
|
204
234
|
isNextVisibleRangeInvalid() {
|
|
205
|
-
return isInvalid(endDate.add({days: 1}), minValue, maxValue);
|
|
235
|
+
return this.isInvalid(endDate.add({days: 1}), minValue, maxValue);
|
|
206
236
|
}
|
|
207
237
|
};
|
|
208
238
|
}
|
|
@@ -10,31 +10,46 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {alignCenter} from './utils';
|
|
14
|
-
import {Calendar, CalendarDate,
|
|
13
|
+
import {alignCenter, isInvalid} from './utils';
|
|
14
|
+
import {Calendar, CalendarDate, DateDuration, GregorianCalendar, isEqualDay, maxDate, minDate, toCalendar, toCalendarDate} from '@internationalized/date';
|
|
15
|
+
import {CalendarState, RangeCalendarState} from './types';
|
|
15
16
|
import {DateRange, DateValue} from '@react-types/calendar';
|
|
16
17
|
import {RangeCalendarProps} from '@react-types/calendar';
|
|
17
|
-
import {RangeCalendarState} from './types';
|
|
18
18
|
import {RangeValue} from '@react-types/shared';
|
|
19
19
|
import {useCalendarState} from './useCalendarState';
|
|
20
20
|
import {useControlledState} from '@react-stately/utils';
|
|
21
|
-
import {useState} from 'react';
|
|
21
|
+
import {useMemo, useRef, useState} from 'react';
|
|
22
22
|
|
|
23
|
-
interface RangeCalendarStateOptions
|
|
23
|
+
interface RangeCalendarStateOptions extends RangeCalendarProps<DateValue> {
|
|
24
|
+
/** The locale to display and edit the value according to. */
|
|
24
25
|
locale: string,
|
|
26
|
+
/**
|
|
27
|
+
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
|
|
28
|
+
* object for a given calendar identifier. Such a function may be imported from the
|
|
29
|
+
* `@internationalized/date` package, or manually implemented to include support for
|
|
30
|
+
* only certain calendars.
|
|
31
|
+
*/
|
|
25
32
|
createCalendar: (name: string) => Calendar,
|
|
26
|
-
|
|
33
|
+
/**
|
|
34
|
+
* The amount of days that will be displayed at once. This affects how pagination works.
|
|
35
|
+
* @default {months: 1}
|
|
36
|
+
*/
|
|
37
|
+
visibleDuration?: DateDuration
|
|
27
38
|
}
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Provides state management for a range calendar component.
|
|
42
|
+
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
|
|
43
|
+
*/
|
|
44
|
+
export function useRangeCalendarState(props: RangeCalendarStateOptions): RangeCalendarState {
|
|
30
45
|
let {value: valueProp, defaultValue, onChange, createCalendar, locale, visibleDuration = {months: 1}, minValue, maxValue, ...calendarProps} = props;
|
|
31
46
|
let [value, setValue] = useControlledState<DateRange>(
|
|
32
47
|
valueProp,
|
|
33
|
-
defaultValue,
|
|
48
|
+
defaultValue || null,
|
|
34
49
|
onChange
|
|
35
50
|
);
|
|
36
51
|
|
|
37
|
-
let [anchorDate,
|
|
52
|
+
let [anchorDate, setAnchorDateState] = useState(null);
|
|
38
53
|
let alignment: 'center' | 'start' = 'center';
|
|
39
54
|
if (value && value.start && value.end) {
|
|
40
55
|
let start = alignCenter(toCalendarDate(value.start), visibleDuration, locale, minValue, maxValue);
|
|
@@ -45,17 +60,53 @@ export function useRangeCalendarState<T extends DateValue>(props: RangeCalendarS
|
|
|
45
60
|
}
|
|
46
61
|
}
|
|
47
62
|
|
|
63
|
+
// Available range must be stored in a ref so we have access to the updated version immediately in `isInvalid`.
|
|
64
|
+
let availableRangeRef = useRef<RangeValue<DateValue>>(null);
|
|
65
|
+
let [availableRange, setAvailableRange] = useState<RangeValue<DateValue>>(null);
|
|
66
|
+
let min = useMemo(() => maxDate(minValue, availableRange?.start), [minValue, availableRange]);
|
|
67
|
+
let max = useMemo(() => minDate(maxValue, availableRange?.end), [maxValue, availableRange]);
|
|
68
|
+
|
|
48
69
|
let calendar = useCalendarState({
|
|
49
70
|
...calendarProps,
|
|
50
71
|
value: value && value.start,
|
|
51
72
|
createCalendar,
|
|
52
73
|
locale,
|
|
53
74
|
visibleDuration,
|
|
54
|
-
minValue,
|
|
55
|
-
maxValue,
|
|
75
|
+
minValue: min,
|
|
76
|
+
maxValue: max,
|
|
56
77
|
selectionAlignment: alignment
|
|
57
78
|
});
|
|
58
79
|
|
|
80
|
+
let updateAvailableRange = (date) => {
|
|
81
|
+
if (date && props.isDateUnavailable && !props.allowsNonContiguousRanges) {
|
|
82
|
+
availableRangeRef.current = {
|
|
83
|
+
start: nextUnavailableDate(date, calendar, -1),
|
|
84
|
+
end: nextUnavailableDate(date, calendar, 1)
|
|
85
|
+
};
|
|
86
|
+
setAvailableRange(availableRangeRef.current);
|
|
87
|
+
} else {
|
|
88
|
+
availableRangeRef.current = null;
|
|
89
|
+
setAvailableRange(null);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// If the visible range changes, we need to update the available range.
|
|
94
|
+
let lastVisibleRange = useRef(calendar.visibleRange);
|
|
95
|
+
if (!isEqualDay(calendar.visibleRange.start, lastVisibleRange.current.start) || !isEqualDay(calendar.visibleRange.end, lastVisibleRange.current.end)) {
|
|
96
|
+
updateAvailableRange(anchorDate);
|
|
97
|
+
lastVisibleRange.current = calendar.visibleRange;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let setAnchorDate = (date: CalendarDate) => {
|
|
101
|
+
if (date) {
|
|
102
|
+
setAnchorDateState(date);
|
|
103
|
+
updateAvailableRange(date);
|
|
104
|
+
} else {
|
|
105
|
+
setAnchorDateState(null);
|
|
106
|
+
updateAvailableRange(null);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
59
110
|
let highlightedRange = anchorDate ? makeRange(anchorDate, calendar.focusedDate) : value && makeRange(value.start, value.end);
|
|
60
111
|
let selectDate = (date: CalendarDate) => {
|
|
61
112
|
if (props.isReadOnly) {
|
|
@@ -93,7 +144,10 @@ export function useRangeCalendarState<T extends DateValue>(props: RangeCalendarS
|
|
|
93
144
|
}
|
|
94
145
|
},
|
|
95
146
|
isSelected(date) {
|
|
96
|
-
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0;
|
|
147
|
+
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date) && !calendar.isCellUnavailable(date);
|
|
148
|
+
},
|
|
149
|
+
isInvalid(date) {
|
|
150
|
+
return calendar.isInvalid(date) || isInvalid(date, availableRangeRef.current?.start, availableRangeRef.current?.end);
|
|
97
151
|
},
|
|
98
152
|
isDragging,
|
|
99
153
|
setDragging
|
|
@@ -124,3 +178,19 @@ function convertValue(newValue: CalendarDate, oldValue: DateValue) {
|
|
|
124
178
|
|
|
125
179
|
return newValue;
|
|
126
180
|
}
|
|
181
|
+
|
|
182
|
+
function nextUnavailableDate(anchorDate: CalendarDate, state: CalendarState, dir: number) {
|
|
183
|
+
let nextDate = anchorDate.add({days: dir});
|
|
184
|
+
while (
|
|
185
|
+
(dir < 0 ? nextDate.compare(state.visibleRange.start) >= 0 : nextDate.compare(state.visibleRange.end) <= 0) &&
|
|
186
|
+
!state.isCellUnavailable(nextDate)
|
|
187
|
+
) {
|
|
188
|
+
nextDate = nextDate.add({days: dir});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (state.isCellUnavailable(nextDate)) {
|
|
192
|
+
return nextDate.add({days: -dir});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return null;
|
|
196
|
+
}
|