@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
@@ -785,22 +785,23 @@ const CAutocomplete = defineComponent({
785
785
  handleClear()
786
786
  },
787
787
  }),
788
- h('button', {
789
- type: 'button',
790
- class: 'autocomplete-indicator',
791
- disabled:
792
- !(props.searchNoResultsLabel || filteredOptions.value.length > 0) &&
793
- !isExternalSearch(props.search),
794
- onClick: (event: Event) => {
795
- event.preventDefault()
796
- event.stopPropagation()
797
- if (visible.value) {
798
- handleDropdownHide()
799
- } else {
800
- handleDropdownShow()
801
- }
802
- },
803
- }),
788
+ props.indicator &&
789
+ h('button', {
790
+ type: 'button',
791
+ class: 'autocomplete-indicator',
792
+ disabled:
793
+ !(props.searchNoResultsLabel || filteredOptions.value.length > 0) &&
794
+ !isExternalSearch(props.search),
795
+ onClick: (event: Event) => {
796
+ event.preventDefault()
797
+ event.stopPropagation()
798
+ if (visible.value) {
799
+ handleDropdownHide()
800
+ } else {
801
+ handleDropdownShow()
802
+ }
803
+ },
804
+ }),
804
805
  ]),
805
806
  ]
806
807
  ),
