@coreui/react-pro 5.23.5 → 5.24.1

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 +20 -9
  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 +20 -9
  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 +6 -6
  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 +110 -10
  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
@@ -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'
@@ -60,8 +60,17 @@ const getMondayOfISOWeek = (year: number, week: number): Date => {
60
60
  * @returns A number representing year*12 + month for easy comparison.
61
61
  */
62
62
  const dateToMonthNumber = (date: Date): number => {
63
- // prettier-ignore
64
- return (date.getFullYear() * 12) + date.getMonth()
63
+ return date.getFullYear() * 12 + date.getMonth()
64
+ }
65
+
66
+ /**
67
+ * Helper function to convert a date to a quarter number for comparison.
68
+ * @param date - The date to convert.
69
+ * @returns A number representing year*4 + quarter for easy comparison.
70
+ */
71
+ const dateToQuarterNumber = (date: Date): number => {
72
+ const quarter = Math.floor(date.getMonth() / 3)
73
+ return date.getFullYear() * 4 + quarter
65
74
  }
66
75
 
67
76
  /**
@@ -122,6 +131,36 @@ const parseWeekString = (dateString: string): Date | null => {
122
131
  return convertIsoWeekToDate(dateString)
123
132
  }
124
133
 
134
+ /**
135
+ * Parses a quarter string and returns a Date object for the first day of that quarter.
136
+ * @param dateString - The quarter string to parse.
137
+ * @returns The Date object for the first day of the quarter, or null if invalid.
138
+ */
139
+ const parseQuarterString = (dateString: string): Date | null => {
140
+ const quarterPatterns = [
141
+ /^(\d{4})-Q(\d{1})$/, // 2023-Q1, 2023-Q4
142
+ /^(\d{4})Q(\d{1})$/, // 2023Q1, 2023Q4
143
+ /^(\d{4})\s+Q(\d{1})$/, // 2023 Q1, 2023 Q4
144
+ ]
145
+
146
+ for (const pattern of quarterPatterns) {
147
+ const match = dateString.trim().match(pattern)
148
+ if (match) {
149
+ const parsedYear = parseYearSmart(match[1])
150
+ const parsedQuarter = Number.parseInt(match[2], 10)
151
+
152
+ // Validate quarter (1-4)
153
+ if (parsedQuarter >= 1 && parsedQuarter <= 4) {
154
+ // Calculate the first month of the quarter (Q1=0, Q2=3, Q3=6, Q4=9)
155
+ const monthIndex = (parsedQuarter - 1) * 3
156
+ return new Date(parsedYear, monthIndex, 1)
157
+ }
158
+ }
159
+ }
160
+
161
+ return null
162
+ }
163
+
125
164
  /**
126
165
  * Parses a month string and returns a Date object for the first day of that month.
127
166
  * @param dateString - The month string to parse.
@@ -508,6 +547,9 @@ export const convertToDateObject = (
508
547
  case 'month': {
509
548
  return parseMonthString(dateString)
510
549
  }
550
+ case 'quarter': {
551
+ return parseQuarterString(dateString)
552
+ }
511
553
  case 'year': {
512
554
  return parseYearString(dateString)
513
555
  }
@@ -523,7 +565,7 @@ export const convertToDateObject = (
523
565
  * @param dateString - The date string to parse.
524
566
  * @param locale - The locale to use for date format patterns.
525
567
  * @param includeTime - Whether to include time parsing.
526
- * @param selectionType - The selection type ('day', 'week', 'month', 'year').
568
+ * @param selectionType - The selection type ('day', 'week', 'month', 'quarter', 'year').
527
569
  * @returns A Date object if parsing succeeds, null if parsing fails.
528
570
  */
529
571
  export const getLocalDateFromString = (
@@ -565,7 +607,7 @@ export const getCalendarDate = (calendarDate: Date, order: number, view: ViewTyp
565
607
  return new Date(calendarDate.getFullYear(), calendarDate.getMonth() + order, 1)
566
608
  }
567
609
 
568
- if (order !== 0 && view === 'months') {
610
+ if (order !== 0 && (view === 'months' || view === 'quarters')) {
569
611
  return new Date(calendarDate.getFullYear() + order, calendarDate.getMonth(), 1)
570
612
  }
571
613
 
@@ -580,7 +622,7 @@ export const getCalendarDate = (calendarDate: Date, order: number, view: ViewTyp
580
622
  /**
581
623
  * Formats a date based on the selection type.
582
624
  * @param date - The date to format.
583
- * @param selectionType - The type of selection ('day', 'week', 'month', 'year').
625
+ * @param selectionType - The type of selection ('day', 'week', 'month', 'quarter', 'year').
584
626
  * @returns A formatted date string or the original Date object.
585
627
  */
586
628
  export const getDateBySelectionType = (
@@ -601,6 +643,11 @@ export const getDateBySelectionType = (
601
643
  return `${date.getFullYear()}-${monthNumber}`
602
644
  }
603
645
 
646
+ if (selectionType === 'quarter') {
647
+ const quarter = Math.floor(date.getMonth() / 3) + 1
648
+ return `${date.getFullYear()}Q${quarter}`
649
+ }
650
+
604
651
  if (selectionType === 'year') {
605
652
  return `${date.getFullYear()}`
606
653
  }
@@ -650,7 +697,10 @@ export const getFirstAvailableDateInRange = (
650
697
  * @param format - The format of the month names ('short' or 'long').
651
698
  * @returns An array of month names.
652
699
  */
653
- export const getMonthsNames = (locale: string, format: 'short' | 'long' = 'short'): string[] => {
700
+ export const getMonthsNames = (
701
+ locale: string,
702
+ format: 'long' | 'narrow' | 'short' | 'numeric' | '2-digit' = 'short'
703
+ ): string[] => {
654
704
  return Array.from({ length: 12 }, (_, i) => {
655
705
  return new Date(2000, i, 1).toLocaleString(locale, { month: format })
656
706
  })
@@ -1031,6 +1081,102 @@ export const isMonthInRange = (date: Date, start: Date | null, end: Date | null)
1031
1081
  return Boolean(_start && _end && _start <= _date && _date <= _end)
1032
1082
  }
1033
1083
 
1084
+ /**
1085
+ * Checks if a quarter is disabled based on the 'quarter' period type.
1086
+ * @param date - The date representing the quarter to check.
1087
+ * @param min - Minimum allowed date.
1088
+ * @param max - Maximum allowed date.
1089
+ * @param disabledDates - Criteria for disabled dates.
1090
+ * @returns True if the quarter is disabled, false otherwise.
1091
+ */
1092
+ export const isQuarterDisabled = (
1093
+ date: Date,
1094
+ min?: Date | null,
1095
+ max?: Date | null,
1096
+ disabledDates?: DisabledDate | DisabledDate[]
1097
+ ) => {
1098
+ const current = dateToQuarterNumber(date)
1099
+ const _min = min ? dateToQuarterNumber(min) : null
1100
+ const _max = max ? dateToQuarterNumber(max) : null
1101
+
1102
+ if (isOutsideRange(current, _min, _max)) {
1103
+ return true
1104
+ }
1105
+
1106
+ if (disabledDates === undefined) {
1107
+ return false
1108
+ }
1109
+
1110
+ // Get the start and end of the quarter
1111
+ const quarter = Math.floor(date.getMonth() / 3)
1112
+ const quarterStartMonth = quarter * 3
1113
+ const quarterEndMonth = quarterStartMonth + 2
1114
+ const year = date.getFullYear()
1115
+
1116
+ const quarterStart = new Date(year, quarterStartMonth, 1)
1117
+ const quarterEnd = new Date(year, quarterEndMonth + 1, 0) // Last day of the quarter
1118
+
1119
+ const startTime = min ? Math.max(quarterStart.getTime(), min.getTime()) : quarterStart.getTime()
1120
+ const endTime = max ? Math.min(quarterEnd.getTime(), max.getTime()) : quarterEnd.getTime()
1121
+
1122
+ for (
1123
+ const currentDate = new Date(startTime);
1124
+ currentDate.getTime() <= endTime;
1125
+ currentDate.setDate(currentDate.getDate() + 1)
1126
+ ) {
1127
+ if (!isDateDisabled(currentDate, min, max, disabledDates)) {
1128
+ return false
1129
+ }
1130
+ }
1131
+
1132
+ return false
1133
+ }
1134
+
1135
+ /**
1136
+ * Checks if a quarter is selected based on start and end dates.
1137
+ * @param date - The date representing the quarter.
1138
+ * @param start - Start date.
1139
+ * @param end - End date.
1140
+ * @returns True if the quarter is selected, false otherwise.
1141
+ */
1142
+ export const isQuarterSelected = (date: Date, start: Date | null, end: Date | null): boolean => {
1143
+ const year = date.getFullYear()
1144
+ const quarter = Math.floor(date.getMonth() / 3)
1145
+
1146
+ if (start !== null) {
1147
+ const startYear = start.getFullYear()
1148
+ const startQuarter = Math.floor(start.getMonth() / 3)
1149
+ if (year === startYear && quarter === startQuarter) {
1150
+ return true
1151
+ }
1152
+ }
1153
+
1154
+ if (end !== null) {
1155
+ const endYear = end.getFullYear()
1156
+ const endQuarter = Math.floor(end.getMonth() / 3)
1157
+ if (year === endYear && quarter === endQuarter) {
1158
+ return true
1159
+ }
1160
+ }
1161
+
1162
+ return false
1163
+ }
1164
+
1165
+ /**
1166
+ * Checks if a quarter is within a specified range.
1167
+ * @param date - The date representing the quarter.
1168
+ * @param start - Start date.
1169
+ * @param end - End date.
1170
+ * @returns True if the quarter is within the range, false otherwise.
1171
+ */
1172
+ export const isQuarterInRange = (date: Date, start: Date | null, end: Date | null): boolean => {
1173
+ const _start = start ? dateToQuarterNumber(start) : null
1174
+ const _end = end ? dateToQuarterNumber(end) : null
1175
+ const _date = dateToQuarterNumber(date)
1176
+
1177
+ return Boolean(_start && _end && _start <= _date && _date <= _end)
1178
+ }
1179
+
1034
1180
  /**
1035
1181
  * Checks if two dates are the same calendar date.
1036
1182
  * @param date - First date.