@coreui/react-pro 4.1.4 → 4.2.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +1 -1
  2. package/dist/components/Types.d.ts +1 -1
  3. package/dist/components/accordion/index.d.ts +7 -0
  4. package/dist/components/alert/index.d.ts +4 -0
  5. package/dist/components/avatar/index.d.ts +2 -0
  6. package/dist/components/backdrop/index.d.ts +2 -0
  7. package/dist/components/badge/index.d.ts +2 -0
  8. package/dist/components/breadcrumb/index.d.ts +3 -0
  9. package/dist/components/button/index.d.ts +2 -0
  10. package/dist/components/button-group/index.d.ts +3 -0
  11. package/dist/components/calendar/CCalendar.d.ts +113 -0
  12. package/dist/components/callout/index.d.ts +2 -0
  13. package/dist/components/card/index.d.ts +12 -0
  14. package/dist/components/carousel/index.d.ts +4 -0
  15. package/dist/components/close-button/index.d.ts +2 -0
  16. package/dist/components/collapse/index.d.ts +2 -0
  17. package/dist/components/datepicker/CDatePicker.d.ts +13 -0
  18. package/dist/components/datepicker/index.d.ts +2 -0
  19. package/dist/components/daterangepicker/CDateRangePicker.d.ts +65 -0
  20. package/dist/components/daterangepicker/index.d.ts +2 -0
  21. package/dist/components/dropdown/CDropdown.d.ts +10 -1
  22. package/dist/components/dropdown/CDropdownToggle.d.ts +4 -0
  23. package/dist/components/dropdown/index.d.ts +8 -0
  24. package/dist/components/footer/index.d.ts +2 -0
  25. package/dist/components/form/CForm.d.ts +2 -2
  26. package/dist/components/form/CFormCheck.d.ts +2 -1
  27. package/dist/components/form/CFormControlValidation.d.ts +46 -0
  28. package/dist/components/form/CFormControlWrapper.d.ts +31 -0
  29. package/dist/components/form/CFormInput.d.ts +2 -9
  30. package/dist/components/form/CFormRange.d.ts +7 -1
  31. package/dist/components/form/CFormSelect.d.ts +3 -10
  32. package/dist/components/form/CFormTextarea.d.ts +2 -9
  33. package/dist/components/form/index.d.ts +14 -0
  34. package/dist/components/grid/index.d.ts +4 -0
  35. package/dist/components/header/index.d.ts +7 -0
  36. package/dist/components/image/index.d.ts +2 -0
  37. package/dist/components/index.d.ts +41 -0
  38. package/dist/components/link/index.d.ts +2 -0
  39. package/dist/components/list-group/index.d.ts +3 -0
  40. package/dist/components/loading-button/index.d.ts +2 -0
  41. package/dist/components/modal/CModal.d.ts +3 -0
  42. package/dist/components/modal/index.d.ts +8 -0
  43. package/dist/components/multi-select/index.d.ts +2 -0
  44. package/dist/components/nav/index.d.ts +7 -0
  45. package/dist/components/navbar/index.d.ts +6 -0
  46. package/dist/components/offcanvas/index.d.ts +5 -0
  47. package/dist/components/pagination/index.d.ts +4 -0
  48. package/dist/components/picker/CPicker.d.ts +78 -0
  49. package/dist/components/placeholder/index.d.ts +2 -0
  50. package/dist/components/popover/CPopover.d.ts +2 -2
  51. package/dist/components/popover/index.d.ts +2 -0
  52. package/dist/components/progress/index.d.ts +3 -0
  53. package/dist/components/sidebar/index.d.ts +7 -0
  54. package/dist/components/smart-table/index.d.ts +2 -0
  55. package/dist/components/spinner/index.d.ts +2 -0
  56. package/dist/components/table/index.d.ts +9 -0
  57. package/dist/components/tabs/index.d.ts +3 -0
  58. package/dist/components/timepicker/CTimePicker.d.ts +45 -0
  59. package/dist/components/timepicker/CTimePickerRollCol.d.ts +11 -0
  60. package/dist/components/timepicker/index.d.ts +2 -0
  61. package/dist/components/toast/index.d.ts +6 -0
  62. package/dist/components/tooltip/CTooltip.d.ts +2 -2
  63. package/dist/components/tooltip/index.d.ts +2 -0
  64. package/dist/index.d.ts +0 -125
  65. package/dist/index.es.js +3268 -1339
  66. package/dist/index.es.js.map +1 -1
  67. package/dist/index.js +3513 -1582
  68. package/dist/index.js.map +1 -1
  69. package/dist/utils/calendar.d.ts +23 -0
  70. package/dist/utils/hooks/useStateWithCallback.d.ts +2 -1
  71. package/dist/utils/time.d.ts +21 -0
  72. package/package.json +12 -11
  73. package/src/components/Types.tsx +2 -2
  74. package/src/components/accordion/CAccordionButton.tsx +2 -1
  75. package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.tsx.snap +2 -0
  76. package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.tsx.snap +2 -0
  77. package/src/components/accordion/index.ts +15 -0
  78. package/src/components/alert/CAlert.tsx +14 -3
  79. package/src/components/alert/index.ts +5 -0
  80. package/src/components/avatar/index.ts +3 -0
  81. package/src/components/backdrop/CBackdrop.tsx +10 -3
  82. package/src/components/backdrop/index.ts +3 -0
  83. package/src/components/badge/index.ts +3 -0
  84. package/src/components/breadcrumb/index.ts +4 -0
  85. package/src/components/button/index.ts +3 -0
  86. package/src/components/button-group/index.ts +4 -0
  87. package/src/components/calendar/CCalendar.tsx +559 -0
  88. package/src/components/calendar/__tests__/CCalendar.spec.tsx +9 -0
  89. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +573 -0
  90. package/src/components/callout/index.ts +3 -0
  91. package/src/components/card/index.ts +25 -0
  92. package/src/components/carousel/index.ts +5 -0
  93. package/src/components/close-button/index.ts +3 -0
  94. package/src/components/collapse/CCollapse.tsx +1 -0
  95. package/src/components/collapse/index.ts +3 -0
  96. package/src/components/datepicker/CDatePicker.tsx +50 -0
  97. package/src/components/datepicker/__tests__/CDatePicker.spec.tsx +9 -0
  98. package/src/components/datepicker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +617 -0
  99. package/src/components/datepicker/index.ts +3 -0
  100. package/src/components/daterangepicker/CDateRangePicker.tsx +432 -0
  101. package/src/components/daterangepicker/__tests__/CDateRangePicker.spec.tsx +9 -0
  102. package/src/components/daterangepicker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +1201 -0
  103. package/src/components/daterangepicker/index.ts +3 -0
  104. package/src/components/dropdown/CDropdown.tsx +19 -24
  105. package/src/components/dropdown/CDropdownItem.tsx +1 -1
  106. package/src/components/dropdown/CDropdownMenu.tsx +55 -3
  107. package/src/components/dropdown/CDropdownToggle.tsx +28 -5
  108. package/src/components/dropdown/index.ts +17 -0
  109. package/src/components/footer/index.ts +3 -0
  110. package/src/components/form/CForm.tsx +2 -2
  111. package/src/components/form/CFormCheck.tsx +32 -7
  112. package/src/components/form/CFormControlValidation.tsx +97 -0
  113. package/src/components/form/CFormControlWrapper.tsx +85 -0
  114. package/src/components/form/CFormInput.tsx +47 -18
  115. package/src/components/form/CFormRange.tsx +18 -4
  116. package/src/components/form/CFormSelect.tsx +60 -32
  117. package/src/components/form/CFormTextarea.tsx +45 -17
  118. package/src/components/form/index.ts +29 -0
  119. package/src/components/grid/index.ts +5 -0
  120. package/src/components/header/index.ts +8 -0
  121. package/src/components/image/index.ts +3 -0
  122. package/src/components/index.ts +41 -0
  123. package/src/components/link/index.ts +3 -0
  124. package/src/components/list-group/index.ts +4 -0
  125. package/src/components/loading-button/index.ts +3 -0
  126. package/src/components/modal/CModal.tsx +3 -2
  127. package/src/components/modal/index.ts +9 -0
  128. package/src/components/multi-select/CMultiSelect.tsx +45 -38
  129. package/src/components/multi-select/index.ts +3 -0
  130. package/src/components/nav/CNavGroup.tsx +1 -0
  131. package/src/components/nav/index.ts +8 -0
  132. package/src/components/navbar/index.ts +7 -0
  133. package/src/components/offcanvas/COffcanvas.tsx +1 -0
  134. package/src/components/offcanvas/index.ts +6 -0
  135. package/src/components/pagination/index.ts +5 -0
  136. package/src/components/picker/CPicker.tsx +207 -0
  137. package/src/components/picker/__tests__/CPicker.spec.tsx +9 -0
  138. package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +23 -0
  139. package/src/components/placeholder/index.ts +3 -0
  140. package/src/components/popover/CPopover.tsx +78 -70
  141. package/src/components/popover/index.ts +3 -0
  142. package/src/components/progress/index.ts +4 -0
  143. package/src/components/sidebar/index.ts +8 -0
  144. package/src/components/smart-table/index.ts +3 -0
  145. package/src/components/spinner/index.ts +3 -0
  146. package/src/components/table/index.ts +19 -0
  147. package/src/components/tabs/CTabPane.tsx +7 -3
  148. package/src/components/tabs/index.ts +4 -0
  149. package/src/components/timepicker/CTimePicker.tsx +313 -0
  150. package/src/components/timepicker/CTimePickerRollCol.tsx +63 -0
  151. package/src/components/timepicker/__tests__/CTimePicker.spec.tsx +9 -0
  152. package/src/components/timepicker/index.ts +3 -0
  153. package/src/components/toast/CToast.tsx +6 -1
  154. package/src/components/toast/index.ts +7 -0
  155. package/src/components/tooltip/CTooltip.tsx +68 -60
  156. package/src/components/tooltip/index.ts +3 -0
  157. package/src/index.ts +0 -252
  158. package/src/utils/calendar.ts +270 -0
  159. package/src/utils/hooks/useStateWithCallback.ts +6 -3
  160. package/src/utils/time.ts +84 -0
  161. package/dist/components/dropdown/CDropdownToggleCustom.d.ts +0 -15
  162. package/src/components/dropdown/CDropdownToggleCustom.tsx +0 -81
