@coreui/react-pro 5.10.0 → 5.11.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/README.md +1 -1
- package/dist/cjs/components/accordion/CAccordionButton.js +2 -2
- package/dist/cjs/components/accordion/CAccordionButton.js.map +1 -1
- package/dist/cjs/components/accordion/CAccordionItem.d.ts +1 -0
- package/dist/cjs/components/accordion/CAccordionItem.js +6 -3
- package/dist/cjs/components/accordion/CAccordionItem.js.map +1 -1
- package/dist/cjs/components/badge/CBadge.js +1 -1
- package/dist/cjs/components/badge/CBadge.js.map +1 -1
- package/dist/cjs/components/calendar/CCalendar.d.ts +57 -44
- package/dist/cjs/components/calendar/CCalendar.js +51 -187
- package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
- package/dist/cjs/components/calendar/CCalendarNavigation.d.ts +21 -0
- package/dist/cjs/components/calendar/CCalendarNavigation.js +23 -0
- package/dist/cjs/components/calendar/CCalendarNavigation.js.map +1 -0
- package/dist/cjs/components/calendar/CCalendarPanel.d.ts +28 -0
- package/dist/cjs/components/calendar/CCalendarPanel.js +149 -0
- package/dist/cjs/components/calendar/CCalendarPanel.js.map +1 -0
- package/dist/cjs/components/calendar/types.d.ts +3 -0
- package/dist/cjs/components/calendar/utils.d.ts +175 -18
- package/dist/cjs/components/calendar/utils.js +312 -43
- package/dist/cjs/components/calendar/utils.js.map +1 -1
- package/dist/cjs/components/date-picker/CDatePicker.d.ts +1 -1
- package/dist/cjs/components/date-range-picker/CDateRangePicker.d.ts +2 -2
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js +0 -2
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/cjs/components/date-range-picker/utils.d.ts +16 -0
- package/dist/cjs/components/date-range-picker/utils.js +18 -2
- package/dist/cjs/components/date-range-picker/utils.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdownToggle.js +1 -1
- package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/cjs/components/modal/CModal.js +0 -1
- package/dist/cjs/components/modal/CModal.js.map +1 -1
- package/dist/cjs/components/nav/CNavGroup.js +1 -1
- package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
- package/dist/cjs/components/progress/CProgress.d.ts +1 -1
- package/dist/cjs/components/range-slider/CRangeSlider.js +6 -2
- package/dist/cjs/components/range-slider/CRangeSlider.js.map +1 -1
- package/dist/cjs/components/sidebar/CSidebar.d.ts +7 -2
- package/dist/cjs/components/sidebar/CSidebar.js +7 -6
- package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
- package/dist/cjs/components/smart-pagination/CSmartPagination.d.ts +4 -12
- package/dist/cjs/components/smart-pagination/CSmartPagination.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableHead.js +10 -25
- package/dist/cjs/components/smart-table/CSmartTableHead.js.map +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.d.ts +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/cjs/components/time-picker/types.d.ts +5 -0
- package/dist/cjs/components/time-picker/utils.d.ts +8 -11
- package/dist/cjs/components/time-picker/utils.js +8 -4
- package/dist/cjs/components/time-picker/utils.js.map +1 -1
- package/dist/cjs/hooks/index.d.ts +2 -1
- package/dist/cjs/hooks/useClipboard.d.ts +12 -0
- package/dist/cjs/hooks/useClipboard.js +54 -0
- package/dist/cjs/hooks/useClipboard.js.map +1 -0
- package/dist/cjs/hooks/useColorModes.js +5 -5
- package/dist/cjs/hooks/useColorModes.js.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node_modules/react-device-detect/dist/lib.js +1 -1
- package/dist/cjs/node_modules/react-device-detect/dist/lib.js.map +1 -1
- package/dist/cjs/node_modules/tslib/tslib.es6.js +40 -0
- package/dist/cjs/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +2 -1
- package/dist/cjs/utils/mergeClassNames.d.ts +2 -0
- package/dist/esm/components/accordion/CAccordionButton.js +2 -2
- package/dist/esm/components/accordion/CAccordionButton.js.map +1 -1
- package/dist/esm/components/accordion/CAccordionItem.d.ts +1 -0
- package/dist/esm/components/accordion/CAccordionItem.js +7 -4
- package/dist/esm/components/accordion/CAccordionItem.js.map +1 -1
- package/dist/esm/components/badge/CBadge.js +1 -1
- package/dist/esm/components/badge/CBadge.js.map +1 -1
- package/dist/esm/components/calendar/CCalendar.d.ts +57 -44
- package/dist/esm/components/calendar/CCalendar.js +52 -188
- package/dist/esm/components/calendar/CCalendar.js.map +1 -1
- package/dist/esm/components/calendar/CCalendarNavigation.d.ts +21 -0
- package/dist/esm/components/calendar/CCalendarNavigation.js +21 -0
- package/dist/esm/components/calendar/CCalendarNavigation.js.map +1 -0
- package/dist/esm/components/calendar/CCalendarPanel.d.ts +28 -0
- package/dist/esm/components/calendar/CCalendarPanel.js +147 -0
- package/dist/esm/components/calendar/CCalendarPanel.js.map +1 -0
- package/dist/esm/components/calendar/types.d.ts +3 -0
- package/dist/esm/components/calendar/utils.d.ts +175 -18
- package/dist/esm/components/calendar/utils.js +306 -44
- package/dist/esm/components/calendar/utils.js.map +1 -1
- package/dist/esm/components/date-picker/CDatePicker.d.ts +1 -1
- package/dist/esm/components/date-range-picker/CDateRangePicker.d.ts +2 -2
- package/dist/esm/components/date-range-picker/CDateRangePicker.js +0 -2
- package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/esm/components/date-range-picker/utils.d.ts +16 -0
- package/dist/esm/components/date-range-picker/utils.js +18 -2
- package/dist/esm/components/date-range-picker/utils.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdownToggle.js +1 -1
- package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/esm/components/modal/CModal.js +0 -1
- package/dist/esm/components/modal/CModal.js.map +1 -1
- package/dist/esm/components/nav/CNavGroup.js +1 -1
- package/dist/esm/components/nav/CNavGroup.js.map +1 -1
- package/dist/esm/components/progress/CProgress.d.ts +1 -1
- package/dist/esm/components/range-slider/CRangeSlider.js +6 -2
- package/dist/esm/components/range-slider/CRangeSlider.js.map +1 -1
- package/dist/esm/components/sidebar/CSidebar.d.ts +7 -2
- package/dist/esm/components/sidebar/CSidebar.js +7 -6
- package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
- package/dist/esm/components/smart-pagination/CSmartPagination.d.ts +4 -12
- package/dist/esm/components/smart-pagination/CSmartPagination.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableHead.js +11 -26
- package/dist/esm/components/smart-table/CSmartTableHead.js.map +1 -1
- package/dist/esm/components/time-picker/CTimePicker.d.ts +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/esm/components/time-picker/types.d.ts +5 -0
- package/dist/esm/components/time-picker/utils.d.ts +8 -11
- package/dist/esm/components/time-picker/utils.js +8 -4
- package/dist/esm/components/time-picker/utils.js.map +1 -1
- package/dist/esm/hooks/index.d.ts +2 -1
- package/dist/esm/hooks/useClipboard.d.ts +12 -0
- package/dist/esm/hooks/useClipboard.js +52 -0
- package/dist/esm/hooks/useClipboard.js.map +1 -0
- package/dist/esm/hooks/useColorModes.js +5 -5
- package/dist/esm/hooks/useColorModes.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/react-device-detect/dist/lib.js +1 -1
- package/dist/esm/node_modules/react-device-detect/dist/lib.js.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js +39 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/esm/utils/index.d.ts +2 -1
- package/dist/esm/utils/mergeClassNames.d.ts +2 -0
- package/package.json +12 -10
- package/src/components/accordion/CAccordionButton.tsx +3 -2
- package/src/components/accordion/CAccordionItem.tsx +8 -3
- package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.tsx.snap +0 -2
- package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.tsx.snap +0 -2
- package/src/components/badge/CBadge.tsx +1 -1
- package/src/components/calendar/CCalendar.tsx +154 -489
- package/src/components/calendar/CCalendarNavigation.tsx +120 -0
- package/src/components/calendar/CCalendarPanel.tsx +306 -0
- package/src/components/calendar/types.ts +5 -0
- package/src/components/calendar/utils.ts +414 -109
- package/src/components/carousel/__tests__/CCarousel.spec.tsx +1 -2
- package/src/components/date-picker/CDatePicker.tsx +1 -1
- package/src/components/date-range-picker/CDateRangePicker.tsx +2 -4
- package/src/components/date-range-picker/utils.ts +23 -3
- package/src/components/dropdown/CDropdownToggle.tsx +1 -1
- package/src/components/dropdown/__tests__/CDropdown.spec.tsx +43 -19
- package/src/components/modal/CModal.tsx +0 -2
- package/src/components/modal/__tests__/CModal.spec.tsx +33 -25
- package/src/components/nav/CNavGroup.tsx +5 -1
- package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +4 -1
- package/src/components/popover/__tests__/CPopover.spec.tsx +1 -1
- package/src/components/popover/__tests__/__snapshots__/CPopover.spec.tsx.snap +2 -3
- package/src/components/progress/CProgress.tsx +1 -1
- package/src/components/range-slider/CRangeSlider.tsx +7 -2
- package/src/components/sidebar/CSidebar.tsx +15 -5
- package/src/components/smart-pagination/CSmartPagination.tsx +4 -12
- package/src/components/smart-table/CSmartTableHead.tsx +7 -34
- package/src/components/time-picker/CTimePicker.tsx +3 -3
- package/src/components/time-picker/types.ts +7 -0
- package/src/components/time-picker/utils.ts +15 -13
- package/src/components/tooltip/__tests__/__snapshots__/CTooltip.spec.tsx.snap +0 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useClipboard.ts +38 -0
- package/src/hooks/useColorModes.ts +5 -5
- package/src/utils/index.ts +2 -0
- package/src/utils/mergeClassNames.ts +25 -0
|
@@ -1,595 +1,250 @@
|
|
|
1
|
-
import React, { forwardRef,
|
|
1
|
+
import React, { forwardRef, ReactNode, useEffect, useRef, useState } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { CCalendarNavigation } from './CCalendarNavigation'
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
convertToDateObject,
|
|
9
|
-
createGroupsInArray,
|
|
10
9
|
getCalendarDate,
|
|
11
10
|
getDateBySelectionType,
|
|
12
|
-
|
|
13
|
-
getMonthsNames,
|
|
14
|
-
getYears,
|
|
11
|
+
getSelectableDates,
|
|
15
12
|
isDateDisabled,
|
|
16
|
-
isDateInRange,
|
|
17
|
-
isDateSelected,
|
|
18
13
|
isDisableDateInRange,
|
|
19
14
|
isSameDateAs,
|
|
20
|
-
isToday,
|
|
21
15
|
} from './utils'
|
|
16
|
+
import type { DisabledDate, SelectionTypes, ViewTypes } from './types'
|
|
22
17
|
|
|
23
18
|
import { useForkedRef, useStateWithCallback } from '../../hooks'
|
|
24
|
-
|
|
25
|
-
export type DisabledDate = ((date: Date) => boolean) | Date | Date[]
|
|
19
|
+
import { CCalendarPanel } from './CCalendarPanel'
|
|
26
20
|
|
|
27
21
|
export interface CCalendarProps {
|
|
28
22
|
/**
|
|
29
|
-
* A string that provides an accessible label for the button that navigates to the next month in the
|
|
23
|
+
* A string that provides an accessible label for the button that navigates to the next month in the React Calendar component. This label is read by screen readers to describe the action associated with the button. Customize for a more accessible calendar experience.
|
|
30
24
|
*
|
|
25
|
+
* @default 'Next month'
|
|
31
26
|
* @since 5.5.0
|
|
32
27
|
*/
|
|
28
|
+
|
|
33
29
|
ariaNavNextMonthLabel?: string
|
|
30
|
+
|
|
34
31
|
/**
|
|
35
|
-
* A string that provides an accessible label for the button that navigates to the next year in the
|
|
32
|
+
* A string that provides an accessible label for the button that navigates to the next year in the React Calendar component. Screen readers utilize this label to inform users of the button's functionality, aiding in a more inclusive application.
|
|
36
33
|
*
|
|
34
|
+
* @default 'Next year'
|
|
37
35
|
* @since 5.5.0
|
|
38
36
|
*/
|
|
39
37
|
ariaNavNextYearLabel?: string
|
|
38
|
+
|
|
40
39
|
/**
|
|
41
|
-
* A string that provides an accessible label for the button that navigates to the previous month in the
|
|
40
|
+
* A string that provides an accessible label for the button that navigates to the previous month in the React Calendar component. This label is announced by screen readers, ensuring clarity around the button's purpose.
|
|
42
41
|
*
|
|
42
|
+
* @default 'Previous month'
|
|
43
43
|
* @since 5.5.0
|
|
44
44
|
*/
|
|
45
45
|
ariaNavPrevMonthLabel?: string
|
|
46
|
+
|
|
46
47
|
/**
|
|
47
|
-
* A string that provides an accessible label for the button that navigates to the previous year in the
|
|
48
|
+
* A string that provides an accessible label for the button that navigates to the previous year in the React Calendar component. Use it to enhance the experience for screen readers and further accessibility.
|
|
48
49
|
*
|
|
50
|
+
* @default 'Previous year'
|
|
49
51
|
* @since 5.5.0
|
|
50
52
|
*/
|
|
51
53
|
ariaNavPrevYearLabel?: string
|
|
54
|
+
|
|
52
55
|
/**
|
|
53
|
-
*
|
|
56
|
+
* Defines the initial date or reference date for the React Calendar component. This date can be either a Date object or a string that can be converted into a valid date.
|
|
54
57
|
*/
|
|
55
58
|
calendarDate?: Date | string | null
|
|
59
|
+
|
|
56
60
|
/**
|
|
57
|
-
*
|
|
61
|
+
* Specifies how many individual calendars should be displayed side by side on desktop devices. Increasing this number allows your users to view multiple months (or years, etc.) simultaneously.
|
|
58
62
|
*/
|
|
59
63
|
calendars?: number
|
|
64
|
+
|
|
60
65
|
/**
|
|
61
|
-
* A string of all
|
|
66
|
+
* A string of all classNames you want to apply to the outermost container of the React Calendar component. Use this to style or theme your calendar.
|
|
62
67
|
*/
|
|
63
68
|
className?: string
|
|
69
|
+
|
|
64
70
|
/**
|
|
65
|
-
*
|
|
71
|
+
* Sets the format for day names. Accepts either a built-in format ('numeric' or '2-digit') or a custom function to return any desired string or number for the day.
|
|
66
72
|
*
|
|
67
73
|
* @default 'numeric'
|
|
68
74
|
* @since 4.3.0
|
|
69
75
|
*/
|
|
70
76
|
dayFormat?: 'numeric' | '2-digit' | ((date: Date) => string | number)
|
|
77
|
+
|
|
71
78
|
/**
|
|
72
|
-
*
|
|
79
|
+
* Specifies one or more dates that cannot be selected by the user. This is useful for disabling weekends, holidays, or any dates that you need to restrict within your React Calendar component.
|
|
73
80
|
*/
|
|
74
81
|
disabledDates?: DisabledDate | DisabledDate[]
|
|
82
|
+
|
|
75
83
|
/**
|
|
76
|
-
*
|
|
84
|
+
* Defines the initially selected ending date (applicable when using range selection). Accepts both Date objects and valid date strings.
|
|
77
85
|
*/
|
|
78
86
|
endDate?: Date | string | null
|
|
87
|
+
|
|
79
88
|
/**
|
|
80
|
-
* Sets the day of
|
|
81
|
-
* - 0
|
|
82
|
-
* - 1
|
|
83
|
-
* - 2
|
|
84
|
-
* - 3
|
|
85
|
-
* - 4
|
|
86
|
-
* - 5
|
|
87
|
-
* - 6
|
|
89
|
+
* Sets the first day of the week. This can be adjusted for different locales or preferences:
|
|
90
|
+
* - `0` = Sunday
|
|
91
|
+
* - `1` = Monday
|
|
92
|
+
* - `2` = Tuesday
|
|
93
|
+
* - `3` = Wednesday
|
|
94
|
+
* - `4` = Thursday
|
|
95
|
+
* - `5` = Friday
|
|
96
|
+
* - `6` = Saturday
|
|
88
97
|
*
|
|
89
98
|
* @default 1
|
|
90
99
|
*/
|
|
91
100
|
firstDayOfWeek?: number
|
|
101
|
+
|
|
92
102
|
/**
|
|
93
|
-
*
|
|
103
|
+
* Indicates the locale for the React Calendar component. If not explicitly provided, it inherits the locale settings from the browser.
|
|
94
104
|
*
|
|
95
105
|
* @default 'default'
|
|
96
106
|
*/
|
|
97
107
|
locale?: string
|
|
108
|
+
|
|
98
109
|
/**
|
|
99
|
-
*
|
|
110
|
+
* The maximum date that can be selected. Any date beyond this value will be disabled within the calendar. This is often used to restrict future selections.
|
|
100
111
|
*/
|
|
101
112
|
maxDate?: Date | string | null
|
|
113
|
+
|
|
102
114
|
/**
|
|
103
|
-
*
|
|
115
|
+
* The minimum date that can be selected. Any date before this value will be disabled in the calendar. Useful for preventing selection of past dates or creating limited booking windows.
|
|
104
116
|
*/
|
|
105
117
|
minDate?: Date | string | null
|
|
118
|
+
|
|
106
119
|
/**
|
|
107
|
-
*
|
|
120
|
+
* Toggles display of arrow-based navigation (previous/next controls) in the React Calendar component. If set to `false`, you can build custom navigation or handle the navigation programmatically.
|
|
108
121
|
*/
|
|
109
122
|
navigation?: boolean
|
|
123
|
+
|
|
110
124
|
/**
|
|
111
|
-
*
|
|
125
|
+
* Customizes the icon for navigating to the next view (month, year, etc.) depending on the current view. Accepts any valid `ReactNode`, enabling you to display text, images, or icons.
|
|
112
126
|
*/
|
|
113
127
|
navNextIcon?: ReactNode
|
|
128
|
+
|
|
114
129
|
/**
|
|
115
|
-
*
|
|
130
|
+
* Customizes the icon for navigating multiple steps forward (double jump), e.g., skipping multiple months or years at once. Ideal for quick navigation through large date ranges.
|
|
116
131
|
*/
|
|
117
132
|
navNextDoubleIcon?: ReactNode
|
|
133
|
+
|
|
118
134
|
/**
|
|
119
|
-
*
|
|
135
|
+
* Customizes the icon for navigating to the previous view in the calendar. Accepts any valid ReactNode to provide flexible styling or theming.
|
|
120
136
|
*/
|
|
121
137
|
navPrevIcon?: ReactNode
|
|
138
|
+
|
|
122
139
|
/**
|
|
123
|
-
*
|
|
140
|
+
* Customizes the icon for a double jump backward (e.g., jumping multiple months or years at once). This feature simplifies larger date range navigation within your React Calendar component.
|
|
124
141
|
*/
|
|
125
142
|
navPrevDoubleIcon?: ReactNode
|
|
143
|
+
|
|
126
144
|
/**
|
|
127
|
-
*
|
|
145
|
+
* Reorders the year and month navigation, rendering the year selector first. This offers a different layout for users, particularly useful if you want to prioritize quick year changes.
|
|
128
146
|
*
|
|
147
|
+
* @default false
|
|
129
148
|
* @since 4.3.0
|
|
130
149
|
*/
|
|
131
150
|
navYearFirst?: boolean
|
|
151
|
+
|
|
132
152
|
/**
|
|
133
|
-
*
|
|
153
|
+
* Enables range selection mode in your React Calendar component, allowing users to select two dates for a range (start and end). Once enabled, the component will manage state for both dates.
|
|
134
154
|
*/
|
|
135
155
|
range?: boolean
|
|
156
|
+
|
|
136
157
|
/**
|
|
137
|
-
*
|
|
158
|
+
* Sets whether days from adjacent months (shown at the start/end of the current view) are selectable. This only applies if `showAdjacementDays` is set to `true`.
|
|
138
159
|
*
|
|
160
|
+
* @default false
|
|
139
161
|
* @since 4.11.0
|
|
140
162
|
*/
|
|
141
163
|
selectAdjacementDays?: boolean
|
|
164
|
+
|
|
142
165
|
/**
|
|
143
|
-
*
|
|
166
|
+
* Controls whether the calendar should display dates from previous or next months (non-selectable if `selectAdjacementDays` is `false`). This can make the calendar visually continuous.
|
|
144
167
|
*
|
|
168
|
+
* @default true
|
|
145
169
|
* @since 4.11.0
|
|
146
170
|
*/
|
|
147
171
|
showAdjacementDays?: boolean
|
|
172
|
+
|
|
148
173
|
/**
|
|
149
|
-
*
|
|
174
|
+
* Toggles the display of week numbers (ISO 8601) in the calendar's left column. Particularly beneficial for applications where users need to see the week index for scheduling or reporting.
|
|
150
175
|
*
|
|
176
|
+
* @default false
|
|
151
177
|
* @since 5.0.0
|
|
152
178
|
*/
|
|
153
179
|
showWeekNumber?: boolean
|
|
180
|
+
|
|
154
181
|
/**
|
|
155
|
-
*
|
|
182
|
+
* Indicates if the user's current selection is targeting the end date in range selection mode. Primarily used for controlled components where you need to manage which date (start or end) is currently active.
|
|
156
183
|
*/
|
|
157
184
|
selectEndDate?: boolean
|
|
185
|
+
|
|
158
186
|
/**
|
|
159
|
-
*
|
|
187
|
+
* Specifies the selection type for the React Calendar component. Supports:
|
|
188
|
+
* - `day`: Regular day selection (default)
|
|
189
|
+
* - `week`: Select an entire week
|
|
190
|
+
* - `month`: Select an entire month
|
|
191
|
+
* - `year`: Select an entire year
|
|
160
192
|
*
|
|
193
|
+
* @default 'day'
|
|
161
194
|
* @since 5.0.0
|
|
162
195
|
*/
|
|
163
|
-
selectionType?:
|
|
196
|
+
selectionType?: SelectionTypes
|
|
197
|
+
|
|
164
198
|
/**
|
|
165
|
-
*
|
|
199
|
+
* Defines the initially selected starting date. This date can be a Date object or a string convertible into a valid date. Useful when you want to show a pre-selected date.
|
|
166
200
|
*/
|
|
167
201
|
startDate?: Date | string | null
|
|
202
|
+
|
|
168
203
|
/**
|
|
169
|
-
*
|
|
204
|
+
* Sets the format or length of the weekday names displayed in the calendar header. You can use numeric values like 2 (two-letter abbreviations) or built-in string formats like `'long'`, `'narrow'`, and `'short'`, or provide a custom function to fully control how weekdays are displayed.
|
|
170
205
|
*
|
|
171
206
|
* @default 2
|
|
172
207
|
*/
|
|
173
208
|
weekdayFormat?: number | 'long' | 'narrow' | 'short' | ((date: Date) => string | number)
|
|
209
|
+
|
|
174
210
|
/**
|
|
175
|
-
*
|
|
211
|
+
* Defines the label that appears above the week numbers column. For example, you might label it `'WK'` or `'Week #'`.
|
|
176
212
|
*
|
|
177
213
|
* @since 5.0.0
|
|
178
214
|
*/
|
|
179
215
|
weekNumbersLabel?: string
|
|
216
|
+
|
|
180
217
|
/**
|
|
181
|
-
* Callback fired when the calendar date
|
|
218
|
+
* Callback fired when the calendar's reference date (i.e., the date indicating which month/year is currently displayed) changes. Receives the new `Date | string` as an argument for further handling.
|
|
182
219
|
*/
|
|
183
220
|
onCalendarDateChange?: (date: Date | string) => void
|
|
221
|
+
|
|
184
222
|
/**
|
|
185
|
-
* Callback fired when the user hovers over
|
|
223
|
+
* Callback fired when the user hovers over a calendar cell. The argument is the date of the cell that the user is currently hovering.
|
|
186
224
|
*/
|
|
187
225
|
onDateHover?: (date: Date | string | null) => void
|
|
226
|
+
|
|
188
227
|
/**
|
|
189
|
-
* Callback
|
|
228
|
+
* Callback triggered when the start date of the selection changes. Useful for updating other parts of your application or performing side effects based on the newly chosen start date.
|
|
190
229
|
*/
|
|
191
|
-
onStartDateChange?: (date: Date | string | null, formatedDate?: string | undefined) => void
|
|
230
|
+
onStartDateChange?: (date: Date | string | null, formatedDate?: string | undefined) => void
|
|
231
|
+
|
|
192
232
|
/**
|
|
193
|
-
* Callback
|
|
233
|
+
* Callback triggered when the end date of the selection changes. Handy for synchronizing the selected date range with external states or components.
|
|
194
234
|
*/
|
|
195
|
-
onEndDateChange?: (date: Date | string | null, formatedDate?: string | undefined) => void
|
|
235
|
+
onEndDateChange?: (date: Date | string | null, formatedDate?: string | undefined) => void
|
|
236
|
+
|
|
196
237
|
/**
|
|
197
|
-
* Callback fired when the selection
|
|
238
|
+
* Callback fired when toggling between selecting the start date and the end date in range selection mode. Receives a boolean indicating if the user is currently selecting the end date.
|
|
198
239
|
*/
|
|
199
240
|
onSelectEndChange?: (value: boolean) => void
|
|
241
|
+
|
|
200
242
|
/**
|
|
201
|
-
* Callback fired when the view
|
|
243
|
+
* Callback fired when the calendar's view changes between days, months, or years. For instance, moving from day view to month view or from month view to year view.
|
|
202
244
|
*/
|
|
203
245
|
onViewChanged?: (view: string) => void
|
|
204
246
|
}
|
|
205
247
|
|
|
206
|
-
const Calendar = (props: {
|
|
207
|
-
calendarDate: Date
|
|
208
|
-
dayFormat?: 'numeric' | '2-digit' | ((date: Date) => string | number)
|
|
209
|
-
disabledDates?: DisabledDate | DisabledDate[]
|
|
210
|
-
endDate: Date | null
|
|
211
|
-
firstDayOfWeek: number
|
|
212
|
-
hoverDate: Date | null
|
|
213
|
-
locale: string
|
|
214
|
-
maxDate: Date | null
|
|
215
|
-
minDate: Date | null
|
|
216
|
-
onCalendarClick: (date: Date) => void
|
|
217
|
-
onCalendarKeyDown: (event: KeyboardEvent<HTMLDivElement>, date: Date) => void
|
|
218
|
-
onCalendarMouseEnter: (date: Date) => void
|
|
219
|
-
onCalendarMouseLeave: () => void
|
|
220
|
-
order: number
|
|
221
|
-
selectAdjacementDays: boolean
|
|
222
|
-
selectEndDate: boolean | undefined
|
|
223
|
-
selectionType: 'day' | 'week' | 'month' | 'year'
|
|
224
|
-
showAdjacementDays: boolean
|
|
225
|
-
showWeekNumber: boolean
|
|
226
|
-
startDate: Date | null
|
|
227
|
-
view: 'days' | 'months' | 'years'
|
|
228
|
-
weekdayFormat: number | 'long' | 'narrow' | 'short' | ((date: Date) => string | number)
|
|
229
|
-
weekNumbersLabel: string | undefined
|
|
230
|
-
}) => {
|
|
231
|
-
const {
|
|
232
|
-
calendarDate,
|
|
233
|
-
dayFormat,
|
|
234
|
-
disabledDates,
|
|
235
|
-
endDate,
|
|
236
|
-
firstDayOfWeek,
|
|
237
|
-
hoverDate,
|
|
238
|
-
locale,
|
|
239
|
-
maxDate,
|
|
240
|
-
minDate,
|
|
241
|
-
onCalendarClick,
|
|
242
|
-
onCalendarKeyDown,
|
|
243
|
-
onCalendarMouseEnter,
|
|
244
|
-
onCalendarMouseLeave,
|
|
245
|
-
selectAdjacementDays,
|
|
246
|
-
selectEndDate,
|
|
247
|
-
selectionType,
|
|
248
|
-
showWeekNumber,
|
|
249
|
-
showAdjacementDays,
|
|
250
|
-
startDate,
|
|
251
|
-
view,
|
|
252
|
-
weekdayFormat,
|
|
253
|
-
weekNumbersLabel,
|
|
254
|
-
} = props
|
|
255
|
-
const [listOfMonths, setListOfMonths] = useState<string[][]>([])
|
|
256
|
-
|
|
257
|
-
useEffect(() => {
|
|
258
|
-
setListOfMonths(createGroupsInArray(getMonthsNames(locale), 4))
|
|
259
|
-
}, [])
|
|
260
|
-
|
|
261
|
-
const monthDetails = getMonthDetails(
|
|
262
|
-
calendarDate.getFullYear(),
|
|
263
|
-
calendarDate.getMonth(),
|
|
264
|
-
firstDayOfWeek,
|
|
265
|
-
)
|
|
266
|
-
const listOfYears = createGroupsInArray(getYears(calendarDate.getFullYear()), 4)
|
|
267
|
-
const weekDays = monthDetails[0].days
|
|
268
|
-
|
|
269
|
-
return (
|
|
270
|
-
<table>
|
|
271
|
-
{view === 'days' && (
|
|
272
|
-
<thead>
|
|
273
|
-
<tr>
|
|
274
|
-
{showWeekNumber && (
|
|
275
|
-
<th className="calendar-cell">
|
|
276
|
-
<div className="calendar-header-cell-inner">{weekNumbersLabel}</div>
|
|
277
|
-
</th>
|
|
278
|
-
)}
|
|
279
|
-
{weekDays.map(({ date }: { date: Date }, idx: number) => (
|
|
280
|
-
<th
|
|
281
|
-
className="calendar-cell"
|
|
282
|
-
abbr={date.toLocaleDateString(locale, { weekday: 'long' })}
|
|
283
|
-
key={idx}
|
|
284
|
-
>
|
|
285
|
-
<div className="calendar-header-cell-inner">
|
|
286
|
-
{typeof weekdayFormat === 'function'
|
|
287
|
-
? weekdayFormat(date)
|
|
288
|
-
: typeof weekdayFormat === 'string'
|
|
289
|
-
? date.toLocaleDateString(locale, { weekday: weekdayFormat })
|
|
290
|
-
: date
|
|
291
|
-
.toLocaleDateString(locale, { weekday: 'long' })
|
|
292
|
-
.slice(0, weekdayFormat)}
|
|
293
|
-
</div>
|
|
294
|
-
</th>
|
|
295
|
-
))}
|
|
296
|
-
</tr>
|
|
297
|
-
</thead>
|
|
298
|
-
)}
|
|
299
|
-
<tbody>
|
|
300
|
-
{view === 'days' &&
|
|
301
|
-
monthDetails.map((week, index) => {
|
|
302
|
-
const date = convertToDateObject(
|
|
303
|
-
week.weekNumber === 0
|
|
304
|
-
? `${calendarDate.getFullYear()}W53`
|
|
305
|
-
: `${calendarDate.getFullYear()}W${week.weekNumber}`,
|
|
306
|
-
selectionType,
|
|
307
|
-
)
|
|
308
|
-
const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
|
|
309
|
-
const isSelected = isDateSelected(date, startDate, endDate)
|
|
310
|
-
const current = week.days.some((day) => day.month === 'current')
|
|
311
|
-
return (
|
|
312
|
-
<tr
|
|
313
|
-
className={classNames('calendar-row', {
|
|
314
|
-
disabled: isDisabled,
|
|
315
|
-
range: selectionType === 'week' && isDateInRange(date, startDate, endDate),
|
|
316
|
-
'range-hover':
|
|
317
|
-
selectionType === 'week' && hoverDate && selectEndDate
|
|
318
|
-
? isDateInRange(date, startDate, hoverDate)
|
|
319
|
-
: isDateInRange(date, hoverDate, endDate),
|
|
320
|
-
selected: isSelected,
|
|
321
|
-
})}
|
|
322
|
-
key={index}
|
|
323
|
-
tabIndex={selectionType === 'week' && current && !isDisabled ? 0 : -1}
|
|
324
|
-
{...(isSelected && { 'aria-selected': true })}
|
|
325
|
-
{...(selectionType === 'week' &&
|
|
326
|
-
!isDisabled && {
|
|
327
|
-
onBlur: () => onCalendarMouseLeave(),
|
|
328
|
-
onClick: () => onCalendarClick(date),
|
|
329
|
-
onFocus: () => onCalendarMouseEnter(date),
|
|
330
|
-
onKeyDown: (event) => onCalendarKeyDown(event, date),
|
|
331
|
-
onMouseEnter: () => onCalendarMouseEnter(date),
|
|
332
|
-
onMouseLeave: () => onCalendarMouseLeave(),
|
|
333
|
-
})}
|
|
334
|
-
>
|
|
335
|
-
{showWeekNumber && (
|
|
336
|
-
<th className="calendar-cell-week-number">
|
|
337
|
-
{week.weekNumber === 0 ? 53 : week.weekNumber}
|
|
338
|
-
</th>
|
|
339
|
-
)}
|
|
340
|
-
{week.days.map(({ date, month }: { date: Date; month: string }, idx: number) => {
|
|
341
|
-
const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
|
|
342
|
-
const isSelected = isDateSelected(date, startDate, endDate)
|
|
343
|
-
return month === 'current' || showAdjacementDays ? (
|
|
344
|
-
<td
|
|
345
|
-
className={classNames('calendar-cell', {
|
|
346
|
-
...(selectionType === 'day' && {
|
|
347
|
-
clickable: month !== 'current' && selectAdjacementDays,
|
|
348
|
-
disabled: isDisabled,
|
|
349
|
-
'range-hover':
|
|
350
|
-
month === 'current' &&
|
|
351
|
-
(hoverDate && selectEndDate
|
|
352
|
-
? isDateInRange(date, startDate, hoverDate)
|
|
353
|
-
: isDateInRange(date, hoverDate, endDate)),
|
|
354
|
-
range: month === 'current' && isDateInRange(date, startDate, endDate),
|
|
355
|
-
selected: isSelected,
|
|
356
|
-
}),
|
|
357
|
-
[month]: true,
|
|
358
|
-
today: month === 'current' && isToday(date),
|
|
359
|
-
})}
|
|
360
|
-
key={idx}
|
|
361
|
-
tabIndex={
|
|
362
|
-
selectionType === 'day' &&
|
|
363
|
-
(month === 'current' || selectAdjacementDays) &&
|
|
364
|
-
!isDisabled
|
|
365
|
-
? 0
|
|
366
|
-
: -1
|
|
367
|
-
}
|
|
368
|
-
title={date.toLocaleDateString(locale)}
|
|
369
|
-
{...(isSelected && { 'aria-selected': true })}
|
|
370
|
-
{...(selectionType === 'day' &&
|
|
371
|
-
(month === 'current' || selectAdjacementDays) && {
|
|
372
|
-
onBlur: () => onCalendarMouseLeave(),
|
|
373
|
-
onClick: () => onCalendarClick(date),
|
|
374
|
-
onFocus: () => onCalendarMouseEnter(date),
|
|
375
|
-
onKeyDown: (event) => onCalendarKeyDown(event, date),
|
|
376
|
-
onMouseEnter: () => onCalendarMouseEnter(date),
|
|
377
|
-
onMouseLeave: () => onCalendarMouseLeave(),
|
|
378
|
-
})}
|
|
379
|
-
{...(month !== 'current' &&
|
|
380
|
-
!selectAdjacementDays && {
|
|
381
|
-
onMouseEnter: () => onCalendarMouseLeave(),
|
|
382
|
-
})}
|
|
383
|
-
>
|
|
384
|
-
<div className="calendar-cell-inner">
|
|
385
|
-
{typeof dayFormat === 'function'
|
|
386
|
-
? dayFormat(date)
|
|
387
|
-
: date.toLocaleDateString(locale, { day: dayFormat })}
|
|
388
|
-
</div>
|
|
389
|
-
</td>
|
|
390
|
-
) : (
|
|
391
|
-
<td key={idx}></td>
|
|
392
|
-
)
|
|
393
|
-
})}
|
|
394
|
-
</tr>
|
|
395
|
-
)
|
|
396
|
-
})}
|
|
397
|
-
{view === 'months' &&
|
|
398
|
-
listOfMonths.map((row, index) => {
|
|
399
|
-
return (
|
|
400
|
-
<tr key={index}>
|
|
401
|
-
{row.map((month, idx) => {
|
|
402
|
-
const monthNumber = index * 3 + idx
|
|
403
|
-
const date = new Date(calendarDate.getFullYear(), monthNumber, 1)
|
|
404
|
-
const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
|
|
405
|
-
const isSelected = isDateSelected(date, startDate, endDate)
|
|
406
|
-
return (
|
|
407
|
-
<td
|
|
408
|
-
className={classNames('calendar-cell', {
|
|
409
|
-
disabled: isDisabled,
|
|
410
|
-
selected: isSelected,
|
|
411
|
-
'range-hover':
|
|
412
|
-
selectionType === 'month' &&
|
|
413
|
-
(hoverDate && selectEndDate
|
|
414
|
-
? isDateInRange(date, startDate, hoverDate)
|
|
415
|
-
: isDateInRange(date, hoverDate, endDate)),
|
|
416
|
-
range: isDateInRange(date, startDate, endDate),
|
|
417
|
-
})}
|
|
418
|
-
key={idx}
|
|
419
|
-
tabIndex={isDisabled ? -1 : 0}
|
|
420
|
-
{...(isSelected && { 'aria-selected': true })}
|
|
421
|
-
{...(!isDisabled && {
|
|
422
|
-
onBlur: () => onCalendarMouseLeave(),
|
|
423
|
-
onClick: () => onCalendarClick(date),
|
|
424
|
-
onFocus: () => onCalendarMouseEnter(date),
|
|
425
|
-
onKeyDown: (event) => onCalendarKeyDown(event, date),
|
|
426
|
-
onMouseEnter: () => onCalendarMouseEnter(date),
|
|
427
|
-
onMouseLeave: () => onCalendarMouseLeave(),
|
|
428
|
-
})}
|
|
429
|
-
>
|
|
430
|
-
<div className="calendar-cell-inner">{month}</div>
|
|
431
|
-
</td>
|
|
432
|
-
)
|
|
433
|
-
})}
|
|
434
|
-
</tr>
|
|
435
|
-
)
|
|
436
|
-
})}
|
|
437
|
-
{view === 'years' &&
|
|
438
|
-
listOfYears.map((row, index) => {
|
|
439
|
-
return (
|
|
440
|
-
<tr key={index}>
|
|
441
|
-
{row.map((year, idx) => {
|
|
442
|
-
const date = new Date(year, 0, 1)
|
|
443
|
-
const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
|
|
444
|
-
const isSelected = isDateSelected(date, startDate, endDate)
|
|
445
|
-
return (
|
|
446
|
-
<td
|
|
447
|
-
className={classNames('calendar-cell year', {
|
|
448
|
-
disabled: isDisabled,
|
|
449
|
-
selected: isSelected,
|
|
450
|
-
'range-hover':
|
|
451
|
-
selectionType === 'year' &&
|
|
452
|
-
(hoverDate && selectEndDate
|
|
453
|
-
? isDateInRange(date, startDate, hoverDate)
|
|
454
|
-
: isDateInRange(date, hoverDate, endDate)),
|
|
455
|
-
range: isDateInRange(date, startDate, endDate),
|
|
456
|
-
})}
|
|
457
|
-
key={idx}
|
|
458
|
-
tabIndex={isDisabled ? -1 : 0}
|
|
459
|
-
{...(isSelected && { 'aria-selected': true })}
|
|
460
|
-
{...(!isDisabled && {
|
|
461
|
-
onBlur: () => onCalendarMouseLeave(),
|
|
462
|
-
onClick: () => onCalendarClick(date),
|
|
463
|
-
onFocus: () => onCalendarMouseEnter(date),
|
|
464
|
-
onKeyDown: (event) => onCalendarKeyDown(event, date),
|
|
465
|
-
onMouseEnter: () => onCalendarMouseEnter(date),
|
|
466
|
-
onMouseLeave: () => onCalendarMouseLeave(),
|
|
467
|
-
})}
|
|
468
|
-
>
|
|
469
|
-
<div className="calendar-cell-inner">
|
|
470
|
-
{new Date(year, 0, 1).toLocaleDateString(locale, { year: 'numeric' })}
|
|
471
|
-
</div>
|
|
472
|
-
</td>
|
|
473
|
-
)
|
|
474
|
-
})}
|
|
475
|
-
</tr>
|
|
476
|
-
)
|
|
477
|
-
})}
|
|
478
|
-
</tbody>
|
|
479
|
-
</table>
|
|
480
|
-
)
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
const Navigation = (props: {
|
|
484
|
-
ariaNavNextMonthLabel: string
|
|
485
|
-
ariaNavNextYearLabel: string
|
|
486
|
-
ariaNavPrevMonthLabel: string
|
|
487
|
-
ariaNavPrevYearLabel: string
|
|
488
|
-
calendarDate: Date
|
|
489
|
-
locale: string
|
|
490
|
-
navigation: boolean
|
|
491
|
-
navNextDoubleIcon: ReactNode
|
|
492
|
-
navNextIcon: ReactNode
|
|
493
|
-
navPrevDoubleIcon: ReactNode
|
|
494
|
-
navPrevIcon: ReactNode
|
|
495
|
-
navYearFirst: boolean | undefined
|
|
496
|
-
onMonthClick: () => void
|
|
497
|
-
onNavigationClick: (direction: string, double?: boolean) => void
|
|
498
|
-
onYearClick: () => void
|
|
499
|
-
view: 'days' | 'months' | 'years'
|
|
500
|
-
}) => {
|
|
501
|
-
const {
|
|
502
|
-
ariaNavNextMonthLabel,
|
|
503
|
-
ariaNavNextYearLabel,
|
|
504
|
-
ariaNavPrevMonthLabel,
|
|
505
|
-
ariaNavPrevYearLabel,
|
|
506
|
-
calendarDate,
|
|
507
|
-
locale,
|
|
508
|
-
navigation,
|
|
509
|
-
navNextDoubleIcon,
|
|
510
|
-
navNextIcon,
|
|
511
|
-
navPrevDoubleIcon,
|
|
512
|
-
navPrevIcon,
|
|
513
|
-
navYearFirst,
|
|
514
|
-
onMonthClick,
|
|
515
|
-
onNavigationClick,
|
|
516
|
-
onYearClick,
|
|
517
|
-
view,
|
|
518
|
-
} = props
|
|
519
|
-
|
|
520
|
-
return (
|
|
521
|
-
<div className="calendar-nav">
|
|
522
|
-
{navigation && (
|
|
523
|
-
<div className="calendar-nav-prev">
|
|
524
|
-
<CButton
|
|
525
|
-
color="transparent"
|
|
526
|
-
size="sm"
|
|
527
|
-
aria-label={ariaNavPrevYearLabel}
|
|
528
|
-
onClick={() => onNavigationClick('prev', true)}
|
|
529
|
-
>
|
|
530
|
-
{navPrevDoubleIcon ?? (
|
|
531
|
-
<span className="calendar-nav-icon calendar-nav-icon-double-prev" />
|
|
532
|
-
)}
|
|
533
|
-
</CButton>
|
|
534
|
-
{view === 'days' && (
|
|
535
|
-
<CButton
|
|
536
|
-
color="transparent"
|
|
537
|
-
size="sm"
|
|
538
|
-
aria-label={ariaNavPrevMonthLabel}
|
|
539
|
-
onClick={() => onNavigationClick('prev')}
|
|
540
|
-
>
|
|
541
|
-
{navPrevIcon ?? <span className="calendar-nav-icon calendar-nav-icon-prev" />}
|
|
542
|
-
</CButton>
|
|
543
|
-
)}
|
|
544
|
-
</div>
|
|
545
|
-
)}
|
|
546
|
-
<div
|
|
547
|
-
className="calendar-nav-date"
|
|
548
|
-
aria-live="polite"
|
|
549
|
-
{...(navYearFirst && { style: { display: 'flex', justifyContent: 'center' } })}
|
|
550
|
-
>
|
|
551
|
-
{view === 'days' && (
|
|
552
|
-
<CButton color="transparent" size="sm" onClick={() => navigation && onMonthClick()}>
|
|
553
|
-
{calendarDate && calendarDate.toLocaleDateString(locale, { month: 'long' })}
|
|
554
|
-
</CButton>
|
|
555
|
-
)}
|
|
556
|
-
<CButton
|
|
557
|
-
color="transparent"
|
|
558
|
-
size="sm"
|
|
559
|
-
onClick={() => navigation && onYearClick()}
|
|
560
|
-
{...(navYearFirst && { style: { order: '-1' } })}
|
|
561
|
-
>
|
|
562
|
-
{calendarDate && calendarDate.toLocaleDateString(locale, { year: 'numeric' })}
|
|
563
|
-
</CButton>
|
|
564
|
-
</div>
|
|
565
|
-
{navigation && (
|
|
566
|
-
<div className="calendar-nav-next">
|
|
567
|
-
{view === 'days' && (
|
|
568
|
-
<CButton
|
|
569
|
-
color="transparent"
|
|
570
|
-
size="sm"
|
|
571
|
-
aria-label={ariaNavNextMonthLabel}
|
|
572
|
-
onClick={() => onNavigationClick('next')}
|
|
573
|
-
>
|
|
574
|
-
{navNextIcon ?? <span className="calendar-nav-icon calendar-nav-icon-next" />}
|
|
575
|
-
</CButton>
|
|
576
|
-
)}
|
|
577
|
-
<CButton
|
|
578
|
-
color="transparent"
|
|
579
|
-
size="sm"
|
|
580
|
-
aria-label={ariaNavNextYearLabel}
|
|
581
|
-
onClick={() => onNavigationClick('next', true)}
|
|
582
|
-
>
|
|
583
|
-
{navNextDoubleIcon ?? (
|
|
584
|
-
<span className="calendar-nav-icon calendar-nav-icon-double-next" />
|
|
585
|
-
)}
|
|
586
|
-
</CButton>
|
|
587
|
-
</div>
|
|
588
|
-
)}
|
|
589
|
-
</div>
|
|
590
|
-
)
|
|
591
|
-
}
|
|
592
|
-
|
|
593
248
|
export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
594
249
|
(
|
|
595
250
|
{
|
|
@@ -637,20 +292,14 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
637
292
|
const [_calendarDate, setCalendarDate] = useState<Date | null>(null)
|
|
638
293
|
|
|
639
294
|
useEffect(() => {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
295
|
+
const viewMap = {
|
|
296
|
+
day: 'days',
|
|
297
|
+
week: 'days',
|
|
298
|
+
month: 'months',
|
|
299
|
+
year: 'years',
|
|
643
300
|
}
|
|
644
301
|
|
|
645
|
-
|
|
646
|
-
setView('months')
|
|
647
|
-
return
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
if (selectionType === 'year') {
|
|
651
|
-
setView('years')
|
|
652
|
-
return
|
|
653
|
-
}
|
|
302
|
+
setView((viewMap[selectionType] as ViewTypes) || 'days')
|
|
654
303
|
}, [selectionType])
|
|
655
304
|
|
|
656
305
|
useEffect(() => {
|
|
@@ -715,13 +364,21 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
715
364
|
}, [selectEndDate])
|
|
716
365
|
|
|
717
366
|
useEffect(() => {
|
|
718
|
-
!isInitialMount.current &&
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
onSelectEndChange(_selectEndDate)
|
|
367
|
+
if (!isInitialMount.current && typeof _selectEndDate === 'boolean') {
|
|
368
|
+
onSelectEndChange?.(_selectEndDate)
|
|
369
|
+
}
|
|
722
370
|
}, [_selectEndDate])
|
|
723
371
|
|
|
724
|
-
const [view, setView] = useStateWithCallback<
|
|
372
|
+
const [view, setView] = useStateWithCallback<ViewTypes>('days', onViewChanged)
|
|
373
|
+
const [focusOn, setFocusOn] = useState<number | undefined>()
|
|
374
|
+
|
|
375
|
+
useEffect(() => {
|
|
376
|
+
if (typeof focusOn === 'number') {
|
|
377
|
+
const list = getSelectableDates(calendarRef.current as HTMLDivElement)
|
|
378
|
+
list[focusOn]?.focus()
|
|
379
|
+
setFocusOn(undefined)
|
|
380
|
+
}
|
|
381
|
+
}, [view])
|
|
725
382
|
|
|
726
383
|
useEffect(() => {
|
|
727
384
|
isInitialMount.current = false
|
|
@@ -736,19 +393,23 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
736
393
|
const month = _calendarDate.getMonth()
|
|
737
394
|
const d = new Date(year, month, 1)
|
|
738
395
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
396
|
+
if (years) {
|
|
397
|
+
d.setFullYear(d.getFullYear() + years)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (months) {
|
|
401
|
+
d.setMonth(d.getMonth() + months)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (typeof setMonth === 'number') {
|
|
405
|
+
d.setMonth(setMonth)
|
|
406
|
+
}
|
|
742
407
|
|
|
743
408
|
setCalendarDate(d)
|
|
744
|
-
onCalendarDateChange
|
|
409
|
+
onCalendarDateChange?.(d)
|
|
745
410
|
}
|
|
746
411
|
|
|
747
412
|
const handleCalendarClick = (date: Date, index?: number) => {
|
|
748
|
-
if (isDateDisabled(date, _minDate, _maxDate, disabledDates)) {
|
|
749
|
-
return
|
|
750
|
-
}
|
|
751
|
-
|
|
752
413
|
const _date = new Date(date)
|
|
753
414
|
|
|
754
415
|
if (view === 'days') {
|
|
@@ -767,6 +428,11 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
767
428
|
return
|
|
768
429
|
}
|
|
769
430
|
|
|
431
|
+
// Allow to change the calendarDate but not startDate or endDate
|
|
432
|
+
if (isDateDisabled(date, _minDate, _maxDate, disabledDates)) {
|
|
433
|
+
return
|
|
434
|
+
}
|
|
435
|
+
|
|
770
436
|
if (range) {
|
|
771
437
|
if (_selectEndDate) {
|
|
772
438
|
setSelectEndDate(false)
|
|
@@ -814,6 +480,13 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
814
480
|
) => {
|
|
815
481
|
if (event.code === 'Space' || event.key === 'Enter') {
|
|
816
482
|
event.preventDefault()
|
|
483
|
+
if (
|
|
484
|
+
(view === 'months' && selectionType !== 'month') ||
|
|
485
|
+
(view === 'years' && selectionType !== 'year')
|
|
486
|
+
) {
|
|
487
|
+
setFocusOn(0)
|
|
488
|
+
}
|
|
489
|
+
|
|
817
490
|
handleCalendarClick(date, index)
|
|
818
491
|
}
|
|
819
492
|
|
|
@@ -826,16 +499,16 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
826
499
|
event.preventDefault()
|
|
827
500
|
|
|
828
501
|
if (
|
|
829
|
-
|
|
830
|
-
date >=
|
|
502
|
+
_maxDate &&
|
|
503
|
+
date >= _maxDate &&
|
|
831
504
|
(event.key === 'ArrowRight' || event.key === 'ArrowDown')
|
|
832
505
|
) {
|
|
833
506
|
return
|
|
834
507
|
}
|
|
835
508
|
|
|
836
509
|
if (
|
|
837
|
-
|
|
838
|
-
date <=
|
|
510
|
+
_minDate &&
|
|
511
|
+
date <= _minDate &&
|
|
839
512
|
(event.key === 'ArrowLeft' || event.key === 'ArrowUp')
|
|
840
513
|
) {
|
|
841
514
|
return
|
|
@@ -847,12 +520,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
847
520
|
element = element.closest('tr[tabindex="0"]') as HTMLElement
|
|
848
521
|
}
|
|
849
522
|
|
|
850
|
-
const list: HTMLElement[] =
|
|
851
|
-
...Element.prototype.querySelectorAll.call(
|
|
852
|
-
calendarRef.current,
|
|
853
|
-
selectionType === 'week' ? 'tr[tabindex="0"]' : 'td[tabindex="0"]',
|
|
854
|
-
),
|
|
855
|
-
)
|
|
523
|
+
const list: HTMLElement[] = getSelectableDates(calendarRef.current as HTMLDivElement)
|
|
856
524
|
|
|
857
525
|
const index = list.indexOf(element)
|
|
858
526
|
const first = index === 0
|
|
@@ -889,19 +557,14 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
889
557
|
}
|
|
890
558
|
|
|
891
559
|
setTimeout(() => {
|
|
892
|
-
const _list
|
|
893
|
-
...Element.prototype.querySelectorAll.call(
|
|
894
|
-
element.parentNode?.parentNode,
|
|
895
|
-
'td[tabindex="0"], tr[tabindex="0"]',
|
|
896
|
-
),
|
|
897
|
-
)
|
|
560
|
+
const _list = getSelectableDates(element.parentNode?.parentNode as HTMLDivElement)
|
|
898
561
|
|
|
899
562
|
if (_list.length > 0 && event.key === 'ArrowRight') {
|
|
900
563
|
_list[0].focus()
|
|
901
564
|
}
|
|
902
565
|
|
|
903
566
|
if (_list.length > 0 && event.key === 'ArrowLeft') {
|
|
904
|
-
_list
|
|
567
|
+
_list.at(-1)?.focus()
|
|
905
568
|
}
|
|
906
569
|
|
|
907
570
|
if (_list.length > 0 && event.key === 'ArrowDown') {
|
|
@@ -941,12 +604,14 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
941
604
|
|
|
942
605
|
setHoverDate(date)
|
|
943
606
|
|
|
944
|
-
|
|
607
|
+
if (date) {
|
|
608
|
+
onDateHover?.(getDateBySelectionType(date, selectionType))
|
|
609
|
+
}
|
|
945
610
|
}
|
|
946
611
|
|
|
947
612
|
const handleCalendarMouseLeave = () => {
|
|
948
613
|
setHoverDate(null)
|
|
949
|
-
onDateHover
|
|
614
|
+
onDateHover?.(null)
|
|
950
615
|
}
|
|
951
616
|
|
|
952
617
|
const handleNavigationOnClick = (direction: string, double = false) => {
|
|
@@ -998,7 +663,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
998
663
|
const calendarDate = getCalendarDate(_calendarDate, index, view)
|
|
999
664
|
return (
|
|
1000
665
|
<div className={classNames('calendar', view)} key={index}>
|
|
1001
|
-
<
|
|
666
|
+
<CCalendarNavigation
|
|
1002
667
|
ariaNavNextMonthLabel={ariaNavNextMonthLabel}
|
|
1003
668
|
ariaNavNextYearLabel={ariaNavNextYearLabel}
|
|
1004
669
|
ariaNavPrevMonthLabel={ariaNavPrevMonthLabel}
|
|
@@ -1016,7 +681,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
1016
681
|
onYearClick={() => setView('years')}
|
|
1017
682
|
view={view}
|
|
1018
683
|
/>
|
|
1019
|
-
<
|
|
684
|
+
<CCalendarPanel
|
|
1020
685
|
calendarDate={calendarDate}
|
|
1021
686
|
dayFormat={dayFormat}
|
|
1022
687
|
disabledDates={disabledDates}
|