@coreui/react-pro 5.23.5 → 5.24.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 (82) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/autocomplete/CAutocomplete.js +19 -7
  3. package/dist/cjs/components/autocomplete/CAutocomplete.js.map +1 -1
  4. package/dist/cjs/components/autocomplete/CAutocompleteOptions.js +9 -6
  5. package/dist/cjs/components/autocomplete/CAutocompleteOptions.js.map +1 -1
  6. package/dist/cjs/components/calendar/CCalendar.d.ts +58 -2
  7. package/dist/cjs/components/calendar/CCalendar.js +16 -6
  8. package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
  9. package/dist/cjs/components/calendar/CCalendarPanel.d.ts +25 -1
  10. package/dist/cjs/components/calendar/CCalendarPanel.js +55 -7
  11. package/dist/cjs/components/calendar/CCalendarPanel.js.map +1 -1
  12. package/dist/cjs/components/calendar/types.d.ts +2 -2
  13. package/dist/cjs/components/calendar/utils.d.ts +28 -3
  14. package/dist/cjs/components/calendar/utils.js +122 -5
  15. package/dist/cjs/components/calendar/utils.js.map +1 -1
  16. package/dist/cjs/components/chip/CChip.d.ts +76 -0
  17. package/dist/cjs/components/chip/CChip.js +178 -0
  18. package/dist/cjs/components/chip/CChip.js.map +1 -0
  19. package/dist/cjs/components/chip/index.d.ts +2 -0
  20. package/dist/cjs/components/form/CChipInput.d.ts +92 -0
  21. package/dist/cjs/components/form/CChipInput.js +253 -0
  22. package/dist/cjs/components/form/CChipInput.js.map +1 -0
  23. package/dist/cjs/components/form/index.d.ts +2 -1
  24. package/dist/cjs/components/index.d.ts +1 -0
  25. package/dist/cjs/components/multi-select/CMultiSelectOptions.js +1 -1
  26. package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
  27. package/dist/cjs/components/smart-table/CSmartTable.js +1 -0
  28. package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
  29. package/dist/cjs/components/smart-table/CSmartTableBody.js +1 -0
  30. package/dist/cjs/components/smart-table/CSmartTableBody.js.map +1 -1
  31. package/dist/cjs/components/smart-table/CSmartTableHead.js +1 -0
  32. package/dist/cjs/components/smart-table/CSmartTableHead.js.map +1 -1
  33. package/dist/cjs/index.js +4 -0
  34. package/dist/cjs/index.js.map +1 -1
  35. package/dist/esm/components/autocomplete/CAutocomplete.js +20 -8
  36. package/dist/esm/components/autocomplete/CAutocomplete.js.map +1 -1
  37. package/dist/esm/components/autocomplete/CAutocompleteOptions.js +10 -7
  38. package/dist/esm/components/autocomplete/CAutocompleteOptions.js.map +1 -1
  39. package/dist/esm/components/calendar/CCalendar.d.ts +58 -2
  40. package/dist/esm/components/calendar/CCalendar.js +16 -6
  41. package/dist/esm/components/calendar/CCalendar.js.map +1 -1
  42. package/dist/esm/components/calendar/CCalendarPanel.d.ts +25 -1
  43. package/dist/esm/components/calendar/CCalendarPanel.js +56 -8
  44. package/dist/esm/components/calendar/CCalendarPanel.js.map +1 -1
  45. package/dist/esm/components/calendar/types.d.ts +2 -2
  46. package/dist/esm/components/calendar/utils.d.ts +28 -3
  47. package/dist/esm/components/calendar/utils.js +120 -6
  48. package/dist/esm/components/calendar/utils.js.map +1 -1
  49. package/dist/esm/components/chip/CChip.d.ts +76 -0
  50. package/dist/esm/components/chip/CChip.js +176 -0
  51. package/dist/esm/components/chip/CChip.js.map +1 -0
  52. package/dist/esm/components/chip/index.d.ts +2 -0
  53. package/dist/esm/components/form/CChipInput.d.ts +92 -0
  54. package/dist/esm/components/form/CChipInput.js +251 -0
  55. package/dist/esm/components/form/CChipInput.js.map +1 -0
  56. package/dist/esm/components/form/index.d.ts +2 -1
  57. package/dist/esm/components/index.d.ts +1 -0
  58. package/dist/esm/components/multi-select/CMultiSelectOptions.js +1 -1
  59. package/dist/esm/components/smart-table/CSmartTable.js +1 -0
  60. package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
  61. package/dist/esm/components/smart-table/CSmartTableBody.js +1 -0
  62. package/dist/esm/components/smart-table/CSmartTableBody.js.map +1 -1
  63. package/dist/esm/components/smart-table/CSmartTableHead.js +1 -0
  64. package/dist/esm/components/smart-table/CSmartTableHead.js.map +1 -1
  65. package/dist/esm/index.js +2 -0
  66. package/dist/esm/index.js.map +1 -1
  67. package/package.json +5 -5
  68. package/src/components/autocomplete/CAutocomplete.tsx +29 -8
  69. package/src/components/autocomplete/CAutocompleteOptions.tsx +1 -1
  70. package/src/components/calendar/CCalendar.tsx +105 -6
  71. package/src/components/calendar/CCalendarPanel.tsx +119 -8
  72. package/src/components/calendar/types.ts +2 -2
  73. package/src/components/calendar/utils.ts +152 -6
  74. package/src/components/chip/CChip.tsx +372 -0
  75. package/src/components/chip/__tests__/CChip.spec.tsx +113 -0
  76. package/src/components/chip/__tests__/__snapshots__/CChip.spec.tsx.snap +65 -0
  77. package/src/components/chip/index.ts +3 -0
  78. package/src/components/form/CChipInput.tsx +477 -0
  79. package/src/components/form/__tests__/CChipInput.spec.tsx +62 -0
  80. package/src/components/form/__tests__/__snapshots__/CChipInput.spec.tsx.snap +91 -0
  81. package/src/components/form/index.ts +2 -0
  82. package/src/components/index.ts +1 -0