@@ -905,6 +905,7 @@ const CCalendar = defineComponent({
905
905
  h(
906
906
  'button',
907
907
  {
908
+ type: 'button',
908
909
  class: 'calendar-nav-btn',
909
910
  'aria-label': props.ariaNavPrevYearLabel,
910
911
  onClick: () => handleNavigationOnClick('prev', true),
@@ -920,6 +921,7 @@ const CCalendar = defineComponent({
920
921
  h(
921
922
  'button',
922
923
  {
924
+ type: 'button',
923
925
  class: 'calendar-nav-btn',
924
926
  'aria-label': props.ariaNavPrevMonthLabel,
925
927
  onClick: () => handleNavigationOnClick('prev'),
@@ -945,6 +947,7 @@ const CCalendar = defineComponent({
945
947
  h(
946
948
  'button',
947
949
  {
950
+ type: 'button',
948
951
  class: 'calendar-nav-btn',
949
952
  onClick: () => {
950
953
  if (props.navigation) view.value = 'months'
@@ -955,6 +958,7 @@ const CCalendar = defineComponent({
955
958
  h(
956
959
  'button',
957
960
  {
961
+ type: 'button',
958
962
  class: 'calendar-nav-btn',
959
963
  onClick: () => {
960
964
  if (props.navigation) view.value = 'years'
@@ -976,6 +980,7 @@ const CCalendar = defineComponent({
976
980
  h(
977
981
  'button',
978
982
  {
983
+ type: 'button',
979
984
  class: 'calendar-nav-btn',
980
985
  'aria-label': props.ariaNavNextMonthLabel,
981
986
  onClick: () => handleNavigationOnClick('next'),
@@ -990,6 +995,7 @@ const CCalendar = defineComponent({
990
995
  h(
991
996
  'button',
992
997
  {
998
+ type: 'button',
993
999
  class: 'calendar-nav-btn',
994
1000
  'aria-label': props.ariaNavNextYearLabel,
995
1001
  onClick: () => handleNavigationOnClick('next', true),
@@ -1,4 +1,15 @@
1
- import { defineComponent, h, ref, provide, watch, PropType, onUnmounted, nextTick } from 'vue'
1
+ import {
2
+ computed,
3
+ defineComponent,
4
+ h,
5
+ nextTick,
6
+ onUnmounted,
7
+ provide,
8
+ PropType,
9
+ ref,
10
+ Ref,
11
+ watch,
12
+ } from 'vue'
2
13
  import type { Placement } from '@popperjs/core'
3
14
 
4
15
  import { usePopper } from '../../composables'
@@ -6,7 +17,8 @@ import type { Triggers } from '../../types'
6
17
  import { getNextActiveElement, isRTL } from '../../utils'
7
18
 
8
19
  import type { Alignments } from './types'
9
- import { getPlacement } from './utils'
20
+ import { getPlacement, getReferenceElement } from './utils'
21
+ import { CFocusTrap } from '../focus-trap'
10
22
 
11
23
  const CDropdown = defineComponent({
12
24
  name: 'CDropdown',
@@ -53,7 +65,7 @@ const CDropdown = defineComponent({
53
65
  * - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
54
66
  */
55
67
  autoClose: {
56
- type: [Boolean, String],
68
+ type: [Boolean, String] as PropType<boolean | 'inside' | 'outside'>,
57
69
  default: true,
58
70
  validator: (value: boolean | string) => {
59
71
  return typeof value === 'boolean' || ['inside', 'outside'].includes(value)
@@ -112,6 +124,21 @@ const CDropdown = defineComponent({
112
124
  type: Boolean,
113
125
  default: true,
114
126
  },
127
+ /**
128
+ * Sets the reference element for positioning the Vue Dropdown Menu.
129
+ * - `toggle` - The Vue Dropdown Toggle button (default).
130
+ * - `parent` - The Vue Dropdown wrapper element.
131
+ * - `HTMLElement` - A custom HTML element.
132
+ * - `Ref` - A custom reference element.
133
+ *
134
+ * @since 5.7.0
135
+ */
136
+ reference: {
137
+ type: [String, Object] as PropType<
138
+ 'parent' | 'toggle' | HTMLElement | Ref<HTMLElement | null>
139
+ >,
140
+ default: 'toggle',
141
+ },
115
142
  /**
116
143
  * Generates dropdown menu using Teleport.
117
144
  *
@@ -156,15 +183,16 @@ const CDropdown = defineComponent({
156
183
  'show',
157
184
  ],
158
185
  setup(props, { slots, emit }) {
159
- const dropdownToggleRef = ref()
160
- const dropdownMenuRef = ref()
186
+ const dropdownRef = ref<HTMLElement | null>(null)
187
+ const dropdownMenuRef = ref<HTMLElement | null>(null)
188
+ const dropdownToggleRef = ref<HTMLElement | null>(null)
161
189
  const pendingKeyDownEventRef = ref<KeyboardEvent | null>(null)
162
190
  const popper = ref(typeof props.alignment === 'object' ? false : props.popper)
163
191
  const visible = ref(props.visible)
164
192
 
165
193
  const { initPopper, destroyPopper } = usePopper()
166
194
 
167
- const popperConfig = {
195
+ const popperConfig = computed(() => ({
168
196
  modifiers: [
169
197
  {
170
198
  name: 'offset',
@@ -179,7 +207,7 @@ const CDropdown = defineComponent({
179
207
  props.alignment,
180
208
  isRTL(dropdownMenuRef.value)
181
209
  ) as Placement,
182
- }
210
+ }))
183
211
 
184
212
  watch(
185
213
  () => props.visible,
@@ -190,11 +218,16 @@ const CDropdown = defineComponent({
190
218
 
191
219
  watch(visible, () => {
192
220
  if (visible.value && dropdownToggleRef.value && dropdownMenuRef.value) {
193
- if (popper.value) {
194
- initPopper(dropdownToggleRef.value, dropdownMenuRef.value, popperConfig)
221
+ const referenceElement = getReferenceElement(
222
+ props.reference,
223
+ dropdownToggleRef,
224
+ dropdownRef
225
+ )
226
+ if (referenceElement && popper.value) {
227
+ initPopper(referenceElement, dropdownMenuRef.value, popperConfig.value)
195
228
  }
196
229
 
197
- window.addEventListener('mouseup', handleMouseUp)
230
+ window.addEventListener('click', handleClick)
198
231
  window.addEventListener('keyup', handleKeyup)
199
232
  dropdownToggleRef.value.addEventListener('keydown', handleKeydown)
200
233
  dropdownMenuRef.value.addEventListener('keydown', handleKeydown)
@@ -205,15 +238,20 @@ const CDropdown = defineComponent({
205
238
  pendingKeyDownEventRef.value = null
206
239
  })
207
240
  }
208
-
241
+
209
242
  emit('show')
210
243
  return
211
244
  }
212
245
 
213
- popper.value && destroyPopper()
214
- window.removeEventListener('mouseup', handleMouseUp)
246
+ if (popper.value) {
247
+ destroyPopper()
248
+ }
249
+
250
+ window.removeEventListener('click', handleClick)
215
251
  window.removeEventListener('keyup', handleKeyup)
216
252
  dropdownMenuRef.value && dropdownMenuRef.value.removeEventListener('keydown', handleKeydown)
253
+ dropdownToggleRef.value &&
254
+ dropdownToggleRef.value.removeEventListener('keydown', handleKeydown)
217
255
  emit('hide')
218
256
  })
219
257
 
@@ -259,24 +297,36 @@ const CDropdown = defineComponent({
259
297
  }
260
298
  }
261
299
 
262
- const handleMouseUp = (event: Event) => {
300
+ const handleClick = (event: Event) => {
263
301
  if (!dropdownToggleRef.value || !dropdownMenuRef.value) {
264
302
  return
265
303
  }
266
304
 
267
- if (dropdownToggleRef.value.contains(event.target as HTMLElement)) {
305
+ if ((event as MouseEvent).button === 2) {
306
+ return
307
+ }
308
+
309
+ const composedPath = event.composedPath()
310
+ const isOnToggle = composedPath.includes(dropdownToggleRef.value)
311
+ const isOnMenu = composedPath.includes(dropdownMenuRef.value)
312
+
313
+ if (isOnToggle) {
314
+ return
315
+ }
316
+
317
+ const target = event.target as HTMLElement | null
318
+ const FORM_TAG_RE = /^(input|select|option|textarea|form|button|label)$/i
319
+
320
+ if (isOnMenu && target && FORM_TAG_RE.test(target.tagName)) {
268
321
  return
269
322
  }
270
323
 
271
324
  if (
272
325
  props.autoClose === true ||
273
- (props.autoClose === 'inside' &&
274
- dropdownMenuRef.value.contains(event.target as HTMLElement)) ||
275
- (props.autoClose === 'outside' &&
276
- !dropdownMenuRef.value.contains(event.target as HTMLElement))
326
+ (props.autoClose === 'inside' && isOnMenu) ||
327
+ (props.autoClose === 'outside' && !isOnMenu)
277
328
  ) {
278
329
  setVisible(false)
279
- return
280
330
  }
281
331
  }
282
332
 
@@ -299,22 +349,28 @@ const CDropdown = defineComponent({
299
349
  provide('setVisible', setVisible)
300
350
 
301
351
  return () =>
302
- props.variant === 'input-group'
303
- ? [slots.default && slots.default()]
304
- : h(
305
- 'div',
306
- {
307
- class: [
308
- props.variant === 'nav-item' ? 'nav-item dropdown' : props.variant,
309
- props.direction === 'center'
310
- ? 'dropdown-center'
311
- : props.direction === 'dropup-center'
312
- ? 'dropup dropup-center'
313
- : props.direction,
314
- ],
315
- },
316
- slots.default && slots.default()
317
- )
352
+ h(
353
+ CFocusTrap,
354
+ { active: props.teleport && visible.value, additionalContainer: dropdownMenuRef },
355
+ () =>
356
+ props.variant === 'input-group'
357
+ ? [slots.default && slots.default()]
358
+ : h(
359
+ 'div',
360
+ {
361
+ class: [
362
+ props.variant === 'nav-item' ? 'nav-item dropdown' : props.variant,
363
+ props.direction === 'center'
364
+ ? 'dropdown-center'
365
+ : props.direction === 'dropup-center'
366
+ ? 'dropup dropup-center'
367
+ : props.direction,
368
+ ],
369
+ ref: dropdownRef,
370
+ },
371
+ slots.default && slots.default()
372
+ )
373
+ )
318
374
  },
319
375
  })
320
376
 
@@ -74,6 +74,15 @@ const CDropdownToggle = defineComponent({
74
74
  * Similarly, create split button dropdowns with virtually the same markup as single button dropdowns, but with the addition of `.dropdown-toggle-split` className for proper spacing around the dropdown caret.
75
75
  */
76
76
  split: Boolean,
77
+ /**
78
+ * Screen reader label for split button dropdown toggle.
79
+ *
80
+ * @since 5.7.0
81
+ */
82
+ splitLabel: {
83
+ type: String,
84
+ default: 'Toggle Dropdown',
85
+ },
77
86
  /**
78
87
  * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
79
88
  *
@@ -194,7 +203,7 @@ const CDropdownToggle = defineComponent({
194
203
  },
195
204
  () =>
196
205
  props.split
197
- ? h('span', { class: 'visually-hidden' }, 'Toggle Dropdown')
206
+ ? h('span', { class: 'visually-hidden' }, props.splitLabel)
198
207
  : slots.default && slots.default(),
199
208
  )
200
209
  },
@@ -1,3 +1,4 @@
1
+ import { Ref } from 'vue'
1
2
  import type { Placement } from '@popperjs/core'
2
3
  import type { Placements } from '../../types'
3
4
  import type { Alignments, Breakpoints } from './types'
@@ -49,3 +50,23 @@ export const getPlacement = (
49
50
 
50
51
  return _placement
51
52
  }
53
+
54
+ export const getReferenceElement = (
55
+ reference: 'parent' | 'toggle' | Ref<HTMLElement | null> | HTMLElement,
56
+ dropdownToggleRef: Ref<HTMLElement | null>,
57
+ dropdownRef: Ref<HTMLElement | null>
58
+ ): HTMLElement | null => {
59
+ if (reference === 'parent') {
60
+ return dropdownRef.value
61
+ }
62
+
63
+ if (reference instanceof HTMLElement) {
64
+ return reference
65
+ }
66
+
67
+ if (reference instanceof Object && 'value' in reference) {
68
+ return reference.value
69
+ }
70
+
71
+ return dropdownToggleRef.value
72
+ }
@@ -32,6 +32,7 @@ export * from './multi-select'
32
32
  export * from './nav'
33
33
  export * from './navbar'
34
34
  export * from './offcanvas'
35
+ export * from './one-time-password-input'
35
36
  export * from './password-input'
36
37
  export * from './pagination'
37
38
  export * from './picker'
@@ -5,7 +5,7 @@ import type { ComponentProps } from '../../utils/ComponentProps'
5
5
 
6
6
  interface CNavItemProps extends ComponentProps<typeof CNavLink> {
7
7
  as: string
8
- class: string
8
+ class?: string
9
9
  }
10
10
 
11
11
  const CNavItem = defineComponent({