@coreui/vue-pro 5.9.0 → 5.10.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 (67) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/accordion/CAccordionBody.js +2 -1
  3. package/dist/cjs/components/accordion/CAccordionBody.js.map +1 -1
  4. package/dist/cjs/components/accordion/CAccordionButton.js +3 -1
  5. package/dist/cjs/components/accordion/CAccordionButton.js.map +1 -1
  6. package/dist/cjs/components/accordion/CAccordionItem.d.ts +8 -0
  7. package/dist/cjs/components/accordion/CAccordionItem.js +10 -2
  8. package/dist/cjs/components/accordion/CAccordionItem.js.map +1 -1
  9. package/dist/cjs/components/calendar/CCalendar.d.ts +6 -6
  10. package/dist/cjs/components/calendar/CCalendar.js +40 -36
  11. package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
  12. package/dist/cjs/components/calendar/types.d.ts +3 -0
  13. package/dist/cjs/components/calendar/utils.d.ts +175 -18
  14. package/dist/cjs/components/calendar/utils.js +311 -43
  15. package/dist/cjs/components/calendar/utils.js.map +1 -1
  16. package/dist/cjs/components/date-picker/CDatePicker.d.ts +1 -1
  17. package/dist/cjs/components/date-range-picker/CDateRangePicker.d.ts +1 -1
  18. package/dist/cjs/components/multi-select/CMultiSelect.js +5 -1
  19. package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
  20. package/dist/cjs/components/nav/CNavGroup.js +6 -2
  21. package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
  22. package/dist/cjs/components/range-slider/CRangeSlider.js +6 -2
  23. package/dist/cjs/components/range-slider/CRangeSlider.js.map +1 -1
  24. package/dist/cjs/utils/index.d.ts +2 -1
  25. package/dist/cjs/utils/isEqual.d.ts +2 -0
  26. package/dist/cjs/utils/isEqual.js +78 -0
  27. package/dist/cjs/utils/isEqual.js.map +1 -0
  28. package/dist/esm/components/accordion/CAccordionBody.js +2 -1
  29. package/dist/esm/components/accordion/CAccordionBody.js.map +1 -1
  30. package/dist/esm/components/accordion/CAccordionButton.js +3 -1
  31. package/dist/esm/components/accordion/CAccordionButton.js.map +1 -1
  32. package/dist/esm/components/accordion/CAccordionItem.d.ts +8 -0
  33. package/dist/esm/components/accordion/CAccordionItem.js +11 -3
  34. package/dist/esm/components/accordion/CAccordionItem.js.map +1 -1
  35. package/dist/esm/components/calendar/CCalendar.d.ts +6 -6
  36. package/dist/esm/components/calendar/CCalendar.js +42 -38
  37. package/dist/esm/components/calendar/CCalendar.js.map +1 -1
  38. package/dist/esm/components/calendar/types.d.ts +3 -0
  39. package/dist/esm/components/calendar/utils.d.ts +175 -18
  40. package/dist/esm/components/calendar/utils.js +305 -44
  41. package/dist/esm/components/calendar/utils.js.map +1 -1
  42. package/dist/esm/components/date-picker/CDatePicker.d.ts +1 -1
  43. package/dist/esm/components/date-range-picker/CDateRangePicker.d.ts +1 -1
  44. package/dist/esm/components/multi-select/CMultiSelect.js +5 -1
  45. package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
  46. package/dist/esm/components/nav/CNavGroup.js +6 -2
  47. package/dist/esm/components/nav/CNavGroup.js.map +1 -1
  48. package/dist/esm/components/range-slider/CRangeSlider.js +6 -2
  49. package/dist/esm/components/range-slider/CRangeSlider.js.map +1 -1
  50. package/dist/esm/utils/index.d.ts +2 -1
  51. package/dist/esm/utils/isEqual.d.ts +2 -0
  52. package/dist/esm/utils/isEqual.js +74 -0
  53. package/dist/esm/utils/isEqual.js.map +1 -0
  54. package/package.json +6 -6
  55. package/src/components/accordion/CAccordionBody.ts +2 -1
  56. package/src/components/accordion/CAccordionButton.ts +3 -1
  57. package/src/components/accordion/CAccordionItem.ts +11 -3
  58. package/src/components/calendar/CCalendar.ts +62 -52
  59. package/src/components/calendar/types.ts +5 -0
  60. package/src/components/calendar/utils.ts +414 -109
  61. package/src/components/date-picker/CDatePicker.ts +1 -1
  62. package/src/components/date-range-picker/CDateRangePicker.ts +1 -1
  63. package/src/components/multi-select/CMultiSelect.ts +10 -2
  64. package/src/components/nav/CNavGroup.ts +7 -2
  65. package/src/components/range-slider/CRangeSlider.ts +7 -2
  66. package/src/utils/index.ts +10 -1
  67. package/src/utils/isEqual.ts +75 -0
