@coreui/vue-pro 4.8.0-next.0 → 4.8.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 (44) hide show
  1. package/README.md +1 -1
  2. package/dist/components/form/CFormCheck.d.ts +13 -0
  3. package/dist/components/form/CFormSwitch.d.ts +13 -0
  4. package/dist/components/index.d.ts +1 -0
  5. package/dist/components/multi-select/CMultiSelect.d.ts +35 -44
  6. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
  7. package/dist/components/multi-select/CMultiSelectOptions.d.ts +13 -11
  8. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
  9. package/dist/components/multi-select/types.d.ts +14 -0
  10. package/dist/components/multi-select/utils.d.ts +6 -0
  11. package/dist/components/smart-table/CSmartTable.d.ts +1 -1
  12. package/dist/components/smart-table/CSmartTableHead.d.ts +1 -1
  13. package/dist/components/virtual-scroller/CVirtualScroller.d.ts +23 -0
  14. package/dist/components/virtual-scroller/index.d.ts +6 -0
  15. package/dist/index.es.js +249 -135
  16. package/dist/index.es.js.map +1 -1
  17. package/dist/index.js +249 -133
  18. package/dist/index.js.map +1 -1
  19. package/dist/utils/index.d.ts +1 -3
  20. package/package.json +1 -1
  21. package/src/components/carousel/CCarousel.ts +36 -34
  22. package/src/components/form/CFormCheck.ts +7 -0
  23. package/src/components/form/CFormSwitch.ts +7 -0
  24. package/src/components/index.ts +1 -0
  25. package/src/components/multi-select/CMultiSelect.ts +33 -89
  26. package/src/components/multi-select/CMultiSelectNativeSelect.ts +2 -1
  27. package/src/components/multi-select/CMultiSelectOptions.ts +31 -17
  28. package/src/components/multi-select/CMultiSelectSelection.ts +2 -1
  29. package/src/components/multi-select/types.ts +15 -0
  30. package/src/components/multi-select/utils.ts +92 -0
  31. package/src/components/virtual-scroller/CVirtualScroller.ts +109 -0
  32. package/src/components/virtual-scroller/index.ts +10 -0
  33. package/src/utils/index.ts +1 -3
  34. package/dist/components/accordion/CAccordionCollapse.d.ts +0 -22
  35. package/dist/components/multi-select/CMultiSelect copy.d.ts +0 -305
  36. package/dist/components/pagination/CSmartPagination.d.ts +0 -257
  37. package/dist/utils/calendar.d.ts +0 -23
  38. package/dist/utils/getNextSibling.d.ts +0 -2
  39. package/dist/utils/getPreviousSibling.d.ts +0 -2
  40. package/dist/utils/isObjectInArray.d.ts +0 -2
  41. package/dist/utils/isVisible.d.ts +0 -2
  42. package/dist/utils/time.d.ts +0 -21
  43. package/src/utils/getNextSibling.ts +0 -18
  44. package/src/utils/getPreviousSibling.ts +0 -18
@@ -1,4 +1,2 @@
1
- import getNextSibling from './getNextSibling';
2
- import getPreviousSibling from './getPreviousSibling';
3
1
  import isInViewport from './isInViewport';
4
- export { getNextSibling, getPreviousSibling, isInViewport };
2
+ export { isInViewport };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreui/vue-pro",
3
- "version": "4.8.0-next.0",
3
+ "version": "4.8.0",
4
4
  "description": "UI Components Library for Vue.js",
