@coreui/vue-pro 4.5.0 → 4.7.0-alpha.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 (60) hide show
  1. package/dist/components/Types.d.ts +5 -5
  2. package/dist/components/calendar/CCalendar.d.ts +41 -3
  3. package/dist/components/date-picker/CDatePicker.d.ts +43 -4
  4. package/dist/components/date-range-picker/CDateRangePicker.d.ts +191 -4
  5. package/dist/components/form/CFormInput.d.ts +166 -1
  6. package/dist/components/form/CFormSelect.d.ts +1 -1
  7. package/dist/components/grid/CCol.d.ts +3 -3
  8. package/dist/components/grid/CRow.d.ts +1 -1
  9. package/dist/components/index.d.ts +1 -0
  10. package/dist/components/multi-select/CMultiSelect.d.ts +143 -4
  11. package/dist/components/multi-select/CMultiSelectOptions.d.ts +11 -0
  12. package/dist/components/multi-select/CMultiSelectSelection.d.ts +3 -3
  13. package/dist/components/pagination/index.d.ts +1 -2
  14. package/dist/components/picker/CPicker.d.ts +1 -1
  15. package/dist/components/popover/CPopover.d.ts +1 -1
  16. package/dist/components/smart-pagination/CSmartPagination.d.ts +257 -0
  17. package/dist/components/smart-pagination/index.d.ts +6 -0
  18. package/dist/components/smart-table/CSmartTable.d.ts +6 -4
  19. package/dist/components/smart-table/CSmartTableFilter.d.ts +2 -2
  20. package/dist/components/smart-table/CSmartTableHead.d.ts +2 -2
  21. package/dist/components/smart-table/CSmartTableInterface.d.ts +4 -1
  22. package/dist/components/table/CTable.d.ts +1 -1
  23. package/dist/components/table/CTableCaption.d.ts +2 -8
  24. package/dist/components/time-picker/CTimePicker.d.ts +2 -1
  25. package/dist/components/tooltip/CTooltip.d.ts +1 -1
  26. package/dist/components/widgets/CWidgetStatsD.d.ts +1 -1
  27. package/dist/index.es.js +1560 -1017
  28. package/dist/index.es.js.map +1 -1
  29. package/dist/index.js +1559 -1015
  30. package/dist/index.js.map +1 -1
  31. package/dist/utils/getNextSibling.d.ts +2 -0
  32. package/dist/utils/getPreviousSibling.d.ts +2 -0
  33. package/dist/utils/index.d.ts +4 -0
  34. package/dist/utils/isVisible.d.ts +2 -0
  35. package/dist/utils/time.d.ts +2 -2
  36. package/package.json +2 -2
  37. package/src/components/calendar/CCalendar.ts +46 -4
  38. package/src/components/carousel/CCarousel.ts +1 -9
  39. package/src/components/date-picker/CDatePicker.ts +44 -3
  40. package/src/components/date-range-picker/CDateRangePicker.ts +340 -170
  41. package/src/components/form/CFormInput.ts +2 -0
  42. package/src/components/index.ts +1 -0
  43. package/src/components/loading-button/CLoadingButton.ts +1 -2
  44. package/src/components/multi-select/CMultiSelect.ts +295 -173
  45. package/src/components/multi-select/CMultiSelectOptions.ts +48 -10
  46. package/src/components/multi-select/CMultiSelectSelection.ts +1 -1
  47. package/src/components/pagination/index.ts +1 -3
  48. package/src/components/sidebar/CSidebar.ts +2 -10
  49. package/src/components/{pagination → smart-pagination}/CSmartPagination.ts +1 -2
  50. package/src/components/smart-pagination/index.ts +10 -0
  51. package/src/components/smart-table/CSmartTable.ts +10 -5
  52. package/src/components/smart-table/CSmartTableInterface.ts +4 -0
  53. package/src/components/table/CTableCaption.ts +0 -1
  54. package/src/components/time-picker/CTimePicker.ts +198 -64
  55. package/src/components/time-picker/CTimePickerRollCol.ts +9 -0
  56. package/src/utils/getNextSibling.ts +18 -0
  57. package/src/utils/getPreviousSibling.ts +18 -0
  58. package/src/utils/index.ts +5 -0
  59. package/src/utils/isVisible.ts +11 -0
  60. package/src/utils/time.ts +14 -6
