@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
package/dist/index.js CHANGED
@@ -1909,38 +1909,6 @@ const CCardPlugin = {
1909
1909
  },
1910
1910
  };
1911
1911
 
1912
- const getNextSibling = (elem, selector) => {
1913
- // Get the next sibling element
1914
- let sibling = elem.nextElementSibling;
1915
- // If there's no selector, return the first sibling
1916
- if (!selector)
1917
- return sibling;
1918
- // If the sibling matches our selector, use it
1919
- // If not, jump to the next sibling and continue the loop
1920
- while (sibling) {
1921
- if (sibling.matches(selector))
1922
- return sibling;
1923
- sibling = sibling.nextElementSibling;
1924
- }
1925
- return;
1926
- };
1927
-
1928
- const getPreviousSibling = (elem, selector) => {
1929
- // Get the next sibling element
1930
- let sibling = elem.previousElementSibling;
1931
- // If there's no selector, return the first sibling
1932
- if (!selector)
1933
- return sibling;
1934
- // If the sibling matches our selector, use it
1935
- // If not, jump to the next sibling and continue the loop
1936
- while (sibling) {
1937
- if (sibling.matches(selector))
1938
- return sibling;
1939
- sibling = sibling.previousElementSibling;
1940
- }
1941
- return;
1942
- };
1943
-
1944
1912
  const isInViewport = (element) => {
1945
1913
  const rect = element.getBoundingClientRect();
1946
1914
  return (Math.floor(rect.top) >= 0 &&
@@ -2015,10 +1983,13 @@ const CCarousel = vue.defineComponent({
2015
1983
  },
2016
1984
  setup(props, { slots }) {
2017
1985
  const carouselRef = vue.ref();
2018
- const timeout = vue.ref();
1986
+ const active = vue.ref(props.index);
2019
1987
  const animating = vue.ref(false);
2020
- const visible = vue.ref();
2021
1988
  const customInterval = vue.ref(props.interval);
1989
+ const direction = vue.ref('next');
1990
+ const items = vue.ref([]);
1991
+ const timeout = vue.ref();
1992
+ const visible = vue.ref();
2022
1993
  const setAnimating = (value) => {
2023
1994
  animating.value = value;
2024
1995
  };
@@ -2034,27 +2005,16 @@ const CCarousel = vue.defineComponent({
2034
2005
  timeout.value = setTimeout(() => nextItemWhenVisible(), typeof customInterval.value === 'number' ? customInterval.value : props.interval);
2035
2006
  }
2036
2007
  };
2037
- const state = vue.reactive({
2038
- items: [],
2039
- active: props.index,
2040
- direction: 'next',
2041
- });
2042
- vue.onBeforeMount(() => {
2043
- if (slots.default) {
2044
- // @ts-expect-error TODO: fix types
2045
- state.items = slots.default().filter((child) => child.type.name === 'CCarouselItem');
2046
- }
2047
- });
2048
- const handleControlClick = (direction) => {
2008
+ const handleControlClick = (_direction) => {
2049
2009
  if (animating.value) {
2050
2010
  return;
2051
2011
  }
2052
- state.direction = direction;
2053
- if (direction === 'next') {
2054
- state.active === state.items.length - 1 ? (state.active = 0) : state.active++;
2012
+ direction.value = _direction;
2013
+ if (_direction === 'next') {
2014
+ active.value === items.value.length - 1 ? (active.value = 0) : active.value++;
2055
2015
  }
2056
2016
  else {
2057
- state.active === 0 ? (state.active = state.items.length - 1) : state.active--;
2017
+ active.value === 0 ? (active.value = items.value.length - 1) : active.value--;
2058
2018
  }
2059
2019
  };
2060
2020
  const nextItemWhenVisible = () => {
@@ -2065,17 +2025,17 @@ const CCarousel = vue.defineComponent({
2065
2025
  }
2066
2026
  };
2067
2027
  const handleIndicatorClick = (index) => {
2068
- if (state.active === index) {
2028
+ if (active.value === index) {
2069
2029
  return;
2070
2030
  }
2071
- if (state.active < index) {
2072
- state.direction = 'next';
2073
- state.active = index;
2031
+ if (active.value < index) {
2032
+ direction.value = 'next';
2033
+ active.value = index;
2074
2034
  return;
2075
2035
  }
2076
- if (state.active > index) {
2077
- state.direction = 'prev';
2078
- state.active = index;
2036
+ if (active.value > index) {
2037
+ direction.value = 'prev';
2038
+ active.value = index;
2079
2039
  }
2080
2040
  };
2081
2041
  const handleScroll = () => {
@@ -2086,6 +2046,15 @@ const CCarousel = vue.defineComponent({
2086
2046
  visible.value = false;
2087
2047
  }
2088
2048
  };
2049
+ vue.onBeforeMount(() => {
2050
+ if (slots.default) {
2051
+ const children = typeof slots.default()[0].type === 'symbol' ? slots.default()[0].children : slots.default();
2052
+ if (children && Array.isArray(children)) {
2053
+ // @ts-expect-error TODO: fix types
2054
+ items.value = children.filter((child) => child.type.name === 'CCarouselItem');
2055
+ }
2056
+ }
2057
+ });
2089
2058
  vue.onMounted(() => {
2090
2059
  window.addEventListener('scroll', handleScroll);
2091
2060
  });
@@ -2095,7 +2064,7 @@ const CCarousel = vue.defineComponent({
2095
2064
  !animating.value && cycle();
2096
2065
  return;
2097
2066
  }
2098
- if (!props.wrap && state.active < state.items.length - 1) {
2067
+ if (!props.wrap && active.value < items.value.length - 1) {
2099
2068
  !animating.value && cycle();
2100
2069
  }
2101
2070
  });
@@ -2116,19 +2085,19 @@ const CCarousel = vue.defineComponent({
2116
2085
  props.indicators &&
2117
2086
  vue.h('div', {
2118
2087
  class: 'carousel-indicators',
2119
- }, state.items.map((_, index) => {
2088
+ }, items.value.map((_, index) => {
2120
2089
  return vue.h('button', {
2121
2090
  type: 'button',
2122
2091
  id: index,
2123
2092
  'data-coreui-target': '',
2124
- ...(state.active === index && { class: 'active' }),
2093
+ ...(active.value === index && { class: 'active' }),
2125
2094
  onClick: () => handleIndicatorClick(index),
2126
2095
  });
2127
2096
  })),
2128
- vue.h('div', { class: 'carousel-inner' }, state.items.map((item, index) => {
2097
+ vue.h('div', { class: 'carousel-inner' }, items.value.map((item, index) => {
2129
2098
  return vue.h(item, {
2130
- active: state.active === index ? true : false,
2131
- direction: state.direction,
2099
+ active: active.value === index ? true : false,
2100
+ direction: direction.value,
2132
2101
  });
2133
2102
  })),
2134
2103
  props.controls && [
@@ -4847,6 +4816,12 @@ const CFormCheck = vue.defineComponent({
4847
4816
  type: [Boolean, String],
4848
4817
  value: undefined,
4849
4818
  },
4819
+ /**
4820
+ * Put checkboxes or radios on the opposite side.
4821
+ *
4822
+ * @sinve 4.8.0
4823
+ */
4824
+ reverse: Boolean,
4850
4825
  /**
4851
4826
  * Display validation feedback in a styled tooltip.
4852
4827
  *
@@ -4889,6 +4864,7 @@ const CFormCheck = vue.defineComponent({
4889
4864
  'form-check',
4890
4865
  {
4891
4866
  'form-check-inline': props.inline,
4867
+ 'form-check-reverse': props.reverse,
4892
4868
  'is-invalid': props.invalid,
4893
4869
  'is-valid': props.valid,
4894
4870
  },
@@ -5586,6 +5562,12 @@ const CFormSwitch = vue.defineComponent({
5586
5562
  type: [Boolean, String],
5587
5563
  value: undefined,
5588
5564
  },
5565
+ /**
5566
+ * Put checkboxes or radios on the opposite side.
5567
+ *
5568
+ * @sinve 4.8.0
5569
+ */
5570
+ reverse: Boolean,
5589
5571
  /**
5590
5572
  * Size the component large or extra large. Works only with `switch`.
5591
5573
  *
@@ -5633,6 +5615,7 @@ const CFormSwitch = vue.defineComponent({
5633
5615
  class: [
5634
5616
  'form-check form-switch',
5635
5617
  {
5618
+ 'form-check-reverse': props.reverse,
5636
5619
  [`form-switch-${props.size}`]: props.size,
5637
5620
  'is-invalid': props.invalid,
5638
5621
  'is-valid': props.valid,
@@ -11534,6 +11517,159 @@ const CMultiSelectNativeSelect = vue.defineComponent({
11534
11517
  },
11535
11518
  });
11536
11519
 
11520
+ const CVirtualScroller = vue.defineComponent({
11521
+ name: 'CVirtualScroller',
11522
+ props: {
11523
+ /**
11524
+ * Amount of visible items
11525
+ */
11526
+ visibleItems: {
11527
+ type: Number,
11528
+ default: 10,
11529
+ },
11530
+ },
11531
+ setup(props, { slots }) {
11532
+ const virtualScrollRef = vue.ref();
11533
+ const virtualScrollContentRef = vue.ref();
11534
+ const currentItemIndex = vue.ref(1);
11535
+ const itemHeight = vue.ref(0);
11536
+ const itemsNumber = vue.ref(0);
11537
+ const viewportPadding = vue.ref(0);
11538
+ const buffer = vue.computed(() => Math.floor(props.visibleItems / 2));
11539
+ const maxHeight = vue.computed(() => itemsNumber.value * itemHeight.value + 2 * viewportPadding.value);
11540
+ const viewportHeight = vue.computed(() => props.visibleItems * itemHeight.value + 2 * viewportPadding.value);
11541
+ vue.onMounted(() => {
11542
+ if (virtualScrollRef.value) {
11543
+ viewportPadding.value = parseFloat(getComputedStyle(virtualScrollRef.value).paddingTop);
11544
+ // It's necessary to calculate heights of items
11545
+ virtualScrollRef.value.dispatchEvent(new CustomEvent('scroll'));
11546
+ }
11547
+ });
11548
+ const handleScroll = (scrollTop) => {
11549
+ currentItemIndex.value =
11550
+ itemHeight.value && Math.max(Math.ceil(scrollTop / itemHeight.value), 1);
11551
+ };
11552
+ return () => {
11553
+ const children = slots.default
11554
+ ? Array.isArray(slots.default()[0].children)
11555
+ ? slots.default()[0].children
11556
+ : slots.default()
11557
+ : [];
11558
+ itemsNumber.value = children && children.length ? children.length : 0;
11559
+ return vue.h('div', {
11560
+ class: ['virtual-scroller'],
11561
+ onScroll: (event) => handleScroll(event.target.scrollTop),
11562
+ style: {
11563
+ height: `${maxHeight.value > viewportHeight.value ? viewportHeight.value : maxHeight.value}px`,
11564
+ overflowY: 'auto',
11565
+ },
11566
+ ref: virtualScrollRef,
11567
+ }, vue.h('div', {
11568
+ class: 'virtual-scroller-content',
11569
+ style: {
11570
+ height: `${maxHeight.value}px`,
11571
+ },
11572
+ ref: virtualScrollContentRef,
11573
+ }, children.map((slot, index) => index + 1 > Math.max(currentItemIndex.value - buffer.value, 0) &&
11574
+ index + 1 <= currentItemIndex.value + props.visibleItems + buffer.value &&
11575
+ vue.cloneVNode(slot, {
11576
+ class: [
11577
+ {
11578
+ 'virtual-scroller-item-preload': index + 1 > currentItemIndex.value + props.visibleItems ||
11579
+ index + 1 < currentItemIndex.value,
11580
+ },
11581
+ ],
11582
+ style: {
11583
+ ...(currentItemIndex.value > buffer.value && {
11584
+ transform: `translateY(${(currentItemIndex.value - buffer.value) * itemHeight.value}px)`,
11585
+ }),
11586
+ },
11587
+ ref: (node) => {
11588
+ if (node && node.offsetHeight) {
11589
+ itemHeight.value =
11590
+ node.offsetHeight +
11591
+ parseFloat(getComputedStyle(node).marginTop) +
11592
+ parseFloat(getComputedStyle(node).marginBottom);
11593
+ }
11594
+ },
11595
+ }))));
11596
+ };
11597
+ },
11598
+ });
11599
+
11600
+ const CVirtualScrollerPlugin = {
11601
+ install: (app) => {
11602
+ app.component(CVirtualScroller.name, CVirtualScroller);
11603
+ },
11604
+ };
11605
+
11606
+ const filterOptionsList = (search, _options) => {
11607
+ return search.length
11608
+ ? _options &&
11609
+ _options.reduce((acc, val) => {
11610
+ const options = val.options &&
11611
+ val.options.filter((element) => element.text && element.text.toLowerCase().includes(search.toLowerCase()));
11612
+ if ((val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
11613
+ (options && options.length)) {
11614
+ acc.push(Object.assign({}, val, options && options.length && { options }));
11615
+ }
11616
+ return acc;
11617
+ }, [])
11618
+ : _options;
11619
+ };
11620
+ const flattenArray = (options) => {
11621
+ return options.reduce((acc, val) => {
11622
+ return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
11623
+ }, []);
11624
+ };
11625
+ const getNextSibling = (elem, selector) => {
11626
+ // Get the next sibling element
11627
+ let sibling = elem.nextElementSibling;
11628
+ // If there's no selector, return the first sibling
11629
+ if (!selector)
11630
+ return sibling;
11631
+ // If the sibling matches our selector, use it
11632
+ // If not, jump to the next sibling and continue the loop
11633
+ while (sibling) {
11634
+ if (sibling.matches(selector))
11635
+ return sibling;
11636
+ sibling = sibling.nextElementSibling;
11637
+ }
11638
+ return;
11639
+ };
11640
+ const getPreviousSibling = (elem, selector) => {
11641
+ // Get the next sibling element
11642
+ let sibling = elem.previousElementSibling;
11643
+ // If there's no selector, return the first sibling
11644
+ if (!selector)
11645
+ return sibling;
11646
+ // If the sibling matches our selector, use it
11647
+ // If not, jump to the next sibling and continue the loop
11648
+ while (sibling) {
11649
+ if (sibling.matches(selector))
11650
+ return sibling;
11651
+ sibling = sibling.previousElementSibling;
11652
+ }
11653
+ return;
11654
+ };
11655
+ const selectOptions = (options, selected, deselected) => {
11656
+ let _selected = [...selected, ...options];
11657
+ if (deselected) {
11658
+ _selected = _selected.filter((selectedOption) => !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value));
11659
+ }
11660
+ const deduplicated = _selected.reduce((unique, option) => {
11661
+ if (!unique.some((obj) => obj.value === option.value)) {
11662
+ unique.push({
11663
+ value: option.value,
11664
+ text: option.text,
11665
+ ...(option.disabled && { disabled: option.disabled }),
11666
+ });
11667
+ }
11668
+ return unique;
11669
+ }, []);
11670
+ return deduplicated;
11671
+ };
11672
+
11537
11673
  const CMultiSelectOptions = vue.defineComponent({
11538
11674
  name: 'CMultiSelectOptions',
11539
11675
  props: {
@@ -11543,7 +11679,6 @@ const CMultiSelectOptions = vue.defineComponent({
11543
11679
  options: {
11544
11680
  type: Array,
11545
11681
  default: () => [],
11546
- required: false,
11547
11682
  },
11548
11683
  /**
11549
11684
  * Sets maxHeight of options list.
@@ -11553,7 +11688,6 @@ const CMultiSelectOptions = vue.defineComponent({
11553
11688
  optionsMaxHeight: {
11554
11689
  type: [Number, String],
11555
11690
  default: 'auto',
11556
- required: false,
11557
11691
  },
11558
11692
  /**
11559
11693
  * Sets option style.
@@ -11564,7 +11698,6 @@ const CMultiSelectOptions = vue.defineComponent({
11564
11698
  optionsStyle: {
11565
11699
  type: String,
11566
11700
  default: 'checkbox',
11567
- required: false,
11568
11701
  validator: (value) => {
11569
11702
  return ['checkbox', 'text'].includes(value);
11570
11703
  },
@@ -11575,12 +11708,15 @@ const CMultiSelectOptions = vue.defineComponent({
11575
11708
  searchNoResultsLabel: {
11576
11709
  type: String,
11577
11710
  default: 'no items',
11578
- required: false,
11579
11711
  },
11580
11712
  selected: {
11581
11713
  type: Array,
11582
11714
  default: () => [],
11583
- required: false,
11715
+ },
11716
+ virtualScroller: Boolean,
11717
+ visibleItems: {
11718
+ type: Number,
11719
+ default: 10,
11584
11720
  },
11585
11721
  },
11586
11722
  emits: ['optionClick'],
@@ -11632,12 +11768,19 @@ const CMultiSelectOptions = vue.defineComponent({
11632
11768
  tabindex: 0,
11633
11769
  }, option.text))
11634
11770
  : vue.h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel);
11635
- return () => vue.h('div', {
11636
- class: 'form-multi-select-options',
11637
- ...(props.optionsMaxHeight !== 'auto' && {
11638
- style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
11639
- }),
11640
- }, createOptions(props.options));
11771
+ return () => props.virtualScroller
11772
+ ? vue.h(CVirtualScroller, {
11773
+ class: 'form-multi-select-options',
11774
+ visibleItems: props.visibleItems,
11775
+ }, {
11776
+ default: () => createOptions(props.options),
11777
+ })
11778
+ : vue.h('div', {
11779
+ class: 'form-multi-select-options',
11780
+ ...(props.optionsMaxHeight !== 'auto' && {
11781
+ style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
11782
+ }),
11783
+ }, createOptions(props.options));
11641
11784
  },
11642
11785
  });
11643
11786
 
@@ -11728,11 +11871,6 @@ const CMultiSelectSelection = vue.defineComponent({
11728
11871
  },
11729
11872
  });
11730
11873
 
11731
- const flattenArray = (options) => {
11732
- return options.reduce((acc, val) => {
11733
- return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
11734
- }, []);
11735
- };
11736
11874
  const CMultiSelect = vue.defineComponent({
11737
11875
  name: 'CMultiSelect',
11738
11876
  props: {
@@ -11743,7 +11881,6 @@ const CMultiSelect = vue.defineComponent({
11743
11881
  */
11744
11882
  cleaner: {
11745
11883
  type: Boolean,
11746
- required: false,
11747
11884
  default: true,
11748
11885
  },
11749
11886
  /**
@@ -11751,7 +11888,6 @@ const CMultiSelect = vue.defineComponent({
11751
11888
  */
11752
11889
  disabled: {
11753
11890
  type: Boolean,
11754
- required: false,
11755
11891
  default: false,
11756
11892
  },
11757
11893
  /**
@@ -11806,7 +11942,6 @@ const CMultiSelect = vue.defineComponent({
11806
11942
  multiple: {
11807
11943
  type: Boolean,
11808
11944
  default: true,
11809
- required: false,
11810
11945
  },
11811
11946
  /**
11812
11947
  * List of option elements.
@@ -11814,7 +11949,6 @@ const CMultiSelect = vue.defineComponent({
11814
11949
  options: {
11815
11950
  type: Array,
11816
11951
  default: () => [],
11817
- required: false,
11818
11952
  },
11819
11953
  /**
11820
11954
  * Sets maxHeight of options list.
@@ -11824,7 +11958,6 @@ const CMultiSelect = vue.defineComponent({
11824
11958
  optionsMaxHeight: {
11825
11959
  type: [Number, String],
11826
11960
  default: 'auto',
11827
- required: false,
11828
11961
  },
11829
11962
  /**
11830
11963
  * Sets option style.
@@ -11835,7 +11968,6 @@ const CMultiSelect = vue.defineComponent({
11835
11968
  optionsStyle: {
11836
11969
  type: String,
11837
11970
  default: 'checkbox',
11838
- required: false,
11839
11971
  validator: (value) => {
11840
11972
  return ['checkbox', 'text'].includes(value);
11841
11973
  },
@@ -11848,7 +11980,6 @@ const CMultiSelect = vue.defineComponent({
11848
11980
  placeholder: {
11849
11981
  type: String,
11850
11982
  default: 'Select...',
11851
- required: false,
11852
11983
  },
11853
11984
  /**
11854
11985
  * Enables search input element.
@@ -11856,7 +11987,6 @@ const CMultiSelect = vue.defineComponent({
11856
11987
  search: {
11857
11988
  type: [Boolean, String],
11858
11989
  default: true,
11859
- required: false,
11860
11990
  validator: (value) => {
11861
11991
  if (typeof value == 'string') {
11862
11992
  return ['external'].includes(value);
@@ -11873,7 +12003,6 @@ const CMultiSelect = vue.defineComponent({
11873
12003
  searchNoResultsLabel: {
11874
12004
  type: String,
11875
12005
  default: 'no items',
11876
- required: false,
11877
12006
  },
11878
12007
  /**
11879
12008
  * Enables select all button.
@@ -11882,7 +12011,6 @@ const CMultiSelect = vue.defineComponent({
11882
12011
  */
11883
12012
  selectAll: {
11884
12013
  type: Boolean,
11885
- required: false,
11886
12014
  default: true,
11887
12015
  },
11888
12016
  /**
@@ -11892,7 +12020,6 @@ const CMultiSelect = vue.defineComponent({
11892
12020
  */
11893
12021
  selectAllLabel: {
11894
12022
  type: String,
11895
- required: false,
11896
12023
  default: 'Select all options',
11897
12024
  },
11898
12025
  /**
@@ -11904,7 +12031,6 @@ const CMultiSelect = vue.defineComponent({
11904
12031
  selectionType: {
11905
12032
  type: String,
11906
12033
  default: 'tags',
11907
- required: false,
11908
12034
  validator: (value) => {
11909
12035
  return ['counter', 'tags', 'text'].includes(value);
11910
12036
  },
@@ -11917,7 +12043,6 @@ const CMultiSelect = vue.defineComponent({
11917
12043
  selectionTypeCounterText: {
11918
12044
  type: String,
11919
12045
  default: 'item(s) selected',
11920
- required: false,
11921
12046
  },
11922
12047
  /**
11923
12048
  * Size the component small or large.
@@ -11926,7 +12051,6 @@ const CMultiSelect = vue.defineComponent({
11926
12051
  */
11927
12052
  size: {
11928
12053
  type: String,
11929
- required: false,
11930
12054
  validator: (value) => {
11931
12055
  return ['sm', 'lg'].includes(value);
11932
12056
  },
@@ -11951,6 +12075,12 @@ const CMultiSelect = vue.defineComponent({
11951
12075
  * @since 4.6.0
11952
12076
  */
11953
12077
  valid: Boolean,
12078
+ /**
12079
+ * Enable virtual scroller for the options list.
12080
+ *
12081
+ * @since 4.8.0
12082
+ */
12083
+ virtualScroller: Boolean,
11954
12084
  /**
11955
12085
  * Toggle the visibility of multi select dropdown.
11956
12086
  *
@@ -11959,7 +12089,16 @@ const CMultiSelect = vue.defineComponent({
11959
12089
  visible: {
11960
12090
  type: Boolean,
11961
12091
  default: false,
11962
- required: false,
12092
+ },
12093
+ /**
12094
+ *
12095
+ * Amount of visible items when virtualScroller is set to `true`.
12096
+ *
12097
+ * @since 4.8.0
12098
+ */
12099
+ visibleItems: {
12100
+ type: Number,
12101
+ default: 10,
11963
12102
  },
11964
12103
  },
11965
12104
  emits: [
@@ -11976,29 +12115,12 @@ const CMultiSelect = vue.defineComponent({
11976
12115
  ],
11977
12116
  setup(props, { attrs, emit }) {
11978
12117
  const nativeSelectRef = vue.ref();
11979
- vue.provide('nativeSelectRef', nativeSelectRef);
11980
- const searchRef = vue.ref();
11981
12118
  const options = vue.ref(props.options);
11982
12119
  const search = vue.ref('');
12120
+ const searchRef = vue.ref();
11983
12121
  const selected = vue.ref([]);
11984
12122
  const visible = vue.ref(props.visible);
11985
- const selectOptions = (options, deselected) => {
11986
- let _selected = [...selected.value, ...options];
11987
- if (deselected) {
11988
- _selected = _selected.filter((selectedOption) => !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value));
11989
- }
11990
- const deduplicated = _selected.reduce((unique, option) => {
11991
- if (!unique.some((obj) => obj.value === option.value)) {
11992
- unique.push({
11993
- value: option.value,
11994
- text: option.text,
11995
- ...(option.disabled && { disabled: option.disabled }),
11996
- });
11997
- }
11998
- return unique;
11999
- }, []);
12000
- selected.value = deduplicated;
12001
- };
12123
+ vue.provide('nativeSelectRef', nativeSelectRef);
12002
12124
  vue.watch(() => props.options, (newValue, oldValue) => {
12003
12125
  if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
12004
12126
  options.value = newValue;
@@ -12016,27 +12138,15 @@ const CMultiSelect = vue.defineComponent({
12016
12138
  }
12017
12139
  return;
12018
12140
  });
12019
- _selected && selectOptions(_selected, deselected);
12141
+ if (_selected) {
12142
+ selected.value = selectOptions(_selected, selected.value, deselected);
12143
+ }
12020
12144
  }
12021
- });
12145
+ }, { immediate: true });
12022
12146
  vue.watch(selected, () => {
12023
12147
  nativeSelectRef.value &&
12024
12148
  nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }));
12025
12149
  });
12026
- const filterOptionsList = (search, _options) => {
12027
- return search.length
12028
- ? _options &&
12029
- _options.reduce((acc, val) => {
12030
- const options = val.options &&
12031
- val.options.filter((element) => element.text && element.text.toLowerCase().includes(search.toLowerCase()));
12032
- if ((val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
12033
- (options && options.length)) {
12034
- acc.push(Object.assign({}, val, options && options.length && { options }));
12035
- }
12036
- return acc;
12037
- }, [])
12038
- : options.value;
12039
- };
12040
12150
  const handleSearchChange = (event) => {
12041
12151
  const target = event.target;
12042
12152
  search.value = target.value.toLowerCase();
@@ -12074,7 +12184,7 @@ const CMultiSelect = vue.defineComponent({
12074
12184
  }
12075
12185
  };
12076
12186
  const handleSelectAll = () => {
12077
- selectOptions(flattenArray(options.value).filter((option) => !option.disabled));
12187
+ selected.value = selectOptions(flattenArray(options.value).filter((option) => !option.disabled), selected.value);
12078
12188
  };
12079
12189
  const handleDeselectAll = () => {
12080
12190
  selected.value = selected.value.filter((option) => option.disabled);
@@ -12165,7 +12275,7 @@ const CMultiSelect = vue.defineComponent({
12165
12275
  ref: searchRef,
12166
12276
  }),
12167
12277
  ]),
12168
- default: () => vue.h('div', {}, [
12278
+ default: () => visible.value && [
12169
12279
  props.multiple &&
12170
12280
  props.selectAll &&
12171
12281
  vue.h('button', {
@@ -12181,9 +12291,11 @@ const CMultiSelect = vue.defineComponent({
12181
12291
  optionsMaxHeight: props.optionsMaxHeight,
12182
12292
  optionsStyle: props.optionsStyle,
12183
12293
  searchNoResultsLabel: props.searchNoResultsLabel,
12184
- selected: selected.value
12294
+ selected: selected.value,
12295
+ virtualScroller: props.virtualScroller,
12296
+ visibleItems: props.visibleItems,
12185
12297
  }),
12186
- ]),
12298
+ ],
12187
12299
  }),
12188
12300
  }),
12189
12301
  ];
@@ -16688,6 +16800,8 @@ var Components = /*#__PURE__*/Object.freeze({
16688
16800
  CToaster: CToaster,
16689
16801
  CTooltip: CTooltip,
16690
16802
  CTooltipPlugin: CTooltipPlugin,
16803
+ CVirtualScroller: CVirtualScroller,
16804
+ CVirtualScrollerPlugin: CVirtualScrollerPlugin,
16691
16805
  CWidgetStatsA: CWidgetStatsA,
16692
16806
  CWidgetStatsB: CWidgetStatsB,
16693
16807
  CWidgetStatsC: CWidgetStatsC,
@@ -17096,6 +17210,8 @@ exports.CToastPlugin = CToastPlugin;
17096
17210
  exports.CToaster = CToaster;
17097
17211
  exports.CTooltip = CTooltip;
17098
17212
  exports.CTooltipPlugin = CTooltipPlugin;
17213
+ exports.CVirtualScroller = CVirtualScroller;
17214
+ exports.CVirtualScrollerPlugin = CVirtualScrollerPlugin;
17099
17215
  exports.CWidgetStatsA = CWidgetStatsA;
17100
17216
  exports.CWidgetStatsB = CWidgetStatsB;
17101
17217
  exports.CWidgetStatsC = CWidgetStatsC;