@@ -34,7 +34,8 @@ import {
34
34
  } from './utils'
35
35
 
36
36
  export interface CAutocompleteProps
37
- extends Omit<CFormControlWrapperProps, 'floatingClassName' | 'floatingLabel'>,
37
+ extends
38
+ Omit<CFormControlWrapperProps, 'floatingClassName' | 'floatingLabel'>,
38
39
  Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onInput'> {
39
40
  /**
40
41
  * Only allow selection of predefined options.
@@ -484,6 +485,32 @@ export const CAutocomplete = forwardRef<HTMLDivElement, CAutocompleteProps>(
484
485
  }
485
486
  }
486
487
 
488
+ const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {
489
+ const inputValue = event.target.value
490
+
491
+ if (inputValue.length === 0) {
492
+ return
493
+ }
494
+
495
+ const inputValueLower = inputValue.toLowerCase()
496
+ const exactMatches = flattenOptionsArray(options).filter(
497
+ (option) => getOptionLabel(option).toLowerCase() === inputValueLower
498
+ )
499
+
500
+ if (exactMatches.length === 1) {
501
+ handleSelect(exactMatches[0] as Option)
502
+ return
503
+ }
504
+
505
+ if (allowOnlyDefinedOptions) {
506
+ handleClear()
507
+ return
508
+ }
509
+
510
+ setHint(undefined)
511
+ onChange?.(inputValue)
512
+ }
513
+
487
514
  const handleInputChange = (event: FormEvent<HTMLInputElement>) => {
488
515
  const value = (event.target as HTMLInputElement).value
489
516
  handleSearch(value)
@@ -716,13 +743,7 @@ export const CAutocomplete = forwardRef<HTMLDivElement, CAutocompleteProps>(
716
743
  disabled={disabled}
717
744
  id={id || `autocomplete-${uniqueId}`}
718
745
  name={name || `autocomplete-${uniqueId}`}
719
- onBlur={(event) => {
720
- event.preventDefault()
721
- event.stopPropagation()
722
- if (allowOnlyDefinedOptions && selected === null && filteredOptions.length === 0) {
723
- handleClear()
724
- }
725
- }}
746
+ onBlur={handleInputBlur}
726
747
  onChange={handleInputChange}
727
748
  onKeyDown={handleInputKeyDown}
728
749
  placeholder={placeholder}
@@ -111,7 +111,7 @@ export const CAutocompleteOptions = forwardRef<HTMLDivElement, CAutocompleteOpti
111
111
  ? optionsGroupsTemplate(option as OptionsGroup)
112
112
  : option.label}
113
113
  </div>
114
- {option.options.map((option: Option, index: number) => createOption(option, index))}
114
+ {option.options?.map((option: Option, index: number) => createOption(option, index))}
115
115
  </React.Fragment>
116
116
  ) : (
117
117
  createOption(option as Option, index)
@@ -69,7 +69,7 @@ export interface CCalendarProps {
69
69
  className?: string
70
70
 
71
71
  /**
72
- * 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.
72
+ * Sets the format for days. Accepts either a built-in format ('numeric' or '2-digit') or a custom function to return any desired string or number for the day.
73
73
  *
74
74
  * @default 'numeric'
75
75
  * @since 4.3.0
@@ -117,6 +117,14 @@ export interface CCalendarProps {
117
117
  */
