@coreui/vue-pro 5.15.0 → 5.17.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 (89) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/autocomplete/CAutocomplete.js +17 -16
  3. package/dist/cjs/components/autocomplete/CAutocomplete.js.map +1 -1
  4. package/dist/cjs/components/calendar/CCalendar.js +6 -0
  5. package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
  6. package/dist/cjs/components/dropdown/CDropdown.d.ts +32 -7
  7. package/dist/cjs/components/dropdown/CDropdown.js +47 -18
  8. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  9. package/dist/cjs/components/dropdown/CDropdownToggle.d.ts +19 -0
  10. package/dist/cjs/components/dropdown/CDropdownToggle.js +10 -1
  11. package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
  12. package/dist/cjs/components/dropdown/utils.d.ts +2 -0
  13. package/dist/cjs/components/dropdown/utils.js +13 -0
  14. package/dist/cjs/components/dropdown/utils.js.map +1 -1
  15. package/dist/cjs/components/index.d.ts +1 -0
  16. package/dist/cjs/components/index.js +4 -0
  17. package/dist/cjs/components/index.js.map +1 -1
  18. package/dist/cjs/components/nav/CNavItem.d.ts +2 -2
  19. package/dist/cjs/components/one-time-password-input/COneTimePassword.d.ts +278 -0
  20. package/dist/cjs/components/one-time-password-input/COneTimePassword.js +393 -0
  21. package/dist/cjs/components/one-time-password-input/COneTimePassword.js.map +1 -0
  22. package/dist/cjs/components/one-time-password-input/COneTimePasswordInput.d.ts +4 -0
  23. package/dist/cjs/components/one-time-password-input/COneTimePasswordInput.js +19 -0
  24. package/dist/cjs/components/one-time-password-input/COneTimePasswordInput.js.map +1 -0
  25. package/dist/cjs/components/one-time-password-input/index.d.ts +3 -0
  26. package/dist/cjs/components/one-time-password-input/utils.d.ts +2 -0
  27. package/dist/cjs/components/one-time-password-input/utils.js +18 -0
  28. package/dist/cjs/components/one-time-password-input/utils.js.map +1 -0
  29. package/dist/cjs/components/stepper/CStepper.d.ts +1 -1
  30. package/dist/cjs/components/time-picker/CTimePicker.d.ts +44 -0
  31. package/dist/cjs/components/time-picker/CTimePicker.js +63 -7
  32. package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
  33. package/dist/cjs/components/time-picker/CTimePickerRollCol.d.ts +19 -7
  34. package/dist/cjs/components/time-picker/CTimePickerRollCol.js +80 -8
  35. package/dist/cjs/components/time-picker/CTimePickerRollCol.js.map +1 -1
  36. package/dist/cjs/index.js +4 -0
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/esm/components/autocomplete/CAutocomplete.js +17 -16
  39. package/dist/esm/components/autocomplete/CAutocomplete.js.map +1 -1
  40. package/dist/esm/components/calendar/CCalendar.js +6 -0
  41. package/dist/esm/components/calendar/CCalendar.js.map +1 -1
  42. package/dist/esm/components/dropdown/CDropdown.d.ts +32 -7
  43. package/dist/esm/components/dropdown/CDropdown.js +49 -20
  44. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  45. package/dist/esm/components/dropdown/CDropdownToggle.d.ts +19 -0
  46. package/dist/esm/components/dropdown/CDropdownToggle.js +10 -1
  47. package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
  48. package/dist/esm/components/dropdown/utils.d.ts +2 -0
  49. package/dist/esm/components/dropdown/utils.js +13 -1
  50. package/dist/esm/components/dropdown/utils.js.map +1 -1
  51. package/dist/esm/components/index.d.ts +1 -0
  52. package/dist/esm/components/index.js +2 -0
  53. package/dist/esm/components/index.js.map +1 -1
  54. package/dist/esm/components/nav/CNavItem.d.ts +2 -2
  55. package/dist/esm/components/one-time-password-input/COneTimePassword.d.ts +278 -0
  56. package/dist/esm/components/one-time-password-input/COneTimePassword.js +391 -0
  57. package/dist/esm/components/one-time-password-input/COneTimePassword.js.map +1 -0
  58. package/dist/esm/components/one-time-password-input/COneTimePasswordInput.d.ts +4 -0
  59. package/dist/esm/components/one-time-password-input/COneTimePasswordInput.js +17 -0
  60. package/dist/esm/components/one-time-password-input/COneTimePasswordInput.js.map +1 -0
  61. package/dist/esm/components/one-time-password-input/index.d.ts +3 -0
  62. package/dist/esm/components/one-time-password-input/utils.d.ts +2 -0
  63. package/dist/esm/components/one-time-password-input/utils.js +15 -0
  64. package/dist/esm/components/one-time-password-input/utils.js.map +1 -0
  65. package/dist/esm/components/stepper/CStepper.d.ts +1 -1
  66. package/dist/esm/components/time-picker/CTimePicker.d.ts +44 -0
  67. package/dist/esm/components/time-picker/CTimePicker.js +63 -7
  68. package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
  69. package/dist/esm/components/time-picker/CTimePickerRollCol.d.ts +19 -7
  70. package/dist/esm/components/time-picker/CTimePickerRollCol.js +80 -8
  71. package/dist/esm/components/time-picker/CTimePickerRollCol.js.map +1 -1
  72. package/dist/esm/index.js +2 -0
  73. package/dist/esm/index.js.map +1 -1
  74. package/package.json +6 -6
  75. package/src/components/autocomplete/CAutocomplete.ts +17 -16
  76. package/src/components/calendar/CCalendar.ts +6 -0
  77. package/src/components/dropdown/CDropdown.ts +92 -36
  78. package/src/components/dropdown/CDropdownToggle.ts +10 -1
  79. package/src/components/dropdown/utils.ts +21 -0
  80. package/src/components/index.ts +1 -0
  81. package/src/components/nav/CNavItem.ts +1 -1
  82. package/src/components/one-time-password-input/COneTimePassword.ts +459 -0
  83. package/src/components/one-time-password-input/COneTimePasswordInput.ts +21 -0
  84. package/src/components/one-time-password-input/__tests__/COneTimePassword.spec.ts +210 -0
  85. package/src/components/one-time-password-input/__tests__/__snapshots__/COneTimePassword.spec.ts.snap +32 -0
  86. package/src/components/one-time-password-input/index.ts +4 -0
  87. package/src/components/one-time-password-input/utils.ts +13 -0
  88. package/src/components/time-picker/CTimePicker.ts +68 -9
  89. package/src/components/time-picker/CTimePickerRollCol.ts +87 -9
