@coreui/vue-pro 4.7.0 → 4.8.0-next.1

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 (55) hide show
  1. package/dist/components/calendar/utils.d.ts +23 -0
  2. package/dist/components/index.d.ts +1 -0
  3. package/dist/components/modal/CModal.d.ts +4 -20
  4. package/dist/components/multi-select/CMultiSelect.d.ts +35 -44
  5. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
  6. package/dist/components/multi-select/CMultiSelectOptions.d.ts +13 -11
  7. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
  8. package/dist/components/multi-select/types.d.ts +14 -0
  9. package/dist/components/multi-select/utils.d.ts +6 -0
  10. package/dist/components/offcanvas/COffcanvas.d.ts +35 -18
  11. package/dist/components/smart-table/CSmartTable.d.ts +65 -87
  12. package/dist/components/smart-table/CSmartTableBody.d.ts +16 -40
  13. package/dist/components/smart-table/CSmartTableHead.d.ts +17 -58
  14. package/dist/components/smart-table/CSmartTableInterface.d.ts +1 -1
  15. package/dist/components/smart-table/types.d.ts +50 -0
  16. package/dist/components/smart-table/utils.d.ts +17 -0
  17. package/dist/components/table/CTable.d.ts +1 -1
  18. package/dist/components/time-picker/types.d.ts +15 -0
  19. package/dist/components/time-picker/utils.d.ts +23 -0
  20. package/dist/components/virtual-scroller/CVirtualScroller.d.ts +23 -0
  21. package/dist/components/virtual-scroller/index.d.ts +6 -0
  22. package/dist/index.es.js +943 -885
  23. package/dist/index.es.js.map +1 -1
  24. package/dist/index.js +943 -883
  25. package/dist/index.js.map +1 -1
  26. package/dist/utils/index.d.ts +1 -3
  27. package/dist/utils/isObjectInArray.d.ts +2 -0
  28. package/package.json +6 -6
  29. package/src/components/calendar/CCalendar.ts +1 -1
  30. package/src/{utils/calendar.ts → components/calendar/utils.ts} +1 -1
  31. package/src/components/date-range-picker/CDateRangePicker.ts +1 -1
  32. package/src/components/element-cover/CElementCover.ts +14 -14
  33. package/src/components/index.ts +1 -0
  34. package/src/components/modal/CModal.ts +10 -10
  35. package/src/components/multi-select/CMultiSelect.ts +33 -99
  36. package/src/components/multi-select/CMultiSelectNativeSelect.ts +2 -1
  37. package/src/components/multi-select/CMultiSelectOptions.ts +31 -17
  38. package/src/components/multi-select/CMultiSelectSelection.ts +2 -1
  39. package/src/components/multi-select/types.ts +15 -0
  40. package/src/components/multi-select/utils.ts +92 -0
  41. package/src/components/offcanvas/COffcanvas.ts +50 -28
  42. package/src/components/smart-table/CSmartTable.ts +365 -268
  43. package/src/components/smart-table/CSmartTableBody.ts +126 -137
  44. package/src/components/smart-table/CSmartTableHead.ts +53 -138
  45. package/src/components/smart-table/CSmartTableInterface.ts +1 -1
  46. package/src/components/smart-table/types.ts +61 -0
  47. package/src/components/smart-table/utils.ts +212 -0
  48. package/src/components/time-picker/CTimePicker.ts +49 -27
  49. package/src/components/time-picker/types.ts +15 -0
  50. package/src/{utils/time.ts → components/time-picker/utils.ts} +43 -2
  51. package/src/components/virtual-scroller/CVirtualScroller.ts +109 -0
  52. package/src/components/virtual-scroller/index.ts +10 -0
  53. package/src/utils/index.ts +1 -3
  54. package/src/utils/getNextSibling.ts +0 -18
  55. 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 &&
@@ -8719,38 +8687,34 @@ const getAmPm = (date, locale) => {
8719
8687
  }
8720
8688
  return date.getHours() >= 12 ? 'pm' : 'am';
8721
8689
  };
8722
- const getListOfHours = (locale, ampm = 'auto') => Array.from({ length: (ampm === 'auto' && isAmPm(locale)) || ampm === true ? 12 : 24 }, (_, i) => {
8723
- return {
8724
- value: (ampm === 'auto' && isAmPm(locale)) || ampm === true ? i + 1 : i,
8725
- label: ((ampm === 'auto' && isAmPm(locale)) || ampm === true ? i + 1 : i).toLocaleString(locale),
8726
- };
8727
- });
8728
- const getListOfMinutes = (locale, valueAsString = false) => Array.from({ length: 60 }, (_, i) => {
8729
- const d = new Date();
8730
- d.setMinutes(i);
8731
- return {
8732
- value: valueAsString ? i.toString() : i,
8733
- label: d
8734
- .toLocaleTimeString(locale, {
8735
- minute: '2-digit',
8736
- second: '2-digit',
8737
- })
8738
- .split(/[^A-Za-z0-9]/)[0],
8739
- };
8740
- });
8741
- const getListOfSeconds = (locale, valueAsString = false) => Array.from({ length: 60 }, (_, i) => {
8742
- const d = new Date();
8743
- d.setSeconds(i);
8690
+ const getLocalizedTimePartials = (locale, ampm = 'auto') => {
8691
+ const date = new Date();
8692
+ const hour12 = ['am', 'AM', 'pm', 'PM'].some((el) => date.toLocaleString(locale).includes(el));
8693
+ const listOfHours = Array.from({ length: (ampm === 'auto' && hour12) || ampm === true ? 12 : 24 }, (_, i) => {
8694
+ return {
8695
+ value: (ampm === 'auto' && hour12) || ampm === true ? i + 1 : i,
8696
+ label: ((ampm === 'auto' && hour12) || ampm === true ? i + 1 : i).toLocaleString(locale),
8697
+ };
8698
+ });
8699
+ const listOfMinutesSeconds = Array.from({ length: 60 }, (_, i) => {
8700
+ date.setMinutes(i);
8701
+ return {
8702
+ value: i,
8703
+ label: date
8704
+ .toLocaleTimeString(locale, {
8705
+ minute: '2-digit',
8706
+ second: '2-digit',
8707
+ })
8708
+ .split(/[^A-Za-z0-9\u06F0-\u06F90-9]/)[0],
8709
+ };
8710
+ });
8744
8711
  return {
8745
- value: valueAsString ? i.toString() : i,
8746
- label: d
8747
- .toLocaleTimeString(locale, {
8748
- minute: '2-digit',
8749
- second: '2-digit',
8750
- })
8751
- .split(/[^A-Za-z0-9]/)[1],
8712
+ listOfHours,
8713
+ listOfMinutes: listOfMinutesSeconds,
8714
+ listOfSeconds: listOfMinutesSeconds,
8715
+ hour12,
8752
8716
  };
8753
- });
8717
+ };
8754
8718
  const getSelectedHour = (date, locale, ampm = 'auto') => date
8755
8719
  ? (ampm === 'auto' && isAmPm(locale)) || ampm === true
8756
8720
  ? convert24hTo12h(date.getHours())