118
118
  minDate?: Date | string | null
119
119
 
120
+ /**
121
+ * Sets the format for month names. Accepts built-in formats ('long', 'narrow', 'short', 'numeric', '2-digit').
122
+ *
123
+ * @since 5.24.0
124
+ * @default 'short'
125
+ */
126
+ monthFormat?: 'long' | 'narrow' | 'short' | 'numeric' | '2-digit'
127
+
120
128
  /**
121
129
  * 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.
122
130
  */
@@ -155,6 +163,64 @@ export interface CCalendarProps {
155
163
  */
156
164
  range?: boolean
157
165
 
166
+ /**
167
+ * A function that allows you to customize the rendering of individual day cells within the calendar. This function receives the date and metadata (like selection and disabled status) as arguments, enabling you to apply custom styles, add tooltips, or include additional content in each day cell.
168
+ *
169
+ * @since 5.24.0
170
+ */
171
+ renderDayCell?: (
172
+ date: Date,
173
+ meta: {
174
+ isDisabled: boolean
175
+ isInCurrentMonth: boolean
176
+ isInRange: boolean
177
+ isSelected: boolean
178
+ isToday: boolean
179
+ }
180
+ ) => ReactNode
181
+
182
+ /**
183
+ * A function that allows you to customize the rendering of individual month cells within the calendar. This function receives the date and metadata (like selection and disabled status) as arguments, enabling you to apply custom styles or include additional content in each month cell.
184
+ *
185
+ * @since 5.24.0
186
+ */
187
+ renderMonthCell?: (
188
+ date: Date,
189
+ meta: {
190
+ isDisabled: boolean
191
+ isInRange: boolean
192
+ isSelected: boolean
193
+ }
194
+ ) => ReactNode
195
+
196
+ /**
197
+ * A function that allows you to customize the rendering of individual quarter cells within the calendar. This function receives the date and metadata (like selection and disabled status) as arguments, enabling you to apply custom styles or include additional content in each quarter cell.
198
+ *
199
+ * @since 5.24.0
200
+ */
201
+ renderQuarterCell?: (
202
+ date: Date,
203
+ meta: {
204
+ isDisabled: boolean
205
+ isInRange: boolean
206
+ isSelected: boolean
207
+ }
208
+ ) => ReactNode
209
+
210
+ /**
211
+ * A function that allows you to customize the rendering of individual year cells within the calendar. This function receives the date and metadata (like selection and disabled status) as arguments, enabling you to apply custom styles or include additional content in each year cell.
212
+ *
213
+ * @since 5.24.0
214
+ */
215
+ renderYearCell?: (
216
+ date: Date,
217
+ meta: {
218
+ isDisabled: boolean
219
+ isInRange: boolean
220
+ isSelected: boolean
221
+ }
222
+ ) => ReactNode
223
+
158
224
  /**
159
225
  * 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`.
160
226
  *
@@ -215,10 +281,21 @@ export interface CCalendarProps {
215
281
  */
216
282
  weekNumbersLabel?: string
217
283
 
284
+ /**
285
+ * Sets the format for years. Accepts built-in formats ('numeric' or '2-digit').
286
+ *
287
+ * @default 'numeric'
288
+ * @since 5.24.0
289
+ */
290
+ yearFormat?: 'numeric' | '2-digit'
291
+
218
292
  /**
219
293
  * 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.
220
294
  */
221
- onCalendarDateChange?: (date: Date | string) => void
295
+ onCalendarDateChange?: (
296
+ date: Date | string,
297
+ view: 'days' | 'months' | 'quarters' | 'years'
298
+ ) => void
222
299
 
223
300
  /**
224
301
  * Callback fired when the user hovers over a calendar cell. The argument is the date of the cell that the user is currently hovering.
@@ -264,6 +341,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
264
341
  locale = 'default',
265
342
  maxDate,
266
343
  minDate,
344
+ monthFormat = 'short',
267
345
  navigation = true,
268
346
  navNextIcon,
269
347
  navNextDoubleIcon,
@@ -271,6 +349,10 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
271
349
  navPrevDoubleIcon,
272
350
  navYearFirst,
273
351
  range,
352
+ renderDayCell,
353
+ renderMonthCell,
354
+ renderQuarterCell,
355
+ renderYearCell,
274
356
  selectAdjacementDays = false,
275
357
  selectEndDate,
276
358
  selectionType = 'day',
@@ -278,6 +360,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
278
360
  showWeekNumber = false,
279
361
  weekdayFormat = 2,
280
362
  weekNumbersLabel,
363
+ yearFormat = 'numeric',
281
364
  onCalendarDateChange,
282
365
  onDateHover,
283
366
  onEndDateChange,
@@ -296,6 +379,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
296
379
  day: 'days',
297
380
  week: 'days',
298
381
  month: 'months',
382
+ quarter: 'quarters',
299
383
  year: 'years',
300
384
  }
301
385
 
@@ -392,7 +476,8 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
392
476
  }
393
477
 
394
478
  setCalendarDate(d)
395
- onCalendarDateChange?.(d)
479
+ onCalendarDateChange?.(d, view)
480
+ console.log('View changed to:', view)
396
481
  }
397
482
 
398
483
  const handleStartDateChange = (date: Date | null) => {
@@ -435,12 +520,20 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
435
520
  if (view === 'months' && selectionType !== 'month') {
436
521
  setCalendarDate(index ? new Date(_date.setMonth(_date.getMonth() - index)) : _date)
437
522
  handleViewChange('days')
523
+ onCalendarDateChange?.(_date, 'days')
438
524
  return
439
525
  }
440
526
 
441
527
  if (view === 'years' && selectionType !== 'year') {
442
528
  setCalendarDate(index ? new Date(_date.setFullYear(_date.getFullYear() - index)) : _date)
443
- handleViewChange('months')
529
+ if (selectionType === 'quarter') {
530
+ handleViewChange('quarters')
531
+ onCalendarDateChange?.(_date, 'quarters')
532
+ } else {
533
+ handleViewChange('months')
534
+ onCalendarDateChange?.(_date, 'months')
535
+ }
536
+
444
537
  return
445
538
  }
446
539
 
@@ -564,7 +657,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
564
657
  setCalendarPage(0, event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1)
565
658
  }
566
659
 
567
- if (view === 'months') {
660
+ if (view === 'months' || view === 'quarters') {
568
661
  setCalendarPage(event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1)
569
662
  }
570
663
 
@@ -709,11 +802,16 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
709
802
  locale={locale}
710
803
  maxDate={_maxDate}
711
804
  minDate={_minDate}
805
+ monthFormat={monthFormat}
712
806
  onCalendarClick={(date) => handleCalendarClick(date, index)}
713
807
  onCalendarKeyDown={(event, date) => handleCalendarKeyDown(event, date, index)}
714
808
  onCalendarMouseEnter={handleCalendarMouseEnter}
715
809
  onCalendarMouseLeave={handleCalendarMouseLeave}
716
810
  order={index}
811
+ renderDayCell={renderDayCell}
812
+ renderMonthCell={renderMonthCell}
813
+ renderQuarterCell={renderQuarterCell}
814
+ renderYearCell={renderYearCell}
717
815
  selectAdjacementDays={selectAdjacementDays}
718
816
  selectEndDate={_selectEndDate}
719
817
  selectionType={selectionType}
@@ -723,6 +821,7 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
723
821
  view={view}
724
822
  weekdayFormat={weekdayFormat}
725
823
  weekNumbersLabel={weekNumbersLabel}
824
+ yearFormat={yearFormat}
726
825
  />
727
826
  </div>
728
827
  )
@@ -759,7 +858,7 @@ CCalendar.propTypes = {
759
858
  range: PropTypes.bool,
760
859
  selectAdjacementDays: PropTypes.bool,
761
860
  selectEndDate: PropTypes.bool,
762
- selectionType: PropTypes.oneOf(['day', 'week', 'month', 'year']),
861
+ selectionType: PropTypes.oneOf(['day', 'week', 'month', 'quarter', 'year']),
763
862
  showAdjacementDays: PropTypes.bool,
764
863
  showWeekNumber: PropTypes.bool,
765
864
  startDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, KeyboardEvent, useEffect, useState } from 'react'
1
+ import React, { forwardRef, KeyboardEvent, ReactNode, useEffect, useState } from 'react'
2
2
  import classNames from 'classnames'
3
3
 
4
4
  import {
@@ -12,6 +12,9 @@ import {
12
12
  isMonthDisabled,
13
13
  isMonthInRange,
14
14
  isMonthSelected,
15
+ isQuarterDisabled,
16
+ isQuarterInRange,
17
+ isQuarterSelected,
15
18
  isToday,
16
19
  isYearDisabled,
17
20
  isYearInRange,
@@ -29,11 +32,46 @@ export interface CCalendarPanelProps {
29
32
  locale: string
30
33
  maxDate: Date | null
31
34
  minDate: Date | null
35
+ monthFormat?: 'long' | 'narrow' | 'short' | 'numeric' | '2-digit'
32
36
  onCalendarClick: (date: Date) => void
33
37
  onCalendarKeyDown: (event: KeyboardEvent<HTMLDivElement>, date: Date) => void
34
38
  onCalendarMouseEnter: (date: Date) => void
35
39
  onCalendarMouseLeave: () => void
36
40
  order: number
41
+ renderDayCell?: (
42
+ date: Date,
43
+ meta: {
44
+ isDisabled: boolean
45
+ isInCurrentMonth: boolean
46
+ isInRange: boolean
47
+ isSelected: boolean
48
+ isToday: boolean
49
+ }
50
+ ) => ReactNode
51
+ renderMonthCell?: (
52
+ date: Date,
53
+ meta: {
54
+ isDisabled: boolean
55
+ isInRange: boolean
56
+ isSelected: boolean
57
+ }
58
+ ) => ReactNode
59
+ renderQuarterCell?: (
60
+ date: Date,
61
+ meta: {
62
+ isDisabled: boolean
63
+ isInRange: boolean
64
+ isSelected: boolean
65
+ }
66
+ ) => ReactNode
67
+ renderYearCell?: (
68
+ date: Date,
69
+ meta: {
70
+ isDisabled: boolean
71
+ isInRange: boolean
72
+ isSelected: boolean
73
+ }
74
+ ) => ReactNode
37
75
  selectAdjacementDays: boolean
38
76
  selectEndDate: boolean | undefined
39
77
  selectionType: SelectionTypes
@@ -43,6 +81,7 @@ export interface CCalendarPanelProps {
43
81
  view: ViewTypes
44
82
  weekdayFormat: number | 'long' | 'narrow' | 'short' | ((date: Date) => string | number)
45
83
  weekNumbersLabel: string | undefined
84
+ yearFormat?: 'numeric' | '2-digit'
46
85
  }
47
86
 
48
87
  export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
@@ -57,10 +96,15 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
57
96
  locale,
58
97
  maxDate,
59
98
  minDate,
99
+ monthFormat,
60
100
  onCalendarClick,
61
101
  onCalendarKeyDown,
62
102
  onCalendarMouseEnter,
63
103
  onCalendarMouseLeave,
104
+ renderDayCell,
105
+ renderMonthCell,
106
+ renderQuarterCell,
107
+ renderYearCell,
64
108
  selectAdjacementDays,
65
109
  selectEndDate,
66
110
  selectionType,
@@ -70,13 +114,14 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
70
114
  view,
71
115
  weekdayFormat,
72
116
  weekNumbersLabel,
117
+ yearFormat,
73
118
  },
74
119
  ref
75
120
  ) => {
76
121
  const [listOfMonths, setListOfMonths] = useState<string[][]>([])
77
122
 
78
123
  useEffect(() => {
79
- setListOfMonths(createGroupsInArray(getMonthsNames(locale), 4))
124
+ setListOfMonths(createGroupsInArray(getMonthsNames(locale, monthFormat), 4))
80
125
  }, [])
81
126
 
82
127
  const monthDetails = getMonthDetails(
@@ -138,7 +183,6 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
138
183
  }
139
184
  )}
140
185
  key={index}
141
- // tabIndex={selectionType === 'week' && !isDisabled ? 0 : -1}
142
186
  {...(selectionType === 'week' && isSelected && { 'aria-selected': true })}
143
187
  {...(selectionType === 'week' &&
144
188
  !isDisabled && {
@@ -196,9 +240,17 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
196
240
  })}
197
241
  >
198
242
  <div className="calendar-cell-inner">
199
- {typeof dayFormat === 'function'
200
- ? dayFormat(date)
201
- : date.toLocaleDateString(locale, { day: dayFormat })}
243
+ {renderDayCell
244
+ ? renderDayCell(date, {
245
+ isDisabled,
246
+ isInCurrentMonth: month === 'current',
247
+ isInRange: isDateInRange(date, startDate, endDate),
248
+ isSelected,
249
+ isToday: isToday(date),
250
+ })
251
+ : typeof dayFormat === 'function'
252
+ ? dayFormat(date)
253
+ : date.toLocaleDateString(locale, { day: dayFormat })}
202
254
  </div>
203
255
  </td>
204
256
  ) : (
@@ -241,13 +293,66 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
241
293
  onMouseLeave: () => onCalendarMouseLeave(),
242
294
  })}
243
295
  >
244
- <div className="calendar-cell-inner">{month}</div>
296
+ <div className="calendar-cell-inner">
297
+ {renderMonthCell
298
+ ? renderMonthCell(date, {
299
+ isDisabled,
300
+ isInRange: isMonthInRange(date, startDate, endDate),
301
+ isSelected,
302
+ })
303
+ : month}
304
+ </div>
245
305
  </td>
246
306
  )
247
307
  })}
248
308
  </tr>
249
309
  )
250
310
  })}
311
+ {view === 'quarters' && (
312
+ <tr>
313
+ {Array.from({ length: 4 }, (_, index) => {
314
+ const date = new Date(calendarDate.getFullYear(), index * 3, 1)
315
+ const isDisabled = isQuarterDisabled(date, minDate, maxDate, disabledDates)
316
+ const isSelected = isQuarterSelected(date, startDate, endDate)
317
+ return (
318
+ <td
319
+ className={classNames('calendar-cell quarters', {
320
+ disabled: isDisabled,
321
+ selected: isSelected,
322
+ 'range-hover':
323
+ selectionType === 'quarter' &&
324
+ (hoverDate && selectEndDate
325
+ ? isQuarterInRange(date, startDate, hoverDate)
326
+ : isQuarterInRange(date, hoverDate, endDate)),
327
+ range: isQuarterInRange(date, startDate, endDate),
328
+ })}
329
+ key={index}
330
+ tabIndex={isDisabled ? -1 : 0}
331
+ {...(isSelected && { 'aria-selected': true })}
332
+ {...(!isDisabled && {
333
+ onBlur: () => onCalendarMouseLeave(),
334
+ onClick: () => onCalendarClick(date),
335
+ onFocus: () => onCalendarMouseEnter(date),
336
+ onKeyDown: (event) => onCalendarKeyDown(event, date),
337
+ onMouseEnter: () => onCalendarMouseEnter(date),
338
+ onMouseLeave: () => onCalendarMouseLeave(),
339
+ })}
340
+ >
341
+ <div className="calendar-cell-inner">
342
+ {renderQuarterCell
343
+ ? renderQuarterCell(date, {
344
+ isDisabled,
345
+ isInRange: isQuarterInRange(date, startDate, endDate),
346
+ isSelected,
347
+ })
348
+ : `Q${index + 1}`}
349
+ </div>
350
+ </td>
351
+ )
352
+ })}
353
+ </tr>
354
+ )}
355
+
251
356
  {view === 'years' &&
252
357
  listOfYears.map((row, index) => {
253
358
  return (
@@ -281,7 +386,13 @@ export const CCalendarPanel = forwardRef<HTMLTableElement, CCalendarPanelProps>(
281
386
  })}
282
387
  >
283
388
  <div className="calendar-cell-inner">
284
- {new Date(year, 0, 1).toLocaleDateString(locale, { year: 'numeric' })}
389
+ {renderYearCell
390
+ ? renderYearCell(date, {
391
+ isDisabled,
392
+ isInRange: isYearInRange(date, startDate, endDate),
393
+ isSelected,
394
+ })
395
+ : date.toLocaleDateString(locale, { year: yearFormat })}
285
396
  </div>
286
397
  </td>
287
398
  )
@@ -1,5 +1,5 @@
1
1
  export type DisabledDate = ((date: Date) => boolean) | Date | Date[]
2
2
 
3
- export type SelectionTypes = 'day' | 'week' | 'month' | 'year'
3
+ export type SelectionTypes = 'day' | 'week' | 'month' | 'quarter' | 'year'
4
4
 
5
- export type ViewTypes = 'days' | 'months' | 'years'
5
+ export type ViewTypes = 'days' | 'months' | 'quarters' | 'years'