@@ -1,18 +1,24 @@
1
- import type { DisabledDate } from './CCalendar'
2
-
3
- export const convertIsoWeekToDate = (isoWeek: string) => {
4
- const [year, week] = isoWeek.split(/w/i)
5
- // Get date for 4th of January for year
6
- const date = new Date(Number(year), 0, 4)
7
- // Get previous Monday, add 7 days for each week after first
1
+ import type { DisabledDate, SelectionTypes, ViewTypes } from './types'
2
+
3
+ /**
4
+ * Converts an ISO week string to a Date object representing the Monday of that week.
5
+ * @param isoWeek - The ISO week string (e.g., "2023W05" or "2023w05").
6
+ * @returns The Date object for the Monday of the specified week, or null if invalid.
7
+ */
8
+ export const convertIsoWeekToDate = (isoWeek: string): Date => {
9
+ const [year, week] = isoWeek.split(/[Ww]/)
10
+ const date = new Date(Number(year), 0, 4) // 4th Jan is always in week 1
8
11
  date.setDate(date.getDate() - (date.getDay() || 7) + 1 + (Number(week) - 1) * 7)
9
12
  return date
10
13
  }
11
14
 
12
- export const convertToDateObject = (
13
- date: Date | string,
14
- selectionType?: 'day' | 'week' | 'month' | 'year',
15
- ) => {
15
+ /**
16
+ * Converts a date string or Date object to a Date object based on selection type.
17
+ * @param date - The date to convert.
18
+ * @param selectionType - The type of selection ('day', 'week', 'month', 'year').
19
+ * @returns The corresponding Date object or null if invalid.
20
+ */
21
+ export const convertToDateObject = (date: Date | string, selectionType?: SelectionTypes): Date => {
16
22
  if (date instanceof Date) {
17
23
  return date
18
24
  }
@@ -30,12 +36,12 @@ export const convertToDateObject = (
30
36
  return new Date(Date.parse(date))
31
37
  }
32
38
 
33
- export const convertToLocalDate = (d: Date, locale: string, options = {}) =>
34
- d.toLocaleDateString(locale, options)
35
-
36
- export const convertToLocalTime = (d: Date, locale: string, options = {}) =>
37
- d.toLocaleTimeString(locale, options)
38
-
39
+ /**
40
+ * Creates groups from an array.
41
+ * @param arr - The array to group.
42
+ * @param numberOfGroups - Number of groups to create.
43
+ * @returns An array of grouped arrays.
44
+ */
39
45
  export const createGroupsInArray = <T>(arr: T[], numberOfGroups: number): T[][] => {
40
46
  const perGroup = Math.ceil(arr.length / numberOfGroups)
41
47
  return Array.from({ length: numberOfGroups })
@@ -43,11 +49,14 @@ export const createGroupsInArray = <T>(arr: T[], numberOfGroups: number): T[][]
43
49
  .map((_, i) => arr.slice(i * perGroup, (i + 1) * perGroup))
44
50
  }
45
51
 
46
- export const getCalendarDate = (
47
- calendarDate: Date,
48
- order: number,
49
- view: 'days' | 'months' | 'years',
50
- ) => {
52
+ /**
53
+ * Adjusts the calendar date based on order and view type.
54
+ * @param calendarDate - The current calendar date.
55
+ * @param order - The order to adjust by.
56
+ * @param view - The current view type.
57
+ * @returns The adjusted Date object.
58
+ */
59
+ export const getCalendarDate = (calendarDate: Date, order: number, view: ViewTypes): Date => {
51
60
  if (order !== 0 && view === 'days') {
52
61
  return new Date(calendarDate.getFullYear(), calendarDate.getMonth() + order, 1)
53
62
  }
@@ -63,14 +72,16 @@ export const getCalendarDate = (
63
72
  return calendarDate
64
73
  }
65
74
 
66
- export const getCurrentYear = () => new Date().getFullYear()
67
-
68
- export const getCurrentMonth = () => new Date().getMonth()
69
-
75
+ /**
76
+ * Formats a date based on the selection type.
77
+ * @param date - The date to format.
78
+ * @param selectionType - The type of selection ('day', 'week', 'month', 'year').
79
+ * @returns A formatted date string or the original Date object.
80
+ */
70
81
  export const getDateBySelectionType = (
71
82
  date: Date | null,
72
- selectionType: 'day' | 'week' | 'month' | 'year',
73
- ) => {
83
+ selectionType: SelectionTypes,
84
+ ): string | Date | null => {
74
85
  if (date === null) {
75
86
  return null
76
87
  }
@@ -91,36 +102,89 @@ export const getDateBySelectionType = (
91
102
  return date
92
103
  }
93
104
 
94
- export const getMonthName = (month: number, locale: string) => {
95
- const d = new Date()
96
- d.setDate(1)
97
- d.setMonth(month)
98
- return d.toLocaleString(locale, { month: 'long' })
99
- }
105
+ /**
106
+ * Retrieves the first available date within a range that is not disabled.
107
+ * @param startDate - Start date of the range.
108
+ * @param endDate - End date of the range.
109
+ * @param min - Minimum allowed date.
110
+ * @param max - Maximum allowed date.
111
+ * @param disabledDates - Criteria for disabled dates.
112
+ * @returns The first available Date object or null if none found.
113
+ */
114
+ export const getFirstAvailableDateInRange = (
115
+ startDate: Date,
116
+ endDate: Date,
117
+ min?: Date | null,
118
+ max?: Date | null,
119
+ disabledDates?: DisabledDate | DisabledDate[],
120
+ ): Date | null => {
121
+ const _min = min ? new Date(Math.max(startDate.getTime(), min.getTime())) : startDate
122
+ const _max = max ? new Date(Math.min(endDate.getTime(), max.getTime())) : endDate
100
123
 
101
- export const getMonthsNames = (locale: string) => {
102
- const months = []
103
- const d = new Date()
104
- d.setDate(1)
124
+ if (disabledDates === undefined) {
125
+ return _min
126
+ }
105
127
 
106
- for (let i = 0; i < 12; i++) {
107
- d.setMonth(i)
108
- months.push(d.toLocaleString(locale, { month: 'short' }))
128
+ for (
129
+ const currentDate = new Date(_min);
130
+ currentDate <= _max;
131
+ currentDate.setDate(currentDate.getDate() + 1)
132
+ ) {
133
+ if (!isDateDisabled(currentDate, min, max, disabledDates)) {
134
+ return currentDate
135
+ }
109
136
  }
110
137
 
111
- return months
138
+ return null
112
139
  }
113
140
 
114
- export const getYears = (year: number) => {
115
- const years = []
116
- for (let _year = year - 6; _year < year + 6; _year++) {
117
- years.push(_year)
118
- }
141
+ /**
142
+ * Retrieves an array of month names based on locale and format.
143
+ * @param locale - The locale string (e.g., 'en-US').
144
+ * @param format - The format of the month names ('short' or 'long').
145
+ * @returns An array of month names.
146
+ */
147
+ export const getMonthsNames = (locale: string, format: 'short' | 'long' = 'short'): string[] => {
148
+ return Array.from({ length: 12 }, (_, i) => {
149
+ return new Date(2000, i, 1).toLocaleString(locale, { month: format })
150
+ })
151
+ }
119
152
 
120
- return years
153
+ /**
154
+ * Retrieves an array of selectable dates from the given element.
155
+ * @param element - The HTML element to search for selectable dates.
156
+ * @param selector - The CSS selector used to identify selectable dates. Defaults to 'tr[tabindex="0"], td[tabindex="0"]'.
157
+ * @returns An array of HTMLElements representing the selectable dates.
158
+ */
159
+ export const getSelectableDates = (
160
+ element: HTMLElement,
161
+ selector: string = 'tr[tabindex="0"], td[tabindex="0"]',
162
+ ) => {
163
+ return [...Element.prototype.querySelectorAll.call(element, selector)] as HTMLElement[]
121
164
  }
122
165
 
123
- const getLeadingDays = (year: number, month: number, firstDayOfWeek: number) => {
166
+ /**
167
+ * Generates an array of years centered around a given year.
168
+ * @param year - The central year.
169
+ * @param range - The number of years before and after the central year.
170
+ * @returns An array of years.
171
+ */
172
+ export const getYears = (year: number, range: number = 6): number[] => {
173
+ return Array.from({ length: range * 2 }, (_, i) => year - range + i)
174
+ }
175
+
176
+ /**
177
+ * Retrieves leading days (from the previous month) for a calendar view.
178
+ * @param year - The year.
179
+ * @param month - The month (0-11).
180
+ * @param firstDayOfWeek - The first day of the week (0-6, where 0 is Sunday).
181
+ * @returns An array of leading day objects.
182
+ */
183
+ const getLeadingDays = (
184
+ year: number,
185
+ month: number,
186
+ firstDayOfWeek: number,
187
+ ): { date: Date; month: string }[] => {
124
188
  // 0: sunday
125
189
  // 1: monday
126
190
  const dates = []
@@ -144,7 +208,13 @@ const getLeadingDays = (year: number, month: number, firstDayOfWeek: number) =>
144
208
  return dates
145
209
  }
146
210
 
147
- const getMonthDays = (year: number, month: number) => {
211
+ /**
212
+ * Retrieves all days within a specific month.
213
+ * @param year - The year.
214
+ * @param month - The month (0-11).
215
+ * @returns An array of day objects.
216
+ */
217
+ const getMonthDays = (year: number, month: number): { date: Date; month: string }[] => {
148
218
  const dates = []
149
219
  const lastDay = new Date(year, month + 1, 0).getDate()
150
220
  for (let i = 1; i <= lastDay; i++) {
@@ -157,6 +227,14 @@ const getMonthDays = (year: number, month: number) => {
157
227
  return dates
158
228
  }
159
229
 
230
+ /**
231
+ * Retrieves trailing days (from the next month) for a calendar view.
232
+ * @param year - The year.
233
+ * @param month - The month (0-11).
234
+ * @param leadingDays - Array of leading day objects.
235
+ * @param monthDays - Array of current month day objects.
236
+ * @returns An array of trailing day objects.
237
+ */
160
238
  const getTrailingDays = (
161
239
  year: number,
162
240
  month: number,
@@ -175,17 +253,38 @@ const getTrailingDays = (
175
253
  return dates
176
254
  }
177
255
 
178
- export const getWeekNumber = (date: Date) => {
179
- const week1 = new Date(date.getFullYear(), 0, 4)
180
- return (
181
- 1 +
182
- Math.round(
183
- ((date.getTime() - week1.getTime()) / 86_400_000 - 3 + ((week1.getDay() + 6) % 7)) / 7,
184
- )
185
- )
256
+ /**
257
+ * Calculates the ISO week number for a given date.
258
+ * @param date - The date to calculate the week number for.
259
+ * @returns The ISO week number.
260
+ */
261
+ export const getWeekNumber = (date: Date): number => {
262
+ const tempDate = new Date(date.getTime())
263
+ tempDate.setHours(0, 0, 0, 0)
264
+
265
+ // Thursday in current week decides the year
266
+ tempDate.setDate(tempDate.getDate() + 3 - ((tempDate.getDay() + 6) % 7))
267
+
268
+ const week1 = new Date(tempDate.getFullYear(), 0, 4)
269
+
270
+ // Calculate full weeks to the date
271
+ const weekNumber = 1 + Math.round((tempDate.getTime() - week1.getTime()) / 86_400_000 / 7)
272
+
273
+ return weekNumber
186
274
  }
187
275
 
188
- export const getMonthDetails = (year: number, month: number, firstDayOfWeek: number) => {
276
+ /**
277
+ * Retrieves detailed information about each week in a month for calendar rendering.
278
+ * @param year - The year.
279
+ * @param month - The month (0-11).
280
+ * @param firstDayOfWeek - The first day of the week (0-6, where 0 is Sunday).
281
+ * @returns An array of week objects containing week numbers and day details.
282
+ */
283
+ export const getMonthDetails = (
284
+ year: number,
285
+ month: number,
286
+ firstDayOfWeek: number,
287
+ ): { weekNumber?: number; days: { date: Date; month: string }[] }[] => {
189
288
  const daysPrevMonth = getLeadingDays(year, month, firstDayOfWeek)
190
289
  const daysThisMonth = getMonthDays(year, month)
191
290
  const daysNextMonth = getTrailingDays(year, month, daysPrevMonth, daysThisMonth)
@@ -209,35 +308,20 @@ export const getMonthDetails = (year: number, month: number, firstDayOfWeek: num
209
308
  return weeks
210
309
  }
211
310
 
212
- export const isDisableDateInRange = (
213
- startDate?: Date | null,
214
- endDate?: Date | null,
215
- disabledDates?: DisabledDate | DisabledDate[],
216
- ) => {
217
- if (startDate && endDate) {
218
- const date = new Date(startDate)
219
- let disabled = false
220
-
221
- while (date < endDate) {
222
- date.setDate(date.getDate() + 1)
223
- if (isDateDisabled(date, null, null, disabledDates)) {
224
- disabled = true
225
- break
226
- }
227
- }
228
-
229
- return disabled
230
- }
231
-
232
- return false
233
- }
234
-
311
+ /**
312
+ * Checks if a date is disabled based on the 'date' period type.
313
+ * @param date - The date to check.
314
+ * @param min - Minimum allowed date.
315
+ * @param max - Maximum allowed date.
316
+ * @param disabledDates - Criteria for disabled dates.
317
+ * @returns True if the date is disabled, false otherwise.
318
+ */
235
319
  export const isDateDisabled = (
236
320
  date: Date,
237
321
  min?: Date | null,
238
322
  max?: Date | null,
239
323
  disabledDates?: DisabledDate | DisabledDate[],
240
- ) => {
324
+ ): boolean => {
241
325
  if (min && date < min) {
242
326
  return true
243
327
  }
@@ -246,6 +330,10 @@ export const isDateDisabled = (
246
330
  return true
247
331
  }
248
332
 
333
+ if (disabledDates === undefined) {
334
+ return false
335
+ }
336
+
249
337
  if (typeof disabledDates === 'function') {
250
338
  return disabledDates(date)
251
339
  }
@@ -273,31 +361,164 @@ export const isDateDisabled = (
273
361
  return false
274
362
  }
275
363
 
276
- export const isDateInRange = (date: Date, start: Date | null, end: Date | null) => {
364
+ /**
365
+ * Checks if a date is within a specified range.
366
+ * @param date - The date to check.
367
+ * @param start - Start date of the range.
368
+ * @param end - End date of the range.
369
+ * @returns True if the date is within the range, false otherwise.
370
+ */
371
+ export const isDateInRange = (date: Date, start: Date | null, end: Date | null): boolean => {
277
372
  const _date = removeTimeFromDate(date)
278
373
  const _start = start ? removeTimeFromDate(start) : null
279
374
  const _end = end ? removeTimeFromDate(end) : null
280
375
 
281
- return _start && _end && _start <= _date && _date <= _end
376
+ return !!(_start && _end && _start <= _date && _date <= _end)
282
377
  }
283
378
 
284
- export const isDateSelected = (date: Date, start: Date | null, end: Date | null) => {
285
- return (start && isSameDateAs(start, date)) || (end && isSameDateAs(end, date))
379
+ /**
380
+ * Checks if a date is selected based on start and end dates.
381
+ * @param date - The date to check.
382
+ * @param start - Start date.
383
+ * @param end - End date.
384
+ * @returns True if the date is selected, false otherwise.
385
+ */
386
+ export const isDateSelected = (date: Date, start: Date | null, end: Date | null): boolean => {
387
+ if (start !== null && isSameDateAs(start, date)) {
388
+ return true
389
+ }
390
+
391
+ if (end !== null && isSameDateAs(end, date)) {
392
+ return true
393
+ }
394
+
395
+ return false
396
+ }
397
+
398
+ /**
399
+ * Determines if any date within a range is disabled.
400
+ * @param startDate - Start date of the range.
401
+ * @param endDate - End date of the range.
402
+ * @param disabledDates - Criteria for disabled dates.
403
+ * @returns True if any date in the range is disabled, false otherwise.
404
+ */
405
+ export const isDisableDateInRange = (
406
+ startDate?: Date | null,
407
+ endDate?: Date | null,
408
+ disabledDates?: DisabledDate | DisabledDate[],
409
+ ): boolean => {
410
+ if (startDate && endDate) {
411
+ const date = new Date(startDate)
412
+ let disabled = false
413
+
414
+ while (date < endDate) {
415
+ date.setDate(date.getDate() + 1)
416
+ if (isDateDisabled(date, null, null, disabledDates)) {
417
+ disabled = true
418
+ break
419
+ }
420
+ }
421
+
422
+ return disabled
423
+ }
424
+
425
+ return false
286
426
  }
287
427
 
288
- export const isEndDate = (date: Date, start: Date | null, end: Date | null) => {
289
- return start && end && isSameDateAs(end, date) && start < end
428
+ /**
429
+ * Checks if a month is disabled based on the 'month' period type.
430
+ * @param date - The date representing the month to check.
431
+ * @param min - Minimum allowed date.
432
+ * @param max - Maximum allowed date.
433
+ * @param disabledDates - Criteria for disabled dates.
434
+ * @returns True if the month is disabled, false otherwise.
435
+ */
436
+ export const isMonthDisabled = (
437
+ date: Date,
438
+ min?: Date | null,
439
+ max?: Date | null,
440
+ disabledDates?: DisabledDate | DisabledDate[],
441
+ ) => {
442
+ const current = date.getFullYear() * 12 + date.getMonth()
443
+ const _min = min ? min.getFullYear() * 12 + min.getMonth() : null
444
+ const _max = max ? max.getFullYear() * 12 + max.getMonth() : null
445
+
446
+ if (_min && current < _min) {
447
+ return true
448
+ }
449
+
450
+ if (_max && current > _max) {
451
+ return true
452
+ }
453
+
454
+ if (disabledDates === undefined) {
455
+ return false
456
+ }
457
+
458
+ const start = min ? Math.max(date.getTime(), min.getTime()) : date
459
+ const end = max
460
+ ? Math.min(date.getTime(), max.getTime())
461
+ : new Date(new Date().getFullYear(), 11, 31)
462
+
463
+ for (
464
+ const currentDate = new Date(start);
465
+ currentDate <= end;
466
+ currentDate.setDate(currentDate.getDate() + 1)
467
+ ) {
468
+ if (!isDateDisabled(currentDate, min, max, disabledDates)) {
469
+ return false
470
+ }
471
+ }
472
+
473
+ return false
290
474
  }
291
475
 
292
- export const isLastDayOfMonth = (date: Date) => {
293
- const test = new Date(date.getTime())
294
- const month = test.getMonth()
476
+ /**
477
+ * Checks if a month is selected based on start and end dates.
478
+ * @param date - The date representing the month.
479
+ * @param start - Start date.
480
+ * @param end - End date.
481
+ * @returns True if the month is selected, false otherwise.
482
+ */
483
+ export const isMonthSelected = (date: Date, start: Date | null, end: Date | null): boolean => {
484
+ const year = date.getFullYear()
485
+ const month = date.getMonth()
486
+
487
+ if (start !== null && year === start.getFullYear() && month === start.getMonth()) {
488
+ return true
489
+ }
490
+
491
+ if (end !== null && year === end.getFullYear() && month === end.getMonth()) {
492
+ return true
493
+ }
494
+
495
+ return false
496
+ }
295
497
 
296
- test.setDate(test.getDate() + 1)
297
- return test.getMonth() !== month
498
+ /**
499
+ * Checks if a month is within a specified range.
500
+ * @param date - The date representing the month.
501
+ * @param start - Start date.
502
+ * @param end - End date.
503
+ * @returns True if the month is within the range, false otherwise.
504
+ */
505
+ export const isMonthInRange = (date: Date, start: Date | null, end: Date | null): boolean => {
506
+ const year = date.getFullYear()
507
+ const month = date.getMonth()
508
+ const _start = start ? start.getFullYear() * 12 + start.getMonth() : null
509
+ const _end = end ? end.getFullYear() * 12 + end.getMonth() : null
510
+ const _date = year * 12 + month
511
+
512
+ return !!(_start && _end && _start <= _date && _date <= _end)
298
513
  }
299
514
 
300
- export const isSameDateAs = (date: Date | null, date2: Date | null) => {
515
+ /**
516
+ * Checks if two dates are the same calendar date.
517
+ * @param date - First date.
518
+ * @param date2 - Second date.
519
+ * @returns True if both dates are the same, false otherwise.
520
+ */
521
+ export const isSameDateAs = (date: Date | null, date2: Date | null): boolean => {
301
522
  if (date instanceof Date && date2 instanceof Date) {
302
523
  return (
303
524
  date.getDate() === date2.getDate() &&
@@ -313,23 +534,107 @@ export const isSameDateAs = (date: Date | null, date2: Date | null) => {
313
534
  return false
314
535
  }
315
536
 
316
- export const isStartDate = (date: Date, start: Date | null, end: Date | null) => {
317
- return start && end && isSameDateAs(start, date) && start < end
537
+ /**
538
+ * Checks if a date is today.
539
+ * @param date - The date to check.
540
+ * @returns True if the date is today, false otherwise.
541
+ */
542
+ export const isToday = (date: Date): boolean => {
543
+ const today = new Date()
544
+ return isSameDateAs(date, today)
318
545
  }
319
546
 
320
- export const isToday = (date: Date) => {
321
- const today = new Date()
322
- return (
323
- date.getDate() === today.getDate() &&
324
- date.getMonth() === today.getMonth() &&
325
- date.getFullYear() === today.getFullYear()
326
- )
547
+ /**
548
+ * Checks if a year is disabled based on the 'year' period type.
549
+ * @param date - The date representing the year to check.
550
+ * @param min - Minimum allowed date.
551
+ * @param max - Maximum allowed date.
552
+ * @param disabledDates - Criteria for disabled dates.
553
+ * @returns True if the year is disabled, false otherwise.
554
+ */
555
+ export const isYearDisabled = (
556
+ date: Date,
557
+ min?: Date | null,
558
+ max?: Date | null,
559
+ disabledDates?: DisabledDate | DisabledDate[],
560
+ ) => {
561
+ const year = date.getFullYear()
562
+ const minYear = min ? min.getFullYear() : null
563
+ const maxYear = max ? max.getFullYear() : null
564
+
565
+ if (minYear && year < minYear) {
566
+ return true
567
+ }
568
+
569
+ if (maxYear && year > maxYear) {
570
+ return true
571
+ }
572
+
573
+ if (disabledDates === undefined) {
574
+ return false
575
+ }
576
+
577
+ const start = min ? Math.max(date.getTime(), min.getTime()) : date
578
+ const end = max
579
+ ? Math.min(date.getTime(), max.getTime())
580
+ : new Date(new Date().getFullYear(), 11, 31)
581
+
582
+ for (
583
+ const currentDate = new Date(start);
584
+ currentDate <= end;
585
+ currentDate.setDate(currentDate.getDate() + 1)
586
+ ) {
587
+ if (!isDateDisabled(currentDate, min, max, disabledDates)) {
588
+ return false
589
+ }
590
+ }
591
+
592
+ return false
327
593
  }
328
594
 
329
- export const isValidDate = (date: string) => {
330
- const d = new Date(date)
331
- return d instanceof Date && d.getTime()
595
+ /**
596
+ * Checks if a year is selected based on start and end dates.
597
+ * @param date - The date representing the year.
598
+ * @param start - Start date.
599
+ * @param end - End date.
600
+ * @returns True if the year matches the start's or end's year, false otherwise.
601
+ */
602
+ export const isYearSelected = (date: Date, start: Date | null, end: Date | null): boolean => {
603
+ const year = date.getFullYear()
604
+
605
+ if (start !== null && year === start.getFullYear()) {
606
+ return true
607
+ }
608
+
609
+ if (end !== null && year === end.getFullYear()) {
610
+ return true
611
+ }
612
+
613
+ return false
614
+ }
615
+
616
+ /**
617
+ * Checks if a year is within a specified range.
618
+ * @param date - The date representing the year.
619
+ * @param start - Start date.
620
+ * @param end - End date.
621
+ * @returns True if the year's value lies between start's year and end's year, false otherwise.
622
+ */
623
+ export const isYearInRange = (date: Date, start: Date | null, end: Date | null): boolean => {
624
+ const year = date.getFullYear()
625
+ const _start = start ? start.getFullYear() : null
626
+ const _end = end ? end.getFullYear() : null
627
+
628
+ return !!(_start && _end && _start <= year && year <= _end)
332
629
  }
333
630
 
334
- export const removeTimeFromDate = (date: Date) =>
335
- new Date(date.getFullYear(), date.getMonth(), date.getDate())
631
+ /**
632
+ * Removes the time component from a Date object.
633
+ * @param date - The original date.
634
+ * @returns A new Date object with the time set to 00:00:00.
635
+ */
636
+ export const removeTimeFromDate = (date: Date): Date => {
637
+ const clearedDate = new Date(date)
638
+ clearedDate.setHours(0, 0, 0, 0)
639
+ return clearedDate
640
+ }
@@ -3,7 +3,7 @@ import { defineComponent, h, PropType } from 'vue'
3
3
  import { CDateRangePicker } from '../date-range-picker/'
4
4
 
5
5
  import { Color } from '../props'
6
- import type { DisabledDate } from '../calendar/CCalendar'
6
+ import type { DisabledDate } from '../calendar/types'
7
7
 
8
8
  const CDatePicker = defineComponent({
9
9
  name: 'CDatePicker',
@@ -12,7 +12,7 @@ import { getInputIdOrName, getLocalDateFromString } from './utils'
12
12
  import { useDebouncedCallback } from '../../composables'
13
13
  import { Color } from '../props'
14
14
 
15
- import type { DisabledDate } from '../calendar/CCalendar'
15
+ import type { DisabledDate } from '../calendar/types'
16
16
 
17
17
  const CDateRangePicker = defineComponent({
18
18
  name: 'CDateRangePicker',
@@ -8,7 +8,7 @@ import { CMultiSelectOptions } from './CMultiSelectOptions'
8
8
  import { CMultiSelectSelection } from './CMultiSelectSelection'
9
9
 
10
10
  import { useDropdownWithPopper } from '../../composables'
11
- import { getNextActiveElement } from '../../utils'
11
+ import { getNextActiveElement, isEqual } from '../../utils'
12
12
 
13
13
  import {
14
14
  createOption,
@@ -401,7 +401,15 @@ const CMultiSelect = defineComponent({
401
401
  ) as Option[]
402
402
 
403
403
  if (_selected.length > 0) {
404
- selected.value = selectOptions(props.multiple, _selected, selected.value, deselected)
404
+ const newSelectedValue = selectOptions(
405
+ props.multiple,
406
+ _selected,
407
+ selected.value,
408
+ deselected,
409
+ )
410
+ if (!isEqual(newSelectedValue, selected.value)) {
411
+ selected.value = newSelectedValue
412
+ }
405
413
  }
406
414
  },
407
415
  { immediate: true },