@@ -0,0 +1,32 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`COneTimePassword Component rendering COneTimePassword customize props 1`] = `"<div class="form-otp" role="group"><input type="text" class="form-otp-control" tabindex="0" aria-label="Digit 1 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 2 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 3 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 4 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="hidden" value=""></div>"`;
4
+
5
+ exports[`COneTimePassword Component rendering loads and displays COneTimePassword component 1`] = `"<div class="form-otp" role="group"><input type="text" class="form-otp-control" tabindex="0" aria-label="Digit 1 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 2 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 3 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="text" class="form-otp-control" tabindex="-1" aria-label="Digit 4 of 0" inputmode="numeric" pattern="[0-9]*" maxlength="1" autocomplete="off" value=""><input type="hidden" value=""></div>"`;
6
+
7
+ exports[`COneTimePassword with default value renders correctly 1`] = `
8
+ "<div class="form-otp" role="group">
9
+ <conetimepasswordinput></conetimepasswordinput>
10
+ <conetimepasswordinput></conetimepasswordinput>
11
+ <conetimepasswordinput></conetimepasswordinput>
12
+ <conetimepasswordinput></conetimepasswordinput><input type="hidden" value="">
13
+ </div>"
14
+ `;
15
+
16
+ exports[`Customize COneTimePassword component renders correctly 1`] = `
17
+ "<div class="form-otp form-otp-lg" role="group">
18
+ <conetimepasswordinput></conetimepasswordinput>
19
+ <conetimepasswordinput></conetimepasswordinput>
20
+ <conetimepasswordinput></conetimepasswordinput>
21
+ <conetimepasswordinput></conetimepasswordinput><input type="hidden" disabled="" value="">
22
+ </div>"
23
+ `;
24
+
25
+ exports[`Loads and display COneTimePassword component renders correctly 1`] = `
26
+ "<div class="form-otp" role="group">
27
+ <conetimepasswordinput></conetimepasswordinput>
28
+ <conetimepasswordinput></conetimepasswordinput>
29
+ <conetimepasswordinput></conetimepasswordinput>
30
+ <conetimepasswordinput></conetimepasswordinput><input type="hidden" value="">
31
+ </div>"
32
+ `;
@@ -0,0 +1,4 @@
1
+ import { COneTimePassword } from './COneTimePassword'
2
+ import { COneTimePasswordInput } from './COneTimePasswordInput'
3
+
4
+ export { COneTimePassword, COneTimePasswordInput }
@@ -0,0 +1,13 @@
1
+ export const isValidInput = (value: string, type: 'number' | 'text'): boolean => {
2
+ if (type === 'number') {
3
+ return /^\d$/.test(value)
4
+ }
5
+ return /^.$/u.test(value)
6
+ }
7
+
8
+ export const extractValidChars = (value: string, type: 'number' | 'text'): string => {
9
+ if (type === 'number') {
10
+ return value.replace(/\D/g, '')
11
+ }
12
+ return value
13
+ }
@@ -25,6 +25,28 @@ import { Color } from '../props'
25
25
  const CTimePicker = defineComponent({
26
26
  name: 'CTimePicker',
27
27
  props: {
28
+ /**
29
+ * Accessible label for the hours selection element.
30
+ */
31
+ ariaSelectHoursLabel: String,
32
+ /**
33
+ * Accessible label for the AM/PM selection element.
34
+ *
35
+ * @since 5.16.0
36
+ */
37
+ ariaSelectMeridiemLabel: String,
38
+ /**
39
+ * Accessible label for the minutes selection element.
40
+ *
41
+ * @since 5.16.0
42
+ */
43
+ ariaSelectMinutesLabel: String,
44
+ /**
45
+ * Accessible label for the seconds selection element.
46
+ *
47
+ * @since 5.16.0
48
+ */
49
+ ariaSelectSecondsLabel: String,
28
50
  /**
29
51
  * Set if the component should use the 12/24 hour format. If `true` forces the interface to a 12-hour format. If `false` forces the interface into a 24-hour format. If `auto` the current locale will determine the 12 or 24-hour interface by default locales.
30
52
  *
@@ -339,9 +361,11 @@ const CTimePicker = defineComponent({
339
361
  setup(props, { emit, attrs, slots }) {
340
362
  const formRef = ref()
341
363
  const inputRef = ref()
342
-
364
+ const columnRefs = ref<(HTMLElement | null)[]>([])
343
365
  const date = ref<Date | null>(convertTimeToDate(props.time))
344
- const ampm = ref<'am' | 'pm'>(date.value ? getAmPm(new Date(date.value), props.locale) : 'am')
366
+ const ampm = ref<'am' | 'pm' | null>(
367
+ date.value ? getAmPm(new Date(date.value), props.locale) : null
368
+ )
345
369
  const initialDate = ref<Date | null>(null)
346
370
  const visible = ref(props.visible)
347
371
  const localizedTimePartials = ref<LocalizedTimePartials>({
@@ -354,6 +378,10 @@ const CTimePicker = defineComponent({
354
378
  props.valid ?? (props.invalid === true ? false : undefined)
355
379
  )
356
380
 
381
+ const setColumnRef = (index: number, el: HTMLElement | null) => {
382
+ columnRefs.value[index] = el
383
+ }
384
+
357
385
  watch(
358
386
  () => props.time,
359
387
  () => {
@@ -421,22 +449,32 @@ const CTimePicker = defineComponent({
421
449
  isValid.value = false
422
450
  }
423
451
 
424
- const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | 'toggle', value: string) => {
452
+ const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | 'meridiem', value: string) => {
425
453
  const _date = date.value || new Date('1970-01-01')
426
454
 
427
- if (set === 'toggle') {
455
+ if (set === 'meridiem') {
456
+ const currentHours = _date.getHours()
457
+
428
458
  if (value === 'am') {
429
- _date.setHours(_date.getHours() - 12)
459
+ ampm.value = 'am'
460
+ // Convert PM hours (12-23) to AM hours (0-11)
461
+ if (currentHours >= 12) {
462
+ _date.setHours(currentHours - 12)
463
+ }
430
464
  }
431
465
 
432
466
  if (value === 'pm') {
433
- _date.setHours(_date.getHours() + 12)
467
+ ampm.value = 'pm'
468
+ // Convert AM hours (0-11) to PM hours (12-23)
469
+ if (currentHours < 12) {
470
+ _date.setHours(currentHours + 12)
471
+ }
434
472
  }
435
473
  }
436
474
 
437
475
  if (set === 'hours') {
438
476
  if (localizedTimePartials.value && localizedTimePartials.value.hour12) {
439
- _date.setHours(convert12hTo24h(ampm.value, Number.parseInt(value)))
477
+ _date.setHours(convert12hTo24h(ampm.value ?? 'am', Number.parseInt(value)))
440
478
  } else {
441
479
  _date.setHours(Number.parseInt(value))
442
480
  }
@@ -527,6 +565,7 @@ const CTimePicker = defineComponent({
527
565
  onChange: (event: Event) =>
528
566
  handleTimeChange('hours', (event.target as HTMLSelectElement).value),
529
567
  ...(date.value && { value: getSelectedHour(date.value, props.locale) }),
568
+ 'aria-label': props.ariaSelectHoursLabel,
530
569
  },
531
570
  localizedTimePartials.value &&
532
571
  localizedTimePartials.value.listOfHours.map((option) =>
@@ -549,6 +588,7 @@ const CTimePicker = defineComponent({
549
588
  onChange: (event: Event) =>
550
589
  handleTimeChange('minutes', (event.target as HTMLSelectElement).value),
551
590
  ...(date.value && { value: getSelectedMinutes(date.value) }),
591
+ 'aria-label': props.ariaSelectMinutesLabel,
552
592
  },
553
593
  localizedTimePartials.value &&
554
594
  localizedTimePartials.value.listOfMinutes?.map((option) =>
@@ -571,6 +611,7 @@ const CTimePicker = defineComponent({
571
611
  onChange: (event: Event) =>
572
612
  handleTimeChange('seconds', (event.target as HTMLSelectElement).value),
573
613
  ...(date.value && { value: getSelectedSeconds(date.value) }),
614
+ 'aria-label': props.ariaSelectSecondsLabel,
574
615
  },
575
616
  localizedTimePartials.value &&
576
617
  localizedTimePartials.value.listOfSeconds?.map((option) =>
@@ -591,8 +632,9 @@ const CTimePicker = defineComponent({
591
632
  class: 'time-picker-inline-select',
592
633
  disabled: props.disabled,
593
634
  onChange: (event: Event) =>
594
- handleTimeChange('toggle', (event.target as HTMLSelectElement).value),
635
+ handleTimeChange('meridiem', (event.target as HTMLSelectElement).value),
595
636
  value: ampm.value,
637
+ 'aria-label': props.ariaSelectMeridiemLabel,
596
638
  },
597
639
  [
598
640
  h(
@@ -615,31 +657,47 @@ const CTimePicker = defineComponent({
615
657
 
616
658
  const TimePickerRoll = () => [
617
659
  h(CTimePickerRollCol, {
660
+ ariaLabel: props.ariaSelectHoursLabel,
661
+ columnIndex: 0,
662
+ columnRefs: columnRefs.value,
618
663
  elements: localizedTimePartials.value && localizedTimePartials.value.listOfHours,
619
664
  onClick: (index: number) => handleTimeChange('hours', index.toString()),
620
665
  selected: getSelectedHour(date.value, props.locale, props.ampm),
666
+ setColumnRef,
621
667
  }),
622
668
  props.minutes &&
623
669
  h(CTimePickerRollCol, {
670
+ ariaLabel: props.ariaSelectMinutesLabel,
671
+ columnIndex: 1,
672
+ columnRefs: columnRefs.value,
624
673
  elements: localizedTimePartials.value && localizedTimePartials.value.listOfMinutes,
625
674
  onClick: (index: number) => handleTimeChange('minutes', index.toString()),
626
675
  selected: getSelectedMinutes(date.value),
676
+ setColumnRef,
627
677
  }),
628
678
  props.seconds &&
629
679
  h(CTimePickerRollCol, {
680
+ ariaLabel: props.ariaSelectSecondsLabel,
681
+ columnIndex: props.minutes ? 2 : 1,
682
+ columnRefs: columnRefs.value,
630
683
  elements: localizedTimePartials.value && localizedTimePartials.value.listOfSeconds,
631
684
  onClick: (index: number) => handleTimeChange('seconds', index.toString()),
632
685
  selected: getSelectedSeconds(date.value),
686
+ setColumnRef,
633
687
  }),
634
688
  localizedTimePartials.value &&
635
689
  localizedTimePartials.value.hour12 &&
636
690
  h(CTimePickerRollCol, {
691
+ ariaLabel: props.ariaSelectMeridiemLabel,
692
+ columnIndex: (props.minutes ? 1 : 0) + (props.seconds ? 1 : 0) + 1,
693
+ columnRefs: columnRefs.value,
637
694
  elements: [
638
695
  { value: 'am', label: 'AM' },
639
696
  { value: 'pm', label: 'PM' },
640
697
  ],
641
- onClick: (value: string) => handleTimeChange('toggle', value),
698
+ onClick: (value: string) => handleTimeChange('meridiem', value),
642
699
  selected: ampm.value,
700
+ setColumnRef,
643
701
  }),
644
702
  ]
645
703
 
@@ -711,6 +769,7 @@ const CTimePicker = defineComponent({
711
769
  ['time-picker-roll']: props.variant === 'roll',
712
770
  },
713
771
  ],
772
+ ...(props.variant !== 'select' && { role: 'group' }),
714
773
  },
715
774
  props.variant === 'select' ? TimePickerSelect() : TimePickerRoll()
716
775
  ),
@@ -1,6 +1,7 @@
1
1
  import { defineComponent, h, onUpdated, PropType, ref, watch } from 'vue'
2
2
 
3
3
  import { useIsVisible } from '../../composables'
4
+ import { getNextActiveElement, isRTL } from '../../utils'
4
5
 
5
6
  export interface Element {
6
7
  value: number | string
@@ -10,13 +11,18 @@ export interface Element {
10
11
  const CTimePickerRollCol = defineComponent({
11
12
  name: 'CTimePickerRollCol',
12
13
  props: {
14
+ ariaLabel: String,
15
+ columnIndex: Number,
16
+ columnRefs: {
17
+ type: Array as PropType<(HTMLElement | null)[]>,
18
+ default: () => [],
19
+ },
13
20
  elements: {
14
21
  type: Array as PropType<Element[]>,
15
22
  required: true,
16
23
  },
17
- selected: {
18
- type: [Number, String],
19
- },
24
+ selected: [Number, String, null],
25
+ setColumnRef: Function as PropType<(index: number, el: HTMLElement | null) => void>,
20
26
  },
21
27
  emits: ['click'],
22
28
  setup(props, { emit }) {
@@ -29,7 +35,7 @@ const CTimePickerRollCol = defineComponent({
29
35
  if (isVisible.value && nodeEl && nodeEl instanceof HTMLElement) {
30
36
  colRef.value?.scrollTo({
31
37
  top: nodeEl.offsetTop,
32
- behavior: init.value ? 'auto' : 'smooth',
38
+ behavior: init.value ? 'instant' : 'smooth',
33
39
  })
34
40
  }
35
41
  }
@@ -42,35 +48,107 @@ const CTimePickerRollCol = defineComponent({
42
48
  }
43
49
  })
44
50
 
51
+ watch(colRef, () => {
52
+ if (props.columnIndex !== undefined && props.setColumnRef) {
53
+ props.setColumnRef(props.columnIndex, colRef.value || null)
54
+ }
55
+ }, { immediate: true })
56
+
45
57
  onUpdated(() => {
46
58
  scrollToSelectedElement()
47
59
  })
48
60
 
61
+ const moveFocusToNextColumn = () => {
62
+ if (!props.columnRefs || props.columnIndex === undefined) return
63
+
64
+ if (props.columnIndex < props.columnRefs.length - 1) {
65
+ const column = props.columnRefs[props.columnIndex + 1]
66
+ const focusableCell = column?.querySelector('.time-picker-roll-cell[tabindex="0"]') as HTMLElement
67
+ focusableCell?.focus()
68
+ }
69
+ }
70
+
71
+ const moveFocusToPreviousColumn = () => {
72
+ if (!props.columnRefs || props.columnIndex === undefined) return
73
+
74
+ if (props.columnIndex > 0) {
75
+ const column = props.columnRefs[props.columnIndex - 1]
76
+ const focusableCell = column?.querySelector('.time-picker-roll-cell[tabindex="0"]') as HTMLElement
77
+ focusableCell?.focus()
78
+ }
79
+ }
80
+
49
81
  const handleKeyDown = (event: KeyboardEvent, value: number | string) => {
50
82
  if (event.code === 'Space' || event.key === 'Enter') {
51
83
  event.preventDefault()
52
84
  emit('click', value)
85
+ moveFocusToNextColumn()
86
+ return
87
+ }
88
+
89
+ if (colRef.value && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
90
+ event.preventDefault()
91
+ const target = event.target as HTMLElement
92
+ const items = [...colRef.value.querySelectorAll('.time-picker-roll-cell')] as HTMLElement[]
93
+
94
+ getNextActiveElement(items, target, event.key === 'ArrowDown', true).focus()
95
+ return
96
+ }
97
+
98
+ if (colRef.value && (event.key === 'Home' || event.key === 'End')) {
99
+ event.preventDefault()
100
+ const items = [...colRef.value.querySelectorAll('.time-picker-roll-cell')] as HTMLElement[]
101
+ const index = event.key === 'Home' ? 0 : items.length - 1
102
+ items[index]?.focus()
103
+ return
104
+ }
105
+
106
+ if (colRef.value && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
107
+ event.preventDefault()
108
+ const rtl = isRTL(colRef.value)
109
+ const shouldGoLeft =
110
+ (event.key === 'ArrowLeft' && !rtl) || (event.key === 'ArrowRight' && rtl)
111
+ if (shouldGoLeft) {
112
+ moveFocusToPreviousColumn()
113
+ } else {
114
+ moveFocusToNextColumn()
115
+ }
53
116
  }
54
117
  }
55
118
 
56
119
  return () =>
57
120
  h(
58
121
  'div',
59
- { class: 'time-picker-roll-col', ref: colRef },
60
- props.elements.map((element) => {
122
+ {
123
+ class: 'time-picker-roll-col',
124
+ onFocusout: (event: FocusEvent) => {
125
+ const currentTarget = event.currentTarget as HTMLElement
126
+ const relatedTarget = event.relatedTarget as HTMLElement | null
127
+ if (currentTarget && (!relatedTarget || !currentTarget.contains(relatedTarget))) {
128
+ scrollToSelectedElement()
129
+ }
130
+ },
131
+ ref: colRef,
132
+ role: 'listbox',
133
+ 'aria-label': props.ariaLabel,
134
+ },
135
+ props.elements.map((element, index) => {
136
+ const isSelected = element.value === props.selected
61
137
  return h(
62
138
  'div',
63
139
  {
64
140
  class: [
65
141
  'time-picker-roll-cell',
66
142
  {
67
- selected: element.value === props.selected,
143
+ selected: isSelected,
68
144
  },
69
145
  ],
70
146
  onClick: () => emit('click', element.value),
71
147
  onKeydown: (event: KeyboardEvent) => handleKeyDown(event, element.value),
72
- role: 'button',
73
- tabindex: 0,
148
+ role: 'option',
149
+ tabindex: isSelected ? 0 : props.selected ? -1 : index === 0 ? 0 : -1,
150
+ 'aria-label': element.label.toString(),
151
+ 'aria-selected': isSelected,
74
152
  },
75
153
  element.label
76
154
  )