@@ -0,0 +1,559 @@
1
+ import React, { forwardRef, ReactNode, useEffect, useState } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ import { CButton } from '../button/CButton'
6
+
7
+ import {
8
+ createGroupsInArray,
9
+ getMonthDetails,
10
+ getMonthsNames,
11
+ getYears,
12
+ isDateDisabled,
13
+ isDateInRange,
14
+ isDateSelected,
15
+ isDisableDateInRange,
16
+ isLastDayOfMonth,
17
+ isSameDateAs,
18
+ isToday,
19
+ isStartDate,
20
+ isEndDate,
21
+ } from '../../utils/calendar'
22
+ import { useStateWithCallback } from '../../utils/hooks'
23
+
24
+ export interface CCalendarProps {
25
+ /**
26
+ * Default date of the component
27
+ */
28
+ calendarDate?: Date | string
29
+ /**
30
+ * A string of all className you want applied to the component.
31
+ */
32
+ className?: string
33
+ /**
34
+ * Specify the list of dates that cannot be selected.
35
+ */
36
+ disabledDates?: Date[] | Date[][]
37
+ /**
38
+ * Initial selected to date (range).
39
+ */
40
+ endDate?: Date | string | null
41
+ /**
42
+ * Sets the day of start week.
43
+ * - 0 - Sunday,
44
+ * - 1 - Monday,
45
+ * - 2 - Tuesday,
46
+ * - 3 - Wednesday,
47
+ * - 4 - Thursday,
48
+ * - 5 - Friday,
49
+ * - 6 - Saturday,
50
+ *
51
+ * @default 1
52
+ */
53
+ firstDayOfWeek?: number
54
+ /**
55
+ * @ignore
56
+ */
57
+ hoverDate?: Date | null
58
+ /**
59
+ * Sets the default locale for components. If not set, it is inherited from the browser.
60
+ *
61
+ * @default 'default'
62
+ */
63
+ locale?: string
64
+ /**
65
+ * Max selectable date.
66
+ */
67
+ maxDate?: Date | string
68
+ /**
69
+ * Min selectable date.
70
+ */
71
+ minDate?: Date | string
72
+ /**
73
+ * Show arrows navigation.
74
+ */
75
+ navigation?: boolean
76
+ /**
77
+ * The custom next icon.
78
+ */
79
+ navNextIcon?: ReactNode
80
+ /**
81
+ * The custom next double icon.
82
+ */
83
+ navNextDoubleIcon?: ReactNode
84
+ /**
85
+ * The custom prev icon.
86
+ */
87
+ navPrevIcon?: ReactNode
88
+ /**
89
+ * The custom prev double icon.
90
+ */
91
+ navPrevDoubleIcon?: ReactNode
92
+ /**
93
+ * Allow range selection.
94
+ */
95
+ range?: boolean
96
+ /**
97
+ * Toggle select mode between start and end date.
98
+ */
99
+ selectEndDate?: boolean
100
+ /**
101
+ * Initial selected date.
102
+ */
103
+ startDate?: Date | string | null
104
+ /**
105
+ * Set length or format of day name.
106
+ *
107
+ * @default 2
108
+ */
109
+ weekdayFormat?: number | 'long' | 'narrow' | 'short'
110
+ /**
111
+ * Callback fired when the user hovers over the calendar cell.
112
+ */
113
+ onCalendarCellHover?: (date: Date | null) => void
114
+ /**
115
+ * Callback fired when the calendar date changed.
116
+ */
117
+ onCalendarDateChange?: (date: Date) => void
118
+ /**
119
+ * Callback fired when the start date changed.
120
+ */
121
+ onStartDateChange?: (date: Date | null) => void
122
+ /**
123
+ * Callback fired when the end date changed.
124
+ */
125
+ onEndDateChange?: (date: Date | null) => void
126
+ /**
127
+ * Callback fired when the selection type changed.
128
+ */
129
+ onSelectEndChange?: (value: boolean) => void
130
+ /**
131
+ * Callback fired when the view type of calendar changed.
132
+ */
133
+ onViewChanged?: (view: string) => void
134
+ }
135
+
136
+ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
137
+ (
138
+ {
139
+ calendarDate,
140
+ disabledDates,
141
+ endDate,
142
+ firstDayOfWeek = 1,
143
+ hoverDate,
144
+ locale = 'default',
145
+ maxDate,
146
+ minDate,
147
+ navigation = true,
148
+ navNextIcon,
149
+ navNextDoubleIcon,
150
+ navPrevIcon,
151
+ navPrevDoubleIcon,
152
+ range,
153
+ selectEndDate = false,
154
+ startDate,
155
+ weekdayFormat = 2,
156
+ onCalendarCellHover,
157
+ onCalendarDateChange,
158
+ onEndDateChange,
159
+ onStartDateChange,
160
+ onSelectEndChange,
161
+ onViewChanged,
162
+ },
163
+ ref,
164
+ ) => {
165
+ const [_calendarDate, setCalendarDate] = useState<Date>(
166
+ calendarDate ? new Date(calendarDate) : new Date(),
167
+ )
168
+ useEffect(() => {
169
+ if (calendarDate) {
170
+ const d = new Date(calendarDate)
171
+ !isSameDateAs(_calendarDate, d) && setCalendarDate(d)
172
+ }
173
+ }, [calendarDate])
174
+
175
+ const [_startDate, setStartDate] = useStateWithCallback<Date | null>(
176
+ startDate ? new Date(startDate) : null,
177
+ onStartDateChange,
178
+ )
179
+ useEffect(() => {
180
+ const date = startDate ? new Date(startDate) : null
181
+ if (!isSameDateAs(date, _startDate)) {
182
+ setStartDate(date)
183
+ }
184
+ }, [startDate])
185
+
186
+ const [_endDate, setEndDate] = useStateWithCallback<Date | null>(
187
+ endDate ? new Date(endDate) : null,
188
+ onEndDateChange,
189
+ )
190
+ useEffect(() => {
191
+ const date = endDate ? new Date(endDate) : null
192
+ if (!isSameDateAs(date, _endDate)) {
193
+ setEndDate(date)
194
+ }
195
+ }, [endDate])
196
+
197
+ const [_hoverDate, setHoverDate] = useState<Date | null>(hoverDate ? new Date(hoverDate) : null)
198
+ useEffect(() => {
199
+ setHoverDate(hoverDate ? new Date(hoverDate) : null)
200
+ }, [hoverDate])
201
+
202
+ const [_selectEndDate, setSelectEndDate] = useStateWithCallback(
203
+ selectEndDate,
204
+ onSelectEndChange,
205
+ )
206
+ useEffect(() => {
207
+ setSelectEndDate(selectEndDate)
208
+ }, [selectEndDate])
209
+
210
+ const [_maxDate, setMaxDate] = useState<Date | null>(maxDate ? new Date(maxDate) : null)
211
+ useEffect(() => {
212
+ maxDate && setMaxDate(new Date(maxDate))
213
+ }, [maxDate])
214
+
215
+ const [_minDate, setMinDate] = useState<Date | null>(minDate ? new Date(minDate) : null)
216
+ useEffect(() => {
217
+ minDate && setMinDate(new Date(minDate))
218
+ }, [minDate])
219
+
220
+ const [view, setView] = useStateWithCallback('days', onViewChanged)
221
+
222
+ const setCalendarPage = (years: number, months = 0, setMonth?: number) => {
223
+ const year = _calendarDate.getFullYear()
224
+ const month = _calendarDate.getMonth()
225
+ const d = new Date(year, month, 1)
226
+
227
+ years && d.setFullYear(d.getFullYear() + years)
228
+ months && d.setMonth(d.getMonth() + months)
229
+ typeof setMonth === 'number' && d.setMonth(setMonth)
230
+
231
+ setCalendarDate(d)
232
+ onCalendarDateChange && onCalendarDateChange(d)
233
+ }
234
+
235
+ const handleCellOnClick = (date: Date) => {
236
+ if (isDateDisabled(date, _minDate, _maxDate, disabledDates)) {
237
+ return
238
+ }
239
+
240
+ if (range) {
241
+ if (_selectEndDate) {
242
+ setSelectEndDate(false)
243
+
244
+ if (_startDate && _startDate > date) {
245
+ setStartDate(null)
246
+ setEndDate(null)
247
+ return
248
+ }
249
+
250
+ if (isDisableDateInRange(_startDate, date, disabledDates)) {
251
+ setStartDate(null)
252
+ setEndDate(null)
253
+ return
254
+ }
255
+
256
+ setEndDate(date)
257
+ return
258
+ }
259
+
260
+ if (_endDate && _endDate < date) {
261
+ setStartDate(null)
262
+ setEndDate(null)
263
+ return
264
+ }
265
+
266
+ if (isDisableDateInRange(date, _endDate, disabledDates)) {
267
+ setStartDate(null)
268
+ setEndDate(null)
269
+ return
270
+ }
271
+
272
+ setSelectEndDate(true)
273
+ setStartDate(date)
274
+ return
275
+ }
276
+
277
+ setStartDate(date)
278
+ }
279
+
280
+ const handleCellMouseEnter = (date: Date) => {
281
+ if (isDateDisabled(date, _minDate, _maxDate, disabledDates)) {
282
+ return
283
+ }
284
+ setHoverDate(date)
285
+ onCalendarCellHover && onCalendarCellHover(date)
286
+ }
287
+
288
+ const handleCellMouseLeave = () => {
289
+ setHoverDate(null)
290
+ onCalendarCellHover && onCalendarCellHover(null)
291
+ }
292
+
293
+ const handleNavigationOnClick = (direction: string, double = false) => {
294
+ if (direction === 'prev') {
295
+ if (double) {
296
+ setCalendarPage(view === 'years' ? -10 : -1)
297
+ return
298
+ }
299
+
300
+ if (view !== 'days') {
301
+ setCalendarPage(-1)
302
+ return
303
+ }
304
+
305
+ setCalendarPage(0, -1)
306
+ return
307
+ }
308
+ if (direction === 'next') {
309
+ if (double) {
310
+ setCalendarPage(view === 'years' ? 10 : 1)
311
+ return
312
+ }
313
+
314
+ if (view !== 'days') {
315
+ setCalendarPage(1)
316
+ return
317
+ }
318
+
319
+ setCalendarPage(0, 1)
320
+ return
321
+ }
322
+ }
323
+
324
+ const Calendar = () => {
325
+ const monthDetails = getMonthDetails(
326
+ _calendarDate.getFullYear(),
327
+ _calendarDate.getMonth(),
328
+ firstDayOfWeek,
329
+ )
330
+ const listOfMonths = createGroupsInArray(getMonthsNames(locale), 4)
331
+ const listOfYears = createGroupsInArray(getYears(_calendarDate.getFullYear()), 4)
332
+ const weekDays = monthDetails[0]
333
+ return (
334
+ <table>
335
+ {view === 'days' && (
336
+ <thead>
337
+ <tr>
338
+ {weekDays.map(({ date }: { date: Date }, idx: number) => (
339
+ <th key={idx} className="calendar-cell">
340
+ <div className="calendar-header-cell-inner">
341
+ {typeof weekdayFormat === 'string'
342
+ ? date.toLocaleDateString(locale, { weekday: weekdayFormat })
343
+ : date
344
+ .toLocaleDateString(locale, { weekday: 'long' })
345
+ .slice(0, weekdayFormat)}
346
+ </div>
347
+ </th>
348
+ ))}
349
+ </tr>
350
+ </thead>
351
+ )}
352
+ <tbody onMouseLeave={() => handleCellMouseLeave()}>
353
+ {view === 'days' &&
354
+ monthDetails.map((week, index) => {
355
+ return (
356
+ <tr key={index}>
357
+ {week.map(({ date, month }: { date: Date; month: string }, idx: number) => (
358
+ <td
359
+ className={classNames('calendar-cell', {
360
+ today: month === 'current' && isToday(date),
361
+ disabled: isDateDisabled(date, _minDate, _maxDate, disabledDates),
362
+ next: month === 'next',
363
+ previous: month === 'previous',
364
+ last: isLastDayOfMonth(date),
365
+ 'range-hover':
366
+ _hoverDate && selectEndDate
367
+ ? month === 'current' && isDateInRange(date, _startDate, _hoverDate)
368
+ : month === 'current' && isDateInRange(date, _hoverDate, _endDate),
369
+ range: month === 'current' && isDateInRange(date, _startDate, _endDate),
370
+ selected: isDateSelected(date, _startDate, _endDate),
371
+ start: isStartDate(date, _startDate, _endDate),
372
+ end: isEndDate(date, _startDate, _endDate),
373
+ })}
374
+ key={idx}
375
+ title={date.toLocaleDateString(locale)}
376
+ {...(month === 'current' && {
377
+ onClick: () => handleCellOnClick(date),
378
+ onMouseEnter: () => handleCellMouseEnter(date),
379
+ })}
380
+ {...(month !== 'current' && {
381
+ onMouseEnter: () => handleCellMouseLeave(),
382
+ })}
383
+ >
384
+ <div className="calendar-cell-inner">
385
+ {date.toLocaleDateString(locale, { day: 'numeric' })}
386
+ </div>
387
+ </td>
388
+ ))}
389
+ </tr>
390
+ )
391
+ })}
392
+ {view === 'months' &&
393
+ listOfMonths.map((row, index) => {
394
+ return (
395
+ <tr key={index}>
396
+ {row.map((month, idx) => {
397
+ return (
398
+ <td
399
+ key={idx}
400
+ className="calendar-cell month"
401
+ onClick={() => {
402
+ setCalendarPage(0, 0, index * 3 + idx)
403
+ setView('days')
404
+ }}
405
+ >
406
+ <div className="calendar-cell-inner">{month}</div>
407
+ </td>
408
+ )
409
+ })}
410
+ </tr>
411
+ )
412
+ })}
413
+ {view === 'years' &&
414
+ listOfYears.map((row, index) => {
415
+ return (
416
+ <tr key={index}>
417
+ {row.map((year, idx) => {
418
+ return (
419
+ <td
420
+ key={idx}
421
+ className="calendar-cell year"
422
+ onClick={() => {
423
+ setCalendarDate(
424
+ new Date(year, _calendarDate.getMonth(), _calendarDate.getDate()),
425
+ )
426
+ setView('months')
427
+ }}
428
+ >
429
+ <div className="calendar-cell-inner">
430
+ {new Date(year, 0, 1).toLocaleDateString(locale, { year: 'numeric' })}
431
+ </div>
432
+ </td>
433
+ )
434
+ })}
435
+ </tr>
436
+ )
437
+ })}
438
+ </tbody>
439
+ </table>
440
+ )
441
+ }
442
+
443
+ const Navigation = () => {
444
+ return (
445
+ <div className="calendar-nav">
446
+ {navigation && (
447
+ <div className="calendar-nav-prev">
448
+ <CButton
449
+ color="transparent"
450
+ size="sm"
451
+ onClick={() => handleNavigationOnClick('prev', true)}
452
+ >
453
+ {navPrevDoubleIcon ? (
454
+ navPrevDoubleIcon
455
+ ) : (
456
+ <span className="calendar-nav-icon calendar-nav-icon-double-prev" />
457
+ )}
458
+ </CButton>
459
+ {view === 'days' && (
460
+ <CButton
461
+ color="transparent"
462
+ size="sm"
463
+ onClick={() => handleNavigationOnClick('prev')}
464
+ >
465
+ {navPrevIcon ? (
466
+ navPrevIcon
467
+ ) : (
468
+ <span className="calendar-nav-icon calendar-nav-icon-prev" />
469
+ )}
470
+ </CButton>
471
+ )}
472
+ </div>
473
+ )}
474
+ <div className="calendar-nav-date">
475
+ {view === 'days' && (
476
+ <CButton
477
+ color="transparent"
478
+ size="sm"
479
+ onClick={() => navigation && setView('months')}
480
+ >
481
+ {_calendarDate.toLocaleDateString(locale, { month: 'long' })}
482
+ </CButton>
483
+ )}
484
+ <CButton color="transparent" size="sm" onClick={() => navigation && setView('years')}>
485
+ {_calendarDate.toLocaleDateString(locale, { year: 'numeric' })}
486
+ </CButton>
487
+ </div>
488
+ {navigation && (
489
+ <div className="calendar-nav-next">
490
+ {view === 'days' && (
491
+ <CButton
492
+ color="transparent"
493
+ size="sm"
494
+ onClick={() => handleNavigationOnClick('next')}
495
+ >
496
+ {navNextIcon ? (
497
+ navNextIcon
498
+ ) : (
499
+ <span className="calendar-nav-icon calendar-nav-icon-next" />
500
+ )}
501
+ </CButton>
502
+ )}
503
+ <CButton
504
+ color="transparent"
505
+ size="sm"
506
+ onClick={() => handleNavigationOnClick('next', true)}
507
+ >
508
+ {navNextDoubleIcon ? (
509
+ navNextDoubleIcon
510
+ ) : (
511
+ <span className="calendar-nav-icon calendar-nav-icon-double-next" />
512
+ )}
513
+ </CButton>
514
+ </div>
515
+ )}
516
+ </div>
517
+ )
518
+ }
519
+
520
+ return (
521
+ <div className={classNames('calendar', view)} ref={ref}>
522
+ <Navigation />
523
+ <Calendar />
524
+ </div>
525
+ )
526
+ },
527
+ )
528
+
529
+ CCalendar.propTypes = {
530
+ className: PropTypes.string,
531
+ calendarDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
532
+ disabledDates: PropTypes.array,
533
+ endDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
534
+ hoverDate: PropTypes.instanceOf(Date),
535
+ firstDayOfWeek: PropTypes.number,
536
+ locale: PropTypes.string,
537
+ maxDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
538
+ minDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
539
+ navigation: PropTypes.bool,
540
+ navNextIcon: PropTypes.node,
541
+ navNextDoubleIcon: PropTypes.node,
542
+ navPrevIcon: PropTypes.node,
543
+ navPrevDoubleIcon: PropTypes.node,
544
+ range: PropTypes.bool,
545
+ selectEndDate: PropTypes.bool,
546
+ startDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
547
+ weekdayFormat: PropTypes.oneOfType([
548
+ PropTypes.number,
549
+ PropTypes.oneOf<'long' | 'narrow' | 'short'>(['long', 'narrow', 'short']),
550
+ ]),
551
+ onCalendarCellHover: PropTypes.func,
552
+ onCalendarDateChange: PropTypes.func,
553
+ onEndDateChange: PropTypes.func,
554
+ onSelectEndChange: PropTypes.func,
555
+ onStartDateChange: PropTypes.func,
556
+ onViewChanged: PropTypes.func,
557
+ }
558
+
559
+ CCalendar.displayName = 'CCalendar'
@@ -0,0 +1,9 @@
1
+ import * as React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import '@testing-library/jest-dom/extend-expect'
4
+ import { CCalendar } from '../CCalendar'
5
+
6
+ test('loads and displays CCalendar component', async () => {
7
+ const { container } = render(<CCalendar />)
8
+ expect(container).toMatchSnapshot()
9
+ })