5
5
  "keywords": [
6
6
  "vue",
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  defineComponent,
3
3
  h,
4
- reactive,
5
4
  ref,
6
5
  VNode,
7
6
  onBeforeMount,
@@ -79,10 +78,15 @@ const CCarousel = defineComponent({
79
78
  },
80
79
  setup(props, { slots }) {
81
80
  const carouselRef = ref()
82
- const timeout = ref()
81
+
82
+ const active = ref(props.index)
83
83
  const animating = ref(false)
84
- const visible = ref()
85
84
  const customInterval = ref<boolean | number>(props.interval)
85
+ const direction = ref('next')
86
+ const items = ref<VNode[]>([])
87
+ const timeout = ref()
88
+ const visible = ref()
89
+
86
90
  const setAnimating = (value: boolean) => {
87
91
  animating.value = value
88
92
  }
@@ -105,28 +109,15 @@ const CCarousel = defineComponent({
105
109
  }
106
110
  }
107
111
 
108
- const state = reactive({
109
- items: [] as VNode[],
110
- active: props.index,
111
- direction: 'next',
112
- })
113
-
114
- onBeforeMount(() => {
115
- if (slots.default) {
116
- // @ts-expect-error TODO: fix types
117
- state.items = slots.default().filter((child) => child.type.name === 'CCarouselItem')
118
- }
119
- })
120
-
121
- const handleControlClick = (direction: string) => {
112
+ const handleControlClick = (_direction: string) => {
122
113
  if (animating.value) {
123
114
  return
124
115
  }
125
- state.direction = direction
126
- if (direction === 'next') {
127
- state.active === state.items.length - 1 ? (state.active = 0) : state.active++
116
+ direction.value = _direction
117
+ if (_direction === 'next') {
118
+ active.value === items.value.length - 1 ? (active.value = 0) : active.value++
128
119
  } else {
129
- state.active === 0 ? (state.active = state.items.length - 1) : state.active--
120
+ active.value === 0 ? (active.value = items.value.length - 1) : active.value--
130
121
  }
131
122
  }
132
123
 
@@ -139,19 +130,19 @@ const CCarousel = defineComponent({
139
130
  }
140
131
 
141
132
  const handleIndicatorClick = (index: number) => {
142
- if (state.active === index) {
133
+ if (active.value === index) {
143
134
  return
144
135
  }
145
136
 
146
- if (state.active < index) {
147
- state.direction = 'next'
148
- state.active = index
137
+ if (active.value < index) {
138
+ direction.value = 'next'
139
+ active.value = index
149
140
  return
150
141
  }
151
142
 
152
- if (state.active > index) {
153
- state.direction = 'prev'
154
- state.active = index
143
+ if (active.value > index) {
144
+ direction.value = 'prev'
145
+ active.value = index
155
146
  }
156
147
  }
157
148
 
@@ -163,6 +154,17 @@ const CCarousel = defineComponent({
163
154
  }
164
155
  }
165
156
 
157
+ onBeforeMount(() => {
158
+ if (slots.default) {
159
+ const children = typeof slots.default()[0].type === 'symbol' ? slots.default()[0].children : slots.default()
160
+
161
+ if (children && Array.isArray(children)) {
162
+ // @ts-expect-error TODO: fix types
163
+ items.value = children.filter((child) => child.type.name === 'CCarouselItem')
164
+ }
165
+ }
166
+ })
167
+
166
168
  onMounted(() => {
167
169
  window.addEventListener('scroll', handleScroll)
168
170
  })
@@ -174,7 +176,7 @@ const CCarousel = defineComponent({
174
176
  return
175
177
  }
176
178
 
177
- if (!props.wrap && state.active < state.items.length - 1) {
179
+ if (!props.wrap && active.value < items.value.length - 1) {
178
180
  !animating.value && cycle()
179
181
  }
180
182
  })
@@ -204,12 +206,12 @@ const CCarousel = defineComponent({
204
206
  {
205
207
  class: 'carousel-indicators',
206
208
  },
207
- state.items.map((_, index) => {
209
+ items.value.map((_, index) => {
208
210
  return h('button', {
209
211
  type: 'button',
210
212
  id: index,
211
213
  'data-coreui-target': '',
212
- ...(state.active === index && { class: 'active' }),
214
+ ...(active.value === index && { class: 'active' }),
213
215
  onClick: () => handleIndicatorClick(index),
214
216
  })
215
217
  }),
@@ -217,10 +219,10 @@ const CCarousel = defineComponent({
217
219
  h(
218
220
  'div',
219
221
  { class: 'carousel-inner' },
220
- state.items.map((item, index) => {
222
+ items.value.map((item, index) => {
221
223
  return h(item, {
222
- active: state.active === index ? true : false,
223
- direction: state.direction,
224
+ active: active.value === index ? true : false,
225
+ direction: direction.value,
224
226
  })
225
227
  }),
226
228
  ),
@@ -83,6 +83,12 @@ const CFormCheck = defineComponent({
83
83
  type: [Boolean, String],
84
84
  value: undefined,
85
85
  },
86
+ /**
87
+ * Put checkboxes or radios on the opposite side.
88
+ *
89
+ * @sinve 4.8.0
90
+ */
91
+ reverse: Boolean,
86
92
  /**
87
93
  * Display validation feedback in a styled tooltip.
88
94
  *
@@ -126,6 +132,7 @@ const CFormCheck = defineComponent({
126
132
  'form-check',
127
133
  {
128
134
  'form-check-inline': props.inline,
135
+ 'form-check-reverse': props.reverse,
129
136
  'is-invalid': props.invalid,
130
137
  'is-valid': props.valid,
131
138
  },
@@ -31,6 +31,12 @@ const CFormSwitch = defineComponent({
31
31
  type: [Boolean, String],
32
32
  value: undefined,
33
33
  },
34
+ /**
35
+ * Put checkboxes or radios on the opposite side.
36
+ *
37
+ * @sinve 4.8.0
38
+ */
39
+ reverse: Boolean,
34
40
  /**
35
41
  * Size the component large or extra large. Works only with `switch`.
36
42
  *
@@ -82,6 +88,7 @@ const CFormSwitch = defineComponent({
82
88
  class: [
83
89
  'form-check form-switch',
84
90
  {
91
+ 'form-check-reverse': props.reverse,
85
92
  [`form-switch-${props.size}`]: props.size,
86
93
  'is-invalid': props.invalid,
87
94
  'is-valid': props.valid,
@@ -43,4 +43,5 @@ export * from './tabs'
43
43
  export * from './time-picker'
44
44
  export * from './toast'
45
45
  export * from './tooltip'
46
+ export * from './virtual-scroller'
46
47
  export * from './widgets'
@@ -6,27 +6,9 @@ import { CPicker } from '../picker'
6
6
  import { CMultiSelectNativeSelect } from './CMultiSelectNativeSelect'
7
7
  import { CMultiSelectOptions } from './CMultiSelectOptions'
8
8
  import { CMultiSelectSelection } from './CMultiSelectSelection'
9
- export interface Option {
10
- disabled?: boolean
11
- label?: string
12
- options?: Option[]
13
- order?: number
14
- selected?: boolean
15
- text: string
16
- value: number | string
17
- }
18
9
 
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
- }
10
+ import { filterOptionsList, flattenArray, selectOptions } from './utils'
11
+ import type { Option, SelectedOption } from './types'
30
12
 
31
13
  const CMultiSelect = defineComponent({
32
14
  name: 'CMultiSelect',
@@ -38,7 +20,6 @@ const CMultiSelect = defineComponent({
38
20
  */
39
21
  cleaner: {
40
22
  type: Boolean,
41
- required: false,
42
23
  default: true,
43
24
  },
44
25
  /**
@@ -46,7 +27,6 @@ const CMultiSelect = defineComponent({
46
27
  */
47
28
  disabled: {
48
29
  type: Boolean,
49
- required: false,
50
30
  default: false,
51
31
  },
52
32
  /**
@@ -101,7 +81,6 @@ const CMultiSelect = defineComponent({
101
81
  multiple: {
102
82
  type: Boolean,
103
83
  default: true,
104
- required: false,
105
84
  },
106
85
  /**
107
86
  * List of option elements.
@@ -109,7 +88,6 @@ const CMultiSelect = defineComponent({
109
88
  options: {
110
89
  type: Array as PropType<Option[]>,
111
90
  default: () => [],
112
- required: false,
113
91
  },
114
92
  /**
115
93
  * Sets maxHeight of options list.
@@ -119,7 +97,6 @@ const CMultiSelect = defineComponent({
119
97
  optionsMaxHeight: {
120
98
  type: [Number, String],
121
99
  default: 'auto',
122
- required: false,
123
100
  },
124
101
  /**
125
102
  * Sets option style.
@@ -130,7 +107,6 @@ const CMultiSelect = defineComponent({
130
107
  optionsStyle: {
131
108
  type: String,
132
109
  default: 'checkbox',
133
- required: false,
134
110
  validator: (value: string) => {
135
111
  return ['checkbox', 'text'].includes(value)
136
112
  },
@@ -143,7 +119,6 @@ const CMultiSelect = defineComponent({
143
119
  placeholder: {
144
120
  type: String,
145
121
  default: 'Select...',
146
- required: false,
147
122
  },
148
123
  /**
149
124
  * Enables search input element.
@@ -151,7 +126,6 @@ const CMultiSelect = defineComponent({
151
126
  search: {
152
127
  type: [Boolean, String],
153
128
  default: true,
154
- required: false,
155
129
  validator: (value: boolean | string) => {
156
130
  if (typeof value == 'string') {
157
131
  return ['external'].includes(value)
@@ -168,7 +142,6 @@ const CMultiSelect = defineComponent({
168
142
  searchNoResultsLabel: {
169
143
  type: String,
170
144
  default: 'no items',
171
- required: false,
172
145
  },
173
146
  /**
174
147
  * Enables select all button.
@@ -177,7 +150,6 @@ const CMultiSelect = defineComponent({
177
150
  */
178
151
  selectAll: {
179
152
  type: Boolean,
180
- required: false,
181
153
  default: true,
182
154
  },
183
155
  /**
@@ -187,7 +159,6 @@ const CMultiSelect = defineComponent({
187
159
  */
188
160
  selectAllLabel: {
189
161
  type: String,
190
- required: false,
191
162
  default: 'Select all options',
192
163
  },
193
164
  /**
@@ -199,7 +170,6 @@ const CMultiSelect = defineComponent({
199
170
  selectionType: {
200
171
  type: String,
201
172
  default: 'tags',
202
- required: false,
203
173
  validator: (value: string) => {
204
174
  return ['counter', 'tags', 'text'].includes(value)
205
175
  },
@@ -212,7 +182,6 @@ const CMultiSelect = defineComponent({
212
182
  selectionTypeCounterText: {
213
183
  type: String,
214
184
  default: 'item(s) selected',
215
- required: false,
216
185
  },
217
186
  /**
218
187
  * Size the component small or large.
@@ -221,7 +190,6 @@ const CMultiSelect = defineComponent({
221
190
  */
222
191
  size: {
223
192
  type: String,
224
- required: false,
225
193
  validator: (value: string) => {
226
194
  return ['sm', 'lg'].includes(value)
227
195
  },
@@ -246,6 +214,12 @@ const CMultiSelect = defineComponent({
246
214
  * @since 4.6.0
247
215
  */
248
216
  valid: Boolean,
217
+ /**
218
+ * Enable virtual scroller for the options list.
219
+ *
220
+ * @since 4.8.0
221
+ */
222
+ virtualScroller: Boolean,
249
223
  /**
250
224
  * Toggle the visibility of multi select dropdown.
251
225
  *
@@ -254,7 +228,16 @@ const CMultiSelect = defineComponent({
254
228
  visible: {
255
229
  type: Boolean,
256
230
  default: false,
257
- required: false,
231
+ },
232
+ /**
233
+ *
234
+ * Amount of visible items when virtualScroller is set to `true`.
235
+ *
236
+ * @since 4.8.0
237
+ */
238
+ visibleItems: {
239
+ type: Number,
240
+ default: 10,
258
241
  },
259
242
  },
260
243
  emits: [
@@ -271,37 +254,13 @@ const CMultiSelect = defineComponent({
271
254
  ],
272
255
  setup(props, { attrs, emit }) {
273
256
  const nativeSelectRef = ref<HTMLSelectElement>()
274
- provide('nativeSelectRef', nativeSelectRef)
275
- const searchRef = ref<HTMLInputElement>()
276
-
277
257
  const options = ref<Option[]>(props.options)
278
258
  const search = ref('')
259
+ const searchRef = ref<HTMLInputElement>()
279
260
  const selected = ref<SelectedOption[]>([])
280
261
  const visible = ref<Boolean>(props.visible)
281
262
 
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
- })
299
- }
300
- return unique
301
- }, []) as SelectedOption[]
302
-
303
- selected.value = deduplicated
304
- }
263
+ provide('nativeSelectRef', nativeSelectRef)
305
264
 
306
265
  watch(
307
266
  () => props.options,
@@ -328,9 +287,12 @@ const CMultiSelect = defineComponent({
328
287
  return
329
288
  })
330
289
 
331
- _selected && selectOptions(_selected, deselected)
290
+ if (_selected) {
291
+ selected.value = selectOptions(_selected, selected.value, deselected)
292
+ }
332
293
  }
333
294
  },
295
+ { immediate: true },
334
296
  )
335
297
 
336
298
  watch(selected, () => {
@@ -338,29 +300,6 @@ const CMultiSelect = defineComponent({
338
300
  nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }))
339
301
  })
340
302
 
341
- const filterOptionsList = (search: string, _options: Option[]) => {
342
- return search.length
343
- ? _options &&
344
- _options.reduce((acc: Option[], val: Option) => {
345
- const options =
346
- val.options &&
347
- val.options.filter(
348
- (element) =>
349
- element.text && element.text.toLowerCase().includes(search.toLowerCase()),
350
- )
351
-
352
- if (
353
- (val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
354
- (options && options.length)
355
- ) {
356
- acc.push(Object.assign({}, val, options && options.length && { options }))
357
- }
358
-
359
- return acc
360
- }, [])
361
- : options.value
362
- }
363
-
364
303
  const handleSearchChange = (event: InputEvent) => {
365
304
  const target = event.target as HTMLInputElement
366
305
  search.value = target.value.toLowerCase()
@@ -404,7 +343,10 @@ const CMultiSelect = defineComponent({
404
343
  }
405
344
 
406
345
  const handleSelectAll = () => {
407
- selectOptions(flattenArray(options.value).filter((option: Option) => !option.disabled))
346
+ selected.value = selectOptions(
347
+ flattenArray(options.value).filter((option: Option) => !option.disabled),
348
+ selected.value,
349
+ )
408
350
  }
409
351
 
410
352
  const handleDeselectAll = () => {
@@ -507,7 +449,7 @@ const CMultiSelect = defineComponent({
507
449
  }),
508
450
  ]),
509
451
  default: () =>
510
- h('div', {}, [
452
+ visible.value && [
511
453
  props.multiple &&
512
454
  props.selectAll &&
513
455
  h(
@@ -528,9 +470,11 @@ const CMultiSelect = defineComponent({
528
470
  optionsMaxHeight: props.optionsMaxHeight,
529
471
  optionsStyle: props.optionsStyle,
530
472
  searchNoResultsLabel: props.searchNoResultsLabel,
531
- selected: selected.value
473
+ selected: selected.value,
474
+ virtualScroller: props.virtualScroller,
475
+ visibleItems: props.visibleItems,
532
476
  }),
533
- ]),
477
+ ],
534
478
  },
535
479
  ),
536
480
  },
@@ -1,5 +1,6 @@
1
1
  import { defineComponent, h, inject, PropType, VNode } from 'vue'
2
- import { Option } from './CMultiSelect'
2
+
3
+ import type { Option } from './types'
3
4
 
4
5
  const CMultiSelectNativeSelect = defineComponent({
5
6
  name: 'CMultiSelectGroupOption',
@@ -1,7 +1,9 @@
1
1
  import { defineComponent, h, PropType, VNode } from 'vue'
2
- import { Option } from './CMultiSelect'
3
2
 
4
- import { getNextSibling, getPreviousSibling } from './../../utils'
3
+ import { CVirtualScroller } from '../virtual-scroller'
4
+
5
+ import { getNextSibling, getPreviousSibling } from './utils'
6
+ import type { Option } from './types'
5
7
 
6
8
  const CMultiSelectOptions = defineComponent({
7
9
  name: 'CMultiSelectOptions',
@@ -12,7 +14,6 @@ const CMultiSelectOptions = defineComponent({
12
14
  options: {
13
15
  type: Array as PropType<Option[]>,
14
16
  default: () => [],
15
- required: false,
16
17
  },
17
18
  /**
18
19
  * Sets maxHeight of options list.
@@ -22,7 +23,6 @@ const CMultiSelectOptions = defineComponent({
22
23
  optionsMaxHeight: {
23
24
  type: [Number, String],
24
25
  default: 'auto',
25
- required: false,
26
26
  },
27
27
  /**
28
28
  * Sets option style.
@@ -33,7 +33,6 @@ const CMultiSelectOptions = defineComponent({
33
33
  optionsStyle: {
34
34
  type: String,
35
35
  default: 'checkbox',
36
- required: false,
37
36
  validator: (value: string) => {
38
37
  return ['checkbox', 'text'].includes(value)
39
38
  },
@@ -44,12 +43,15 @@ const CMultiSelectOptions = defineComponent({
44
43
  searchNoResultsLabel: {
45
44
  type: String,
46
45
  default: 'no items',
47
- required: false,
48
46
  },
49
47
  selected: {
50
48
  type: Array as PropType<Option[]>,
51
49
  default: () => [],
52
- required: false,
50
+ },
51
+ virtualScroller: Boolean,
52
+ visibleItems: {
53
+ type: Number,
54
+ default: 10,
53
55
  },
54
56
  },
55
57
  emits: ['optionClick'],
@@ -114,17 +116,29 @@ const CMultiSelectOptions = defineComponent({
114
116
  ),
115
117
  )
116
118
  : h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel)
119
+
117
120
  return () =>
118
- h(
119
- 'div',
120
- {
121
- class: 'form-multi-select-options',
122
- ...(props.optionsMaxHeight !== 'auto' && {
123
- style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
124
- }),
125
- },
126
- createOptions(props.options),
127
- )
121
+ props.virtualScroller
122
+ ? h(
123
+ CVirtualScroller,
124
+ {
125
+ class: 'form-multi-select-options',
126
+ visibleItems: props.visibleItems,
127
+ },
128
+ {
129
+ default: () => createOptions(props.options),
130
+ },
131
+ )
132
+ : h(
133
+ 'div',
134
+ {
135
+ class: 'form-multi-select-options',
136
+ ...(props.optionsMaxHeight !== 'auto' && {
137
+ style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
138
+ }),
139
+ },
140
+ createOptions(props.options),
141
+ )
128
142
  },
129
143
  })
130
144
 
@@ -1,5 +1,6 @@
1
1
  import { defineComponent, h, PropType } from 'vue'
2
- import { Option } from './CMultiSelect'
2
+
3
+ import type { Option } from './types'
3
4
 
4
5
  const CMultiSelectSelection = defineComponent({
5
6
  name: 'CMultiSelectSelection',
@@ -0,0 +1,15 @@
1
+ export type Option = {
2
+ disabled?: boolean
3
+ label?: string
4
+ options?: Option[]
5
+ order?: number
6
+ selected?: boolean
7
+ text: string
8
+ value: number | string
9
+ }
10
+
11
+ export type SelectedOption = {
12
+ disabled?: boolean
13
+ text: string
14
+ value: number | string
15
+ }