@@ -1,5 +1,6 @@
1
1
  import { defineComponent, h, PropType, provide, ref, watch } from 'vue'
2
2
 
3
+ import { CFormControlWrapper } from './../form/CFormControlWrapper'
3
4
  import { CPicker } from '../picker'
4
5
 
5
6
  import { CMultiSelectNativeSelect } from './CMultiSelectNativeSelect'
@@ -15,6 +16,18 @@ export interface Option {
15
16
  value: number | string
16
17
  }
17
18
 
19
+ export interface SelectedOption {
20
+ disabled?: boolean
21
+ text: string
22
+ value: number | string
23
+ }
24
+
25
+ const flattenArray = (options: Option[]): Option[] => {
26
+ return options.reduce((acc: Option[], val: Option) => {
27
+ return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val)
28
+ }, [])
29
+ }
30
+
18
31
  const CMultiSelect = defineComponent({
19
32
  name: 'CMultiSelect',
20
33
  props: {
@@ -36,6 +49,50 @@ const CMultiSelect = defineComponent({
36
49
  required: false,
37
50
  default: false,
38
51
  },
52
+ /**
53
+ * Provide valuable, actionable feedback.
54
+ *
55
+ * @since 4.6.0
56
+ */
57
+ feedback: {
58
+ type: String,
59
+ },
60
+ /**
61
+ * Provide valuable, actionable feedback.
62
+ *
63
+ * @since 4.6.0
64
+ */
65
+ feedbackInvalid: {
66
+ type: String,
67
+ },
68
+ /**
69
+ * Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
70
+ *
71
+ * @since 4.6.0
72
+ */
73
+ feedbackValid: {
74
+ type: String,
75
+ },
76
+ /**
77
+ * The id global attribute defines an identifier (ID) that must be unique in the whole document.
78
+ */
79
+ id: {
80
+ type: String,
81
+ },
82
+ /**
83
+ * Set component validation state to invalid.
84
+ *
85
+ * @since 4.6.0
86
+ */
87
+ invalid: Boolean,
88
+ /**
89
+ * Add a caption for a component.
90
+ *
91
+ * @since 4.6.0
92
+ */
93
+ label: {
94
+ type: String,
95
+ },
39
96
  /**
40
97
  * It specifies that multiple options can be selected at once.
41
98
  *
@@ -92,9 +149,18 @@ const CMultiSelect = defineComponent({
92
149
  * Enables search input element.
93
150
  */
94
151
  search: {
95
- type: Boolean,
152
+ type: [Boolean, String],
96
153
  default: true,
97
154
  required: false,
155
+ validator: (value: boolean | string) => {
156
+ if (typeof value == 'string') {
157
+ return ['external'].includes(value)
158
+ }
159
+ if (typeof value == 'boolean') {
160
+ return true
161
+ }
162
+ return false
163
+ },
98
164
  },
99
165
  /**
100
166
  * Sets the label for no results when filtering.
@@ -160,6 +226,26 @@ const CMultiSelect = defineComponent({
160
226
  return ['sm', 'lg'].includes(value)
161
227
  },
162
228
  },
229
+ /**
230
+ * Add helper text to the component.
231
+ *
232
+ * @since 4.6.0
233
+ */
234
+ text: {
235
+ type: String,
236
+ },
237
+ /**
238
+ * Display validation feedback in a styled tooltip.
239
+ *
240
+ * @since 4.6.0
241
+ */
242
+ tooltipFeedback: Boolean,
243
+ /**
244
+ * Set component validation state to valid.
245
+ *
246
+ * @since 4.6.0
247
+ */
248
+ valid: Boolean,
163
249
  /**
164
250
  * Toggle the visibility of multi select dropdown.
165
251
  *
@@ -176,70 +262,83 @@ const CMultiSelect = defineComponent({
176
262
  * Execute a function when a user changes the selected option. [docs]
177
263
  */
178
264
  'change',
265
+ /**
266
+ * Execute a function when the filter value changed.
267
+ *
268
+ * @since 4.7.0
269
+ */
270
+ 'filterChange',
179
271
  ],
180
- setup(props, { emit }) {
181
- const flattenArray = (options: Option[]): Option[] => {
182
- return options.reduce((acc: Option[], val: Option) => {
183
- return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val)
184
- }, [])
185
- }
272
+ setup(props, { attrs, emit }) {
273
+ const nativeSelectRef = ref<HTMLSelectElement>()
274
+ provide('nativeSelectRef', nativeSelectRef)
275
+ const searchRef = ref<HTMLInputElement>()
276
+
277
+ const options = ref<Option[]>(props.options)
278
+ const search = ref('')
279
+ const selected = ref<SelectedOption[]>([])
280
+ const visible = ref<Boolean>(props.visible)
186
281
 
187
- const getSelectedOptions = (options: Option[]) => {
188
- return flattenArray(options).filter((option: Option) => {
189
- if (option.selected) {
190
- return option
282
+ const selectOptions = (options: Option[], deselected?: Option[]) => {
283
+ let _selected = [...selected.value, ...options]
284
+
285
+ if (deselected) {
286
+ _selected = _selected.filter(
287
+ (selectedOption) =>
288
+ !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value),
289
+ )
290
+ }
291
+
292
+ const deduplicated = _selected.reduce((unique: Option[], option) => {
293
+ if (!unique.some((obj) => obj.value === option.value)) {
294
+ unique.push({
295
+ value: option.value,
296
+ text: option.text,
297
+ ...(option.disabled && { disabled: option.disabled }),
298
+ })
191
299
  }
192
- return
193
- })
300
+ return unique
301
+ }, []) as SelectedOption[]
302
+
303
+ selected.value = deduplicated
194
304
  }
195
305
 
196
- const updateOptions = (
197
- value: number | string,
198
- _options: Option[] = options.value,
199
- ): Option[] => {
200
- return props.multiple && _options
201
- ? _options &&
202
- _options.map((option: Option) => {
203
- count.value = count.value++
204
- return option.options
205
- ? { ...option, options: updateOptions(value, option.options) }
206
- : option.value == value // TODO: find solution
207
- ? { ...option, selected: !option.selected, order: count.value }
208
- : { ...option }
306
+ watch(
307
+ () => props.options,
308
+ (newValue, oldValue) => {
309
+ if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
310
+ options.value = newValue
311
+ const _selected =
312
+ newValue &&
313
+ flattenArray(newValue).filter((option: Option) => {
314
+ if (option.selected) {
315
+ return option
316
+ }
317
+
318
+ return
209
319
  })
210
- : _options &&
211
- _options.map((option: Option) => {
212
- return option.options
213
- ? { ...option, options: updateOptions(value, option.options) }
214
- : option.value == value // TODO: find solution
215
- ? { ...option, selected: true }
216
- : { ...option, selected: false }
320
+
321
+ const deselected =
322
+ newValue &&
323
+ flattenArray(newValue).filter((option: Option) => {
324
+ if (option.selected === false) {
325
+ return option
326
+ }
327
+
328
+ return
217
329
  })
218
- }
219
330
 
220
- const toggleAllOptions = (
221
- options: Option[],
222
- selected: boolean,
223
- counter: number = count.value,
224
- ): Option[] => {
225
- return options.map((option: Option) => {
226
- !option.selected && counter++
227
- count.value = counter
228
- if (option.options) {
229
- return {
230
- ...option,
231
- options: toggleAllOptions(option.options, selected, counter),
232
- }
331
+ _selected && selectOptions(_selected, deselected)
233
332
  }
234
- return option.disabled
235
- ? { ...option }
236
- : selected && !option.selected
237
- ? { ...option, selected: selected, order: counter }
238
- : { ...option, selected: selected }
239
- })
240
- }
333
+ },
334
+ )
335
+
336
+ watch(selected, () => {
337
+ nativeSelectRef.value &&
338
+ nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }))
339
+ })
241
340
 
242
- const filterOptionsList = (search: string, _options = vOptions.value) => {
341
+ const filterOptionsList = (search: string, _options: Option[]) => {
243
342
  return search.length
244
343
  ? _options &&
245
344
  _options.reduce((acc: Option[], val: Option) => {
@@ -262,76 +361,64 @@ const CMultiSelect = defineComponent({
262
361
  : options.value
263
362
  }
264
363
 
265
- const nativeSelectRef = ref<HTMLSelectElement>()
266
- provide('nativeSelectRef', nativeSelectRef)
267
- const searchRef = ref<HTMLInputElement>()
268
-
269
- const options = ref<Option[]>(props.options)
270
- const vOptions = ref<Option[]>(props.options)
271
- const search = ref('')
272
- const visible = ref<Boolean>(props.visible)
273
-
274
- const selected = ref<Option[]>(getSelectedOptions(props.options))
275
- const count = ref<number>(0)
276
-
277
- watch(
278
- () => props.options,
279
- (newValue, oldValue) => {
280
- if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) options.value = newValue
281
- },
282
- )
364
+ // watch(
365
+ // () => props.options,
366
+ // (newValue, oldValue) => {
367
+ // console.log(props.options)
368
+ // if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) options.value = newValue
369
+ // },
370
+ // )
283
371
 
284
- watch(options, () => {
285
- const _selected = options.value && getSelectedOptions(options.value)
286
372
 
287
- _selected.sort((a: Option, b: Option) => {
288
- if (typeof a.order === 'undefined') {
289
- return -1
290
- }
291
- if (b.order && a.order > b.order) return 1
292
- if (b.order && a.order < b.order) return -1
293
- return 0
294
- })
295
-
296
- selected.value = _selected
297
- })
298
-
299
- watch([options, search], () => {
300
- vOptions.value = filterOptionsList(search.value, options.value)
301
- })
302
-
303
- watch(selected, () => {
304
- nativeSelectRef.value &&
305
- nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }))
306
- })
307
373
 
308
374
  const handleSearchChange = (event: InputEvent) => {
309
375
  const target = event.target as HTMLInputElement
310
376
  search.value = target.value.toLowerCase()
377
+
378
+ emit('filterChange', target.value)
311
379
  }
312
380
 
313
381
  const handleSearchKeyDown = (event: KeyboardEvent) => {
314
- if (search.value.length) return
382
+ if (search.value.length) {
383
+ return
384
+ }
385
+
315
386
  if (event.key === 'Backspace' || event.key === 'Delete') {
316
387
  const last = selected.value.filter((option: Option) => !option.disabled).pop()
317
-
318
388
  if (last) {
319
389
  selected.value = selected.value.filter((option: Option) => option.value !== last.value)
320
- options.value = updateOptions(last.value)
321
390
  }
322
391
  }
323
392
  }
324
393
 
325
394
  const handleOptionClick = (option: Option) => {
326
- options.value = updateOptions(option.value)
395
+ if (!props.multiple) {
396
+ selected.value = [{ value: option.value, text: option.text }] as SelectedOption[]
397
+ visible.value = false
398
+ search.value = ''
399
+ if (searchRef.value) {
400
+ searchRef.value.value = ''
401
+ }
402
+
403
+ return
404
+ }
405
+
406
+ if (selected.value.some((_option) => _option.value === option.value)) {
407
+ selected.value = selected.value.filter((_option) => _option.value !== option.value)
408
+ } else {
409
+ selected.value = [
410
+ ...selected.value,
411
+ { value: option.value, text: option.text },
412
+ ] as SelectedOption[]
413
+ }
327
414
  }
328
415
 
329
416
  const handleSelectAll = () => {
330
- options.value = toggleAllOptions(options.value, true)
417
+ selectOptions(flattenArray(options.value).filter((option: Option) => !option.disabled))
331
418
  }
332
419
 
333
420
  const handleDeselectAll = () => {
334
- options.value = toggleAllOptions(options.value, false)
421
+ selected.value = selected.value.filter((option) => option.disabled)
335
422
  }
336
423
 
337
424
  return () => [
@@ -344,83 +431,118 @@ const CMultiSelect = defineComponent({
344
431
  onChange: () => emit('change', selected.value),
345
432
  }),
346
433
  h(
347
- CPicker,
434
+ CFormControlWrapper,
348
435
  {
349
- class: [
350
- 'form-multi-select',
351
- {
352
- 'form-multi-select-with-cleaner': props.cleaner,
353
- disabled: props.disabled,
354
- [`form-multi-select-${props.size}`]: props.size,
355
- 'form-multi-select-selection-tags': props.multiple && props.selectionType === 'tags',
356
- show: visible.value,
357
- },
358
- ],
359
- disabled: props.disabled,
360
- onShow: () => {
361
- props.search && searchRef.value && searchRef.value.focus()
362
- },
436
+ describedby: attrs['aria-describedby'],
437
+ feedback: props.feedback,
438
+ feedbackInvalid: props.feedbackInvalid,
439
+ feedbackValid: props.feedbackValid,
440
+ id: props.id,
441
+ invalid: props.invalid,
442
+ label: props.label,
443
+ text: props.text,
444
+ tooltipFeedback: props.tooltipFeedback,
445
+ valid: props.valid,
363
446
  },
364
447
  {
365
- toggler: () =>
366
- h('div', {}, [
367
- h(CMultiSelectSelection, {
368
- multiple: props.multiple,
369
- onRemove: (option: Option) => !props.disabled && handleOptionClick(option),
370
- search: props.search,
371
- selected: selected.value,
372
- selectionType: props.selectionType,
373
- selectionTypeCounterText: props.selectionTypeCounterText,
374
- }),
375
- props.multiple &&
376
- props.cleaner &&
377
- selected.value.length > 0 &&
378
- !props.disabled &&
379
- h('button', {
380
- type: 'button',
381
- class: 'form-multi-select-selection-cleaner',
382
- onClick: () => handleDeselectAll(),
383
- }),
384
- props.search &&
385
- h('input', {
386
- type: 'text',
387
- class: 'form-multi-select-search',
388
- autocomplete: 'off',
389
- ...(selected.value.length === 0 && { placeholder: props.placeholder }),
390
- ...(selected.value.length &&
391
- props.selectionType === 'counter' && {
392
- placeholder: `${selected.value.length} ${props.selectionTypeCounterText}`,
448
+ default: () =>
449
+ h(
450
+ CPicker,
451
+ {
452
+ class: [
453
+ 'form-multi-select',
454
+ {
455
+ 'form-multi-select-with-cleaner': props.cleaner,
456
+ disabled: props.disabled,
457
+ [`form-multi-select-${props.size}`]: props.size,
458
+ 'form-multi-select-selection-tags':
459
+ props.multiple && props.selectionType === 'tags',
460
+ show: visible.value,
461
+ 'is-invalid': props.invalid,
462
+ 'is-valid': props.valid,
463
+ },
464
+ ],
465
+ disabled: props.disabled,
466
+ id: props.id,
467
+ onHide: () => {
468
+ visible.value = false
469
+ },
470
+ onShow: () => {
471
+ props.search && searchRef.value && searchRef.value.focus()
472
+ visible.value = true
473
+ },
474
+ visible: visible.value,
475
+ },
476
+ {
477
+ toggler: () =>
478
+ h('div', {}, [
479
+ h(CMultiSelectSelection, {
480
+ multiple: props.multiple,
481
+ onRemove: (option: Option) => !props.disabled && handleOptionClick(option),
482
+ search: props.search,
483
+ selected: selected.value,
484
+ selectionType: props.selectionType,
485
+ selectionTypeCounterText: props.selectionTypeCounterText,
393
486
  }),
394
- ...(selected.value.length &&
395
- !props.multiple && {
396
- placeholder: selected.value.map((option) => option.text)[0],
487
+ props.multiple &&
488
+ props.cleaner &&
489
+ selected.value.length > 0 &&
490
+ !props.disabled &&
491
+ h('button', {
492
+ type: 'button',
493
+ class: 'form-multi-select-selection-cleaner',
494
+ onClick: () => handleDeselectAll(),
495
+ }),
496
+ props.search &&
497
+ h('input', {
498
+ type: 'text',
499
+ class: 'form-multi-select-search',
500
+ autocomplete: 'off',
501
+ ...(selected.value.length === 0 && { placeholder: props.placeholder }),
502
+ ...(selected.value.length &&
503
+ props.selectionType === 'counter' && {
504
+ placeholder: `${selected.value.length} ${props.selectionTypeCounterText}`,
505
+ }),
506
+ ...(selected.value.length &&
507
+ !props.multiple && {
508
+ placeholder: selected.value.map((option) => option.text)[0],
509
+ }),
510
+ disabled: props.disabled,
511
+ onInput: (event: InputEvent) => handleSearchChange(event),
512
+ onKeydown: (event: KeyboardEvent) => handleSearchKeyDown(event),
513
+ ...(props.multiple &&
514
+ selected.value.length &&
515
+ props.selectionType !== 'counter' && { size: search.value.length + 2 }),
516
+ ref: searchRef,
517
+ }),
518
+ ]),
519
+ default: () =>
520
+ h('div', {}, [
521
+ props.multiple &&
522
+ props.selectAll &&
523
+ h(
524
+ 'button',
525
+ {
526
+ class: 'form-multi-select-all',
527
+ onClick: () => handleSelectAll(),
528
+ type: 'button',
529
+ },
530
+ props.selectAllLabel,
531
+ ),
532
+ h(CMultiSelectOptions, {
533
+ onOptionClick: (option: Option) => handleOptionClick(option),
534
+ options:
535
+ props.search === 'external'
536
+ ? options.value
537
+ : filterOptionsList(search.value, options.value),
538
+ optionsMaxHeight: props.optionsMaxHeight,
539
+ optionsStyle: props.optionsStyle,
540
+ searchNoResultsLabel: props.searchNoResultsLabel,
541
+ selected: selected.value
397
542
  }),
398
- disabled: props.disabled,
399
- onInput: (event: InputEvent) => handleSearchChange(event),
400
- onKeydown: (event: KeyboardEvent) => handleSearchKeyDown(event),
401
- ...(props.multiple &&
402
- selected.value.length &&
403
- props.selectionType !== 'counter' && { size: search.value.length + 2 }),
404
- ref: searchRef,
405
- }),
406
- ]),
407
- default: () =>
408
- h('div', {}, [
409
- props.multiple &&
410
- props.selectAll &&
411
- h(
412
- 'button',
413
- { class: 'form-multi-select-all', onClick: () => handleSelectAll() },
414
- props.selectAllLabel,
415
- ),
416
- h(CMultiSelectOptions, {
417
- onOptionClick: (option: Option) => handleOptionClick(option),
418
- options: vOptions.value,
419
- optionsMaxHeight: props.optionsMaxHeight,
420
- optionsStyle: props.optionsStyle,
421
- searchNoResultsLabel: props.searchNoResultsLabel,
422
- }),
423
- ]),
543
+ ]),
544
+ },
545
+ ),
424
546
  },
425
547
  ),
426
548
  ]
@@ -1,6 +1,8 @@
1
1
  import { defineComponent, h, PropType, VNode } from 'vue'
2
2
  import { Option } from './CMultiSelect'
3
3
 
4
+ import { getNextSibling, getPreviousSibling } from './../../utils'
5
+
4
6
  const CMultiSelectOptions = defineComponent({
5
7
  name: 'CMultiSelectOptions',
6
8
  props: {
@@ -44,20 +46,53 @@ const CMultiSelectOptions = defineComponent({
44
46
  default: 'no items',
45
47
  required: false,
46
48
  },
49
+ selected: {
50
+ type: Array as PropType<Option[]>,
51
+ default: () => [],
52
+ required: false,
53
+ },
47
54
  },
48
55
  emits: ['optionClick'],
49
56
  setup(props, { emit }) {
57
+ const handleKeyDown = (event: KeyboardEvent, option: Option) => {
58
+ if (event.code === 'Space' || event.key === 'Enter') {
59
+ event.preventDefault()
60
+ handleOptionClick && handleOptionClick(option)
61
+ return
62
+ }
63
+
64
+ if (event.key === 'Down' || event.key === 'ArrowDown') {
65
+ event.preventDefault()
66
+ const target = event.target as HTMLElement
67
+ const next = getNextSibling(target, '.form-multi-select-option')
68
+ if (next) {
69
+ ;(next as HTMLElement).focus() // eslint-disable-line prettier/prettier
70
+ }
71
+ }
72
+
73
+ if (event.key === 'Up' || event.key === 'ArrowUp') {
74
+ event.preventDefault()
75
+ const target = event.target as HTMLElement
76
+ const prev = getPreviousSibling(target, '.form-multi-select-option')
77
+ if (prev) {
78
+ ;(prev as HTMLElement).focus() // eslint-disable-line prettier/prettier
79
+ }
80
+ }
81
+ }
82
+
50
83
  const handleOptionClick = (option: Option) => {
51
84
  emit('optionClick', option as Option)
52
85
  }
53
- const createOptions = (options: Option[]): VNode | VNode[] => {
54
- return options.length > 0
55
- ? options.map((option: Option) => {
56
- return option.options
57
- ? h('div', { class: 'form-multi-select-options' }, [
86
+
87
+ // TODO: find solution how to remove any
88
+ const createOptions = (options: Option[]): VNode | VNode[] | any =>
89
+ options.length > 0
90
+ ? options.map((option: Option) =>
91
+ option.options
92
+ ? [
58
93
  h('div', { class: 'form-multi-select-optgroup-label' }, option.label),
59
94
  createOptions(option.options),
60
- ])
95
+ ]
61
96
  : h(
62
97
  'div',
63
98
  {
@@ -65,17 +100,20 @@ const CMultiSelectOptions = defineComponent({
65
100
  'form-multi-select-option',
66
101
  {
67
102
  'form-multi-select-option-with-checkbox': props.optionsStyle === 'checkbox',
68
- 'form-multi-selected': option.selected,
103
+ 'form-multi-selected': props.selected.some(
104
+ (_option) => _option.value === option.value,
105
+ ),
69
106
  disabled: option.disabled,
70
107
  },
71
108
  ],
72
109
  onClick: () => handleOptionClick(option),
110
+ onKeydown: (event: any) => handleKeyDown(event, option),
111
+ tabindex: 0,
73
112
  },
74
113
  option.text,
75
- )
76
- })
114
+ ),
115
+ )
77
116
  : h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel)
78
- }
79
117
  return () =>
80
118
  h(
81
119
  'div',
@@ -18,7 +18,7 @@ const CMultiSelectSelection = defineComponent({
18
18
  * Enables search input element.
19
19
  */
20
20
  search: {
21
- type: Boolean,
21
+ type: [Boolean, String],
22
22
  required: false,
23
23
  default: false,
24
24
  },
@@ -1,14 +1,12 @@
1
1
  import { App } from 'vue'
2
2
  import { CPagination } from './CPagination'
3
3
  import { CPaginationItem } from './CPaginationItem'
4
- import { CSmartPagination } from './CSmartPagination'
5
4
 
6
5
  const CPaginationPlugin = {
7
6
  install: (app: App): void => {
8
7
  app.component(CPagination.name, CPagination)
9
8
  app.component(CPaginationItem.name, CPaginationItem)
10
- app.component(CSmartPagination.name, CSmartPagination)
11
9
  },
12
10
  }
13
11
 
14
- export { CPaginationPlugin, CPagination, CPaginationItem, CSmartPagination }
12
+ export { CPaginationPlugin, CPagination, CPaginationItem }