@coreui/react-pro 5.4.0 → 5.5.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.
@@ -23,6 +23,30 @@ import {
23
23
  import { useForkedRef, useStateWithCallback } from '../../hooks'
24
24
 
25
25
  export interface CCalendarProps {
26
+ /**
27
+ * A string that provides an accessible label for the button that navigates to the next month in the calendar. This label is read by screen readers to describe the action associated with the button.
28
+ *
29
+ * @since 5.5.0
30
+ */
31
+ ariaNavNextMonthLabel?: string
32
+ /**
33
+ * A string that provides an accessible label for the button that navigates to the next year in the calendar. This label is intended for screen readers to help users understand the button's functionality.
34
+ *
35
+ * @since 5.5.0
36
+ */
37
+ ariaNavNextYearLabel?: string
38
+ /**
39
+ * A string that provides an accessible label for the button that navigates to the previous month in the calendar. Screen readers will use this label to explain the purpose of the button.
40
+ *
41
+ * @since 5.5.0
42
+ */
43
+ ariaNavPrevMonthLabel?: string
44
+ /**
45
+ * A string that provides an accessible label for the button that navigates to the previous year in the calendar. This label helps screen reader users understand the button's function.
46
+ *
47
+ * @since 5.5.0
48
+ */
49
+ ariaNavPrevYearLabel?: string
26
50
  /**
27
51
  * Default date of the component
28
52
  */
@@ -251,7 +275,11 @@ const Calendar = (props: {
251
275
  </th>
252
276
  )}
253
277
  {weekDays.map(({ date }: { date: Date }, idx: number) => (
254
- <th key={idx} className="calendar-cell">
278
+ <th
279
+ className="calendar-cell"
280
+ abbr={date.toLocaleDateString(locale, { weekday: 'long' })}
281
+ key={idx}
282
+ >
255
283
  <div className="calendar-header-cell-inner">
256
284
  {typeof weekdayFormat === 'function'
257
285
  ? weekdayFormat(date)
@@ -276,6 +304,7 @@ const Calendar = (props: {
276
304
  selectionType,
277
305
  )
278
306
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
307
+ const isSelected = isDateSelected(date, startDate, endDate)
279
308
  const current = week.days.some((day) => day.month === 'current')
280
309
  return (
281
310
  <tr
@@ -286,10 +315,11 @@ const Calendar = (props: {
286
315
  selectionType === 'week' && hoverDate && selectEndDate
287
316
  ? isDateInRange(date, startDate, hoverDate)
288
317
  : isDateInRange(date, hoverDate, endDate),
289
- selected: isDateSelected(date, startDate, endDate),
318
+ selected: isSelected,
290
319
  })}
291
320
  key={index}
292
321
  tabIndex={selectionType === 'week' && current && !isDisabled ? 0 : -1}
322
+ {...(isSelected && { 'aria-selected': true })}
293
323
  {...(selectionType === 'week' &&
294
324
  !isDisabled && {
295
325
  onBlur: () => onCalendarMouseLeave(),
@@ -307,6 +337,7 @@ const Calendar = (props: {
307
337
  )}
308
338
  {week.days.map(({ date, month }: { date: Date; month: string }, idx: number) => {
309
339
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
340
+ const isSelected = isDateSelected(date, startDate, endDate)
310
341
  return month === 'current' || showAdjacementDays ? (
311
342
  <td
312
343
  className={classNames('calendar-cell', {
@@ -319,7 +350,7 @@ const Calendar = (props: {
319
350
  ? isDateInRange(date, startDate, hoverDate)
320
351
  : isDateInRange(date, hoverDate, endDate)),
321
352
  range: month === 'current' && isDateInRange(date, startDate, endDate),
322
- selected: isDateSelected(date, startDate, endDate),
353
+ selected: isSelected,
323
354
  }),
324
355
  [month]: true,
325
356
  today: month === 'current' && isToday(date),
@@ -333,6 +364,7 @@ const Calendar = (props: {
333
364
  : -1
334
365
  }
335
366
  title={date.toLocaleDateString(locale)}
367
+ {...(isSelected && { 'aria-selected': true })}
336
368
  {...(selectionType === 'day' &&
337
369
  (month === 'current' || selectAdjacementDays) && {
338
370
  onBlur: () => onCalendarMouseLeave(),
@@ -368,11 +400,12 @@ const Calendar = (props: {
368
400
  const monthNumber = index * 3 + idx
369
401
  const date = new Date(calendarDate.getFullYear(), monthNumber, 1)
370
402
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
403
+ const isSelected = isDateSelected(date, startDate, endDate)
371
404
  return (
372
405
  <td
373
406
  className={classNames('calendar-cell', {
374
407
  disabled: isDisabled,
375
- selected: isDateSelected(date, startDate, endDate),
408
+ selected: isSelected,
376
409
  'range-hover':
377
410
  selectionType === 'month' &&
378
411
  (hoverDate && selectEndDate
@@ -382,6 +415,7 @@ const Calendar = (props: {
382
415
  })}
383
416
  key={idx}
384
417
  tabIndex={isDisabled ? -1 : 0}
418
+ {...(isSelected && { 'aria-selected': true })}
385
419
  {...(!isDisabled && {
386
420
  onBlur: () => onCalendarMouseLeave(),
387
421
  onClick: () => onCalendarClick(date),
@@ -405,11 +439,12 @@ const Calendar = (props: {
405
439
  {row.map((year, idx) => {
406
440
  const date = new Date(year, 0, 1)
407
441
  const isDisabled = isDateDisabled(date, minDate, maxDate, disabledDates)
442
+ const isSelected = isDateSelected(date, startDate, endDate)
408
443
  return (
409
444
  <td
410
445
  className={classNames('calendar-cell year', {
411
446
  disabled: isDisabled,
412
- selected: isDateSelected(date, startDate, endDate),
447
+ selected: isSelected,
413
448
  'range-hover':
414
449
  selectionType === 'year' &&
415
450
  (hoverDate && selectEndDate
@@ -419,6 +454,7 @@ const Calendar = (props: {
419
454
  })}
420
455
  key={idx}
421
456
  tabIndex={isDisabled ? -1 : 0}
457
+ {...(isSelected && { 'aria-selected': true })}
422
458
  {...(!isDisabled && {
423
459
  onBlur: () => onCalendarMouseLeave(),
424
460
  onClick: () => onCalendarClick(date),
@@ -443,6 +479,10 @@ const Calendar = (props: {
443
479
  }
444
480
 
445
481
  const Navigation = (props: {
482
+ ariaNavNextMonthLabel: string
483
+ ariaNavNextYearLabel: string
484
+ ariaNavPrevMonthLabel: string
485
+ ariaNavPrevYearLabel: string
446
486
  calendarDate: Date
447
487
  locale: string
448
488
  navigation: boolean
@@ -457,6 +497,10 @@ const Navigation = (props: {
457
497
  view: 'days' | 'months' | 'years'
458
498
  }) => {
459
499
  const {
500
+ ariaNavNextMonthLabel,
501
+ ariaNavNextYearLabel,
502
+ ariaNavPrevMonthLabel,
503
+ ariaNavPrevYearLabel,
460
504
  calendarDate,
461
505
  locale,
462
506
  navigation,
@@ -475,13 +519,23 @@ const Navigation = (props: {
475
519
  <div className="calendar-nav">
476
520
  {navigation && (
477
521
  <div className="calendar-nav-prev">
478
- <CButton color="transparent" size="sm" onClick={() => onNavigationClick('prev', true)}>
522
+ <CButton
523
+ color="transparent"
524
+ size="sm"
525
+ aria-label={ariaNavPrevYearLabel}
526
+ onClick={() => onNavigationClick('prev', true)}
527
+ >
479
528
  {navPrevDoubleIcon ?? (
480
529
  <span className="calendar-nav-icon calendar-nav-icon-double-prev" />
481
530
  )}
482
531
  </CButton>
483
532
  {view === 'days' && (
484
- <CButton color="transparent" size="sm" onClick={() => onNavigationClick('prev')}>
533
+ <CButton
534
+ color="transparent"
535
+ size="sm"
536
+ aria-label={ariaNavPrevMonthLabel}
537
+ onClick={() => onNavigationClick('prev')}
538
+ >
485
539
  {navPrevIcon ?? <span className="calendar-nav-icon calendar-nav-icon-prev" />}
486
540
  </CButton>
487
541
  )}
@@ -489,6 +543,7 @@ const Navigation = (props: {
489
543
  )}
490
544
  <div
491
545
  className="calendar-nav-date"
546
+ aria-live="polite"
492
547
  {...(navYearFirst && { style: { display: 'flex', justifyContent: 'center' } })}
493
548
  >
494
549
  {view === 'days' && (
@@ -508,11 +563,21 @@ const Navigation = (props: {
508
563
  {navigation && (
509
564
  <div className="calendar-nav-next">
510
565
  {view === 'days' && (
511
- <CButton color="transparent" size="sm" onClick={() => onNavigationClick('next')}>
566
+ <CButton
567
+ color="transparent"
568
+ size="sm"
569
+ aria-label={ariaNavNextMonthLabel}
570
+ onClick={() => onNavigationClick('next')}
571
+ >
512
572
  {navNextIcon ?? <span className="calendar-nav-icon calendar-nav-icon-next" />}
513
573
  </CButton>
514
574
  )}
515
- <CButton color="transparent" size="sm" onClick={() => onNavigationClick('next', true)}>
575
+ <CButton
576
+ color="transparent"
577
+ size="sm"
578
+ aria-label={ariaNavNextYearLabel}
579
+ onClick={() => onNavigationClick('next', true)}
580
+ >
516
581
  {navNextDoubleIcon ?? (
517
582
  <span className="calendar-nav-icon calendar-nav-icon-double-next" />
518
583
  )}
@@ -526,6 +591,10 @@ const Navigation = (props: {
526
591
  export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
527
592
  (
528
593
  {
594
+ ariaNavNextMonthLabel = 'Next month',
595
+ ariaNavNextYearLabel = 'Next year',
596
+ ariaNavPrevMonthLabel = 'Previous month',
597
+ ariaNavPrevYearLabel = 'Previous year',
529
598
  startDate,
530
599
  endDate,
531
600
  calendarDate = startDate || endDate || null,
@@ -928,6 +997,10 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
928
997
  return (
929
998
  <div className={classNames('calendar', view)} key={index}>
930
999
  <Navigation
1000
+ ariaNavNextMonthLabel={ariaNavNextMonthLabel}
1001
+ ariaNavNextYearLabel={ariaNavNextYearLabel}
1002
+ ariaNavPrevMonthLabel={ariaNavPrevMonthLabel}
1003
+ ariaNavPrevYearLabel={ariaNavPrevYearLabel}
931
1004
  calendarDate={calendarDate}
932
1005
  locale={locale}
933
1006
  navigation={navigation}
@@ -975,6 +1048,10 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
975
1048
  )
976
1049
 
977
1050
  CCalendar.propTypes = {
1051
+ ariaNavNextMonthLabel: PropTypes.string,
1052
+ ariaNavNextYearLabel: PropTypes.string,
1053
+ ariaNavPrevMonthLabel: PropTypes.string,
1054
+ ariaNavPrevYearLabel: PropTypes.string,
978
1055
  className: PropTypes.string,
979
1056
  calendarDate: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
980
1057
  calendars: PropTypes.number,
@@ -19,10 +19,7 @@ export const convertToDateObject = (
19
19
  return convertIsoWeekToDate(date as string)
20
20
  }
21
21
 
22
- const _date = new Date(Date.parse(date))
23
- const userTimezoneOffset = _date.getTimezoneOffset() * 60_000
24
-
25
- return new Date(_date.getTime() + userTimezoneOffset)
22
+ return new Date(Date.parse(date))
26
23
  }
27
24
 
28
25
  export const convertToLocalDate = (d: Date, locale: string, options = {}) =>
@@ -202,6 +202,10 @@ export interface CDateRangePickerProps
202
202
  export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDateRangePickerProps>(
203
203
  (
204
204
  {
205
+ ariaNavNextMonthLabel,
206
+ ariaNavNextYearLabel,
207
+ ariaNavPrevMonthLabel,
208
+ ariaNavPrevYearLabel,
205
209
  calendars = 2,
206
210
  calendarDate,
207
211
  cancelButton = 'Cancel',
@@ -601,6 +605,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
601
605
  </div>
602
606
  )}
603
607
  <CCalendar
608
+ ariaNavNextMonthLabel={ariaNavNextMonthLabel}
609
+ ariaNavNextYearLabel={ariaNavNextYearLabel}
610
+ ariaNavPrevMonthLabel={ariaNavPrevMonthLabel}
611
+ ariaNavPrevYearLabel={ariaNavPrevYearLabel}
604
612
  calendarDate={_calendarDate}
605
613
  calendars={isMobile ? 1 : calendars}
606
614
  className="date-picker-calendars"