@@ -9024,14 +8988,21 @@ const CTimePicker = vue.defineComponent({
9024
8988
  'update:time',
9025
8989
  ],
9026
8990
  setup(props, { emit, attrs, slots }) {
9027
- const visible = vue.ref(props.visible);
9028
8991
  const date = vue.ref(convertTimeToDate(props.time));
9029
- const initialDate = vue.ref(null);
9030
8992
  const ampm = vue.ref(date.value ? getAmPm(new Date(date.value), props.locale) : 'am');
8993
+ const initialDate = vue.ref(null);
8994
+ const visible = vue.ref(props.visible);
8995
+ const localizedTimePartials = vue.ref({
8996
+ listOfHours: [],
8997
+ listOfMinutes: [],
8998
+ listOfSeconds: [],
8999
+ hour12: false,
9000
+ });
9031
9001
  vue.watch(() => props.time, () => {
9032
9002
  date.value = convertTimeToDate(props.time);
9033
9003
  });
9034
9004
  vue.watch(date, () => {
9005
+ localizedTimePartials.value = getLocalizedTimePartials(props.locale, props.ampm);
9035
9006
  if (date.value) {
9036
9007
  ampm.value = getAmPm(new Date(date.value), props.locale);
9037
9008
  }
@@ -9053,7 +9024,7 @@ const CTimePicker = vue.defineComponent({
9053
9024
  }
9054
9025
  }
9055
9026
  if (set === 'hours') {
9056
- if ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm === true) {
9027
+ if (localizedTimePartials.value && localizedTimePartials.value.hour12) {
9057
9028
  _date.setHours(convert12hTo24h(ampm.value, parseInt(value)));
9058
9029
  }
9059
9030
  else {
@@ -9083,8 +9054,7 @@ const CTimePicker = vue.defineComponent({
9083
9054
  readonly: props.inputReadOnly,
9084
9055
  value: date.value
9085
9056
  ? date.value.toLocaleTimeString(props.locale, {
9086
- hour12: (props.ampm === 'auto' && isAmPm(props.locale)) ||
9087
- (props.ampm === 'boolean' && props.ampm),
9057
+ hour12: localizedTimePartials.value && localizedTimePartials.value.hour12,
9088
9058
  ...(!props.seconds && { timeStyle: 'short' }),
9089
9059
  })
9090
9060
  : '',
@@ -9111,33 +9081,45 @@ const CTimePicker = vue.defineComponent({
9111
9081
  vue.h('span', { class: 'time-picker-inline-icon' }),
9112
9082
  vue.h(CFormSelect, {
9113
9083
  disabled: props.disabled,
9114
- options: getListOfHours(props.locale).map((option) => {
9115
- return {
9116
- value: option.value.toString(),
9117
- label: option.label,
9118
- };
9119
- }),
9084
+ options: localizedTimePartials.value &&
9085
+ localizedTimePartials.value.listOfHours?.map((option) => {
9086
+ return {
9087
+ value: option.value.toString(),
9088
+ label: option.label,
9089
+ };
9090
+ }),
9120
9091
  onChange: (event) => handleTimeChange('hours', event.target.value),
9121
9092
  ...(date.value && { value: getSelectedHour(date.value, props.locale) }),
9122
9093
  }),
9123
9094
  ':',
9124
- // @ts-expect-error the getListOfMinutes function returns corect type
9125
9095
  vue.h(CFormSelect, {
9126
9096
  disabled: props.disabled,
9127
- options: getListOfMinutes(props.locale, true),
9097
+ options: localizedTimePartials.value &&
9098
+ localizedTimePartials.value.listOfMinutes.map((option) => {
9099
+ return {
9100
+ value: option.value.toString(),
9101
+ label: option.label,
9102
+ };
9103
+ }),
9128
9104
  onChange: (event) => handleTimeChange('minutes', event.target.value),
9129
9105
  ...(date.value && { value: getSelectedMinutes(date.value) }),
9130
9106
  }),
9131
9107
  props.seconds && ':',
9132
9108
  props.seconds &&
9133
- // @ts-expect-error the getListOfMinutes function returns corect type
9134
9109
  vue.h(CFormSelect, {
9135
9110
  disabled: props.disabled,
9136
- options: getListOfSeconds(props.locale, true),
9111
+ options: localizedTimePartials.value &&
9112
+ localizedTimePartials.value.listOfSeconds.map((option) => {
9113
+ return {
9114
+ value: option.value.toString(),
9115
+ label: option.label,
9116
+ };
9117
+ }),
9137
9118
  onChange: (event) => handleTimeChange('seconds', event.target.value),
9138
9119
  ...(date.value && { value: getSelectedSeconds(date.value) }),
9139
9120
  }),
9140
- isAmPm(props.locale) &&
9121
+ localizedTimePartials.value &&
9122
+ localizedTimePartials.value.hour12 &&
9141
9123
  vue.h(CFormSelect, {
9142
9124
  disabled: props.disabled,
9143
9125
  options: [
@@ -9150,22 +9132,23 @@ const CTimePicker = vue.defineComponent({
9150
9132
  ];
9151
9133
  const TimePickerRoll = () => [
9152
9134
  vue.h(CTimePickerRollCol, {
9153
- elements: getListOfHours(props.locale, props.ampm),
9135
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfHours,
9154
9136
  onClick: (index) => handleTimeChange('hours', index.toString()),
9155
9137
  selected: getSelectedHour(date.value, props.locale, props.ampm),
9156
9138
  }),
9157
9139
  vue.h(CTimePickerRollCol, {
9158
- elements: getListOfMinutes(props.locale),
9140
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfMinutes,
9159
9141
  onClick: (index) => handleTimeChange('minutes', index.toString()),
9160
9142
  selected: getSelectedMinutes(date.value),
9161
9143
  }),
9162
9144
  props.seconds &&
9163
9145
  vue.h(CTimePickerRollCol, {
9164
- elements: getListOfSeconds(props.locale),
9146
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfSeconds,
9165
9147
  onClick: (index) => handleTimeChange('seconds', index.toString()),
9166
9148
  selected: getSelectedSeconds(date.value),
9167
9149
  }),
9168
- ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm === true) &&
9150
+ localizedTimePartials.value &&
9151
+ localizedTimePartials.value.hour12 &&
9169
9152
  vue.h(CTimePickerRollCol, {
9170
9153
  elements: [
9171
9154
  { value: 'am', label: 'AM' },
@@ -10488,16 +10471,16 @@ const CElementCover = vue.defineComponent({
10488
10471
  return () => vue.h('div', {
10489
10472
  style: { ...coverStyles, ...customBoundaries.value },
10490
10473
  ref: elementCoverRef,
10474
+ }, vue.h('div', {
10475
+ style: {
10476
+ position: 'absolute',
10477
+ top: '50%',
10478
+ left: '50%',
10479
+ transform: 'translateX(-50%) translateY(-50%)',
10480
+ },
10491
10481
  }, slots.default
10492
10482
  ? slots.default()
10493
- : vue.h('div', {
10494
- style: {
10495
- position: 'absolute',
10496
- top: '50%',
10497
- left: '50%',
10498
- transform: 'translateX(-50%) translateY(-50%)',
10499
- },
10500
- }, vue.h(CSpinner, {
10483
+ : vue.h(CSpinner, {
10501
10484
  variant: 'grow',
10502
10485
  color: 'primary',
10503
10486
  })));
@@ -11187,7 +11170,6 @@ const CModal = vue.defineComponent({
11187
11170
  */
11188
11171
  alignment: {
11189
11172
  default: 'top',
11190
- required: false,
11191
11173
  validator: (value) => {
11192
11174
  return ['top', 'center'].includes(value);
11193
11175
  },
@@ -11195,12 +11177,20 @@ const CModal = vue.defineComponent({
11195
11177
  /**
11196
11178
  * Apply a backdrop on body while offcanvas is open.
11197
11179
  *
11198
- * @values 'static'
11180
+ * @values boolean | 'static'
11199
11181
  */
11200
11182
  backdrop: {
11201
11183
  type: [Boolean, String],
11202
11184
  default: true,
11203
- require: false,
11185
+ validator: (value) => {
11186
+ if (typeof value == 'string') {
11187
+ return ['static'].includes(value);
11188
+ }
11189
+ if (typeof value == 'boolean') {
11190
+ return true;
11191
+ }
11192
+ return false;
11193
+ },
11204
11194
  },
11205
11195
  /**
11206
11196
  * A string of all className you want applied to the modal content component.
@@ -11208,7 +11198,6 @@ const CModal = vue.defineComponent({
11208
11198
  contentClassName: {
11209
11199
  type: String,
11210
11200
  default: undefined,
11211
- required: false,
11212
11201
  },
11213
11202
  /**
11214
11203
  * Set modal to covers the entire user viewport
@@ -11218,7 +11207,6 @@ const CModal = vue.defineComponent({
11218
11207
  fullscreen: {
11219
11208
  type: [Boolean, String],
11220
11209
  default: undefined,
11221
- required: false,
11222
11210
  validator: (value) => {
11223
11211
  if (typeof value == 'string') {
11224
11212
  return ['sm', 'md', 'lg', 'xl', 'xxl'].includes(value);
@@ -11235,14 +11223,12 @@ const CModal = vue.defineComponent({
11235
11223
  keyboard: {
11236
11224
  type: Boolean,
11237
11225
  default: true,
11238
- required: false,
11239
11226
  },
11240
11227
  /**
11241
11228
  * Create a scrollable modal that allows scrolling the modal body.
11242
11229
  */
11243
11230
  scrollable: {
11244
11231
  type: Boolean,
11245
- required: false,
11246
11232
  },
11247
11233
  /**
11248
11234
  * Size the component small, large, or extra large.
@@ -11252,7 +11238,6 @@ const CModal = vue.defineComponent({
11252
11238
  size: {
11253
11239
  type: String,
11254
11240
  default: undefined,
11255
- required: false,
11256
11241
  validator: (value) => {
11257
11242
  return ['sm', 'lg', 'xl'].includes(value);
11258
11243
  },
@@ -11263,7 +11248,6 @@ const CModal = vue.defineComponent({
11263
11248
  transition: {
11264
11249
  type: Boolean,
11265
11250
  default: true,
11266
- required: false,
11267
11251
  },
11268
11252
  /**
11269
11253
  * By default the component is unmounted after close animation, if you want to keep the component mounted set this property to false.
@@ -11271,7 +11255,6 @@ const CModal = vue.defineComponent({
11271
11255
  unmountOnClose: {
11272
11256
  type: Boolean,
11273
11257
  default: true,
11274
- required: false,
11275
11258
  },
11276
11259
  /**
11277
11260
  * Toggle the visibility of alert component.
@@ -11519,6 +11502,159 @@ const CMultiSelectNativeSelect = vue.defineComponent({
11519
11502
  },
11520
11503
  });
11521
11504
 
11505
+ const CVirtualScroller = vue.defineComponent({
11506
+ name: 'CVirtualScroller',
11507
+ props: {
11508
+ /**
11509
+ * Amount of visible items
11510
+ */
11511
+ visibleItems: {
11512
+ type: Number,
11513
+ default: 10,
11514
+ },
11515
+ },
11516
+ setup(props, { slots }) {
11517
+ const virtualScrollRef = vue.ref();
11518
+ const virtualScrollContentRef = vue.ref();
11519
+ const currentItemIndex = vue.ref(1);
11520
+ const itemHeight = vue.ref(0);
11521
+ const itemsNumber = vue.ref(0);
11522
+ const viewportPadding = vue.ref(0);
11523
+ const buffer = vue.computed(() => Math.floor(props.visibleItems / 2));
11524
+ const maxHeight = vue.computed(() => itemsNumber.value * itemHeight.value + 2 * viewportPadding.value);
11525
+ const viewportHeight = vue.computed(() => props.visibleItems * itemHeight.value + 2 * viewportPadding.value);
11526
+ vue.onMounted(() => {
11527
+ if (virtualScrollRef.value) {
11528
+ viewportPadding.value = parseFloat(getComputedStyle(virtualScrollRef.value).paddingTop);
11529
+ // It's necessary to calculate heights of items
11530
+ virtualScrollRef.value.dispatchEvent(new CustomEvent('scroll'));
11531
+ }
11532
+ });
11533
+ const handleScroll = (scrollTop) => {
11534
+ currentItemIndex.value =
11535
+ itemHeight.value && Math.max(Math.ceil(scrollTop / itemHeight.value), 1);
11536
+ };
11537
+ return () => {
11538
+ const children = slots.default
11539
+ ? Array.isArray(slots.default()[0].children)
11540
+ ? slots.default()[0].children
11541
+ : slots.default()
11542
+ : [];
11543
+ itemsNumber.value = children && children.length ? children.length : 0;
11544
+ return vue.h('div', {
11545
+ class: ['virtual-scroller'],
11546
+ onScroll: (event) => handleScroll(event.target.scrollTop),
11547
+ style: {
11548
+ height: `${maxHeight.value > viewportHeight.value ? viewportHeight.value : maxHeight.value}px`,
11549
+ overflowY: 'auto',
11550
+ },
11551
+ ref: virtualScrollRef,
11552
+ }, vue.h('div', {
11553
+ class: 'virtual-scroller-content',
11554
+ style: {
11555
+ height: `${maxHeight.value}px`,
11556
+ },
11557
+ ref: virtualScrollContentRef,
11558
+ }, children.map((slot, index) => index + 1 > Math.max(currentItemIndex.value - buffer.value, 0) &&
11559
+ index + 1 <= currentItemIndex.value + props.visibleItems + buffer.value &&
11560
+ vue.cloneVNode(slot, {
11561
+ class: [
11562
+ {
11563
+ 'virtual-scroller-item-preload': index + 1 > currentItemIndex.value + props.visibleItems ||
11564
+ index + 1 < currentItemIndex.value,
11565
+ },
11566
+ ],
11567
+ style: {
11568
+ ...(currentItemIndex.value > buffer.value && {
11569
+ transform: `translateY(${(currentItemIndex.value - buffer.value) * itemHeight.value}px)`,
11570
+ }),
11571
+ },
11572
+ ref: (node) => {
11573
+ if (node && node.offsetHeight) {
11574
+ itemHeight.value =
11575
+ node.offsetHeight +
11576
+ parseFloat(getComputedStyle(node).marginTop) +
11577
+ parseFloat(getComputedStyle(node).marginBottom);
11578
+ }
11579
+ },
11580
+ }))));
11581
+ };
11582
+ },
11583
+ });
11584
+
11585
+ const CVirtualScrollerPlugin = {
11586
+ install: (app) => {
11587
+ app.component(CVirtualScroller.name, CVirtualScroller);
11588
+ },
11589
+ };
11590
+
11591
+ const filterOptionsList = (search, _options) => {
11592
+ return search.length
11593
+ ? _options &&
11594
+ _options.reduce((acc, val) => {
11595
+ const options = val.options &&
11596
+ val.options.filter((element) => element.text && element.text.toLowerCase().includes(search.toLowerCase()));
11597
+ if ((val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
11598
+ (options && options.length)) {
11599
+ acc.push(Object.assign({}, val, options && options.length && { options }));
11600
+ }
11601
+ return acc;
11602
+ }, [])
11603
+ : _options;
11604
+ };
11605
+ const flattenArray = (options) => {
11606
+ return options.reduce((acc, val) => {
11607
+ return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
11608
+ }, []);
11609
+ };
11610
+ const getNextSibling = (elem, selector) => {
11611
+ // Get the next sibling element
11612
+ let sibling = elem.nextElementSibling;
11613
+ // If there's no selector, return the first sibling
11614
+ if (!selector)
11615
+ return sibling;
11616
+ // If the sibling matches our selector, use it
11617
+ // If not, jump to the next sibling and continue the loop
11618
+ while (sibling) {
11619
+ if (sibling.matches(selector))
11620
+ return sibling;
11621
+ sibling = sibling.nextElementSibling;
11622
+ }
11623
+ return;
11624
+ };
11625
+ const getPreviousSibling = (elem, selector) => {
11626
+ // Get the next sibling element
11627
+ let sibling = elem.previousElementSibling;
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.previousElementSibling;
11637
+ }
11638
+ return;
11639
+ };
11640
+ const selectOptions = (options, selected, deselected) => {
11641
+ let _selected = [...selected, ...options];
11642
+ if (deselected) {
11643
+ _selected = _selected.filter((selectedOption) => !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value));
11644
+ }
11645
+ const deduplicated = _selected.reduce((unique, option) => {
11646
+ if (!unique.some((obj) => obj.value === option.value)) {
11647
+ unique.push({
11648
+ value: option.value,
11649
+ text: option.text,
11650
+ ...(option.disabled && { disabled: option.disabled }),
11651
+ });
11652
+ }
11653
+ return unique;
11654
+ }, []);
11655
+ return deduplicated;
11656
+ };
11657
+
11522
11658
  const CMultiSelectOptions = vue.defineComponent({
11523
11659
  name: 'CMultiSelectOptions',
11524
11660
  props: {
@@ -11528,7 +11664,6 @@ const CMultiSelectOptions = vue.defineComponent({
11528
11664
  options: {
11529
11665
  type: Array,
11530
11666
  default: () => [],
11531
- required: false,
11532
11667
  },
11533
11668
  /**
11534
11669
  * Sets maxHeight of options list.
@@ -11538,7 +11673,6 @@ const CMultiSelectOptions = vue.defineComponent({
11538
11673
  optionsMaxHeight: {
11539
11674
  type: [Number, String],
11540
11675
  default: 'auto',
11541
- required: false,
11542
11676
  },
11543
11677
  /**
11544
11678
  * Sets option style.
@@ -11549,7 +11683,6 @@ const CMultiSelectOptions = vue.defineComponent({
11549
11683
  optionsStyle: {
11550
11684
  type: String,
11551
11685
  default: 'checkbox',
11552
- required: false,
11553
11686
  validator: (value) => {
11554
11687
  return ['checkbox', 'text'].includes(value);
11555
11688
  },
@@ -11560,12 +11693,15 @@ const CMultiSelectOptions = vue.defineComponent({
11560
11693
  searchNoResultsLabel: {
11561
11694
  type: String,
11562
11695
  default: 'no items',
11563
- required: false,
11564
11696
  },
11565
11697
  selected: {
11566
11698
  type: Array,
11567
11699
  default: () => [],
11568
- required: false,
11700
+ },
11701
+ virtualScroller: Boolean,
11702
+ visibleItems: {
11703
+ type: Number,
11704
+ default: 10,
11569
11705
  },
11570
11706
  },
11571
11707
  emits: ['optionClick'],
@@ -11617,12 +11753,19 @@ const CMultiSelectOptions = vue.defineComponent({
11617
11753
  tabindex: 0,
11618
11754
  }, option.text))
11619
11755
  : vue.h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel);
11620
- return () => vue.h('div', {
11621
- class: 'form-multi-select-options',
11622
- ...(props.optionsMaxHeight !== 'auto' && {
11623
- style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
11624
- }),
11625
- }, createOptions(props.options));
11756
+ return () => props.virtualScroller
11757
+ ? vue.h(CVirtualScroller, {
11758
+ class: 'form-multi-select-options',
11759
+ visibleItems: props.visibleItems,
11760
+ }, {
11761
+ default: () => createOptions(props.options),
11762
+ })
11763
+ : vue.h('div', {
11764
+ class: 'form-multi-select-options',
11765
+ ...(props.optionsMaxHeight !== 'auto' && {
11766
+ style: { maxHeight: props.optionsMaxHeight, overflow: 'scroll' },
11767
+ }),
11768
+ }, createOptions(props.options));
11626
11769
  },
11627
11770
  });
11628
11771
 
@@ -11713,11 +11856,6 @@ const CMultiSelectSelection = vue.defineComponent({
11713
11856
  },
11714
11857
  });
11715
11858
 
11716
- const flattenArray = (options) => {
11717
- return options.reduce((acc, val) => {
11718
- return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
11719
- }, []);
11720
- };
11721
11859
  const CMultiSelect = vue.defineComponent({
11722
11860
  name: 'CMultiSelect',
11723
11861
  props: {
@@ -11728,7 +11866,6 @@ const CMultiSelect = vue.defineComponent({
11728
11866
  */
11729
11867
  cleaner: {
11730
11868
  type: Boolean,
11731
- required: false,
11732
11869
  default: true,
11733
11870
  },
11734
11871
  /**
@@ -11736,7 +11873,6 @@ const CMultiSelect = vue.defineComponent({
11736
11873
  */
11737
11874
  disabled: {
11738
11875
  type: Boolean,
11739
- required: false,
11740
11876
  default: false,
11741
11877
  },
11742
11878
  /**
@@ -11791,7 +11927,6 @@ const CMultiSelect = vue.defineComponent({
11791
11927
  multiple: {
11792
11928
  type: Boolean,
11793
11929
  default: true,
11794
- required: false,
11795
11930
  },
11796
11931
  /**
11797
11932
  * List of option elements.
@@ -11799,7 +11934,6 @@ const CMultiSelect = vue.defineComponent({
11799
11934
  options: {
11800
11935
  type: Array,
11801
11936
  default: () => [],
11802
- required: false,
11803
11937
  },
11804
11938
  /**
11805
11939
  * Sets maxHeight of options list.
@@ -11809,7 +11943,6 @@ const CMultiSelect = vue.defineComponent({
11809
11943
  optionsMaxHeight: {
11810
11944
  type: [Number, String],
11811
11945
  default: 'auto',
11812
- required: false,
11813
11946
  },
11814
11947
  /**
11815
11948
  * Sets option style.
@@ -11820,7 +11953,6 @@ const CMultiSelect = vue.defineComponent({
11820
11953
  optionsStyle: {
11821
11954
  type: String,
11822
11955
  default: 'checkbox',
11823
- required: false,
11824
11956
  validator: (value) => {
11825
11957
  return ['checkbox', 'text'].includes(value);
11826
11958
  },
@@ -11833,7 +11965,6 @@ const CMultiSelect = vue.defineComponent({
11833
11965
  placeholder: {
11834
11966
  type: String,
11835
11967
  default: 'Select...',
11836
- required: false,
11837
11968
  },
11838
11969
  /**
11839
11970
  * Enables search input element.
@@ -11841,7 +11972,6 @@ const CMultiSelect = vue.defineComponent({
11841
11972
  search: {
11842
11973
  type: [Boolean, String],
11843
11974
  default: true,
11844
- required: false,
11845
11975
  validator: (value) => {
11846
11976
  if (typeof value == 'string') {
11847
11977
  return ['external'].includes(value);
@@ -11858,7 +11988,6 @@ const CMultiSelect = vue.defineComponent({
11858
11988
  searchNoResultsLabel: {
11859
11989
  type: String,
11860
11990
  default: 'no items',
11861
- required: false,
11862
11991
  },
11863
11992
  /**
11864
11993
  * Enables select all button.
@@ -11867,7 +11996,6 @@ const CMultiSelect = vue.defineComponent({
11867
11996
  */
11868
11997
  selectAll: {
11869
11998
  type: Boolean,
11870
- required: false,
11871
11999
  default: true,
11872
12000
  },
11873
12001
  /**
@@ -11877,7 +12005,6 @@ const CMultiSelect = vue.defineComponent({
11877
12005
  */
11878
12006
  selectAllLabel: {
11879
12007
  type: String,
11880
- required: false,
11881
12008
  default: 'Select all options',
11882
12009
  },
11883
12010
  /**
@@ -11889,7 +12016,6 @@ const CMultiSelect = vue.defineComponent({
11889
12016
  selectionType: {
11890
12017
  type: String,
11891
12018
  default: 'tags',
11892
- required: false,
11893
12019
  validator: (value) => {
11894
12020
  return ['counter', 'tags', 'text'].includes(value);
11895
12021
  },
@@ -11902,7 +12028,6 @@ const CMultiSelect = vue.defineComponent({
11902
12028
  selectionTypeCounterText: {
11903
12029
  type: String,
11904
12030
  default: 'item(s) selected',
11905
- required: false,
11906
12031
  },
11907
12032
  /**
11908
12033
  * Size the component small or large.
@@ -11911,7 +12036,6 @@ const CMultiSelect = vue.defineComponent({
11911
12036
  */
11912
12037
  size: {
11913
12038
  type: String,
11914
- required: false,
11915
12039
  validator: (value) => {
11916
12040
  return ['sm', 'lg'].includes(value);
11917
12041
  },
@@ -11936,6 +12060,12 @@ const CMultiSelect = vue.defineComponent({
11936
12060
  * @since 4.6.0
11937
12061
  */
11938
12062
  valid: Boolean,
12063
+ /**
12064
+ * Enable virtual scroller for the options list.
12065
+ *
12066
+ * @since 4.8.0
12067
+ */
12068
+ virtualScroller: Boolean,
11939
12069
  /**
11940
12070
  * Toggle the visibility of multi select dropdown.
11941
12071
  *
@@ -11944,7 +12074,16 @@ const CMultiSelect = vue.defineComponent({
11944
12074
  visible: {
11945
12075
  type: Boolean,
11946
12076
  default: false,
11947
- required: false,
12077
+ },
12078
+ /**
12079
+ *
12080
+ * Amount of visible items when virtualScroller is set to `true`.
12081
+ *
12082
+ * @since 4.8.0
12083
+ */
12084
+ visibleItems: {
12085
+ type: Number,
12086
+ default: 10,
11948
12087
  },
11949
12088
  },
11950
12089
  emits: [
@@ -11961,29 +12100,12 @@ const CMultiSelect = vue.defineComponent({
11961
12100
  ],
11962
12101
  setup(props, { attrs, emit }) {
11963
12102
  const nativeSelectRef = vue.ref();
11964
- vue.provide('nativeSelectRef', nativeSelectRef);
11965
- const searchRef = vue.ref();
11966
12103
  const options = vue.ref(props.options);
11967
12104
  const search = vue.ref('');
12105
+ const searchRef = vue.ref();
11968
12106
  const selected = vue.ref([]);
11969
12107
  const visible = vue.ref(props.visible);
11970
- const selectOptions = (options, deselected) => {
11971
- let _selected = [...selected.value, ...options];
11972
- if (deselected) {
11973
- _selected = _selected.filter((selectedOption) => !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value));
11974
- }
11975
- const deduplicated = _selected.reduce((unique, option) => {
11976
- if (!unique.some((obj) => obj.value === option.value)) {
11977
- unique.push({
11978
- value: option.value,
11979
- text: option.text,
11980
- ...(option.disabled && { disabled: option.disabled }),
11981
- });
11982
- }
11983
- return unique;
11984
- }, []);
11985
- selected.value = deduplicated;
11986
- };
12108
+ vue.provide('nativeSelectRef', nativeSelectRef);
11987
12109
  vue.watch(() => props.options, (newValue, oldValue) => {
11988
12110
  if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
11989
12111
  options.value = newValue;
@@ -12001,34 +12123,15 @@ const CMultiSelect = vue.defineComponent({
12001
12123
  }
12002
12124
  return;
12003
12125
  });
12004
- _selected && selectOptions(_selected, deselected);
12126
+ if (_selected) {
12127
+ selected.value = selectOptions(_selected, selected.value, deselected);
12128
+ }
12005
12129
  }
12006
- });
12130
+ }, { immediate: true });
12007
12131
  vue.watch(selected, () => {
12008
12132
  nativeSelectRef.value &&
12009
12133
  nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }));
12010
12134
  });
12011
- const filterOptionsList = (search, _options) => {
12012
- return search.length
12013
- ? _options &&
12014
- _options.reduce((acc, val) => {
12015
- const options = val.options &&
12016
- val.options.filter((element) => element.text && element.text.toLowerCase().includes(search.toLowerCase()));
12017
- if ((val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
12018
- (options && options.length)) {
12019
- acc.push(Object.assign({}, val, options && options.length && { options }));
12020
- }
12021
- return acc;
12022
- }, [])
12023
- : options.value;
12024
- };
12025
- // watch(
12026
- // () => props.options,
12027
- // (newValue, oldValue) => {
12028
- // console.log(props.options)
12029
- // if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) options.value = newValue
12030
- // },
12031
- // )
12032
12135
  const handleSearchChange = (event) => {
12033
12136
  const target = event.target;
12034
12137
  search.value = target.value.toLowerCase();
@@ -12066,7 +12169,7 @@ const CMultiSelect = vue.defineComponent({
12066
12169
  }
12067
12170
  };
12068
12171
  const handleSelectAll = () => {
12069
- selectOptions(flattenArray(options.value).filter((option) => !option.disabled));
12172
+ selected.value = selectOptions(flattenArray(options.value).filter((option) => !option.disabled), selected.value);
12070
12173
  };
12071
12174
  const handleDeselectAll = () => {
12072
12175
  selected.value = selected.value.filter((option) => option.disabled);
@@ -12157,7 +12260,7 @@ const CMultiSelect = vue.defineComponent({
12157
12260
  ref: searchRef,
12158
12261
  }),
12159
12262
  ]),
12160
- default: () => vue.h('div', {}, [
12263
+ default: () => visible.value && [
12161
12264
  props.multiple &&
12162
12265
  props.selectAll &&
12163
12266
  vue.h('button', {
@@ -12173,9 +12276,11 @@ const CMultiSelect = vue.defineComponent({
12173
12276
  optionsMaxHeight: props.optionsMaxHeight,
12174
12277
  optionsStyle: props.optionsStyle,
12175
12278
  searchNoResultsLabel: props.searchNoResultsLabel,
12176
- selected: selected.value
12279
+ selected: selected.value,
12280
+ virtualScroller: props.virtualScroller,
12281
+ visibleItems: props.visibleItems,
12177
12282
  }),
12178
- ]),
12283
+ ],
12179
12284
  }),
12180
12285
  }),
12181
12286
  ];
@@ -12613,11 +12718,21 @@ const COffcanvas = vue.defineComponent({
12613
12718
  props: {
12614
12719
  /**
12615
12720
  * Apply a backdrop on body while offcanvas is open.
12721
+ *
12722
+ * @values boolean | 'static'
12616
12723
  */
12617
12724
  backdrop: {
12618
- type: Boolean,
12725
+ type: [Boolean, String],
12619
12726
  default: true,
12620
- require: false,
12727
+ validator: (value) => {
12728
+ if (typeof value === 'string') {
12729
+ return ['static'].includes(value);
12730
+ }
12731
+ if (typeof value === 'boolean') {
12732
+ return true;
12733
+ }
12734
+ return false;
12735
+ },
12621
12736
  },
12622
12737
  /**
12623
12738
  * Closes the offcanvas when escape key is pressed.
@@ -12625,7 +12740,6 @@ const COffcanvas = vue.defineComponent({
12625
12740
  keyboard: {
12626
12741
  type: Boolean,
12627
12742
  default: true,
12628
- require: false,
12629
12743
  },
12630
12744
  /**
12631
12745
  * Components placement, there’s no default placement.
@@ -12640,21 +12754,36 @@ const COffcanvas = vue.defineComponent({
12640
12754
  return ['start', 'end', 'top', 'bottom'].includes(value);
12641
12755
  },
12642
12756
  },
12757
+ /**
12758
+ * Responsive offcanvas property hide content outside the viewport from a specified breakpoint and down.
12759
+ *
12760
+ * @values boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'
12761
+ * @since 4.7.0
12762
+ */
12763
+ responsive: {
12764
+ type: [Boolean, String],
12765
+ default: true,
12766
+ validator: (value) => {
12767
+ if (typeof value === 'string') {
12768
+ return ['sm', 'md', 'lg', 'xl', 'xxl'].includes(value);
12769
+ }
12770
+ if (typeof value === 'boolean') {
12771
+ return true;
12772
+ }
12773
+ return false;
12774
+ },
12775
+ },
12643
12776
  /**
12644
12777
  * Allow body scrolling while offcanvas is open
12645
12778
  */
12646
12779
  scroll: {
12647
12780
  type: Boolean,
12648
12781
  default: false,
12649
- required: false,
12650
12782
  },
12651
12783
  /**
12652
12784
  * Toggle the visibility of offcanvas component.
12653
12785
  */
12654
- visible: {
12655
- type: Boolean,
12656
- require: false,
12657
- },
12786
+ visible: Boolean,
12658
12787
  },
12659
12788
  emits: [
12660
12789
  /**
@@ -12689,40 +12818,31 @@ const COffcanvas = vue.defineComponent({
12689
12818
  emit('show');
12690
12819
  executeAfterTransition(() => done(), el);
12691
12820
  setTimeout(() => {
12692
- el.style.visibility = 'visible';
12693
12821
  el.classList.add('show');
12694
12822
  }, 1);
12695
12823
  };
12696
12824
  const handleAfterEnter = () => {
12697
- window.addEventListener('mousedown', handleMouseDown);
12698
- window.addEventListener('keyup', handleKeyUp);
12825
+ offcanvasRef.value.focus();
12699
12826
  };
12700
12827
  const handleLeave = (el, done) => {
12701
12828
  executeAfterTransition(() => done(), el);
12702
- window.removeEventListener('mousedown', handleMouseDown);
12703
- window.removeEventListener('keyup', handleKeyUp);
12704
- el.classList.remove('show');
12829
+ el.classList.add('hiding');
12705
12830
  };
12706
12831
  const handleAfterLeave = (el) => {
12707
- el.style.visibility = 'hidden';
12832
+ el.classList.remove('show', 'hiding');
12708
12833
  };
12709
12834
  const handleDismiss = () => {
12710
12835
  visible.value = false;
12711
12836
  emit('hide');
12712
12837
  };
12713
- const handleKeyUp = (event) => {
12714
- if (offcanvasRef.value && !offcanvasRef.value.contains(event.target)) {
12715
- if (event.key === 'Escape' && props.keyboard && props.backdrop) {
12716
- return handleDismiss();
12717
- }
12838
+ const handleBackdropDismiss = () => {
12839
+ if (props.backdrop !== 'static') {
12840
+ handleDismiss();
12718
12841
  }
12719
12842
  };
12720
- const handleMouseDown = (event) => {
12721
- window.addEventListener('mouseup', () => handleMouseUp(event), { once: true });
12722
- };
12723
- const handleMouseUp = (event) => {
12724
- if (offcanvasRef.value && !offcanvasRef.value.contains(event.target)) {
12725
- props.backdrop && handleDismiss();
12843
+ const handleKeyDown = (event) => {
12844
+ if (event.key === 'Escape' && props.keyboard) {
12845
+ handleDismiss();
12726
12846
  }
12727
12847
  };
12728
12848
  return () => [
@@ -12734,17 +12854,20 @@ const COffcanvas = vue.defineComponent({
12734
12854
  onAfterLeave: (el) => handleAfterLeave(el),
12735
12855
  }, () => vue.withDirectives(vue.h('div', {
12736
12856
  class: [
12737
- 'offcanvas',
12738
12857
  {
12858
+ [`offcanvas${typeof props.responsive !== 'boolean' ? '-' + props.responsive : ''}`]: props.responsive,
12739
12859
  [`offcanvas-${props.placement}`]: props.placement,
12740
12860
  },
12741
12861
  ],
12862
+ onKeydown: (event) => handleKeyDown(event),
12742
12863
  ref: offcanvasRef,
12743
12864
  role: 'dialog',
12865
+ tabindex: -1,
12744
12866
  }, slots.default && slots.default()), [[vVisible, props.visible]])),
12745
12867
  props.backdrop &&
12746
12868
  vue.h(CBackdrop, {
12747
12869
  class: 'offcanvas-backdrop',
12870
+ onClick: handleBackdropDismiss,
12748
12871
  visible: visible.value,
12749
12872
  }),
12750
12873
  ];
@@ -13834,6 +13957,140 @@ const CSmartPaginationPlugin = {
13834
13957
  },
13835
13958
  };
13836
13959
 
13960
+ var cilArrowBottom = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='367.997 338.75 271.999 434.747 271.999 17.503 239.999 17.503 239.999 434.745 144.003 338.75 121.376 361.377 256 496 390.624 361.377 367.997 338.75' class='ci-primary'/>"];
13961
+
13962
+ var cilArrowTop = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='390.624 150.625 256 16 121.376 150.625 144.004 173.252 240.001 77.254 240.001 495.236 272.001 495.236 272.001 77.257 367.996 173.252 390.624 150.625' class='ci-primary'/>"];
13963
+
13964
+ var cilFilterX = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='40 16 40 53.828 109.024 136 150.815 136 76.896 48 459.51 48 304 242.388 304 401.373 241.373 464 240 464 240 368 208 368 208 496 254.627 496 336 414.627 336 253.612 496 53.612 496 16 40 16' class='ci-primary'/><polygon fill='var(--ci-primary-color, currentColor)' points='166.403 248.225 226.864 187.763 204.237 165.135 143.775 225.597 83.313 165.135 60.687 187.763 121.148 248.225 60.687 308.687 83.313 331.314 143.775 270.852 204.237 331.314 226.864 308.687 166.403 248.225' class='ci-primary'/>"];
13965
+
13966
+ var cilSwapVertical = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='384 433.373 384 160 352 160 352 434.51 282.177 364.687 259.55 387.313 367.432 495.196 475.313 387.313 452.687 364.687 384 433.373' class='ci-primary'/><polygon fill='var(--ci-primary-color, currentColor)' points='159.432 17.372 51.55 125.255 74.177 147.882 144 78.059 144 352 176 352 176 79.195 244.687 147.882 267.313 125.255 159.432 17.372' class='ci-primary'/>"];
13967
+
13968
+ const CIcon = vue.defineComponent({
13969
+ name: 'CIcon',
13970
+ props: {
13971
+ /**
13972
+ * Use `:icon="..."` instead of
13973
+ *
13974
+ * @deprecated since version 3.0
13975
+ */
13976
+ content: {
13977
+ type: [String, Array],
13978
+ default: undefined,
13979
+ required: false,
13980
+ },
13981
+ /**
13982
+ * Use for replacing default CIcon component classes. Prop is overriding the 'size' prop.
13983
+ */
13984
+ customClassName: {
13985
+ type: [String, Array, Object],
13986
+ default: undefined,
13987
+ required: false,
13988
+ },
13989
+ /**
13990
+ * Name of the icon placed in React object or SVG content.
13991
+ */
13992
+ icon: {
13993
+ type: [String, Array],
13994
+ default: undefined,
13995
+ required: false,
13996
+ },
13997
+ /**
13998
+ * Use `icon="..."` instead of
13999
+ *
14000
+ * @deprecated since version 3.0
14001
+ */
14002
+ name: {
14003
+ type: String,
14004
+ default: undefined,
14005
+ required: false,
14006
+ },
14007
+ /**
14008
+ * Size of the icon. Available sizes: 'sm', 'lg', 'xl', 'xxl', '3xl...9xl', 'custom', 'custom-size'.
14009
+ */
14010
+ size: {
14011
+ type: String,
14012
+ default: undefined,
14013
+ required: false,
14014
+ validator: (value) => {
14015
+ return [
14016
+ 'custom',
14017
+ 'custom-size',
14018
+ 'sm',
14019
+ 'lg',
14020
+ 'xl',
14021
+ 'xxl',
14022
+ '3xl',
14023
+ '4xl',
14024
+ '5xl',
14025
+ '6xl',
14026
+ '7xl',
14027
+ '8xl',
14028
+ '9xl',
14029
+ ].includes(value);
14030
+ },
14031
+ },
14032
+ /**
14033
+ * Title tag content.
14034
+ */
14035
+ title: {
14036
+ type: String,
14037
+ default: undefined,
14038
+ required: false,
14039
+ },
14040
+ /**
14041
+ * If defined component will be rendered using 'use' tag.
14042
+ */
14043
+ use: {
14044
+ type: String,
14045
+ default: undefined,
14046
+ required: false,
14047
+ },
14048
+ },
14049
+ setup(props, { attrs }) {
14050
+ const icons = vue.inject('icons');
14051
+ const _icon = props.icon || props.content || props.name;
14052
+ const toCamelCase = (str) => {
14053
+ return str
14054
+ .replace(/([-_][a-z0-9])/gi, ($1) => {
14055
+ return $1.toUpperCase();
14056
+ })
14057
+ .replace(/-/gi, '');
14058
+ };
14059
+ const iconName = vue.computed(() => _icon && typeof _icon === 'string' ? (_icon.includes('-') ? toCamelCase(_icon) : _icon) : '');
14060
+ const titleCode = props.title ? `<title>${props.title}</title>` : 'undefined';
14061
+ const code = vue.computed(() => Array.isArray(_icon)
14062
+ ? _icon
14063
+ : typeof _icon === 'string' && iconName.value && icons[iconName.value]
14064
+ ? icons[iconName.value]
14065
+ : 'undefined');
14066
+ const iconCode = Array.isArray(code.value) ? code.value[1] || code.value[0] : code.value;
14067
+ const scale = Array.isArray(code.value) && code.value.length > 1 ? code.value[0] : '64 64';
14068
+ const viewBox = attrs.viewBox || `0 0 ${scale}`;
14069
+ const size = () => {
14070
+ const addCustom = !props.size && (attrs.width || attrs.height);
14071
+ return props.size === 'custom' || addCustom ? 'custom-size' : props.size;
14072
+ };
14073
+ const classNames = (() => {
14074
+ return [props.customClassName || ['icon', { [`icon-${size()}`]: size() }], attrs.class];
14075
+ })();
14076
+ return () => props.use
14077
+ ? vue.h('svg', {
14078
+ ...attrs,
14079
+ xmlns: 'http://www.w3.org/2000/svg',
14080
+ class: classNames,
14081
+ role: 'img',
14082
+ }, vue.h('use', { href: props.use }))
14083
+ : vue.h('svg', {
14084
+ ...attrs,
14085
+ xmlns: 'http://www.w3.org/2000/svg',
14086
+ class: classNames,
14087
+ viewBox: viewBox,
14088
+ innerHTML: `${titleCode}${iconCode}`,
14089
+ role: 'img',
14090
+ });
14091
+ },
14092
+ });
14093
+
13837
14094
  const CTableBody = vue.defineComponent({
13838
14095
  name: 'CTableBody',
13839
14096
  props: {
@@ -14019,7 +14276,7 @@ const CTableRow = vue.defineComponent({
14019
14276
  },
14020
14277
  });
14021
14278
 
14022
- const pretifyName = (name) => {
14279
+ const pretifyName$1 = (name) => {
14023
14280
  return name
14024
14281
  .replace(/[-_.]/g, ' ')
14025
14282
  .replace(/ +/g, ' ')
@@ -14031,8 +14288,8 @@ const pretifyName = (name) => {
14031
14288
  const label = (column) => typeof column === 'object'
14032
14289
  ? column.label !== undefined
14033
14290
  ? column.label
14034
- : pretifyName(column.key)
14035
- : pretifyName(column);
14291
+ : pretifyName$1(column.key)
14292
+ : pretifyName$1(column);
14036
14293
  const CTable = vue.defineComponent({
14037
14294
  name: 'CTable',
14038
14295
  props: {
@@ -14322,120 +14579,244 @@ const CTablePlugin = {
14322
14579
  },
14323
14580
  };
14324
14581
 
14582
+ const filterColumns = (items, columnFilter, columnFilterState, itemsDataColumns) => {
14583
+ if (columnFilter && typeof columnFilter === 'object' && columnFilter.external) {
14584
+ return items;
14585
+ }
14586
+ Object.entries(columnFilterState).forEach(([key, value]) => {
14587
+ if (value instanceof Function) {
14588
+ items = items.filter((item) => value(item[key]));
14589
+ return;
14590
+ }
14591
+ const columnFilter = String(value).toLowerCase();
14592
+ if (columnFilter && itemsDataColumns.includes(key)) {
14593
+ items = items.filter((item) => {
14594
+ return String(item[key]).toLowerCase().includes(columnFilter);
14595
+ });
14596
+ }
14597
+ });
14598
+ return items;
14599
+ };
14600
+ const filterTable = (items, tableFilter, tableFilterState, itemsDataColumns) => {
14601
+ if (!tableFilterState ||
14602
+ (tableFilter && typeof tableFilter === 'object' && tableFilter.external)) {
14603
+ return items;
14604
+ }
14605
+ const filter = tableFilterState.toLowerCase();
14606
+ const valueContainFilter = (val) => String(val).toLowerCase().includes(filter);
14607
+ items = items.filter((item) => {
14608
+ return !!itemsDataColumns.find((key) => valueContainFilter(item[key]));
14609
+ });
14610
+ return items;
14611
+ };
14612
+ const getClickedColumnName = (target, columnNames) => {
14613
+ const closest = target.closest('tr');
14614
+ const children = closest ? Array.from(closest.children) : [];
14615
+ const clickedCell = children.filter((child) => child.contains(target))[0];
14616
+ return columnNames[children.indexOf(clickedCell)];
14617
+ };
14618
+ const getColumnKey = (column) => typeof column === 'object' ? column.key : column;
14619
+ const getColumnLabel = (column) => typeof column === 'object'
14620
+ ? column.label !== undefined
14621
+ ? column.label
14622
+ : pretifyName(column.key)
14623
+ : pretifyName(column);
14624
+ const getColumnNames = (columns, items) => columns
14625
+ ? columns.map((column) => {
14626
+ if (typeof column === 'object')
14627
+ return column.key;
14628
+ else
14629
+ return column;
14630
+ })
14631
+ : getColumnNamesFromItems(items);
14632
+ const getColumnNamesFromItems = (items) => Object.keys(items[0] || {}).filter((el) => el.charAt(0) !== '_');
14633
+ const getColumnSorterState = (key, sorterState) => {
14634
+ if (sorterState && sorterState.column === key) {
14635
+ if (sorterState.state) {
14636
+ return sorterState.state;
14637
+ }
14638
+ return 0;
14639
+ }
14640
+ return 0;
14641
+ };
14642
+ const getColumnValues = (items, key) => {
14643
+ return items.map((item) => item[key]);
14644
+ };
14645
+ const getTableDataCellProps = (item, colName) => {
14646
+ const props = item._cellProps && {
14647
+ ...(item._cellProps['all'] && { ...item._cellProps['all'] }),
14648
+ ...(item._cellProps[colName] && { ...item._cellProps[colName] }),
14649
+ };
14650
+ return props;
14651
+ };
14652
+ const getTableHeaderCellProps = (column) => {
14653
+ if (typeof column === 'object' && column._props) {
14654
+ return column._props;
14655
+ }
14656
+ return {};
14657
+ };
14658
+ const getTableHeaderCellStyles = (column, columnSorter) => {
14659
+ const style = {};
14660
+ if (columnSorter &&
14661
+ (typeof column !== 'object' ||
14662
+ (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter)))) {
14663
+ style['cursor'] = 'pointer';
14664
+ }
14665
+ if (typeof column === 'object' && column._style) {
14666
+ return { ...style, ...column._style };
14667
+ }
14668
+ return style;
14669
+ };
14670
+ const isObjectInArray = (array, item, ignore = []) => array.some((_item) => {
14671
+ let result = true;
14672
+ for (const key in item) {
14673
+ if (!ignore.includes(key) && item[key] !== _item[key]) {
14674
+ result = false;
14675
+ break;
14676
+ }
14677
+ }
14678
+ return result;
14679
+ });
14680
+ const isSortable = (i, columns, columnSorter, itemsDataColumns, columnNames) => {
14681
+ const isDataColumn = itemsDataColumns.includes(columnNames[i]);
14682
+ let column;
14683
+ if (columns)
14684
+ column = columns[i];
14685
+ return (columnSorter &&
14686
+ (!columns ||
14687
+ typeof column !== 'object' ||
14688
+ (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter))) &&
14689
+ isDataColumn);
14690
+ };
14691
+ const pretifyName = (name) => {
14692
+ return name
14693
+ .replace(/[-_.]/g, ' ')
14694
+ .replace(/ +/g, ' ')
14695
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
14696
+ .split(' ')
14697
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
14698
+ .join(' ');
14699
+ };
14700
+ const sortItems = (columnSorter, items, itemsDataColumns, sorterState) => {
14701
+ const column = sorterState.column;
14702
+ if (!column ||
14703
+ !itemsDataColumns.includes(column) ||
14704
+ (columnSorter && typeof columnSorter === 'object' && columnSorter.external)) {
14705
+ return items;
14706
+ }
14707
+ const flip = sorterState.state === 'asc' ? 1 : sorterState.state === 'desc' ? -1 : 0;
14708
+ const sorted = items.slice().sort((item, item2) => {
14709
+ const value = item[column];
14710
+ const value2 = item2[column];
14711
+ const a = typeof value === 'number' ? value : String(value).toLowerCase();
14712
+ const b = typeof value2 === 'number' ? value2 : String(value2).toLowerCase();
14713
+ return a > b ? 1 * flip : b > a ? -1 * flip : 0;
14714
+ });
14715
+ return sorted;
14716
+ };
14717
+
14325
14718
  const CSmartTableBody = vue.defineComponent({
14326
14719
  name: 'CSmartTableBody',
14327
14720
  props: {
14328
- clickableRows: {
14329
- type: Boolean,
14330
- require: false,
14721
+ clickableRows: Boolean,
14722
+ columnNames: {
14723
+ type: Array,
14724
+ default: () => [],
14725
+ require: true,
14331
14726
  },
14332
14727
  currentItems: {
14333
14728
  type: Array,
14334
14729
  default: () => [],
14335
- required: false,
14336
14730
  },
14337
14731
  firstItemOnActivePageIndex: {
14338
14732
  type: Number,
14339
14733
  require: true,
14340
14734
  default: 0,
14341
14735
  },
14342
- noItemLabel: {
14343
- type: String,
14344
- default: undefined,
14345
- require: false,
14346
- },
14347
- rawColumnNames: {
14348
- type: Array,
14349
- default: () => [],
14350
- require: true,
14351
- },
14352
- scopedSlots: {
14353
- type: Object,
14354
- default: undefined,
14355
- require: false,
14356
- },
14736
+ noItemsLabel: String,
14737
+ scopedSlots: Object,
14357
14738
  selectable: Boolean,
14739
+ selected: Array,
14358
14740
  },
14359
14741
  emits: ['rowChecked', 'rowClick'],
14360
14742
  setup(props, { emit }) {
14361
- const handleRowClick = (item, index, columnName, event) => {
14362
- emit('rowClick', item, index, columnName, event);
14363
- };
14364
- const handleRowChecked = (id, value) => {
14365
- emit('rowChecked', id, value);
14366
- };
14367
- const tableDataCellProps = (item, colName) => {
14368
- const props = item._cellProps && {
14369
- ...(item._cellProps['all'] && { ...item._cellProps['all'] }),
14370
- ...(item._cellProps[colName] && { ...item._cellProps[colName] }),
14371
- };
14372
- return props;
14373
- };
14374
- const getColumnName = (event) => {
14375
- const target = event.target;
14376
- const closest = target.closest('tr');
14377
- const children = closest ? Array.from(closest.children) : [];
14378
- const clickedCell = children.filter((child) => child.contains(target))[0];
14379
- return props.rawColumnNames[children.indexOf(clickedCell)];
14380
- };
14743
+ const colspan = props.selectable
14744
+ ? props.columnNames.length + 1
14745
+ : props.columnNames.length;
14381
14746
  return () => vue.h(CTableBody, {
14382
14747
  ...(props.clickableRows && { style: 'cursor:pointer;' }),
14383
14748
  }, {
14384
- default: () => props.currentItems.map((item, trIndex) => [
14385
- vue.h(CTableRow, {
14386
- ...(item._props && { ...item._props }),
14387
- ...(props.clickableRows && { tabindex: 0 }),
14388
- onClick: (event) => handleRowClick(item, trIndex + props.firstItemOnActivePageIndex, getColumnName(event), event),
14389
- }, {
14390
- default: () => [
14391
- props.selectable &&
14392
- vue.h(CTableDataCell, {}, () => vue.h(CFormCheck, {
14393
- checked: item._selected ? item._selected : false,
14394
- onChange: (event) => handleRowChecked(item._id, event.target.checked),
14395
- })),
14396
- props.rawColumnNames.map((colName) => props.scopedSlots &&
14397
- props.scopedSlots[colName] &&
14398
- typeof props.scopedSlots[colName] === 'function'
14399
- ? vue.h(props.scopedSlots[colName], { item: item })
14400
- : vue.h(CTableDataCell, {
14401
- ...tableDataCellProps(item, colName),
14402
- }, {
14403
- default: () => String(item[colName]),
14404
- })),
14405
- ],
14406
- }),
14407
- props.scopedSlots &&
14408
- props.scopedSlots['details'] && [
14409
- vue.h(CTableRow, {
14410
- colspan: props.selectable
14411
- ? props.rawColumnNames.length + 1
14412
- : props.rawColumnNames.length,
14413
- class: 'p-0',
14414
- style: { 'border-bottom-width': '0' },
14415
- tabindex: '-1',
14416
- }),
14749
+ default: () => props.currentItems.length
14750
+ ? props.currentItems.map((item, trIndex) => [
14417
14751
  vue.h(CTableRow, {
14418
- class: 'p-0',
14419
- key: `details${trIndex}`,
14420
- onClick: (event) => handleRowClick(item, trIndex + props.firstItemOnActivePageIndex, getColumnName(event), true),
14752
+ ...(item._props && { ...item._props }),
14753
+ ...(props.clickableRows && { tabindex: 0 }),
14754
+ onClick: (event) => {
14755
+ emit('rowClick', item, trIndex + props.firstItemOnActivePageIndex, getClickedColumnName(event.target, props.columnNames), event);
14756
+ },
14421
14757
  }, {
14422
- default: () => vue.h(CTableDataCell, {
14758
+ default: () => [
14759
+ props.selectable &&
14760
+ vue.h(CTableDataCell, {}, () => vue.h(CFormCheck, {
14761
+ checked: props.selected &&
14762
+ isObjectInArray(props.selected, item, [
14763
+ '_cellProps',
14764
+ '_props',
14765
+ '_selected',
14766
+ ]),
14767
+ onChange: (event) => {
14768
+ emit('rowChecked', item, event.target.checked);
14769
+ },
14770
+ })),
14771
+ props.columnNames.map((colName) => props.scopedSlots &&
14772
+ props.scopedSlots[colName] &&
14773
+ typeof props.scopedSlots[colName] === 'function'
14774
+ ? vue.h(props.scopedSlots[colName], { item: item })
14775
+ : vue.h(CTableDataCell, {
14776
+ ...getTableDataCellProps(item, colName),
14777
+ }, {
14778
+ default: () => String(item[colName]),
14779
+ })),
14780
+ ],
14781
+ }),
14782
+ props.scopedSlots &&
14783
+ props.scopedSlots['details'] && [
14784
+ vue.h(CTableRow, {
14423
14785
  colspan: props.selectable
14424
- ? props.rawColumnNames.length + 1
14425
- : props.rawColumnNames.length,
14786
+ ? props.columnNames.length + 1
14787
+ : props.columnNames.length,
14426
14788
  class: 'p-0',
14427
- style: { border: 0 },
14789
+ style: { 'border-bottom-width': '0' },
14790
+ tabindex: '-1',
14791
+ }),
14792
+ vue.h(CTableRow, {
14793
+ class: 'p-0',
14794
+ key: `details${trIndex}`,
14795
+ onClick: (event) => {
14796
+ emit('rowClick', item, trIndex + props.firstItemOnActivePageIndex, getClickedColumnName(event.target, props.columnNames), true);
14797
+ },
14428
14798
  }, {
14429
- default: () => props.scopedSlots &&
14430
- props.scopedSlots['details'] &&
14431
- vue.h(props.scopedSlots['details'], {
14432
- item: item,
14433
- onClick: (event) => handleRowClick(item, trIndex + props.firstItemOnActivePageIndex, getColumnName(event), true),
14434
- }),
14799
+ default: () => vue.h(CTableDataCell, {
14800
+ colspan: props.selectable
14801
+ ? props.columnNames.length + 1
14802
+ : props.columnNames.length,
14803
+ class: 'p-0',
14804
+ style: { border: 0 },
14805
+ }, {
14806
+ default: () => props.scopedSlots &&
14807
+ props.scopedSlots['details'] &&
14808
+ vue.h(props.scopedSlots['details'], {
14809
+ item: item,
14810
+ }),
14811
+ }),
14435
14812
  }),
14813
+ ],
14814
+ ])
14815
+ : vue.h(CTableRow, {}, {
14816
+ default: () => vue.h(CTableDataCell, { colspan: colspan }, {
14817
+ default: () => props.noItemsLabel,
14436
14818
  }),
14437
- ],
14438
- ]),
14819
+ }),
14439
14820
  });
14440
14821
  },
14441
14822
  });
@@ -14443,140 +14824,63 @@ const CSmartTableBody = vue.defineComponent({
14443
14824
  const CSmartTableHead = vue.defineComponent({
14444
14825
  name: 'CSmartTableHead',
14445
14826
  props: {
14446
- clearSorterAndFilter: {
14447
- type: String,
14448
- require: false,
14449
- default: '',
14450
- },
14451
- columnFilter: {
14452
- type: [Boolean, Object],
14453
- require: false,
14454
- },
14455
- columnFilterValue: {
14456
- type: Object,
14457
- required: false,
14458
- },
14459
- columnSorter: {
14460
- type: [Boolean, Object],
14461
- default: undefined,
14462
- require: false,
14463
- },
14827
+ columnFilter: [Boolean, Object],
14828
+ columnFilterValue: Object,
14829
+ columnSorter: [Boolean, Object],
14464
14830
  component: {
14465
14831
  type: String,
14466
14832
  default: 'head',
14467
- require: false,
14468
14833
  },
14469
14834
  columns: {
14470
14835
  type: Array,
14471
14836
  default: () => [],
14472
- required: false,
14473
14837
  },
14474
14838
  items: {
14475
14839
  type: Array,
14476
14840
  default: () => [],
14477
- required: false,
14478
14841
  },
14479
14842
  selectable: Boolean,
14480
- selectAll: [Boolean, String],
14481
- sorterState: {
14482
- type: Object,
14483
- default: undefined,
14484
- require: false,
14485
- },
14843
+ selectAll: [Boolean, Object],
14844
+ selectedAll: [Boolean, String],
14845
+ sorterState: Object,
14486
14846
  },
14487
14847
  emits: ['customFilterChange', 'filterInput', 'filterChange', 'selectAllChecked', 'sortClick'],
14488
14848
  setup(props, { slots, emit }) {
14489
- const handleSortClick = (key, index) => {
14490
- emit('sortClick', key, index);
14491
- };
14492
- const tableHeaderCellProps = (column) => {
14493
- if (typeof column === 'object' && column._props) {
14494
- return column._props;
14495
- }
14496
- return {};
14497
- };
14498
- const tableHeaderCellStyles = (column) => {
14499
- const style = { verticalAlign: 'middle', overflow: 'hidden', cursor: '' };
14500
- if (props.columnSorter &&
14501
- (typeof column !== 'object' ||
14502
- (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter)))) {
14503
- style.cursor = 'pointer';
14504
- }
14505
- if (typeof column === 'object' && column._style) {
14506
- return { ...style, ...column._style };
14507
- }
14508
- return style;
14509
- };
14510
- const pretifyName = (name) => {
14511
- return name
14512
- .replace(/[-_.]/g, ' ')
14513
- .replace(/ +/g, ' ')
14514
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
14515
- .split(' ')
14516
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
14517
- .join(' ');
14518
- };
14519
- const label = (column) => typeof column === 'object'
14520
- ? column.label !== undefined
14521
- ? column.label
14522
- : pretifyName(column.key)
14523
- : pretifyName(column);
14524
- const key = (column) => (typeof column === 'object' ? column.key : column);
14525
- const getColumnSorterState = (key) => {
14526
- if (props.sorterState && props.sorterState.column === key) {
14527
- if (props.sorterState.state) {
14528
- return props.sorterState.state;
14529
- }
14530
- return 0;
14531
- }
14532
- return 0;
14533
- };
14534
- const getValues = (items, key) => {
14535
- return items.map((a) => a[key]);
14536
- };
14537
14849
  const columnSorterIcon = (column) => {
14538
- if (getColumnSorterState(key(column)) === 0) {
14850
+ if (getColumnSorterState(getColumnKey(column), props.sorterState) === 0) {
14539
14851
  return vue.h('span', { class: 'opacity-25 float-end me-1' }, slots.sortingIcon && slots.sortingIcon());
14540
14852
  }
14541
- if (getColumnSorterState(key(column)) === 'asc') {
14853
+ if (getColumnSorterState(getColumnKey(column), props.sorterState) === 'asc') {
14542
14854
  return vue.h('span', { class: 'float-end me-1' }, slots.sortingIconAscending && slots.sortingIconAscending());
14543
14855
  }
14544
- if (getColumnSorterState(key(column)) === 'desc') {
14856
+ if (getColumnSorterState(getColumnKey(column), props.sorterState) === 'desc') {
14545
14857
  return vue.h('span', { class: 'float-end me-1' }, slots.sortingIconDescending && slots.sortingIconDescending());
14546
14858
  }
14547
14859
  return;
14548
14860
  };
14549
- const handleOnCustomFilterChange = (key, value) => {
14550
- emit('customFilterChange', key, value);
14551
- };
14552
- const handleFilterInput = (key, value) => {
14553
- emit('filterInput', key, value);
14554
- };
14555
- const handleFilterChange = (key, value) => {
14556
- emit('filterChange', key, value);
14557
- };
14558
- const handleSelectAllChecked = () => {
14559
- emit('selectAllChecked');
14560
- };
14561
14861
  return () => vue.h(props.component === 'head' ? CTableHead : CTableFoot, {}, {
14562
14862
  default: () => [
14563
14863
  vue.h(CTableRow, {}, {
14564
14864
  default: () => [
14565
14865
  props.selectable &&
14566
14866
  vue.h(CTableHeaderCell, {}, () => vue.h(CFormCheck, {
14567
- checked: typeof props.selectAll === 'boolean' ? props.selectAll : false,
14568
- indeterminate: props.selectAll === 'indeterminate' ? true : false,
14569
- onChange: () => handleSelectAllChecked(),
14867
+ checked: typeof props.selectedAll === 'boolean' ? props.selectAll : false,
14868
+ indeterminate: props.selectedAll === 'indeterminate' ? true : false,
14869
+ onChange: () => {
14870
+ emit('selectAllChecked');
14871
+ },
14570
14872
  })),
14571
14873
  props.columns.map((column, index) => vue.h(CTableHeaderCell, {
14572
- ...tableHeaderCellProps(column),
14573
- onClick: () => handleSortClick(key(column), index),
14574
- style: tableHeaderCellStyles(column),
14874
+ ...getTableHeaderCellProps(column),
14875
+ onClick: () => {
14876
+ emit('sortClick', getColumnKey(column), index);
14877
+ },
14878
+ style: getTableHeaderCellStyles(column, props.columnSorter),
14575
14879
  }, {
14576
14880
  default: () => [
14577
14881
  vue.h('div', {
14578
14882
  class: 'd-inline',
14579
- }, label(column)),
14883
+ }, getColumnLabel(column)),
14580
14884
  props.columnSorter &&
14581
14885
  (typeof column !== 'object'
14582
14886
  ? true
@@ -14593,7 +14897,7 @@ const CSmartTableHead = vue.defineComponent({
14593
14897
  default: () => [
14594
14898
  props.selectable && vue.h(CTableHeaderCell),
14595
14899
  props.columns.map((column) => vue.h(CTableHeaderCell, {
14596
- ...tableHeaderCellProps(column),
14900
+ ...getTableHeaderCellProps(column),
14597
14901
  }, {
14598
14902
  default: () => (typeof column !== 'object'
14599
14903
  ? true
@@ -14601,15 +14905,21 @@ const CSmartTableHead = vue.defineComponent({
14601
14905
  ? true
14602
14906
  : column.filter)
14603
14907
  ? typeof column !== 'string' && typeof column.filter === 'function'
14604
- ? column.filter(getValues(props.items, key(column)), (value) => handleOnCustomFilterChange(key(column), value))
14908
+ ? column.filter(getColumnValues(props.items, getColumnKey(column)), (value) => {
14909
+ emit('customFilterChange', getColumnKey(column), value);
14910
+ })
14605
14911
  : vue.h(CFormInput, {
14606
14912
  size: 'sm',
14607
- onInput: (event) => handleFilterInput(key(column), event.target.value),
14608
- onChange: (event) => handleFilterChange(key(column), event.target.value),
14609
- 'aria-label': `column name: '${label(column)}' filter input`,
14913
+ onInput: (event) => {
14914
+ emit('filterInput', getColumnKey(column), event.target.value);
14915
+ },
14916
+ onChange: (event) => {
14917
+ emit('filterChange', event.target.value);
14918
+ },
14919
+ 'aria-label': `column name: '${getColumnLabel(column)}' filter input`,
14610
14920
  ...(props.columnFilterValue &&
14611
- props.columnFilterValue[key(column)] && {
14612
- value: props.columnFilterValue[key(column)],
14921
+ props.columnFilterValue[getColumnKey(column)] && {
14922
+ value: props.columnFilterValue[getColumnKey(column)],
14613
14923
  }),
14614
14924
  })
14615
14925
  : '',
@@ -14621,268 +14931,6 @@ const CSmartTableHead = vue.defineComponent({
14621
14931
  },
14622
14932
  });
14623
14933
 
14624
- const CSmartTableFilterProps = {
14625
- filterLabel: {
14626
- type: String,
14627
- require: false,
14628
- default: 'Filter:',
14629
- },
14630
- filterPlaceholder: {
14631
- type: String,
14632
- require: false,
14633
- default: 'type string...',
14634
- },
14635
- value: {
14636
- type: [String, Number],
14637
- require: false,
14638
- default: '',
14639
- },
14640
- };
14641
- const CSmartTableFilter = vue.defineComponent({
14642
- name: 'CSmartTableFilter',
14643
- props: CSmartTableFilterProps,
14644
- emits: ['filterInput', 'filterChange'],
14645
- setup(props, { emit }) {
14646
- const handleFilterInput = (event) => {
14647
- const target = event.target;
14648
- emit('filterInput', target.value);
14649
- };
14650
- const handleFilterChange = (event) => {
14651
- const target = event.target;
14652
- emit('filterChange', target.value);
14653
- };
14654
- return () => vue.h('div', {
14655
- class: 'row mb-2',
14656
- }, {
14657
- default: () => [
14658
- vue.h(CFormLabel, {
14659
- class: 'col-sm-auto col-form-label',
14660
- }, {
14661
- default: () => props.filterLabel,
14662
- }),
14663
- vue.h('div', {
14664
- class: 'col-sm-auto',
14665
- }, vue.h(CFormInput, {
14666
- placeholder: props.filterPlaceholder,
14667
- value: props.value,
14668
- onInput: handleFilterInput,
14669
- onChange: handleFilterChange,
14670
- })),
14671
- ],
14672
- });
14673
- },
14674
- });
14675
-
14676
- const CSmartTableCleaner = vue.defineComponent({
14677
- name: 'CSmartTableCleaner',
14678
- props: {
14679
- isFiltered: {
14680
- type: String,
14681
- default: undefined,
14682
- required: false,
14683
- },
14684
- },
14685
- emits: ['tableCleanerClick'],
14686
- setup(props, { emit, slots }) {
14687
- const handleClick = () => {
14688
- emit('tableCleanerClick');
14689
- };
14690
- return () => vue.h('button', {
14691
- type: 'button',
14692
- class: 'btn btn-transparent',
14693
- ...(!props.isFiltered && { disabled: true, tabIndex: -1 }),
14694
- onClick: handleClick,
14695
- }, slots.cleanerIcon && slots.cleanerIcon());
14696
- },
14697
- });
14698
-
14699
- const CSmartTableItemsPerPageSelector = vue.defineComponent({
14700
- name: 'CSmartTableItemsPerPageSelector',
14701
- props: {
14702
- itemsPerPage: {
14703
- type: Number,
14704
- default: undefined,
14705
- require: false,
14706
- },
14707
- itemsPerPageLabel: {
14708
- type: String,
14709
- default: undefined,
14710
- require: false,
14711
- },
14712
- itemsPerPageOptions: {
14713
- type: Array,
14714
- default: () => [],
14715
- require: false,
14716
- },
14717
- },
14718
- emits: ['changeItemsPerPage'],
14719
- setup(props, { emit }) {
14720
- const handleChange = (event) => {
14721
- const target = event.target;
14722
- emit('changeItemsPerPage', Number(target.value));
14723
- };
14724
- return () => vue.h('div', {
14725
- class: 'row',
14726
- }, {
14727
- default: () => [
14728
- vue.h(CFormLabel, {
14729
- class: 'col-auto col-form-label',
14730
- }, {
14731
- default: () => props.itemsPerPageLabel,
14732
- }),
14733
- vue.h('div', {
14734
- class: 'col-auto',
14735
- }, vue.h(CFormSelect, {
14736
- value: props.itemsPerPage,
14737
- onChange: handleChange,
14738
- }, {
14739
- default: () => props.itemsPerPageOptions &&
14740
- props.itemsPerPageOptions.map((number, index) => {
14741
- return vue.h('option', {
14742
- value: number,
14743
- key: index,
14744
- }, number);
14745
- }),
14746
- })),
14747
- ],
14748
- });
14749
- },
14750
- });
14751
-
14752
- const CIcon = vue.defineComponent({
14753
- name: 'CIcon',
14754
- props: {
14755
- /**
14756
- * Use `:icon="..."` instead of
14757
- *
14758
- * @deprecated since version 3.0
14759
- */
14760
- content: {
14761
- type: [String, Array],
14762
- default: undefined,
14763
- required: false,
14764
- },
14765
- /**
14766
- * Use for replacing default CIcon component classes. Prop is overriding the 'size' prop.
14767
- */
14768
- customClassName: {
14769
- type: [String, Array, Object],
14770
- default: undefined,
14771
- required: false,
14772
- },
14773
- /**
14774
- * Name of the icon placed in React object or SVG content.
14775
- */
14776
- icon: {
14777
- type: [String, Array],
14778
- default: undefined,
14779
- required: false,
14780
- },
14781
- /**
14782
- * Use `icon="..."` instead of
14783
- *
14784
- * @deprecated since version 3.0
14785
- */
14786
- name: {
14787
- type: String,
14788
- default: undefined,
14789
- required: false,
14790
- },
14791
- /**
14792
- * Size of the icon. Available sizes: 'sm', 'lg', 'xl', 'xxl', '3xl...9xl', 'custom', 'custom-size'.
14793
- */
14794
- size: {
14795
- type: String,
14796
- default: undefined,
14797
- required: false,
14798
- validator: (value) => {
14799
- return [
14800
- 'custom',
14801
- 'custom-size',
14802
- 'sm',
14803
- 'lg',
14804
- 'xl',
14805
- 'xxl',
14806
- '3xl',
14807
- '4xl',
14808
- '5xl',
14809
- '6xl',
14810
- '7xl',
14811
- '8xl',
14812
- '9xl',
14813
- ].includes(value);
14814
- },
14815
- },
14816
- /**
14817
- * Title tag content.
14818
- */
14819
- title: {
14820
- type: String,
14821
- default: undefined,
14822
- required: false,
14823
- },
14824
- /**
14825
- * If defined component will be rendered using 'use' tag.
14826
- */
14827
- use: {
14828
- type: String,
14829
- default: undefined,
14830
- required: false,
14831
- },
14832
- },
14833
- setup(props, { attrs }) {
14834
- const icons = vue.inject('icons');
14835
- const _icon = props.icon || props.content || props.name;
14836
- const toCamelCase = (str) => {
14837
- return str
14838
- .replace(/([-_][a-z0-9])/gi, ($1) => {
14839
- return $1.toUpperCase();
14840
- })
14841
- .replace(/-/gi, '');
14842
- };
14843
- const iconName = vue.computed(() => _icon && typeof _icon === 'string' ? (_icon.includes('-') ? toCamelCase(_icon) : _icon) : '');
14844
- const titleCode = props.title ? `<title>${props.title}</title>` : 'undefined';
14845
- const code = vue.computed(() => Array.isArray(_icon)
14846
- ? _icon
14847
- : typeof _icon === 'string' && iconName.value && icons[iconName.value]
14848
- ? icons[iconName.value]
14849
- : 'undefined');
14850
- const iconCode = Array.isArray(code.value) ? code.value[1] || code.value[0] : code.value;
14851
- const scale = Array.isArray(code.value) && code.value.length > 1 ? code.value[0] : '64 64';
14852
- const viewBox = attrs.viewBox || `0 0 ${scale}`;
14853
- const size = () => {
14854
- const addCustom = !props.size && (attrs.width || attrs.height);
14855
- return props.size === 'custom' || addCustom ? 'custom-size' : props.size;
14856
- };
14857
- const classNames = (() => {
14858
- return [props.customClassName || ['icon', { [`icon-${size()}`]: size() }], attrs.class];
14859
- })();
14860
- return () => props.use
14861
- ? vue.h('svg', {
14862
- ...attrs,
14863
- xmlns: 'http://www.w3.org/2000/svg',
14864
- class: classNames,
14865
- role: 'img',
14866
- }, vue.h('use', { href: props.use }))
14867
- : vue.h('svg', {
14868
- ...attrs,
14869
- xmlns: 'http://www.w3.org/2000/svg',
14870
- class: classNames,
14871
- viewBox: viewBox,
14872
- innerHTML: `${titleCode}${iconCode}`,
14873
- role: 'img',
14874
- });
14875
- },
14876
- });
14877
-
14878
- var cilArrowBottom = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='367.997 338.75 271.999 434.747 271.999 17.503 239.999 17.503 239.999 434.745 144.003 338.75 121.376 361.377 256 496 390.624 361.377 367.997 338.75' class='ci-primary'/>"];
14879
-
14880
- var cilArrowTop = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='390.624 150.625 256 16 121.376 150.625 144.004 173.252 240.001 77.254 240.001 495.236 272.001 495.236 272.001 77.257 367.996 173.252 390.624 150.625' class='ci-primary'/>"];
14881
-
14882
- var cilFilterX = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='40 16 40 53.828 109.024 136 150.815 136 76.896 48 459.51 48 304 242.388 304 401.373 241.373 464 240 464 240 368 208 368 208 496 254.627 496 336 414.627 336 253.612 496 53.612 496 16 40 16' class='ci-primary'/><polygon fill='var(--ci-primary-color, currentColor)' points='166.403 248.225 226.864 187.763 204.237 165.135 143.775 225.597 83.313 165.135 60.687 187.763 121.148 248.225 60.687 308.687 83.313 331.314 143.775 270.852 204.237 331.314 226.864 308.687 166.403 248.225' class='ci-primary'/>"];
14883
-
14884
- var cilSwapVertical = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='384 433.373 384 160 352 160 352 434.51 282.177 364.687 259.55 387.313 367.432 495.196 475.313 387.313 452.687 364.687 384 433.373' class='ci-primary'/><polygon fill='var(--ci-primary-color, currentColor)' points='159.432 17.372 51.55 125.255 74.177 147.882 144 78.059 144 352 176 352 176 79.195 244.687 147.882 267.313 125.255 159.432 17.372' class='ci-primary'/>"];
14885
-
14886
14934
  const CSmartTable = vue.defineComponent({
14887
14935
  name: 'CSmartTable',
14888
14936
  props: {
@@ -14892,7 +14940,6 @@ const CSmartTable = vue.defineComponent({
14892
14940
  activePage: {
14893
14941
  type: Number,
14894
14942
  default: 1,
14895
- required: false,
14896
14943
  },
14897
14944
  /**
14898
14945
  * When set, displays table cleaner above table, next to the table filter (or in place of table filter if `tableFilter` prop is not set)
@@ -14901,14 +14948,12 @@ const CSmartTable = vue.defineComponent({
14901
14948
  */
14902
14949
  cleaner: {
14903
14950
  type: Boolean,
14904
- required: false,
14905
14951
  },
14906
14952
  /**
14907
14953
  * Style table items as clickable.
14908
14954
  */
14909
14955
  clickableRows: {
14910
14956
  type: Boolean,
14911
- required: false,
14912
14957
  },
14913
14958
  /**
14914
14959
  * When set, displays additional filter row between table header and items, allowing filtering by specific column.
@@ -14918,7 +14963,6 @@ const CSmartTable = vue.defineComponent({
14918
14963
  */
14919
14964
  columnFilter: {
14920
14965
  type: [Boolean, Object],
14921
- required: false,
14922
14966
  },
14923
14967
  /**
14924
14968
  * Value of table filter. To set pass object where keys are column names and values are filter strings e.g.:
@@ -14926,8 +14970,6 @@ const CSmartTable = vue.defineComponent({
14926
14970
  */
14927
14971
  columnFilterValue: {
14928
14972
  type: Object,
14929
- default: undefined,
14930
- required: false,
14931
14973
  },
14932
14974
  /**
14933
14975
  * Prop for table columns configuration. If prop is not defined, table will display columns based on the first item keys, omitting keys that begins with underscore (e.g. '_props')
@@ -14944,7 +14986,6 @@ const CSmartTable = vue.defineComponent({
14944
14986
  */
14945
14987
  columns: {
14946
14988
  type: Array,
14947
- required: false,
14948
14989
  },
14949
14990
  /**
14950
14991
  * Enables table sorting by column value. Sorting will be performed corectly only if values in column are of one type: string (case insensitive) or number.
@@ -14955,8 +14996,6 @@ const CSmartTable = vue.defineComponent({
14955
14996
  */
14956
14997
  columnSorter: {
14957
14998
  type: [Boolean, Object],
14958
- default: undefined,
14959
- required: false,
14960
14999
  },
14961
15000
  /**
14962
15001
  * If `true` Displays table footer, which mirrors table header. (without column filter).
@@ -14969,14 +15008,12 @@ const CSmartTable = vue.defineComponent({
14969
15008
  */
14970
15009
  footer: {
14971
15010
  type: [Boolean, Array],
14972
- required: false,
14973
15011
  },
14974
15012
  /**
14975
15013
  * Set to false to remove table header.
14976
15014
  */
14977
15015
  header: {
14978
15016
  type: Boolean,
14979
- required: false,
14980
15017
  default: true,
14981
15018
  },
14982
15019
  /**
@@ -14989,22 +15026,25 @@ const CSmartTable = vue.defineComponent({
14989
15026
  items: {
14990
15027
  type: Array,
14991
15028
  default: () => [],
14992
- required: false,
14993
15029
  },
15030
+ /**
15031
+ * The total number of items. Use if you pass a portion of data from an external source to let know component what is the total number of items.
15032
+ *
15033
+ * @since 4.8.0
15034
+ */
15035
+ itemsNumber: Number,
14994
15036
  /**
14995
15037
  * Number of items per site, when pagination is enabled.
14996
15038
  */
14997
15039
  itemsPerPage: {
14998
15040
  type: Number,
14999
15041
  default: 10,
15000
- required: false,
15001
15042
  },
15002
15043
  /**
15003
15044
  * Label for items per page selector.
15004
15045
  */
15005
15046
  itemsPerPageLabel: {
15006
15047
  type: String,
15007
- required: false,
15008
15048
  default: 'Items per page:',
15009
15049
  },
15010
15050
  /**
@@ -15013,7 +15053,6 @@ const CSmartTable = vue.defineComponent({
15013
15053
  itemsPerPageOptions: {
15014
15054
  type: Array,
15015
15055
  default: () => [5, 10, 20, 50],
15016
- required: false,
15017
15056
  },
15018
15057
  /**
15019
15058
  * Adds select element over table, which is used for control items per page in pagination. If you want to customize this element, pass object with optional values:
@@ -15023,15 +15062,12 @@ const CSmartTable = vue.defineComponent({
15023
15062
  */
15024
15063
  itemsPerPageSelect: {
15025
15064
  type: [Boolean, Object],
15026
- default: undefined,
15027
- required: false,
15028
15065
  },
15029
15066
  /**
15030
15067
  * When set, table will have loading style: loading spinner and reduced opacity. When 'small' prop is enabled spinner will be also smaller.
15031
15068
  */
15032
15069
  loading: {
15033
15070
  type: Boolean,
15034
- required: false,
15035
15071
  },
15036
15072
  /**
15037
15073
  * ReactNode or string for passing custom noItemsLabel texts.
@@ -15039,51 +15075,63 @@ const CSmartTable = vue.defineComponent({
15039
15075
  noItemsLabel: {
15040
15076
  type: String,
15041
15077
  default: 'No items found',
15042
- required: false,
15043
15078
  },
15044
15079
  /**
15045
15080
  * Enables default pagination. Set to true for default setup or pass an object with additional CPagination props. Default pagination will always have the computed number of pages that cannot be changed. The number of pages is generated based on the number of passed items and 'itemsPerPage' prop. If this restriction is an obstacle, you can make external CPagination instead.
15046
15081
  */
15047
15082
  pagination: {
15048
15083
  type: [Boolean, Object],
15049
- required: false,
15050
15084
  },
15051
15085
  /**
15052
15086
  * Properties to [CSmartPagination](https://coreui.io/vue/docs/components/smart-pagination#csmartpagination) component.
15053
15087
  */
15054
15088
  paginationProps: {
15055
15089
  type: Object,
15056
- default: undefined,
15057
- required: false,
15058
15090
  },
15059
15091
  /**
15060
15092
  * Add checkboxes to make table rows selectable.
15061
15093
  */
15062
15094
  selectable: Boolean,
15095
+ /**
15096
+ * Enables select all checkbox displayed in the header of the table.
15097
+ *
15098
+ * Can be customized, by passing prop as object with additional options as keys. Available options:
15099
+ * - external (Boolean) - Disables automatic selection inside the component.
15100
+ *
15101
+ * @since 4.8.0
15102
+ */
15103
+ selectAll: {
15104
+ type: [Boolean, Object],
15105
+ },
15106
+ /**
15107
+ * Array of selected objects, where each object represents one item - row in table.
15108
+ *
15109
+ * Example item: `{ name: 'John' , age: 12 }`
15110
+ *
15111
+ * @since 4.8.0
15112
+ */
15113
+ selected: {
15114
+ type: Array,
15115
+ default: () => [],
15116
+ },
15063
15117
  /**
15064
15118
  * State of the sorter. Name key is column name, direction can be 'asc' or 'desc'. eg.:
15065
15119
  * { column: 'status', state: 'asc' }
15066
15120
  */
15067
15121
  sorterValue: {
15068
15122
  type: Object,
15069
- default: undefined,
15070
- required: false,
15071
15123
  },
15072
15124
  /**
15073
15125
  * Properties to [CTableBody](https://coreui.io/vue/docs/components/table/#ctablebody) component.
15074
15126
  */
15075
15127
  tableBodyProps: {
15076
15128
  type: Object,
15077
- default: undefined,
15078
- required: false,
15079
15129
  },
15080
15130
  /**
15081
15131
  * Properties to [CTableFoot](https://coreui.io/vue/docs/components/table/#ctablefoot) component.
15082
15132
  */
15083
15133
  tableFootProps: {
15084
15134
  type: Object,
15085
- default: undefined,
15086
- required: false,
15087
15135
  },
15088
15136
  /**
15089
15137
  * When set, displays table filter above table, allowing filtering by specific column.
@@ -15094,7 +15142,6 @@ const CSmartTable = vue.defineComponent({
15094
15142
  */
15095
15143
  tableFilter: {
15096
15144
  type: [Boolean, Object],
15097
- required: false,
15098
15145
  },
15099
15146
  /**
15100
15147
  * The element represents a caption for a component.
@@ -15102,7 +15149,6 @@ const CSmartTable = vue.defineComponent({
15102
15149
  tableFilterLabel: {
15103
15150
  type: String,
15104
15151
  default: 'Filter:',
15105
- required: false,
15106
15152
  },
15107
15153
  /**
15108
15154
  * Specifies a short hint that is visible in the search input.
@@ -15110,31 +15156,24 @@ const CSmartTable = vue.defineComponent({
15110
15156
  tableFilterPlaceholder: {
15111
15157
  type: String,
15112
15158
  default: 'type string...',
15113
- required: false,
15114
15159
  },
15115
15160
  /**
15116
15161
  * Value of table filter.
15117
15162
  */
15118
15163
  tableFilterValue: {
15119
15164
  type: String,
15120
- default: undefined,
15121
- required: false,
15122
15165
  },
15123
15166
  /**
15124
15167
  * Properties to [CTableHead](https://coreui.io/vue/docs/components/table/#ctablehead) component.
15125
15168
  */
15126
15169
  tableHeadProps: {
15127
15170
  type: Object,
15128
- default: undefined,
15129
- required: false,
15130
15171
  },
15131
15172
  /**
15132
15173
  * Properties to [CTable](https://coreui.io/vue/docs/components/table/#ctable) component.
15133
15174
  */
15134
15175
  tableProps: {
15135
15176
  type: Object,
15136
- default: undefined,
15137
- required: false,
15138
15177
  },
15139
15178
  },
15140
15179
  emits: [
@@ -15171,6 +15210,12 @@ const CSmartTable = vue.defineComponent({
15171
15210
  * @property {event} event
15172
15211
  */
15173
15212
  'rowClick',
15213
+ /**
15214
+ * Select all callback.
15215
+ *
15216
+ * @since 4.8.0
15217
+ */
15218
+ 'selectAll',
15174
15219
  /**
15175
15220
  * Selected items change callback.
15176
15221
  *
@@ -15191,66 +15236,90 @@ const CSmartTable = vue.defineComponent({
15191
15236
  'tableFilterChange',
15192
15237
  ],
15193
15238
  setup(props, { emit, slots }) {
15194
- // reactive data
15239
+ const activePage = vue.ref(props.activePage);
15240
+ const columnFilterState = vue.ref(props.columnFilterValue ? props.columnFilterValue : {});
15195
15241
  const items = vue.ref(props.items.map((item, index) => {
15196
15242
  return { ...item, _id: index };
15197
15243
  }));
15244
+ const itemsNumber = vue.ref(props.itemsNumber);
15245
+ const itemsPerPage = vue.ref(props.itemsPerPage || items.value.length);
15246
+ const selected = vue.ref([]);
15247
+ const selectedAll = vue.ref();
15248
+ const sorterState = vue.ref(props.sorterValue || {});
15249
+ const tableFilterState = vue.ref(props.tableFilterValue ? props.tableFilterValue : '');
15250
+ vue.watch(() => props.activePage, () => {
15251
+ activePage.value = props.activePage;
15252
+ });
15253
+ vue.watch(() => props.columnFilterValue, () => {
15254
+ if (props.columnFilterValue) {
15255
+ columnFilterState.value = props.columnFilterValue;
15256
+ }
15257
+ });
15198
15258
  vue.watch(() => props.items, () => {
15199
- items.value = props.items.map((item, index) => {
15200
- return { ...item, _id: index };
15201
- });
15202
- if (items.value &&
15203
- items.value.length < itemsPerPage.value * activePage.value - itemsPerPage.value) {
15259
+ if (props.items &&
15260
+ props.items.length < itemsPerPage.value * activePage.value - itemsPerPage.value) {
15204
15261
  activePage.value = 1;
15205
15262
  }
15263
+ props.items.forEach((item) => {
15264
+ if (item._selected) {
15265
+ const _item = { ...item };
15266
+ delete _item['_cellProps'];
15267
+ delete _item['_props'];
15268
+ delete _item['_selected'];
15269
+ selected.value = [...selected.value, _item];
15270
+ }
15271
+ });
15272
+ if (Array.isArray(props.items)) {
15273
+ items.value = props.items;
15274
+ itemsNumber.value = props.itemsNumber || props.items.length;
15275
+ }
15206
15276
  });
15207
- const selectedAll = vue.ref();
15208
- vue.watch(items, () => {
15209
- const selected = items.value.filter((item) => item._selected === true);
15277
+ vue.watch(() => props.itemsNumber, () => {
15278
+ itemsNumber.value = props.itemsNumber;
15279
+ });
15280
+ vue.watch(() => props.itemsPerPage, () => {
15281
+ itemsPerPage.value = props.itemsPerPage;
15282
+ });
15283
+ vue.watch(() => props.selected, () => {
15284
+ selected.value = props.selected;
15285
+ });
15286
+ vue.watch(() => props.sorterValue, () => {
15287
+ if (props.sorterValue) {
15288
+ sorterState.value = props.sorterValue;
15289
+ }
15290
+ });
15291
+ vue.watch(itemsPerPage, () => {
15292
+ if (props.itemsPerPage !== itemsPerPage.value) {
15293
+ activePage.value = 1; // TODO: set proper page after _itemsPerPage update
15294
+ }
15295
+ emit('itemsPerPageChange', itemsPerPage.value);
15296
+ });
15297
+ vue.watch([selected, itemsNumber], () => {
15210
15298
  emit('selectedItemsChange', selected);
15211
- if (selected.length === items.value.length) {
15299
+ if (selected.value.length === itemsNumber.value) {
15212
15300
  selectedAll.value = true;
15213
15301
  return;
15214
15302
  }
15215
- if (selected.length === 0) {
15303
+ if (selected.value.length === 0) {
15216
15304
  selectedAll.value = false;
15217
15305
  return;
15218
15306
  }
15219
- if (selected.length !== 0 && selected.length !== items.value.length) {
15307
+ if (selected.value.length !== 0 && selected.value.length !== itemsNumber.value) {
15220
15308
  selectedAll.value = 'indeterminate';
15221
15309
  }
15222
15310
  });
15223
- const itemsPerPage = vue.ref(props.itemsPerPage || items.value.length);
15224
- const activePage = vue.ref(props.activePage);
15225
- const sorterState = vue.reactive(props.sorterValue || {});
15226
- const columnFilterState = vue.ref(props.columnFilterValue ? props.columnFilterValue : {});
15227
- const tableFilterState = vue.ref(props.tableFilterValue ? props.tableFilterValue : '');
15228
15311
  vue.onMounted(() => {
15229
15312
  if (items.value &&
15230
15313
  items.value.length < itemsPerPage.value * activePage.value - itemsPerPage.value) {
15231
15314
  activePage.value = 1;
15232
15315
  }
15233
15316
  });
15234
- // functions
15235
- const isLazy = (columnFilter) => columnFilter && typeof columnFilter === 'object' && columnFilter.lazy === true;
15236
- const isSortable = (i) => {
15237
- const isDataColumn = itemsDataColumns.value.includes(rawColumnNames.value[i]);
15238
- let column;
15239
- if (props.columns)
15240
- column = props.columns[i];
15241
- return (props.columnSorter &&
15242
- (!props.columns ||
15243
- typeof column !== 'object' ||
15244
- (typeof column === 'object' &&
15245
- (typeof column.sorter === 'undefined' || column.sorter))) &&
15246
- isDataColumn);
15247
- };
15248
- const sorterChange = (column, index) => {
15249
- if (!isSortable(index)) {
15317
+ const handleSorterChange = (column, index) => {
15318
+ if (!isSortable(index, props.columns, props.columnSorter, itemsDataColumns.value, columnNames.value)) {
15250
15319
  return;
15251
15320
  }
15252
15321
  //if column changed or sort was descending change asc to true
15253
- const state = sorterState;
15322
+ const state = sorterState.value;
15254
15323
  if (state.column === column) {
15255
15324
  if (state.state === 0) {
15256
15325
  state.state = 'asc';
@@ -15271,40 +15340,47 @@ const CSmartTable = vue.defineComponent({
15271
15340
  state.column = column;
15272
15341
  state.state = 'asc';
15273
15342
  }
15274
- sorterState.column = state.column;
15275
- sorterState.state = state.state;
15276
- emit('sorterChange', sorterState);
15343
+ sorterState.value.column = state.column;
15344
+ sorterState.value.state = state.state;
15345
+ emit('sorterChange', sorterState.value);
15277
15346
  };
15278
15347
  const handleActivePageChange = (page) => {
15279
15348
  activePage.value = page;
15280
15349
  emit('activePageChange', page);
15281
15350
  };
15282
- const handleItemsPerPageChange = (itemsPerPageNumber) => {
15283
- itemsPerPage.value = itemsPerPageNumber;
15284
- itemsPerPageNumber !== props.itemsPerPage && handleActivePageChange(1); // TODO: set proper page after _itemsPerPage update
15285
- emit('itemsPerPageChange', itemsPerPageNumber);
15286
- };
15287
- const handleRowChecked = (id, value) => {
15288
- const newArr = [...items.value];
15289
- newArr[id]._selected = value;
15290
- items.value = newArr;
15351
+ const handleItemsPerPageChange = (event) => {
15352
+ if (typeof props.itemsPerPageSelect !== 'object' ||
15353
+ (typeof props.itemsPerPageSelect === 'object' && !props.itemsPerPageSelect.external)) {
15354
+ itemsPerPage.value = Number(event.target.value);
15355
+ }
15291
15356
  };
15292
- const handleRowClick = (item, index, columnName, event) => {
15293
- emit('rowClick', item, index, columnName, event);
15357
+ const handleRowChecked = (item, value) => {
15358
+ if (value && !isObjectInArray(selected.value, item, ['_cellProps', '_props', '_selected'])) {
15359
+ selected.value = [...selected.value, item];
15360
+ return;
15361
+ }
15362
+ selected.value = selected.value.filter((_item) => !isObjectInArray([_item], item, ['_cellProps', '_props', '_selected']));
15294
15363
  };
15295
15364
  const handleSelectAllChecked = () => {
15296
15365
  if (selectedAll.value === true) {
15297
- items.value = items.value.map((item) => {
15298
- return { ...item, _selected: false };
15299
- });
15366
+ selected.value = [];
15367
+ return;
15368
+ }
15369
+ emit('selectAll');
15370
+ if (props.selectAll && typeof props.selectAll === 'object' && props.selectAll.external) {
15300
15371
  return;
15301
15372
  }
15302
- items.value = items.value.map((item) => {
15303
- return { ...item, _selected: true };
15373
+ selected.value = items.value.map((item) => {
15374
+ delete item['_cellProps'];
15375
+ delete item['_props'];
15376
+ delete item['_selected'];
15377
+ return item;
15304
15378
  });
15305
15379
  };
15306
- const columnFilterChange = (colName, value, type) => {
15307
- const _isLazy = isLazy(props.columnFilter);
15380
+ const handleColumnFilterChange = (colName, value, type) => {
15381
+ const _isLazy = props.columnFilter &&
15382
+ typeof props.columnFilter === 'object' &&
15383
+ props.columnFilter.lazy === true;
15308
15384
  if ((_isLazy && type === 'input') || (!_isLazy && type === 'change')) {
15309
15385
  return;
15310
15386
  }
@@ -15312,98 +15388,32 @@ const CSmartTable = vue.defineComponent({
15312
15388
  columnFilterState.value = { ...columnFilterState.value, [`${colName}`]: value };
15313
15389
  emit('columnFilterChange', columnFilterState.value);
15314
15390
  };
15315
- const tableFilterChange = (value, type) => {
15316
- const _isLazy = isLazy(props.columnFilter);
15391
+ const handleTableFilterChange = (value, type) => {
15392
+ const _isLazy = props.columnFilter &&
15393
+ typeof props.columnFilter === 'object' &&
15394
+ props.columnFilter.lazy === true;
15317
15395
  if ((_isLazy && type === 'input') || (!_isLazy && type === 'change')) {
15318
15396
  return;
15319
15397
  }
15320
15398
  activePage.value = 1;
15321
15399
  tableFilterState.value = value;
15322
- emit('tableFilterChange', tableFilterState);
15400
+ emit('tableFilterChange', tableFilterState.value);
15323
15401
  };
15324
- const clean = () => {
15402
+ const handleClean = () => {
15325
15403
  tableFilterState.value = '';
15326
15404
  columnFilterState.value = {};
15327
- sorterState.column = '';
15328
- sorterState.state = '';
15405
+ sorterState.value = {};
15329
15406
  };
15330
- // computed
15331
- const genCols = vue.computed(() => Object.keys(items.value[0] || {}).filter((el) => el.charAt(0) !== '_'));
15332
- const rawColumnNames = vue.computed(() => props.columns
15333
- ? props.columns.map((column) => {
15334
- if (typeof column === 'object')
15335
- return column.key;
15336
- else
15337
- return column;
15338
- })
15339
- : genCols.value); //! || el
15340
- const itemsDataColumns = vue.computed(() => rawColumnNames.value.filter((name) => genCols.value.includes(name)));
15341
- // variables
15342
- const filteredColumns = vue.computed(() => {
15343
- let _items = items.value;
15344
- if (props.columnFilter &&
15345
- typeof props.columnFilter === 'object' &&
15346
- props.columnFilter.external) {
15347
- return _items;
15348
- }
15349
- Object.entries(columnFilterState.value).forEach(([key, value]) => {
15350
- if (value instanceof Function) {
15351
- _items = _items.filter((item) => value(item[key]));
15352
- return;
15353
- }
15354
- const columnFilter = String(value).toLowerCase();
15355
- if (columnFilter && itemsDataColumns.value.includes(key)) {
15356
- _items = _items.filter((item) => {
15357
- return String(item[key]).toLowerCase().includes(columnFilter);
15358
- });
15359
- }
15360
- });
15361
- return _items;
15362
- });
15363
- const filteredTable = vue.computed(() => {
15364
- let items = filteredColumns.value;
15365
- if (!tableFilterState.value ||
15366
- (props.tableFilter && typeof props.tableFilter === 'object' && props.tableFilter.external)) {
15367
- return items;
15368
- }
15369
- const filter = tableFilterState.value.toLowerCase();
15370
- const valueContainFilter = (val) => String(val).toLowerCase().includes(filter);
15371
- items = items.filter((item) => {
15372
- return !!itemsDataColumns.value.find((key) => valueContainFilter(item[key]));
15373
- });
15374
- emit('filteredItemsChange', items);
15375
- return items;
15376
- });
15377
- const sortedItems = vue.computed(() => {
15378
- const col = sorterState.column;
15379
- if (!col ||
15380
- !itemsDataColumns.value.includes(col) ||
15381
- (props.columnSorter &&
15382
- typeof props.columnSorter === 'object' &&
15383
- props.columnSorter.external)) {
15384
- return filteredTable.value;
15385
- }
15386
- //if values in column are to be sorted by numeric value they all have to be type number
15387
- // const flip = sorterState.asc ? 1 : -1
15388
- const flip = sorterState.state === 'asc' ? 1 : sorterState.state === 'desc' ? -1 : 0;
15389
- const sorted = filteredTable.value.slice().sort((item, item2) => {
15390
- const value = item[col];
15391
- const value2 = item2[col];
15392
- const a = typeof value === 'number' ? value : String(value).toLowerCase();
15393
- const b = typeof value2 === 'number' ? value2 : String(value2).toLowerCase();
15394
- return a > b ? 1 * flip : b > a ? -1 * flip : 0;
15395
- });
15396
- return sorted;
15397
- });
15407
+ const columnNames = vue.computed(() => getColumnNames(props.columns, items.value));
15408
+ const itemsDataColumns = vue.computed(() => columnNames.value.filter((name) => getColumnNamesFromItems(items.value).includes(name)));
15409
+ const filteredColumns = vue.computed(() => filterColumns(items.value, props.columnFilter, columnFilterState.value, itemsDataColumns.value));
15410
+ const filteredTable = vue.computed(() => filterTable(filteredColumns.value, props.tableFilter, tableFilterState.value, itemsDataColumns.value));
15411
+ const sortedItems = vue.computed(() => sortItems(props.columnSorter, filteredTable.value, itemsDataColumns.value, sorterState.value));
15398
15412
  const numberOfPages = vue.computed(() => itemsPerPage.value ? Math.ceil(sortedItems.value.length / itemsPerPage.value) : 1);
15399
15413
  const firstItemOnActivePageIndex = vue.computed(() => activePage.value ? (activePage.value - 1) * itemsPerPage.value : 0);
15400
- const itemsOnActivePage = vue.computed(() => sortedItems.value.slice(firstItemOnActivePageIndex.value, firstItemOnActivePageIndex.value + itemsPerPage.value));
15401
- const currentItems = vue.computed(() => activePage.value ? itemsOnActivePage.value : sortedItems.value);
15402
- const isFiltered = vue.computed(() => {
15403
- return (tableFilterState.value ||
15404
- sorterState.column ||
15405
- Object.values(columnFilterState.value).join(''));
15406
- });
15414
+ const currentItems = vue.computed(() => activePage.value
15415
+ ? sortedItems.value.slice(firstItemOnActivePageIndex.value, firstItemOnActivePageIndex.value + itemsPerPage.value)
15416
+ : sortedItems.value);
15407
15417
  return () => vue.h('div', {}, [
15408
15418
  (props.tableFilter || props.cleaner) &&
15409
15419
  vue.h('div', {
@@ -15413,25 +15423,46 @@ const CSmartTable = vue.defineComponent({
15413
15423
  vue.h('div', {
15414
15424
  class: 'col-auto p-0',
15415
15425
  }, props.tableFilter &&
15416
- vue.h(CSmartTableFilter, {
15417
- filterLabel: props.tableFilterLabel,
15418
- filterPlaceholder: props.tableFilterPlaceholder,
15419
- onFilterInput: (value) => tableFilterChange(value, 'input'),
15420
- onFilterChange: (value) => tableFilterChange(value, 'change'),
15421
- value: tableFilterState.value,
15426
+ vue.h('div', {
15427
+ class: 'row mb-2',
15428
+ }, {
15429
+ default: () => [
15430
+ vue.h(CFormLabel, {
15431
+ class: 'col-sm-auto col-form-label',
15432
+ }, {
15433
+ default: () => props.tableFilterLabel,
15434
+ }),
15435
+ vue.h('div', {
15436
+ class: 'col-sm-auto',
15437
+ }, vue.h(CFormInput, {
15438
+ onInput: (e) => {
15439
+ handleTableFilterChange(e.target.value, 'input');
15440
+ },
15441
+ onChange: (e) => {
15442
+ handleTableFilterChange(e.target.value, 'change');
15443
+ },
15444
+ placeholder: props.tableFilterPlaceholder,
15445
+ value: tableFilterState.value,
15446
+ })),
15447
+ ],
15422
15448
  })),
15423
15449
  props.cleaner &&
15424
15450
  vue.h('div', {
15425
15451
  class: 'col-auto p-0',
15426
- }, vue.h(CSmartTableCleaner, {
15427
- onClick: () => clean(),
15428
- isFiltered: isFiltered.value,
15429
- }, {
15430
- // @slot Cleaner icon.
15431
- cleanerIcon: () => slots.cleanerIcon
15432
- ? slots.cleanerIcon()
15433
- : vue.h(CIcon, { width: '18', content: cilFilterX }),
15434
- })),
15452
+ }, vue.h('button', {
15453
+ type: 'button',
15454
+ class: 'btn btn-transparent',
15455
+ ...(!(tableFilterState.value ||
15456
+ sorterState.value.column ||
15457
+ Object.values(columnFilterState.value).join('')) && { disabled: true, tabIndex: -1 }),
15458
+ onClick: () => handleClean(),
15459
+ onKeydown: (event) => {
15460
+ if (event.key === 'Enter')
15461
+ handleClean();
15462
+ },
15463
+ }, slots.cleanerIcon
15464
+ ? slots.cleanerIcon()
15465
+ : vue.h(CIcon, { width: '18', content: cilFilterX }))),
15435
15466
  ]),
15436
15467
  vue.h('div', {
15437
15468
  class: 'position-relative',
@@ -15447,17 +15478,18 @@ const CSmartTable = vue.defineComponent({
15447
15478
  ...props.tableHeadProps,
15448
15479
  columnFilter: props.columnFilter,
15449
15480
  columnFilterValue: columnFilterState.value,
15450
- columns: props.columns ? props.columns : rawColumnNames.value,
15481
+ columns: props.columns ? props.columns : columnNames.value,
15451
15482
  columnSorter: props.columnSorter,
15452
15483
  items: items.value,
15453
15484
  selectable: props.selectable,
15454
- selectAll: selectedAll.value,
15455
- sorterState: sorterState,
15456
- onCustomFilterChange: (key, value) => columnFilterChange(key, value),
15457
- onFilterInput: (key, value) => columnFilterChange(key, value, 'input'),
15458
- onFilterChange: (key, value) => columnFilterChange(key, value, 'change'),
15485
+ selectAll: props.selectAll,
15486
+ selectedAll: selectedAll.value,
15487
+ sorterState: sorterState.value,
15488
+ onCustomFilterChange: (key, value) => handleColumnFilterChange(key, value),
15489
+ onFilterInput: (key, value) => handleColumnFilterChange(key, value, 'input'),
15490
+ onFilterChange: (key, value) => handleColumnFilterChange(key, value, 'change'),
15459
15491
  onSelectAllChecked: () => handleSelectAllChecked(),
15460
- onSortClick: (key, index) => sorterChange(key, index),
15492
+ onSortClick: (key, index) => handleSorterChange(key, index),
15461
15493
  }, {
15462
15494
  // @slot Sorter icon when items are unsorted.
15463
15495
  sortingIcon: () => slots.sortingIcon
@@ -15472,36 +15504,35 @@ const CSmartTable = vue.defineComponent({
15472
15504
  // @slot Sorter icon when items are sorted ascending.
15473
15505
  sortingIconAscending: () => slots.sortingIconAscending
15474
15506
  ? slots.sortingIconAscending()
15475
- : // : h(CIcon, { content: cilArrowBottom }, 'b'),
15476
- vue.h('svg', {
15477
- xmlns: 'http://www.w3.org/2000/svg',
15478
- class: 'icon',
15479
- viewBox: '0 0 512 512',
15480
- role: 'img',
15481
- innerHTML: cilArrowBottom[1],
15482
- }),
15507
+ : vue.h('svg', {
15508
+ xmlns: 'http://www.w3.org/2000/svg',
15509
+ class: 'icon',
15510
+ viewBox: '0 0 512 512',
15511
+ role: 'img',
15512
+ innerHTML: cilArrowBottom[1],
15513
+ }),
15483
15514
  // @slot Sorter icon when items are sorted descending.
15484
15515
  sortingIconDescending: () => slots.sortingIconDescending
15485
15516
  ? slots.sortingIconDescending()
15486
- : // : h(CIcon, { content: cilArrowTop }, 'c'),
15487
- vue.h('svg', {
15488
- xmlns: 'http://www.w3.org/2000/svg',
15489
- class: 'icon',
15490
- viewBox: '0 0 512 512',
15491
- role: 'img',
15492
- innerHTML: cilArrowTop[1],
15493
- }),
15517
+ : vue.h('svg', {
15518
+ xmlns: 'http://www.w3.org/2000/svg',
15519
+ class: 'icon',
15520
+ viewBox: '0 0 512 512',
15521
+ role: 'img',
15522
+ innerHTML: cilArrowTop[1],
15523
+ }),
15494
15524
  }),
15495
15525
  vue.h(CSmartTableBody, {
15526
+ clickableRows: props.clickableRows,
15527
+ columnNames: columnNames.value,
15496
15528
  currentItems: currentItems.value,
15497
15529
  firstItemOnActivePageIndex: firstItemOnActivePageIndex.value,
15498
15530
  noItemsLabel: props.noItemsLabel,
15531
+ onRowChecked: (item, value) => handleRowChecked(item, value),
15532
+ onRowClick: (item, index, columnName, event) => props.clickableRows && emit('rowClick', item, index, columnName, event),
15499
15533
  scopedSlots: slots,
15500
15534
  selectable: props.selectable,
15501
- onRowChecked: (id, value) => handleRowChecked(id, value),
15502
- onRowClick: (item, index, columnName, event) => handleRowClick(item, index, columnName, event),
15503
- rawColumnNames: rawColumnNames.value,
15504
- clickableRows: props.clickableRows,
15535
+ selected: selected.value,
15505
15536
  ...props.tableBodyProps,
15506
15537
  }),
15507
15538
  typeof props.footer === 'boolean' &&
@@ -15511,9 +15542,10 @@ const CSmartTable = vue.defineComponent({
15511
15542
  ...props.tableFootProps,
15512
15543
  columnFilter: false,
15513
15544
  columnSorter: false,
15514
- columns: props.columns ? props.columns : rawColumnNames.value,
15545
+ columns: props.columns ? props.columns : columnNames.value,
15515
15546
  selectable: props.selectable,
15516
- selectAll: selectedAll.value,
15547
+ selectAll: props.selectAll,
15548
+ selectedAll: selectedAll.value,
15517
15549
  onSelectAllChecked: () => handleSelectAllChecked(),
15518
15550
  }),
15519
15551
  Array.isArray(props.footer) &&
@@ -15540,6 +15572,11 @@ const CSmartTable = vue.defineComponent({
15540
15572
  { sides: ['top'], query: 'tbody' },
15541
15573
  { sides: ['bottom'], query: 'tbody' },
15542
15574
  ],
15575
+ }, {
15576
+ // @slot elementCover.
15577
+ ...(slots.elementCover && {
15578
+ default: () => slots.elementCover && slots.elementCover(),
15579
+ }),
15543
15580
  }),
15544
15581
  ],
15545
15582
  }),
@@ -15562,14 +15599,33 @@ const CSmartTable = vue.defineComponent({
15562
15599
  vue.h('div', {
15563
15600
  class: 'col-auto ms-auto',
15564
15601
  }, props.itemsPerPageSelect &&
15565
- vue.h(CSmartTableItemsPerPageSelector, {
15566
- itemsPerPage: itemsPerPage.value,
15567
- itemsPerPageLabel: props.itemsPerPageLabel,
15568
- itemsPerPageOptions: props.itemsPerPageOptions,
15569
- onChangeItemsPerPage: handleItemsPerPageChange,
15602
+ vue.h('div', {
15603
+ class: 'row',
15604
+ }, {
15605
+ default: () => [
15606
+ vue.h(CFormLabel, {
15607
+ class: 'col-auto col-form-label',
15608
+ }, {
15609
+ default: () => props.itemsPerPageLabel,
15610
+ }),
15611
+ vue.h('div', {
15612
+ class: 'col-auto',
15613
+ }, vue.h(CFormSelect, {
15614
+ value: itemsPerPage.value,
15615
+ onChange: handleItemsPerPageChange,
15616
+ }, {
15617
+ default: () => props.itemsPerPageOptions &&
15618
+ props.itemsPerPageOptions.map((number, index) => {
15619
+ return vue.h('option', {
15620
+ value: number,
15621
+ key: index,
15622
+ }, number);
15623
+ }),
15624
+ })),
15625
+ ],
15570
15626
  })),
15571
15627
  ]),
15572
- ]); //h
15628
+ ]);
15573
15629
  },
15574
15630
  });
15575
15631
 
@@ -16729,6 +16785,8 @@ var Components = /*#__PURE__*/Object.freeze({
16729
16785
  CToaster: CToaster,
16730
16786
  CTooltip: CTooltip,
16731
16787
  CTooltipPlugin: CTooltipPlugin,
16788
+ CVirtualScroller: CVirtualScroller,
16789
+ CVirtualScrollerPlugin: CVirtualScrollerPlugin,
16732
16790
  CWidgetStatsA: CWidgetStatsA,
16733
16791
  CWidgetStatsB: CWidgetStatsB,
16734
16792
  CWidgetStatsC: CWidgetStatsC,
@@ -17137,6 +17195,8 @@ exports.CToastPlugin = CToastPlugin;
17137
17195
  exports.CToaster = CToaster;
17138
17196
  exports.CTooltip = CTooltip;
17139
17197
  exports.CTooltipPlugin = CTooltipPlugin;
17198
+ exports.CVirtualScroller = CVirtualScroller;
17199
+ exports.CVirtualScrollerPlugin = CVirtualScrollerPlugin;
17140
17200
  exports.CWidgetStatsA = CWidgetStatsA;
17141
17201
  exports.CWidgetStatsB = CWidgetStatsB;
17142
17202
  exports.CWidgetStatsC = CWidgetStatsC;