@coreui/vue-pro 4.5.0 → 4.7.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/components/Types.d.ts +5 -5
  2. package/dist/components/calendar/CCalendar.d.ts +41 -3
  3. package/dist/components/date-picker/CDatePicker.d.ts +43 -4
  4. package/dist/components/date-range-picker/CDateRangePicker.d.ts +191 -4
  5. package/dist/components/form/CFormInput.d.ts +166 -1
  6. package/dist/components/form/CFormSelect.d.ts +1 -1
  7. package/dist/components/grid/CCol.d.ts +3 -3
  8. package/dist/components/grid/CRow.d.ts +1 -1
  9. package/dist/components/index.d.ts +1 -0
  10. package/dist/components/multi-select/CMultiSelect.d.ts +143 -4
  11. package/dist/components/multi-select/CMultiSelectOptions.d.ts +11 -0
  12. package/dist/components/multi-select/CMultiSelectSelection.d.ts +3 -3
  13. package/dist/components/pagination/index.d.ts +1 -2
  14. package/dist/components/picker/CPicker.d.ts +1 -1
  15. package/dist/components/popover/CPopover.d.ts +1 -1
  16. package/dist/components/smart-pagination/CSmartPagination.d.ts +257 -0
  17. package/dist/components/smart-pagination/index.d.ts +6 -0
  18. package/dist/components/smart-table/CSmartTable.d.ts +6 -4
  19. package/dist/components/smart-table/CSmartTableFilter.d.ts +2 -2
  20. package/dist/components/smart-table/CSmartTableHead.d.ts +2 -2
  21. package/dist/components/smart-table/CSmartTableInterface.d.ts +4 -1
  22. package/dist/components/table/CTable.d.ts +1 -1
  23. package/dist/components/table/CTableCaption.d.ts +2 -8
  24. package/dist/components/time-picker/CTimePicker.d.ts +2 -1
  25. package/dist/components/tooltip/CTooltip.d.ts +1 -1
  26. package/dist/components/widgets/CWidgetStatsD.d.ts +1 -1
  27. package/dist/index.es.js +1560 -1017
  28. package/dist/index.es.js.map +1 -1
  29. package/dist/index.js +1559 -1015
  30. package/dist/index.js.map +1 -1
  31. package/dist/utils/getNextSibling.d.ts +2 -0
  32. package/dist/utils/getPreviousSibling.d.ts +2 -0
  33. package/dist/utils/index.d.ts +4 -0
  34. package/dist/utils/isVisible.d.ts +2 -0
  35. package/dist/utils/time.d.ts +2 -2
  36. package/package.json +2 -2
  37. package/src/components/calendar/CCalendar.ts +46 -4
  38. package/src/components/carousel/CCarousel.ts +1 -9
  39. package/src/components/date-picker/CDatePicker.ts +44 -3
  40. package/src/components/date-range-picker/CDateRangePicker.ts +340 -170
  41. package/src/components/form/CFormInput.ts +2 -0
  42. package/src/components/index.ts +1 -0
  43. package/src/components/loading-button/CLoadingButton.ts +1 -2
  44. package/src/components/multi-select/CMultiSelect.ts +295 -173
  45. package/src/components/multi-select/CMultiSelectOptions.ts +48 -10
  46. package/src/components/multi-select/CMultiSelectSelection.ts +1 -1
  47. package/src/components/pagination/index.ts +1 -3
  48. package/src/components/sidebar/CSidebar.ts +2 -10
  49. package/src/components/{pagination → smart-pagination}/CSmartPagination.ts +1 -2
  50. package/src/components/smart-pagination/index.ts +10 -0
  51. package/src/components/smart-table/CSmartTable.ts +10 -5
  52. package/src/components/smart-table/CSmartTableInterface.ts +4 -0
  53. package/src/components/table/CTableCaption.ts +0 -1
  54. package/src/components/time-picker/CTimePicker.ts +198 -64
  55. package/src/components/time-picker/CTimePickerRollCol.ts +9 -0
  56. package/src/utils/getNextSibling.ts +18 -0
  57. package/src/utils/getPreviousSibling.ts +18 -0
  58. package/src/utils/index.ts +5 -0
  59. package/src/utils/isVisible.ts +11 -0
  60. package/src/utils/time.ts +14 -6
package/dist/index.js CHANGED
@@ -1163,6 +1163,29 @@ const CCalendar = vue.defineComponent({
1163
1163
  type: Number,
1164
1164
  default: 1,
1165
1165
  },
1166
+ /**
1167
+ * Set the format of day name.
1168
+ *
1169
+ * @default 'numeric'
1170
+ * @since 4.6.0
1171
+ */
1172
+ dayFormat: {
1173
+ type: [Function, String],
1174
+ default: 'numeric',
1175
+ required: false,
1176
+ validator: (value) => {
1177
+ if (typeof value === 'string') {
1178
+ return ['numeric', '2-digit'].includes(value);
1179
+ }
1180
+ if (typeof value === 'function') {
1181
+ return true;
1182
+ }
1183
+ if (typeof value === 'function') {
1184
+ return true;
1185
+ }
1186
+ return false;
1187
+ },
1188
+ },
1166
1189
  /**
1167
1190
  * Specify the list of dates that cannot be selected.
1168
1191
  */
@@ -1215,6 +1238,12 @@ const CCalendar = vue.defineComponent({
1215
1238
  type: Boolean,
1216
1239
  default: true,
1217
1240
  },
1241
+ /**
1242
+ * Reorder year-month navigation, and render year first.
1243
+ *
1244
+ * @since 4.6.0
1245
+ */
1246
+ navYearFirst: Boolean,
1218
1247
  /**
1219
1248
  * Allow range selection.
1220
1249
  */
@@ -1235,7 +1264,7 @@ const CCalendar = vue.defineComponent({
1235
1264
  * @type number | 'long' | 'narrow' | 'short'
1236
1265
  */
1237
1266
  weekdayFormat: {
1238
- type: [Number, String],
1267
+ type: [Function, Number, String],
1239
1268
  default: 2,
1240
1269
  validator: (value) => {
1241
1270
  if (typeof value === 'string') {
@@ -1244,6 +1273,9 @@ const CCalendar = vue.defineComponent({
1244
1273
  if (typeof value === 'number') {
1245
1274
  return true;
1246
1275
  }
1276
+ if (typeof value === 'function') {
1277
+ return true;
1278
+ }
1247
1279
  return false;
1248
1280
  },
1249
1281
  },
@@ -1419,11 +1451,15 @@ const CCalendar = vue.defineComponent({
1419
1451
  vue.h('thead', {}, vue.h('tr', {}, weekDays.map(({ date }) => {
1420
1452
  return vue.h('th', { class: 'calendar-cell' }, vue.h('div', {
1421
1453
  class: 'calendar-header-cell-inner',
1422
- }, props.weekdayFormat === 'string'
1423
- ? date.toLocaleDateString(props.locale, { weekday: props.weekdayFormat })
1424
- : date
1425
- .toLocaleDateString(props.locale, { weekday: 'long' })
1426
- .slice(0, props.weekdayFormat)));
1454
+ }, typeof props.weekdayFormat === 'function'
1455
+ ? props.weekdayFormat(date)
1456
+ : typeof props.weekdayFormat === 'string'
1457
+ ? date.toLocaleDateString(props.locale, {
1458
+ weekday: props.weekdayFormat,
1459
+ })
1460
+ : date
1461
+ .toLocaleDateString(props.locale, { weekday: 'long' })
1462
+ .slice(0, props.weekdayFormat)));
1427
1463
  }))),
1428
1464
  vue.h('tbody', {}, [
1429
1465
  view.value === 'days' &&
@@ -1456,7 +1492,11 @@ const CCalendar = vue.defineComponent({
1456
1492
  }),
1457
1493
  }, vue.h('div', {
1458
1494
  class: 'calendar-cell-inner',
1459
- }, date.toLocaleDateString(props.locale, { day: 'numeric' })));
1495
+ }, typeof props.dayFormat === 'function'
1496
+ ? props.dayFormat(date)
1497
+ : date.toLocaleDateString(props.locale, {
1498
+ day: props.dayFormat,
1499
+ })));
1460
1500
  }));
1461
1501
  }),
1462
1502
  view.value === 'months' &&
@@ -1524,6 +1564,7 @@ const CCalendar = vue.defineComponent({
1524
1564
  ]),
1525
1565
  vue.h('div', {
1526
1566
  class: 'calendar-nav-date',
1567
+ ...(props.navYearFirst && { style: { display: 'flex', justifyContent: 'center' } }),
1527
1568
  }, [
1528
1569
  view.value === 'days' &&
1529
1570
  vue.h(CButton, {
@@ -1541,6 +1582,7 @@ const CCalendar = vue.defineComponent({
1541
1582
  if (props.navigation)
1542
1583
  view.value = 'years';
1543
1584
  },
1585
+ ...(props.navYearFirst && { style: { order: '-1' } }),
1544
1586
  }, () => date.toLocaleDateString(props.locale, { year: 'numeric' })),
1545
1587
  ]),
1546
1588
  props.navigation &&
@@ -1867,13 +1909,46 @@ const CCardPlugin = {
1867
1909
  },
1868
1910
  };
1869
1911
 
1870
- const isVisible$1 = (element) => {
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
+ const isVisible = (element) => {
1871
1945
  const rect = element.getBoundingClientRect();
1872
1946
  return (rect.top >= 0 &&
1873
1947
  rect.left >= 0 &&
1874
1948
  rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1875
1949
  rect.right <= (window.innerWidth || document.documentElement.clientWidth));
1876
1950
  };
1951
+
1877
1952
  const CCarousel = vue.defineComponent({
1878
1953
  name: 'CCarousel',
1879
1954
  props: {
@@ -1985,7 +2060,7 @@ const CCarousel = vue.defineComponent({
1985
2060
  const nextItemWhenVisible = () => {
1986
2061
  // Don't call next when the page isn't visible
1987
2062
  // or the carousel or its parent isn't visible
1988
- if (!document.hidden && isVisible$1(carouselRef.value)) {
2063
+ if (!document.hidden && isVisible(carouselRef.value)) {
1989
2064
  handleControlClick('next');
1990
2065
  }
1991
2066
  };
@@ -2004,7 +2079,7 @@ const CCarousel = vue.defineComponent({
2004
2079
  }
2005
2080
  };
2006
2081
  const handleScroll = () => {
2007
- if (!document.hidden && isVisible$1(carouselRef.value)) {
2082
+ if (!document.hidden && isVisible(carouselRef.value)) {
2008
2083
  visible.value = true;
2009
2084
  }
2010
2085
  else {
@@ -8294,6 +8369,8 @@ const CFormControlWrapper = vue.defineComponent({
8294
8369
  },
8295
8370
  });
8296
8371
 
8372
+ const File = typeof window !== 'undefined' ? window.File : class File extends Object {
8373
+ };
8297
8374
  const CFormInput = vue.defineComponent({
8298
8375
  name: 'CFormInput',
8299
8376
  props: {
@@ -11896,6 +11973,12 @@ const CTimePickerRollCol = vue.defineComponent({
11896
11973
  }
11897
11974
  init.value = false;
11898
11975
  });
11976
+ const handleKeyDown = (event, value) => {
11977
+ if (event.code === 'Space' || event.key === 'Enter') {
11978
+ event.preventDefault();
11979
+ emit('click', value);
11980
+ }
11981
+ };
11899
11982
  return () => vue.h('div', { class: 'time-picker-roll-col', ref: colRef }, props.elements.map((element) => {
11900
11983
  return vue.h('div', {
11901
11984
  class: [
@@ -11905,7 +11988,9 @@ const CTimePickerRollCol = vue.defineComponent({
11905
11988
  },
11906
11989
  ],
11907
11990
  onClick: () => emit('click', element.value),
11991
+ onKeydown: (event) => handleKeyDown(event, element.value),
11908
11992
  role: 'button',
11993
+ tabindex: 0,
11909
11994
  }, element.label);
11910
11995
  }));
11911
11996
  },
@@ -11934,10 +12019,10 @@ const getAmPm = (date, locale) => {
11934
12019
  }
11935
12020
  return date.getHours() >= 12 ? 'pm' : 'am';
11936
12021
  };
11937
- const getListOfHours = (locale) => Array.from({ length: isAmPm(locale) ? 12 : 24 }, (_, i) => {
12022
+ const getListOfHours = (locale, ampm = 'auto') => Array.from({ length: (ampm === 'auto' && isAmPm(locale)) || ampm ? 12 : 24 }, (_, i) => {
11938
12023
  return {
11939
- value: isAmPm(locale) ? i + 1 : i,
11940
- label: (isAmPm(locale) ? i + 1 : i).toLocaleString(locale),
12024
+ value: (ampm === 'auto' && isAmPm(locale)) || ampm ? i + 1 : i,
12025
+ label: ((ampm === 'auto' && isAmPm(locale)) || ampm ? i + 1 : i).toLocaleString(locale),
11941
12026
  };
11942
12027
  });
11943
12028
  const getListOfMinutes = (locale, valueAsString = false) => Array.from({ length: 60 }, (_, i) => {
@@ -11970,7 +12055,11 @@ const getListOfSeconds = (locale, valueAsString = false) => Array.from({ length:
11970
12055
  .split(':')[2],
11971
12056
  };
11972
12057
  });
11973
- const getSelectedHour = (date, locale) => date ? (isAmPm(locale) ? convert24hTo12h(date.getHours()) : date.getHours()) : '';
12058
+ const getSelectedHour = (date, locale, ampm = 'auto') => date
12059
+ ? (ampm === 'auto' && isAmPm(locale)) || ampm
12060
+ ? convert24hTo12h(date.getHours())
12061
+ : date.getHours()
12062
+ : '';
11974
12063
  const getSelectedMinutes = (date) => (date ? date.getMinutes() : '');
11975
12064
  const getSelectedSeconds = (date) => (date ? date.getSeconds() : '');
11976
12065
  const isAmPm = (locale) => ['am', 'AM', 'pm', 'PM'].some((el) => new Date().toLocaleString(locale).includes(el));
@@ -11983,6 +12072,24 @@ const CTimePicker = vue.defineComponent({
11983
12072
  name: 'CTimePicker',
11984
12073
  props: {
11985
12074
  ...CPicker.props,
12075
+ /**
12076
+ * Set if the component should use the 12/24 hour format. If `true` forces the interface to a 12-hour format. If `false` forces the interface into a 24-hour format. If `auto` the current locale will determine the 12 or 24-hour interface by default locales.
12077
+ *
12078
+ * @since 4.7.0
12079
+ */
12080
+ ampm: {
12081
+ type: [Boolean, String],
12082
+ default: 'auto',
12083
+ validator: (value) => {
12084
+ if (typeof value == 'string') {
12085
+ return ['auto'].includes(value);
12086
+ }
12087
+ if (typeof value == 'boolean') {
12088
+ return true;
12089
+ }
12090
+ return false;
12091
+ },
12092
+ },
11986
12093
  /**
11987
12094
  * Toggle visibility or set the content of cancel button.
11988
12095
  */
@@ -12069,6 +12176,34 @@ const CTimePicker = vue.defineComponent({
12069
12176
  return ['ghost', 'outline'].includes(value);
12070
12177
  },
12071
12178
  },
12179
+ /**
12180
+ * Provide valuable, actionable feedback.
12181
+ *
12182
+ * @since 4.6.0
12183
+ */
12184
+ feedback: {
12185
+ type: String,
12186
+ },
12187
+ /**
12188
+ * Provide valuable, actionable feedback.
12189
+ *
12190
+ * @since 4.6.0
12191
+ */
12192
+ feedbackInvalid: {
12193
+ type: String,
12194
+ },
12195
+ /**
12196
+ * Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
12197
+ *
12198
+ * @since 4.6.0
12199
+ */
12200
+ feedbackValid: {
12201
+ type: String,
12202
+ },
12203
+ /**
12204
+ * The id global attribute defines an identifier (ID) that must be unique in the whole document.
12205
+ */
12206
+ id: String,
12072
12207
  /**
12073
12208
  * Toggle visibility or set the content of the input indicator.
12074
12209
  */
@@ -12080,6 +12215,20 @@ const CTimePicker = vue.defineComponent({
12080
12215
  * Toggle the readonly state for the component.
12081
12216
  */
12082
12217
  inputReadOnly: Boolean,
12218
+ /**
12219
+ * Set component validation state to invalid.
12220
+ *
12221
+ * @since 4.6.0
12222
+ */
12223
+ invalid: Boolean,
12224
+ /**
12225
+ * Add a caption for a component.
12226
+ *
12227
+ * @since 4.6.0
12228
+ */
12229
+ label: {
12230
+ type: String,
12231
+ },
12083
12232
  /**
12084
12233
  * Sets the default locale for components. If not set, it is inherited from the navigator.language.
12085
12234
  */
@@ -12094,6 +12243,15 @@ const CTimePicker = vue.defineComponent({
12094
12243
  type: String,
12095
12244
  default: 'Select time',
12096
12245
  },
12246
+ /**
12247
+ * Show seconds.
12248
+ *
12249
+ * @since 4.7.0
12250
+ */
12251
+ seconds: {
12252
+ type: Boolean,
12253
+ default: true,
12254
+ },
12097
12255
  /**
12098
12256
  * Size the component small or large.
12099
12257
  *
@@ -12106,12 +12264,32 @@ const CTimePicker = vue.defineComponent({
12106
12264
  return ['sm', 'lg'].includes(value);
12107
12265
  },
12108
12266
  },
12267
+ /**
12268
+ * Add helper text to the component.
12269
+ *
12270
+ * @since 4.6.0
12271
+ */
12272
+ text: {
12273
+ type: String,
12274
+ },
12109
12275
  /**
12110
12276
  * Initial selected time.
12111
12277
  */
12112
12278
  time: {
12113
12279
  type: [Date, String],
12114
12280
  },
12281
+ /**
12282
+ * Display validation feedback in a styled tooltip.
12283
+ *
12284
+ * @since 4.6.0
12285
+ */
12286
+ tooltipFeedback: Boolean,
12287
+ /**
12288
+ * Set component validation state to valid.
12289
+ *
12290
+ * @since 4.6.0
12291
+ */
12292
+ valid: Boolean,
12115
12293
  /**
12116
12294
  * Set the time picker variant to a roll or select.
12117
12295
  *
@@ -12124,6 +12302,10 @@ const CTimePicker = vue.defineComponent({
12124
12302
  return ['roll', 'select'].includes(value);
12125
12303
  },
12126
12304
  },
12305
+ /**
12306
+ * Toggle the visibility of the component.
12307
+ */
12308
+ visible: Boolean,
12127
12309
  },
12128
12310
  emits: [
12129
12311
  /**
@@ -12138,8 +12320,15 @@ const CTimePicker = vue.defineComponent({
12138
12320
  * Callback fired when the component requests to be shown.
12139
12321
  */
12140
12322
  'show',
12323
+ /**
12324
+ * Callback fired when the time changed.
12325
+ *
12326
+ * @since 4.7.0
12327
+ */
12328
+ 'update:time',
12141
12329
  ],
12142
- setup(props, { emit, slots }) {
12330
+ setup(props, { emit, attrs, slots }) {
12331
+ const visible = vue.ref(props.visible);
12143
12332
  const date = vue.ref(convertTimeToDate(props.time));
12144
12333
  const initialDate = vue.ref(null);
12145
12334
  const ampm = vue.ref(date.value ? getAmPm(new Date(date.value), props.locale) : 'am');
@@ -12154,6 +12343,8 @@ const CTimePicker = vue.defineComponent({
12154
12343
  const handleClear = (event) => {
12155
12344
  event.stopPropagation();
12156
12345
  date.value = null;
12346
+ emit('change', null);
12347
+ emit('update:time', null);
12157
12348
  };
12158
12349
  const handleTimeChange = (set, value) => {
12159
12350
  const _date = date.value || new Date('1970-01-01');
@@ -12166,7 +12357,7 @@ const CTimePicker = vue.defineComponent({
12166
12357
  }
12167
12358
  }
12168
12359
  if (set === 'hours') {
12169
- if (isAmPm(props.locale)) {
12360
+ if ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm) {
12170
12361
  _date.setHours(convert12hTo24h(ampm.value, parseInt(value)));
12171
12362
  }
12172
12363
  else {
@@ -12180,7 +12371,8 @@ const CTimePicker = vue.defineComponent({
12180
12371
  _date.setSeconds(parseInt(value));
12181
12372
  }
12182
12373
  date.value = new Date(_date);
12183
- emit('change', _date.toTimeString(), _date.toLocaleTimeString(), _date);
12374
+ emit('change', _date.toTimeString(), _date.toLocaleTimeString(props.locale), _date);
12375
+ emit('update:time', _date.toLocaleTimeString(props.locale));
12184
12376
  };
12185
12377
  const InputGroup = () => vue.h(CInputGroup, { class: 'picker-input-group', size: props.size }, () => [
12186
12378
  vue.h(CFormInput, {
@@ -12193,7 +12385,12 @@ const CTimePicker = vue.defineComponent({
12193
12385
  },
12194
12386
  placeholder: props.placeholder,
12195
12387
  readonly: props.inputReadOnly,
12196
- value: date.value ? date.value.toLocaleTimeString(props.locale) : '',
12388
+ value: date.value
12389
+ ? date.value.toLocaleTimeString(props.locale, {
12390
+ hour12: (props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm ? true : false,
12391
+ ...(!props.seconds && { timeStyle: 'short' }),
12392
+ })
12393
+ : '',
12197
12394
  }),
12198
12395
  (props.indicator || props.cleaner) &&
12199
12396
  vue.h(CInputGroupText, {}, () => [
@@ -12234,14 +12431,15 @@ const CTimePicker = vue.defineComponent({
12234
12431
  onChange: (event) => handleTimeChange('minutes', event.target.value),
12235
12432
  ...(date.value && { value: getSelectedMinutes(date.value) }),
12236
12433
  }),
12237
- ':',
12238
- // @ts-expect-error the getListOfMinutes function returns corect type
12239
- vue.h(CFormSelect, {
12240
- disabled: props.disabled,
12241
- options: getListOfSeconds(props.locale, true),
12242
- onChange: (event) => handleTimeChange('seconds', event.target.value),
12243
- ...(date.value && { value: getSelectedSeconds(date.value) }),
12244
- }),
12434
+ props.seconds && ':',
12435
+ props.seconds &&
12436
+ // @ts-expect-error the getListOfMinutes function returns corect type
12437
+ vue.h(CFormSelect, {
12438
+ disabled: props.disabled,
12439
+ options: getListOfSeconds(props.locale, true),
12440
+ onChange: (event) => handleTimeChange('seconds', event.target.value),
12441
+ ...(date.value && { value: getSelectedSeconds(date.value) }),
12442
+ }),
12245
12443
  isAmPm(props.locale) &&
12246
12444
  vue.h(CFormSelect, {
12247
12445
  disabled: props.disabled,
@@ -12255,21 +12453,22 @@ const CTimePicker = vue.defineComponent({
12255
12453
  ];
12256
12454
  const TimePickerRoll = () => [
12257
12455
  vue.h(CTimePickerRollCol, {
12258
- elements: getListOfHours(props.locale),
12456
+ elements: getListOfHours(props.locale, props.ampm),
12259
12457
  onClick: (index) => handleTimeChange('hours', index.toString()),
12260
- selected: getSelectedHour(date.value, props.locale),
12458
+ selected: getSelectedHour(date.value, props.locale, props.ampm),
12261
12459
  }),
12262
12460
  vue.h(CTimePickerRollCol, {
12263
12461
  elements: getListOfMinutes(props.locale),
12264
12462
  onClick: (index) => handleTimeChange('minutes', index.toString()),
12265
12463
  selected: getSelectedMinutes(date.value),
12266
12464
  }),
12267
- vue.h(CTimePickerRollCol, {
12268
- elements: getListOfSeconds(props.locale),
12269
- onClick: (index) => handleTimeChange('seconds', index.toString()),
12270
- selected: getSelectedSeconds(date.value),
12271
- }),
12272
- isAmPm(props.locale) &&
12465
+ props.seconds &&
12466
+ vue.h(CTimePickerRollCol, {
12467
+ elements: getListOfSeconds(props.locale),
12468
+ onClick: (index) => handleTimeChange('seconds', index.toString()),
12469
+ selected: getSelectedSeconds(date.value),
12470
+ }),
12471
+ ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm) &&
12273
12472
  vue.h(CTimePickerRollCol, {
12274
12473
  elements: [
12275
12474
  { value: 'am', label: 'AM' },
@@ -12279,49 +12478,66 @@ const CTimePicker = vue.defineComponent({
12279
12478
  selected: ampm.value,
12280
12479
  }),
12281
12480
  ];
12282
- return () => vue.h(CPicker, {
12283
- cancelButton: props.cancelButton,
12284
- cancelButtonColor: props.cancelButtonColor,
12285
- cancelButtonSize: props.cancelButtonSize,
12286
- cancelButtonVariant: props.cancelButtonVariant,
12287
- class: 'time-picker',
12288
- confirmButton: props.confirmButton,
12289
- confirmButtonColor: props.confirmButtonColor,
12290
- confirmButtonSize: props.confirmButtonSize,
12291
- confirmButtonVariant: props.confirmButtonVariant,
12292
- container: props.container,
12293
- disabled: props.disabled,
12294
- footer: true,
12295
- onCancel: () => {
12296
- if (initialDate.value) {
12297
- date.value = new Date(initialDate.value);
12298
- }
12299
- },
12300
- onHide: () => {
12301
- emit('hide');
12302
- },
12303
- onShow: () => {
12304
- if (date.value) {
12305
- initialDate.value = new Date(date.value);
12306
- }
12307
- emit('show');
12308
- },
12481
+ return () => vue.h(CFormControlWrapper, {
12482
+ describedby: attrs['aria-describedby'],
12483
+ feedback: props.feedback,
12484
+ feedbackInvalid: props.feedbackInvalid,
12485
+ feedbackValid: props.feedbackValid,
12486
+ id: props.id,
12487
+ invalid: props.invalid,
12488
+ label: props.label,
12489
+ text: props.text,
12490
+ tooltipFeedback: props.tooltipFeedback,
12491
+ valid: props.valid,
12309
12492
  }, {
12310
- ...(slots.cancelButton && {
12311
- cancelButton: () => slots.cancelButton && slots.cancelButton(),
12312
- }),
12313
- ...(slots.confirmButton && {
12314
- confirmButton: () => slots.confirmButton && slots.confirmButton(),
12493
+ default: () => vue.h(CPicker, {
12494
+ cancelButton: props.cancelButton,
12495
+ cancelButtonColor: props.cancelButtonColor,
12496
+ cancelButtonSize: props.cancelButtonSize,
12497
+ cancelButtonVariant: props.cancelButtonVariant,
12498
+ class: ['time-picker', { 'is-invalid': props.invalid, 'is-valid': props.valid }],
12499
+ confirmButton: props.confirmButton,
12500
+ confirmButtonColor: props.confirmButtonColor,
12501
+ confirmButtonSize: props.confirmButtonSize,
12502
+ confirmButtonVariant: props.confirmButtonVariant,
12503
+ container: props.container,
12504
+ disabled: props.disabled,
12505
+ footer: true,
12506
+ onCancel: () => {
12507
+ if (initialDate.value) {
12508
+ date.value = new Date(initialDate.value);
12509
+ }
12510
+ visible.value = false;
12511
+ },
12512
+ onHide: () => {
12513
+ visible.value = false;
12514
+ emit('hide');
12515
+ },
12516
+ onShow: () => {
12517
+ if (date.value) {
12518
+ initialDate.value = new Date(date.value);
12519
+ }
12520
+ visible.value = true;
12521
+ emit('show');
12522
+ },
12523
+ visible: visible.value,
12524
+ }, {
12525
+ ...(slots.cancelButton && {
12526
+ cancelButton: () => slots.cancelButton && slots.cancelButton(),
12527
+ }),
12528
+ ...(slots.confirmButton && {
12529
+ confirmButton: () => slots.confirmButton && slots.confirmButton(),
12530
+ }),
12531
+ toggler: () => InputGroup(),
12532
+ default: () => vue.h('div', {
12533
+ class: [
12534
+ 'time-picker-body',
12535
+ {
12536
+ ['time-picker-roll']: props.variant === 'roll',
12537
+ },
12538
+ ],
12539
+ }, props.variant === 'select' ? TimePickerSelect() : TimePickerRoll()),
12315
12540
  }),
12316
- toggler: () => InputGroup(),
12317
- default: () => vue.h('div', {
12318
- class: [
12319
- 'time-picker-body',
12320
- {
12321
- ['time-picker-roll']: props.variant === 'roll',
12322
- },
12323
- ],
12324
- }, props.variant === 'select' ? TimePickerSelect() : TimePickerRoll()),
12325
12541
  });
12326
12542
  },
12327
12543
  });
@@ -12395,6 +12611,15 @@ const CDateRangePicker = vue.defineComponent({
12395
12611
  type: Boolean,
12396
12612
  default: true,
12397
12613
  },
12614
+ /**
12615
+ * If true the dropdown will be immediately closed after submitting the full date.
12616
+ *
12617
+ * @since 4.7.0
12618
+ */
12619
+ closeOnSelect: {
12620
+ type: Boolean,
12621
+ default: true,
12622
+ },
12398
12623
  /**
12399
12624
  * Toggle visibility or set the content of confirm button.
12400
12625
  */
@@ -12434,6 +12659,29 @@ const CDateRangePicker = vue.defineComponent({
12434
12659
  return ['ghost', 'outline'].includes(value);
12435
12660
  },
12436
12661
  },
12662
+ /**
12663
+ * Set the format of day name.
12664
+ *
12665
+ * @default 'numeric'
12666
+ * @since 4.6.0
12667
+ */
12668
+ dayFormat: {
12669
+ type: [Function, String],
12670
+ default: 'numeric',
12671
+ required: false,
12672
+ validator: (value) => {
12673
+ if (typeof value === 'string') {
12674
+ return ['numeric', '2-digit'].includes(value);
12675
+ }
12676
+ if (typeof value === 'function') {
12677
+ return true;
12678
+ }
12679
+ if (typeof value === 'function') {
12680
+ return true;
12681
+ }
12682
+ return false;
12683
+ },
12684
+ },
12437
12685
  /**
12438
12686
  * Toggle the disabled state for the component.
12439
12687
  */
@@ -12451,6 +12699,30 @@ const CDateRangePicker = vue.defineComponent({
12451
12699
  type: [Date, String],
12452
12700
  required: false,
12453
12701
  },
12702
+ /**
12703
+ * Provide valuable, actionable feedback.
12704
+ *
12705
+ * @since 4.6.0
12706
+ */
12707
+ feedback: {
12708
+ type: String,
12709
+ },
12710
+ /**
12711
+ * Provide valuable, actionable feedback.
12712
+ *
12713
+ * @since 4.6.0
12714
+ */
12715
+ feedbackInvalid: {
12716
+ type: String,
12717
+ },
12718
+ /**
12719
+ * Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
12720
+ *
12721
+ * @since 4.6.0
12722
+ */
12723
+ feedbackValid: {
12724
+ type: String,
12725
+ },
12454
12726
  /**
12455
12727
  * Sets the day of start week.
12456
12728
  * - 0 - Sunday,
@@ -12493,6 +12765,20 @@ const CDateRangePicker = vue.defineComponent({
12493
12765
  * Toggle the readonly state for the component.
12494
12766
  */
12495
12767
  inputReadOnly: Boolean,
12768
+ /**
12769
+ * Set component validation state to invalid.
12770
+ *
12771
+ * @since 4.6.0
12772
+ */
12773
+ invalid: Boolean,
12774
+ /**
12775
+ * Add a caption for a component.
12776
+ *
12777
+ * @since 4.6.0
12778
+ */
12779
+ label: {
12780
+ type: String,
12781
+ },
12496
12782
  /**
12497
12783
  * Sets the default locale for components. If not set, it is inherited from the navigator.language.
12498
12784
  */
@@ -12519,6 +12805,12 @@ const CDateRangePicker = vue.defineComponent({
12519
12805
  type: Boolean,
12520
12806
  default: true,
12521
12807
  },
12808
+ /**
12809
+ * Reorder year-month navigation, and render year first.
12810
+ *
12811
+ * @since 4.6.0
12812
+ */
12813
+ navYearFirst: Boolean,
12522
12814
  /**
12523
12815
  * Specifies a short hint that is visible in the input.
12524
12816
  */
@@ -12566,6 +12858,14 @@ const CDateRangePicker = vue.defineComponent({
12566
12858
  startDate: {
12567
12859
  type: [Date, String],
12568
12860
  },
12861
+ /**
12862
+ * Add helper text to the component.
12863
+ *
12864
+ * @since 4.6.0
12865
+ */
12866
+ text: {
12867
+ type: String,
12868
+ },
12569
12869
  /**
12570
12870
  * Provide an additional time selection by adding select boxes to choose times.
12571
12871
  */
@@ -12609,13 +12909,29 @@ const CDateRangePicker = vue.defineComponent({
12609
12909
  return ['ghost', 'outline'].includes(value);
12610
12910
  },
12611
12911
  },
12912
+ /**
12913
+ * Display validation feedback in a styled tooltip.
12914
+ *
12915
+ * @since 4.6.0
12916
+ */
12917
+ tooltipFeedback: Boolean,
12918
+ /**
12919
+ * Set component validation state to valid.
12920
+ *
12921
+ * @since 4.6.0
12922
+ */
12923
+ valid: Boolean,
12924
+ /**
12925
+ * Toggle the visibility of the component.
12926
+ */
12927
+ visible: Boolean,
12612
12928
  /**
12613
12929
  * Set length or format of day name.
12614
12930
  *
12615
12931
  * @type number | 'long' | 'narrow' | 'short'
12616
12932
  */
12617
12933
  weekdayFormat: {
12618
- type: [Number, String],
12934
+ type: [Function, Number, String],
12619
12935
  default: 2,
12620
12936
  validator: (value) => {
12621
12937
  if (typeof value === 'string') {
@@ -12624,6 +12940,9 @@ const CDateRangePicker = vue.defineComponent({
12624
12940
  if (typeof value === 'number') {
12625
12941
  return true;
12626
12942
  }
12943
+ if (typeof value === 'function') {
12944
+ return true;
12945
+ }
12627
12946
  return false;
12628
12947
  },
12629
12948
  },
@@ -12651,12 +12970,27 @@ const CDateRangePicker = vue.defineComponent({
12651
12970
  * @property {string} formatedDate - formated date
12652
12971
  */
12653
12972
  'start-date-change',
12654
- ],
12655
- setup(props, { slots, emit }) {
12656
- const calendarDate = vue.ref(props.calendarDate
12657
- ? new Date(props.calendarDate)
12658
- : props.startDate
12659
- ? new Date(props.startDate)
12973
+ /**
12974
+ * Callback fired when the start date changed.
12975
+ *
12976
+ * @property {Date | null} date - date object
12977
+ * @since 4.7.0
12978
+ */
12979
+ 'update:start-date',
12980
+ /**
12981
+ * Callback fired when the end date changed.
12982
+ *
12983
+ * @property {Date | null} date - date object
12984
+ * @since 4.7.0
12985
+ */
12986
+ 'update:end-date',
12987
+ ],
12988
+ setup(props, { slots, attrs, emit }) {
12989
+ const visible = vue.ref(props.visible);
12990
+ const calendarDate = vue.ref(props.calendarDate
12991
+ ? new Date(props.calendarDate)
12992
+ : props.startDate
12993
+ ? new Date(props.startDate)
12660
12994
  : props.endDate
12661
12995
  ? new Date(props.endDate)
12662
12996
  : new Date());
@@ -12727,6 +13061,13 @@ const CDateRangePicker = vue.defineComponent({
12727
13061
  selectEndDate.value = true;
12728
13062
  }
12729
13063
  emit('start-date-change', date, date ? formatDate(date) : undefined);
13064
+ emit('update:start-date', date);
13065
+ if (props.timepicker || props.footer) {
13066
+ return;
13067
+ }
13068
+ if (props.closeOnSelect && !props.range) {
13069
+ visible.value = false;
13070
+ }
12730
13071
  };
12731
13072
  const handleEndDateChange = (date) => {
12732
13073
  endDate.value = date;
@@ -12735,6 +13076,13 @@ const CDateRangePicker = vue.defineComponent({
12735
13076
  selectEndDate.value = false;
12736
13077
  }
12737
13078
  emit('end-date-change', date, date ? formatDate(date) : undefined);
13079
+ emit('update:end-date', date);
13080
+ if (props.timepicker || props.footer) {
13081
+ return;
13082
+ }
13083
+ if (props.closeOnSelect && startDate.value !== null) {
13084
+ visible.value = false;
13085
+ }
12738
13086
  };
12739
13087
  const handleClear = (event) => {
12740
13088
  event.stopPropagation();
@@ -12742,6 +13090,10 @@ const CDateRangePicker = vue.defineComponent({
12742
13090
  endDate.value = null;
12743
13091
  inputStartHoverValue.value = null;
12744
13092
  inputEndHoverValue.value = null;
13093
+ emit('start-date-change', null);
13094
+ emit('end-date-change', null);
13095
+ emit('update:start-date', null);
13096
+ emit('update:end-date', null);
12745
13097
  };
12746
13098
  const InputGroup = () => vue.h(CInputGroup, {
12747
13099
  class: 'picker-input-group',
@@ -12819,147 +13171,168 @@ const CDateRangePicker = vue.defineComponent({
12819
13171
  : vue.h('span', { class: 'picker-input-group-icon date-picker-cleaner-icon' })),
12820
13172
  ]),
12821
13173
  ]);
12822
- return () => vue.h(CPicker, {
12823
- cancelButton: props.cancelButton,
12824
- cancelButtonColor: props.cancelButtonColor,
12825
- cancelButtonSize: props.cancelButtonSize,
12826
- cancelButtonVariant: props.cancelButtonVariant,
12827
- class: 'date-picker',
12828
- confirmButton: props.confirmButton,
12829
- confirmButtonColor: props.confirmButtonColor,
12830
- confirmButtonSize: props.confirmButtonSize,
12831
- confirmButtonVariant: props.confirmButtonVariant,
12832
- disabled: props.disabled,
12833
- footer: props.footer || props.timepicker,
13174
+ return () => vue.h(CFormControlWrapper, {
13175
+ describedby: attrs['aria-describedby'],
13176
+ feedback: props.feedback,
13177
+ feedbackInvalid: props.feedbackInvalid,
13178
+ feedbackValid: props.feedbackValid,
12834
13179
  id: props.id,
12835
- onCancel: () => {
12836
- startDate.value = initialStartDate.value;
12837
- endDate.value = initialEndDate.value;
12838
- },
12839
- onHide: () => {
12840
- emit('hide');
12841
- },
12842
- onShow: () => {
12843
- if (startDate.value) {
12844
- initialStartDate.value = new Date(startDate.value);
12845
- }
12846
- if (endDate.value) {
12847
- initialEndDate.value = new Date(endDate.value);
12848
- }
12849
- emit('show');
12850
- },
13180
+ invalid: props.invalid,
13181
+ label: props.label,
13182
+ text: props.text,
13183
+ tooltipFeedback: props.tooltipFeedback,
13184
+ valid: props.valid,
12851
13185
  }, {
12852
- ...(slots.cancelButton && {
12853
- cancelButton: () => slots.cancelButton && slots.cancelButton(),
12854
- }),
12855
- ...(slots.confirmButton && {
12856
- confirmButton: () => slots.confirmButton && slots.confirmButton(),
12857
- }),
12858
- toggler: () => InputGroup(),
12859
- footer: () => vue.h(CButton, {
12860
- class: 'me-auto',
12861
- color: props.todayButtonColor,
12862
- size: props.todayButtonSize,
12863
- variant: props.todayButtonVariant,
12864
- onClick: () => {
12865
- const date = new Date();
12866
- startDate.value = date;
12867
- endDate.value = date;
12868
- calendarDate.value = date;
13186
+ default: () => vue.h(CPicker, {
13187
+ cancelButton: props.cancelButton,
13188
+ cancelButtonColor: props.cancelButtonColor,
13189
+ cancelButtonSize: props.cancelButtonSize,
13190
+ cancelButtonVariant: props.cancelButtonVariant,
13191
+ class: ['date-picker', { 'is-invalid': props.invalid, 'is-valid': props.valid }],
13192
+ confirmButton: props.confirmButton,
13193
+ confirmButtonColor: props.confirmButtonColor,
13194
+ confirmButtonSize: props.confirmButtonSize,
13195
+ confirmButtonVariant: props.confirmButtonVariant,
13196
+ disabled: props.disabled,
13197
+ footer: props.footer || props.timepicker,
13198
+ id: props.id,
13199
+ onCancel: () => {
13200
+ startDate.value = initialStartDate.value;
13201
+ endDate.value = initialEndDate.value;
13202
+ visible.value = false;
12869
13203
  },
12870
- }, () => props.todayButton),
12871
- default: () => vue.h('div', {
12872
- class: 'date-picker-body',
12873
- }, [
12874
- props.ranges &&
12875
- vue.h('div', { class: 'date-picker-ranges' }, Object.keys(props.ranges).map((key) => vue.h(CButton, {
12876
- color: 'secondary',
12877
- onClick: () => {
12878
- if (props.ranges) {
12879
- startDate.value = props.ranges[key][0];
12880
- endDate.value = props.ranges[key][1];
12881
- }
12882
- },
12883
- variant: 'ghost',
12884
- }, () => key))),
12885
- vue.h('div', { class: 'date-picker-calendars' }, vue.h(CCalendar, {
12886
- calendarDate: new Date(calendarDate.value.getFullYear(), calendarDate.value.getMonth(), 1),
12887
- calendars: props.calendars,
12888
- disabledDates: props.disabledDates,
12889
- ...(endDate.value && { endDate: endDate.value }),
12890
- firstDayOfWeek: props.firstDayOfWeek,
12891
- locale: props.locale,
12892
- maxDate: maxDate.value,
12893
- minDate: minDate.value,
12894
- navigation: props.navigation,
12895
- range: props.range,
12896
- selectEndDate: selectEndDate.value,
12897
- ...(startDate.value && { startDate: startDate.value }),
12898
- onCalendarCellHover: (date) => handleCalendarCellHover(date),
12899
- onCalendarDateChange: (date) => handleCalendarDateChange(date),
12900
- onStartDateChange: (date) => handleStartDateChange(date),
12901
- onEndDateChange: (date) => handleEndDateChange(date),
12902
- }, {
12903
- /**
12904
- * @slot Location for next icon.
12905
- */
12906
- ...(slots.navNextIcon && {
12907
- navNextIcon: () => slots.navNextIcon && slots.navNextIcon(),
12908
- }),
12909
- /**
12910
- * @slot Location for next double icon.
12911
- */
12912
- ...(slots.navNextDoubleIcon && {
12913
- navNextDoubleIcon: () => slots.navNextDoubleIcon && slots.navNextDoubleIcon(),
12914
- }),
12915
- /**
12916
- * @slot Location for previous icon.
12917
- */
12918
- ...(slots.navPrevIcon && {
12919
- navPrevIcon: () => slots.navPrevIcon && slots.navPrevIcon(),
12920
- }),
12921
- /**
12922
- * @slot Location for double previous icon.
12923
- */
12924
- ...(slots.navPrevDoubleIcon && {
12925
- navPrevDoubleIcon: () => slots.navPrevDoubleIcon && slots.navPrevDoubleIcon(),
12926
- }),
12927
- })),
12928
- props.timepicker &&
12929
- vue.h('div', { class: 'date-picker-timepickers' }, isMobile.value || (props.range && props.calendars === 1)
12930
- ? [
12931
- vue.h(CTimePicker, {
12932
- container: 'inline',
12933
- disabled: startDate.value === null ? true : false,
12934
- locale: props.locale,
12935
- onChange: (_, __, date) => handleStartDateChange(date),
12936
- time: startDate.value,
12937
- variant: 'select',
12938
- }),
12939
- vue.h(CTimePicker, {
13204
+ onHide: () => {
13205
+ visible.value = false;
13206
+ emit('hide');
13207
+ },
13208
+ onShow: () => {
13209
+ if (startDate.value) {
13210
+ initialStartDate.value = new Date(startDate.value);
13211
+ }
13212
+ if (endDate.value) {
13213
+ initialEndDate.value = new Date(endDate.value);
13214
+ }
13215
+ visible.value = true;
13216
+ emit('show');
13217
+ },
13218
+ visible: visible.value,
13219
+ }, {
13220
+ ...(slots.cancelButton && {
13221
+ cancelButton: () => slots.cancelButton && slots.cancelButton(),
13222
+ }),
13223
+ ...(slots.confirmButton && {
13224
+ confirmButton: () => slots.confirmButton && slots.confirmButton(),
13225
+ }),
13226
+ toggler: () => InputGroup(),
13227
+ footer: () => vue.h(CButton, {
13228
+ class: 'me-auto',
13229
+ color: props.todayButtonColor,
13230
+ size: props.todayButtonSize,
13231
+ variant: props.todayButtonVariant,
13232
+ onClick: () => {
13233
+ const date = new Date();
13234
+ startDate.value = date;
13235
+ endDate.value = date;
13236
+ calendarDate.value = date;
13237
+ },
13238
+ }, () => props.todayButton),
13239
+ default: () => vue.h('div', {
13240
+ class: 'date-picker-body',
13241
+ }, [
13242
+ props.ranges &&
13243
+ vue.h('div', { class: 'date-picker-ranges' }, Object.keys(props.ranges).map((key) => vue.h(CButton, {
13244
+ color: 'secondary',
13245
+ onClick: () => {
13246
+ if (props.ranges) {
13247
+ startDate.value = props.ranges[key][0];
13248
+ endDate.value = props.ranges[key][1];
13249
+ }
13250
+ },
13251
+ variant: 'ghost',
13252
+ }, () => key))),
13253
+ vue.h('div', { class: 'date-picker-calendars' }, vue.h(CCalendar, {
13254
+ calendarDate: new Date(calendarDate.value.getFullYear(), calendarDate.value.getMonth(), 1),
13255
+ calendars: props.calendars,
13256
+ dayFormat: props.dayFormat,
13257
+ disabledDates: props.disabledDates,
13258
+ ...(endDate.value && { endDate: endDate.value }),
13259
+ firstDayOfWeek: props.firstDayOfWeek,
13260
+ locale: props.locale,
13261
+ maxDate: maxDate.value,
13262
+ minDate: minDate.value,
13263
+ navYearFirst: props.navYearFirst,
13264
+ navigation: props.navigation,
13265
+ range: props.range,
13266
+ selectEndDate: selectEndDate.value,
13267
+ ...(startDate.value && { startDate: startDate.value }),
13268
+ onCalendarCellHover: (date) => handleCalendarCellHover(date),
13269
+ onCalendarDateChange: (date) => handleCalendarDateChange(date),
13270
+ onStartDateChange: (date) => handleStartDateChange(date),
13271
+ onEndDateChange: (date) => handleEndDateChange(date),
13272
+ }, {
13273
+ /**
13274
+ * @slot Location for next icon.
13275
+ */
13276
+ ...(slots.navNextIcon && {
13277
+ navNextIcon: () => slots.navNextIcon && slots.navNextIcon(),
13278
+ }),
13279
+ /**
13280
+ * @slot Location for next double icon.
13281
+ */
13282
+ ...(slots.navNextDoubleIcon && {
13283
+ navNextDoubleIcon: () => slots.navNextDoubleIcon && slots.navNextDoubleIcon(),
13284
+ }),
13285
+ /**
13286
+ * @slot Location for previous icon.
13287
+ */
13288
+ ...(slots.navPrevIcon && {
13289
+ navPrevIcon: () => slots.navPrevIcon && slots.navPrevIcon(),
13290
+ }),
13291
+ /**
13292
+ * @slot Location for double previous icon.
13293
+ */
13294
+ ...(slots.navPrevDoubleIcon && {
13295
+ navPrevDoubleIcon: () => slots.navPrevDoubleIcon && slots.navPrevDoubleIcon(),
13296
+ }),
13297
+ })),
13298
+ props.timepicker &&
13299
+ vue.h('div', { class: 'date-picker-timepickers' }, isMobile.value || (props.range && props.calendars === 1)
13300
+ ? [
13301
+ vue.h(CTimePicker, {
13302
+ container: 'inline',
13303
+ disabled: startDate.value === null ? true : false,
13304
+ locale: props.locale,
13305
+ onChange: (_, __, date) => handleStartDateChange(date),
13306
+ time: startDate.value,
13307
+ variant: 'select',
13308
+ }),
13309
+ vue.h(CTimePicker, {
13310
+ container: 'inline',
13311
+ disabled: endDate.value === null ? true : false,
13312
+ locale: props.locale,
13313
+ onChange: (_, __, date) => handleEndDateChange(date),
13314
+ time: endDate.value,
13315
+ variant: 'select',
13316
+ }),
13317
+ ]
13318
+ : [...Array(props.calendars)].map((_, index) => vue.h(CTimePicker, {
12940
13319
  container: 'inline',
12941
- disabled: endDate.value === null ? true : false,
13320
+ disabled: index === 0
13321
+ ? startDate.value === null
13322
+ ? true
13323
+ : false
13324
+ : endDate.value === null
13325
+ ? true
13326
+ : false,
12942
13327
  locale: props.locale,
12943
- onChange: (_, __, date) => handleEndDateChange(date),
12944
- time: endDate.value,
13328
+ onChange: (_, __, date) => index === 0
13329
+ ? handleStartDateChange(date)
13330
+ : handleEndDateChange(date),
13331
+ time: index === 0 ? startDate.value : endDate.value,
12945
13332
  variant: 'select',
12946
- }),
12947
- ]
12948
- : [...Array(props.calendars)].map((_, index) => vue.h(CTimePicker, {
12949
- container: 'inline',
12950
- disabled: index === 0
12951
- ? startDate.value === null
12952
- ? true
12953
- : false
12954
- : endDate.value === null
12955
- ? true
12956
- : false,
12957
- locale: props.locale,
12958
- onChange: (_, __, date) => index === 0 ? handleStartDateChange(date) : handleEndDateChange(date),
12959
- time: index === 0 ? startDate.value : endDate.value,
12960
- variant: 'select',
12961
- }))),
12962
- ]),
13333
+ }))),
13334
+ ]),
13335
+ }),
12963
13336
  });
12964
13337
  },
12965
13338
  });
@@ -13065,6 +13438,29 @@ const CDatePicker = vue.defineComponent({
13065
13438
  return ['ghost', 'outline'].includes(value);
13066
13439
  },
13067
13440
  },
13441
+ /**
13442
+ * Set the format of day name.
13443
+ *
13444
+ * @default 'numeric'
13445
+ * @since 4.6.0
13446
+ */
13447
+ dayFormat: {
13448
+ type: [Function, String],
13449
+ default: 'numeric',
13450
+ required: false,
13451
+ validator: (value) => {
13452
+ if (typeof value === 'string') {
13453
+ return ['numeric', '2-digit'].includes(value);
13454
+ }
13455
+ if (typeof value === 'function') {
13456
+ return true;
13457
+ }
13458
+ if (typeof value === 'function') {
13459
+ return true;
13460
+ }
13461
+ return false;
13462
+ },
13463
+ },
13068
13464
  /**
13069
13465
  * Toggle the disabled state for the component.
13070
13466
  */
@@ -13149,6 +13545,12 @@ const CDatePicker = vue.defineComponent({
13149
13545
  type: Boolean,
13150
13546
  default: true,
13151
13547
  },
13548
+ /**
13549
+ * Reorder year-month navigation, and render year first.
13550
+ *
13551
+ * @since 4.6.0
13552
+ */
13553
+ navYearFirst: Boolean,
13152
13554
  /**
13153
13555
  * Specifies a short hint that is visible in the input.
13154
13556
  */
@@ -13178,7 +13580,7 @@ const CDatePicker = vue.defineComponent({
13178
13580
  * @type number | 'long' | 'narrow' | 'short'
13179
13581
  */
13180
13582
  weekdayFormat: {
13181
- type: [Number, String],
13583
+ type: [Function, Number, String],
13182
13584
  default: 2,
13183
13585
  validator: (value) => {
13184
13586
  if (typeof value === 'string') {
@@ -13187,6 +13589,9 @@ const CDatePicker = vue.defineComponent({
13187
13589
  if (typeof value === 'number') {
13188
13590
  return true;
13189
13591
  }
13592
+ if (typeof value === 'function') {
13593
+ return true;
13594
+ }
13190
13595
  return false;
13191
13596
  },
13192
13597
  },
@@ -13199,11 +13604,21 @@ const CDatePicker = vue.defineComponent({
13199
13604
  * @property {string} formatedDate - formated date
13200
13605
  */
13201
13606
  'date-change',
13607
+ /**
13608
+ * Callback fired when the date changed.
13609
+ *
13610
+ * @property {Date | null} date - date object
13611
+ * @since 4.7.0
13612
+ */
13613
+ 'update:date',
13202
13614
  ],
13203
13615
  setup(props, { emit }) {
13204
13616
  return () => vue.h(CDateRangePicker, {
13205
13617
  calendars: 1,
13206
- onStartDateChange: (date, formatedDate) => emit('date-change', date, formatedDate),
13618
+ onStartDateChange: (date, formatedDate) => {
13619
+ emit('date-change', date, formatedDate);
13620
+ emit('update:date', date);
13621
+ },
13207
13622
  range: false,
13208
13623
  startDate: props.date,
13209
13624
  ...props,
@@ -14034,11 +14449,10 @@ const CLoadingButton = vue.defineComponent({
14034
14449
  }
14035
14450
  };
14036
14451
  return () => vue.h(CButton, {
14452
+ ...props,
14037
14453
  class: ['btn-loading', { ['is-loading']: loading.value }],
14038
14454
  ...(props.disabledOnLoading && loading.value && { disabled: true }),
14039
14455
  onClick: () => handleOnClick(),
14040
- // TODO: remove non button props
14041
- ...props,
14042
14456
  }, {
14043
14457
  default: () => [
14044
14458
  vue.h(CSpinner, { class: 'btn-loading-spinner', size: 'sm', variant: props.spinnerType }),
@@ -14440,34 +14854,61 @@ const CMultiSelectOptions = vue.defineComponent({
14440
14854
  default: 'no items',
14441
14855
  required: false,
14442
14856
  },
14857
+ selected: {
14858
+ type: Array,
14859
+ default: () => [],
14860
+ required: false,
14861
+ },
14443
14862
  },
14444
14863
  emits: ['optionClick'],
14445
14864
  setup(props, { emit }) {
14865
+ const handleKeyDown = (event, option) => {
14866
+ if (event.code === 'Space' || event.key === 'Enter') {
14867
+ event.preventDefault();
14868
+ handleOptionClick && handleOptionClick(option);
14869
+ return;
14870
+ }
14871
+ if (event.key === 'Down' || event.key === 'ArrowDown') {
14872
+ event.preventDefault();
14873
+ const target = event.target;
14874
+ const next = getNextSibling(target, '.form-multi-select-option');
14875
+ if (next) {
14876
+ next.focus(); // eslint-disable-line prettier/prettier
14877
+ }
14878
+ }
14879
+ if (event.key === 'Up' || event.key === 'ArrowUp') {
14880
+ event.preventDefault();
14881
+ const target = event.target;
14882
+ const prev = getPreviousSibling(target, '.form-multi-select-option');
14883
+ if (prev) {
14884
+ prev.focus(); // eslint-disable-line prettier/prettier
14885
+ }
14886
+ }
14887
+ };
14446
14888
  const handleOptionClick = (option) => {
14447
14889
  emit('optionClick', option);
14448
14890
  };
14449
- const createOptions = (options) => {
14450
- return options.length > 0
14451
- ? options.map((option) => {
14452
- return option.options
14453
- ? vue.h('div', { class: 'form-multi-select-options' }, [
14454
- vue.h('div', { class: 'form-multi-select-optgroup-label' }, option.label),
14455
- createOptions(option.options),
14456
- ])
14457
- : vue.h('div', {
14458
- class: [
14459
- 'form-multi-select-option',
14460
- {
14461
- 'form-multi-select-option-with-checkbox': props.optionsStyle === 'checkbox',
14462
- 'form-multi-selected': option.selected,
14463
- disabled: option.disabled,
14464
- },
14465
- ],
14466
- onClick: () => handleOptionClick(option),
14467
- }, option.text);
14468
- })
14469
- : vue.h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel);
14470
- };
14891
+ // TODO: find solution how to remove any
14892
+ const createOptions = (options) => options.length > 0
14893
+ ? options.map((option) => option.options
14894
+ ? [
14895
+ vue.h('div', { class: 'form-multi-select-optgroup-label' }, option.label),
14896
+ createOptions(option.options),
14897
+ ]
14898
+ : vue.h('div', {
14899
+ class: [
14900
+ 'form-multi-select-option',
14901
+ {
14902
+ 'form-multi-select-option-with-checkbox': props.optionsStyle === 'checkbox',
14903
+ 'form-multi-selected': props.selected.some((_option) => _option.value === option.value),
14904
+ disabled: option.disabled,
14905
+ },
14906
+ ],
14907
+ onClick: () => handleOptionClick(option),
14908
+ onKeydown: (event) => handleKeyDown(event, option),
14909
+ tabindex: 0,
14910
+ }, option.text))
14911
+ : vue.h('div', { class: 'form-multi-select-options-empty' }, props.searchNoResultsLabel);
14471
14912
  return () => vue.h('div', {
14472
14913
  class: 'form-multi-select-options',
14473
14914
  ...(props.optionsMaxHeight !== 'auto' && {
@@ -14494,7 +14935,7 @@ const CMultiSelectSelection = vue.defineComponent({
14494
14935
  * Enables search input element.
14495
14936
  */
14496
14937
  search: {
14497
- type: Boolean,
14938
+ type: [Boolean, String],
14498
14939
  required: false,
14499
14940
  default: false,
14500
14941
  },
@@ -14564,6 +15005,11 @@ const CMultiSelectSelection = vue.defineComponent({
14564
15005
  },
14565
15006
  });
14566
15007
 
15008
+ const flattenArray = (options) => {
15009
+ return options.reduce((acc, val) => {
15010
+ return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
15011
+ }, []);
15012
+ };
14567
15013
  const CMultiSelect = vue.defineComponent({
14568
15014
  name: 'CMultiSelect',
14569
15015
  props: {
@@ -14585,6 +15031,50 @@ const CMultiSelect = vue.defineComponent({
14585
15031
  required: false,
14586
15032
  default: false,
14587
15033
  },
15034
+ /**
15035
+ * Provide valuable, actionable feedback.
15036
+ *
15037
+ * @since 4.6.0
15038
+ */
15039
+ feedback: {
15040
+ type: String,
15041
+ },
15042
+ /**
15043
+ * Provide valuable, actionable feedback.
15044
+ *
15045
+ * @since 4.6.0
15046
+ */
15047
+ feedbackInvalid: {
15048
+ type: String,
15049
+ },
15050
+ /**
15051
+ * Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
15052
+ *
15053
+ * @since 4.6.0
15054
+ */
15055
+ feedbackValid: {
15056
+ type: String,
15057
+ },
15058
+ /**
15059
+ * The id global attribute defines an identifier (ID) that must be unique in the whole document.
15060
+ */
15061
+ id: {
15062
+ type: String,
15063
+ },
15064
+ /**
15065
+ * Set component validation state to invalid.
15066
+ *
15067
+ * @since 4.6.0
15068
+ */
15069
+ invalid: Boolean,
15070
+ /**
15071
+ * Add a caption for a component.
15072
+ *
15073
+ * @since 4.6.0
15074
+ */
15075
+ label: {
15076
+ type: String,
15077
+ },
14588
15078
  /**
14589
15079
  * It specifies that multiple options can be selected at once.
14590
15080
  *
@@ -14641,9 +15131,18 @@ const CMultiSelect = vue.defineComponent({
14641
15131
  * Enables search input element.
14642
15132
  */
14643
15133
  search: {
14644
- type: Boolean,
15134
+ type: [Boolean, String],
14645
15135
  default: true,
14646
15136
  required: false,
15137
+ validator: (value) => {
15138
+ if (typeof value == 'string') {
15139
+ return ['external'].includes(value);
15140
+ }
15141
+ if (typeof value == 'boolean') {
15142
+ return true;
15143
+ }
15144
+ return false;
15145
+ },
14647
15146
  },
14648
15147
  /**
14649
15148
  * Sets the label for no results when filtering.
@@ -14709,6 +15208,26 @@ const CMultiSelect = vue.defineComponent({
14709
15208
  return ['sm', 'lg'].includes(value);
14710
15209
  },
14711
15210
  },
15211
+ /**
15212
+ * Add helper text to the component.
15213
+ *
15214
+ * @since 4.6.0
15215
+ */
15216
+ text: {
15217
+ type: String,
15218
+ },
15219
+ /**
15220
+ * Display validation feedback in a styled tooltip.
15221
+ *
15222
+ * @since 4.6.0
15223
+ */
15224
+ tooltipFeedback: Boolean,
15225
+ /**
15226
+ * Set component validation state to valid.
15227
+ *
15228
+ * @since 4.6.0
15229
+ */
15230
+ valid: Boolean,
14712
15231
  /**
14713
15232
  * Toggle the visibility of multi select dropdown.
14714
15233
  *
@@ -14725,59 +15244,63 @@ const CMultiSelect = vue.defineComponent({
14725
15244
  * Execute a function when a user changes the selected option. [docs]
14726
15245
  */
14727
15246
  'change',
15247
+ /**
15248
+ * Execute a function when the filter value changed.
15249
+ *
15250
+ * @since 4.7.0
15251
+ */
15252
+ 'filterChange',
14728
15253
  ],
14729
- setup(props, { emit }) {
14730
- const flattenArray = (options) => {
14731
- return options.reduce((acc, val) => {
14732
- return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val);
14733
- }, []);
14734
- };
14735
- const getSelectedOptions = (options) => {
14736
- return flattenArray(options).filter((option) => {
14737
- if (option.selected) {
14738
- return option;
14739
- }
14740
- return;
14741
- });
14742
- };
14743
- const updateOptions = (value, _options = options.value) => {
14744
- return props.multiple && _options
14745
- ? _options &&
14746
- _options.map((option) => {
14747
- count.value = count.value++;
14748
- return option.options
14749
- ? { ...option, options: updateOptions(value, option.options) }
14750
- : option.value == value // TODO: find solution
14751
- ? { ...option, selected: !option.selected, order: count.value }
14752
- : { ...option };
14753
- })
14754
- : _options &&
14755
- _options.map((option) => {
14756
- return option.options
14757
- ? { ...option, options: updateOptions(value, option.options) }
14758
- : option.value == value // TODO: find solution
14759
- ? { ...option, selected: true }
14760
- : { ...option, selected: false };
15254
+ setup(props, { attrs, emit }) {
15255
+ const nativeSelectRef = vue.ref();
15256
+ vue.provide('nativeSelectRef', nativeSelectRef);
15257
+ const searchRef = vue.ref();
15258
+ const options = vue.ref(props.options);
15259
+ const search = vue.ref('');
15260
+ const selected = vue.ref([]);
15261
+ const visible = vue.ref(props.visible);
15262
+ const selectOptions = (options, deselected) => {
15263
+ let _selected = [...selected.value, ...options];
15264
+ if (deselected) {
15265
+ _selected = _selected.filter((selectedOption) => !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value));
15266
+ }
15267
+ const deduplicated = _selected.reduce((unique, option) => {
15268
+ if (!unique.some((obj) => obj.value === option.value)) {
15269
+ unique.push({
15270
+ value: option.value,
15271
+ text: option.text,
15272
+ ...(option.disabled && { disabled: option.disabled }),
14761
15273
  });
14762
- };
14763
- const toggleAllOptions = (options, selected, counter = count.value) => {
14764
- return options.map((option) => {
14765
- !option.selected && counter++;
14766
- count.value = counter;
14767
- if (option.options) {
14768
- return {
14769
- ...option,
14770
- options: toggleAllOptions(option.options, selected, counter),
14771
- };
14772
15274
  }
14773
- return option.disabled
14774
- ? { ...option }
14775
- : selected && !option.selected
14776
- ? { ...option, selected: selected, order: counter }
14777
- : { ...option, selected: selected };
14778
- });
15275
+ return unique;
15276
+ }, []);
15277
+ selected.value = deduplicated;
14779
15278
  };
14780
- const filterOptionsList = (search, _options = vOptions.value) => {
15279
+ vue.watch(() => props.options, (newValue, oldValue) => {
15280
+ if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
15281
+ options.value = newValue;
15282
+ const _selected = newValue &&
15283
+ flattenArray(newValue).filter((option) => {
15284
+ if (option.selected) {
15285
+ return option;
15286
+ }
15287
+ return;
15288
+ });
15289
+ const deselected = newValue &&
15290
+ flattenArray(newValue).filter((option) => {
15291
+ if (option.selected === false) {
15292
+ return option;
15293
+ }
15294
+ return;
15295
+ });
15296
+ _selected && selectOptions(_selected, deselected);
15297
+ }
15298
+ });
15299
+ vue.watch(selected, () => {
15300
+ nativeSelectRef.value &&
15301
+ nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }));
15302
+ });
15303
+ const filterOptionsList = (search, _options) => {
14781
15304
  return search.length
14782
15305
  ? _options &&
14783
15306
  _options.reduce((acc, val) => {
@@ -14791,63 +15314,54 @@ const CMultiSelect = vue.defineComponent({
14791
15314
  }, [])
14792
15315
  : options.value;
14793
15316
  };
14794
- const nativeSelectRef = vue.ref();
14795
- vue.provide('nativeSelectRef', nativeSelectRef);
14796
- const searchRef = vue.ref();
14797
- const options = vue.ref(props.options);
14798
- const vOptions = vue.ref(props.options);
14799
- const search = vue.ref('');
14800
- const visible = vue.ref(props.visible);
14801
- const selected = vue.ref(getSelectedOptions(props.options));
14802
- const count = vue.ref(0);
14803
- vue.watch(() => props.options, (newValue, oldValue) => {
14804
- if (JSON.stringify(newValue) !== JSON.stringify(oldValue))
14805
- options.value = newValue;
14806
- });
14807
- vue.watch(options, () => {
14808
- const _selected = options.value && getSelectedOptions(options.value);
14809
- _selected.sort((a, b) => {
14810
- if (typeof a.order === 'undefined') {
14811
- return -1;
14812
- }
14813
- if (b.order && a.order > b.order)
14814
- return 1;
14815
- if (b.order && a.order < b.order)
14816
- return -1;
14817
- return 0;
14818
- });
14819
- selected.value = _selected;
14820
- });
14821
- vue.watch([options, search], () => {
14822
- vOptions.value = filterOptionsList(search.value, options.value);
14823
- });
14824
- vue.watch(selected, () => {
14825
- nativeSelectRef.value &&
14826
- nativeSelectRef.value.dispatchEvent(new Event('change', { bubbles: true }));
14827
- });
15317
+ // watch(
15318
+ // () => props.options,
15319
+ // (newValue, oldValue) => {
15320
+ // console.log(props.options)
15321
+ // if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) options.value = newValue
15322
+ // },
15323
+ // )
14828
15324
  const handleSearchChange = (event) => {
14829
15325
  const target = event.target;
14830
15326
  search.value = target.value.toLowerCase();
15327
+ emit('filterChange', target.value);
14831
15328
  };
14832
15329
  const handleSearchKeyDown = (event) => {
14833
- if (search.value.length)
15330
+ if (search.value.length) {
14834
15331
  return;
15332
+ }
14835
15333
  if (event.key === 'Backspace' || event.key === 'Delete') {
14836
15334
  const last = selected.value.filter((option) => !option.disabled).pop();
14837
15335
  if (last) {
14838
15336
  selected.value = selected.value.filter((option) => option.value !== last.value);
14839
- options.value = updateOptions(last.value);
14840
15337
  }
14841
15338
  }
14842
15339
  };
14843
15340
  const handleOptionClick = (option) => {
14844
- options.value = updateOptions(option.value);
15341
+ if (!props.multiple) {
15342
+ selected.value = [{ value: option.value, text: option.text }];
15343
+ visible.value = false;
15344
+ search.value = '';
15345
+ if (searchRef.value) {
15346
+ searchRef.value.value = '';
15347
+ }
15348
+ return;
15349
+ }
15350
+ if (selected.value.some((_option) => _option.value === option.value)) {
15351
+ selected.value = selected.value.filter((_option) => _option.value !== option.value);
15352
+ }
15353
+ else {
15354
+ selected.value = [
15355
+ ...selected.value,
15356
+ { value: option.value, text: option.text },
15357
+ ];
15358
+ }
14845
15359
  };
14846
15360
  const handleSelectAll = () => {
14847
- options.value = toggleAllOptions(options.value, true);
15361
+ selectOptions(flattenArray(options.value).filter((option) => !option.disabled));
14848
15362
  };
14849
15363
  const handleDeselectAll = () => {
14850
- options.value = toggleAllOptions(options.value, false);
15364
+ selected.value = selected.value.filter((option) => option.disabled);
14851
15365
  };
14852
15366
  return () => [
14853
15367
  vue.h(CMultiSelectNativeSelect, {
@@ -14858,75 +15372,103 @@ const CMultiSelect = vue.defineComponent({
14858
15372
  : selected.value.map((option) => option.value)[0],
14859
15373
  onChange: () => emit('change', selected.value),
14860
15374
  }),
14861
- vue.h(CPicker, {
14862
- class: [
14863
- 'form-multi-select',
14864
- {
14865
- 'form-multi-select-with-cleaner': props.cleaner,
14866
- disabled: props.disabled,
14867
- [`form-multi-select-${props.size}`]: props.size,
14868
- 'form-multi-select-selection-tags': props.multiple && props.selectionType === 'tags',
14869
- show: visible.value,
14870
- },
14871
- ],
14872
- disabled: props.disabled,
14873
- onShow: () => {
14874
- props.search && searchRef.value && searchRef.value.focus();
14875
- },
15375
+ vue.h(CFormControlWrapper, {
15376
+ describedby: attrs['aria-describedby'],
15377
+ feedback: props.feedback,
15378
+ feedbackInvalid: props.feedbackInvalid,
15379
+ feedbackValid: props.feedbackValid,
15380
+ id: props.id,
15381
+ invalid: props.invalid,
15382
+ label: props.label,
15383
+ text: props.text,
15384
+ tooltipFeedback: props.tooltipFeedback,
15385
+ valid: props.valid,
14876
15386
  }, {
14877
- toggler: () => vue.h('div', {}, [
14878
- vue.h(CMultiSelectSelection, {
14879
- multiple: props.multiple,
14880
- onRemove: (option) => !props.disabled && handleOptionClick(option),
14881
- search: props.search,
14882
- selected: selected.value,
14883
- selectionType: props.selectionType,
14884
- selectionTypeCounterText: props.selectionTypeCounterText,
14885
- }),
14886
- props.multiple &&
14887
- props.cleaner &&
14888
- selected.value.length > 0 &&
14889
- !props.disabled &&
14890
- vue.h('button', {
14891
- type: 'button',
14892
- class: 'form-multi-select-selection-cleaner',
14893
- onClick: () => handleDeselectAll(),
15387
+ default: () => vue.h(CPicker, {
15388
+ class: [
15389
+ 'form-multi-select',
15390
+ {
15391
+ 'form-multi-select-with-cleaner': props.cleaner,
15392
+ disabled: props.disabled,
15393
+ [`form-multi-select-${props.size}`]: props.size,
15394
+ 'form-multi-select-selection-tags': props.multiple && props.selectionType === 'tags',
15395
+ show: visible.value,
15396
+ 'is-invalid': props.invalid,
15397
+ 'is-valid': props.valid,
15398
+ },
15399
+ ],
15400
+ disabled: props.disabled,
15401
+ id: props.id,
15402
+ onHide: () => {
15403
+ visible.value = false;
15404
+ },
15405
+ onShow: () => {
15406
+ props.search && searchRef.value && searchRef.value.focus();
15407
+ visible.value = true;
15408
+ },
15409
+ visible: visible.value,
15410
+ }, {
15411
+ toggler: () => vue.h('div', {}, [
15412
+ vue.h(CMultiSelectSelection, {
15413
+ multiple: props.multiple,
15414
+ onRemove: (option) => !props.disabled && handleOptionClick(option),
15415
+ search: props.search,
15416
+ selected: selected.value,
15417
+ selectionType: props.selectionType,
15418
+ selectionTypeCounterText: props.selectionTypeCounterText,
14894
15419
  }),
14895
- props.search &&
14896
- vue.h('input', {
14897
- type: 'text',
14898
- class: 'form-multi-select-search',
14899
- autocomplete: 'off',
14900
- ...(selected.value.length === 0 && { placeholder: props.placeholder }),
14901
- ...(selected.value.length &&
14902
- props.selectionType === 'counter' && {
14903
- placeholder: `${selected.value.length} ${props.selectionTypeCounterText}`,
15420
+ props.multiple &&
15421
+ props.cleaner &&
15422
+ selected.value.length > 0 &&
15423
+ !props.disabled &&
15424
+ vue.h('button', {
15425
+ type: 'button',
15426
+ class: 'form-multi-select-selection-cleaner',
15427
+ onClick: () => handleDeselectAll(),
14904
15428
  }),
14905
- ...(selected.value.length &&
14906
- !props.multiple && {
14907
- placeholder: selected.value.map((option) => option.text)[0],
15429
+ props.search &&
15430
+ vue.h('input', {
15431
+ type: 'text',
15432
+ class: 'form-multi-select-search',
15433
+ autocomplete: 'off',
15434
+ ...(selected.value.length === 0 && { placeholder: props.placeholder }),
15435
+ ...(selected.value.length &&
15436
+ props.selectionType === 'counter' && {
15437
+ placeholder: `${selected.value.length} ${props.selectionTypeCounterText}`,
15438
+ }),
15439
+ ...(selected.value.length &&
15440
+ !props.multiple && {
15441
+ placeholder: selected.value.map((option) => option.text)[0],
15442
+ }),
15443
+ disabled: props.disabled,
15444
+ onInput: (event) => handleSearchChange(event),
15445
+ onKeydown: (event) => handleSearchKeyDown(event),
15446
+ ...(props.multiple &&
15447
+ selected.value.length &&
15448
+ props.selectionType !== 'counter' && { size: search.value.length + 2 }),
15449
+ ref: searchRef,
14908
15450
  }),
14909
- disabled: props.disabled,
14910
- onInput: (event) => handleSearchChange(event),
14911
- onKeydown: (event) => handleSearchKeyDown(event),
14912
- ...(props.multiple &&
14913
- selected.value.length &&
14914
- props.selectionType !== 'counter' && { size: search.value.length + 2 }),
14915
- ref: searchRef,
15451
+ ]),
15452
+ default: () => vue.h('div', {}, [
15453
+ props.multiple &&
15454
+ props.selectAll &&
15455
+ vue.h('button', {
15456
+ class: 'form-multi-select-all',
15457
+ onClick: () => handleSelectAll(),
15458
+ type: 'button',
15459
+ }, props.selectAllLabel),
15460
+ vue.h(CMultiSelectOptions, {
15461
+ onOptionClick: (option) => handleOptionClick(option),
15462
+ options: props.search === 'external'
15463
+ ? options.value
15464
+ : filterOptionsList(search.value, options.value),
15465
+ optionsMaxHeight: props.optionsMaxHeight,
15466
+ optionsStyle: props.optionsStyle,
15467
+ searchNoResultsLabel: props.searchNoResultsLabel,
15468
+ selected: selected.value
14916
15469
  }),
14917
- ]),
14918
- default: () => vue.h('div', {}, [
14919
- props.multiple &&
14920
- props.selectAll &&
14921
- vue.h('button', { class: 'form-multi-select-all', onClick: () => handleSelectAll() }, props.selectAllLabel),
14922
- vue.h(CMultiSelectOptions, {
14923
- onOptionClick: (option) => handleOptionClick(option),
14924
- options: vOptions.value,
14925
- optionsMaxHeight: props.optionsMaxHeight,
14926
- optionsStyle: props.optionsStyle,
14927
- searchNoResultsLabel: props.searchNoResultsLabel,
14928
- }),
14929
- ]),
15470
+ ]),
15471
+ }),
14930
15472
  }),
14931
15473
  ];
14932
15474
  },
@@ -15643,470 +16185,179 @@ const CPaginationItem = vue.defineComponent({
15643
16185
  },
15644
16186
  });
15645
16187
 
15646
- const CSmartPagination = vue.defineComponent({
15647
- name: 'CSmartPagination',
16188
+ const CPaginationPlugin = {
16189
+ install: (app) => {
16190
+ app.component(CPagination.name, CPagination);
16191
+ app.component(CPaginationItem.name, CPaginationItem);
16192
+ },
16193
+ };
16194
+
16195
+ const BREAKPOINTS$1 = [
16196
+ 'xxl',
16197
+ 'xl',
16198
+ 'lg',
16199
+ 'md',
16200
+ 'sm',
16201
+ 'xs',
16202
+ ];
16203
+ const CPlaceholder = vue.defineComponent({
16204
+ name: 'CPlaceholder',
15648
16205
  props: {
15649
16206
  /**
15650
- * Horizontall align
16207
+ * Set animation type to better convey the perception of something being actively loaded.
15651
16208
  *
15652
- * @default 'start'
16209
+ * @values 'glow', 'wave'
15653
16210
  */
15654
- align: {
16211
+ animation: {
15655
16212
  type: String,
15656
- default: 'start',
16213
+ default: undefined,
15657
16214
  require: false,
15658
16215
  validator: (value) => {
15659
- return ['start', 'center', 'end'].includes(value);
16216
+ return ['glow', 'wave'].includes(value);
15660
16217
  },
15661
16218
  },
15662
16219
  /**
15663
- * Current page number
16220
+ * Sets the color context of the component to one of CoreUI’s themed colors.
15664
16221
  *
15665
- * @default 1
16222
+ * @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
15666
16223
  */
15667
- activePage: {
15668
- type: Number,
15669
- default: 1,
15670
- require: false,
16224
+ color: Color,
16225
+ /**
16226
+ * Component used for the root node. Either a string to use a HTML element or a component.
16227
+ */
16228
+ component: {
16229
+ type: String,
16230
+ default: 'span',
16231
+ required: false,
15671
16232
  },
15672
16233
  /**
15673
- * Show/hide arrows
16234
+ * Size the component extra small, small, or large.
15674
16235
  *
15675
- * @default true
16236
+ * @values 'xs', 'sm', 'lg'
15676
16237
  */
15677
- arrows: {
15678
- type: Boolean,
15679
- default: true,
15680
- require: false,
16238
+ size: {
16239
+ type: String,
16240
+ default: undefined,
16241
+ required: false,
16242
+ validator: (value) => {
16243
+ return ['xs', 'sm', 'lg'].includes(value);
16244
+ },
15681
16245
  },
15682
16246
  /**
15683
- * Show/hide dots
15684
- *
15685
- * @default true
16247
+ * The number of columns on extra small devices (<576px).
15686
16248
  */
15687
- dots: {
15688
- type: Boolean,
15689
- default: true,
16249
+ xs: {
16250
+ type: Number,
16251
+ default: undefined,
15690
16252
  require: false,
15691
16253
  },
15692
16254
  /**
15693
- * Show double arrows buttons
15694
- *
15695
- * @default true
16255
+ * The number of columns on small devices (<768px).
15696
16256
  */
15697
- doubleArrows: {
15698
- type: Boolean,
15699
- default: true,
16257
+ sm: {
16258
+ type: Number,
16259
+ default: undefined,
15700
16260
  require: false,
15701
16261
  },
15702
16262
  /**
15703
- * The content of 'firstButton' button
15704
- *
15705
- * @default '&laquo;'
16263
+ * The number of columns on medium devices (<992px).
15706
16264
  */
15707
- firstButton: {
15708
- type: String,
15709
- default: '&laquo;',
16265
+ md: {
16266
+ type: Number,
16267
+ default: undefined,
15710
16268
  require: false,
15711
16269
  },
15712
16270
  /**
15713
- * The content of 'lastButton' button
15714
- *
15715
- * @default '&raquo;'
16271
+ * The number of columns on large devices (<1200px).
15716
16272
  */
15717
- lastButton: {
15718
- type: String,
15719
- default: '&raquo;',
16273
+ lg: {
16274
+ type: Number,
16275
+ default: undefined,
15720
16276
  require: false,
15721
16277
  },
15722
16278
  /**
15723
- * Maximum items number
15724
- *
15725
- * @default 5
16279
+ * The number of columns on X-Large devices (<1400px).
15726
16280
  */
15727
- limit: {
16281
+ xl: {
15728
16282
  type: Number,
15729
- default: 5,
16283
+ default: undefined,
15730
16284
  require: false,
15731
16285
  },
15732
16286
  /**
15733
- * The content of 'nextButton' button
15734
- *
15735
- * @default '&rsaquo;'
16287
+ * The number of columns on XX-Large devices (≥1400px).
15736
16288
  */
15737
- nextButton: {
15738
- type: String,
15739
- default: '&rsaquo;',
16289
+ xxl: {
16290
+ type: Number,
16291
+ default: undefined,
15740
16292
  require: false,
15741
16293
  },
16294
+ },
16295
+ setup(props, { slots }) {
16296
+ const repsonsiveClassNames = [];
16297
+ BREAKPOINTS$1.forEach((bp) => {
16298
+ const breakpoint = props[bp];
16299
+ const infix = bp === 'xs' ? '' : `-${bp}`;
16300
+ if (typeof breakpoint === 'number') {
16301
+ repsonsiveClassNames.push(`col${infix}-${breakpoint}`);
16302
+ }
16303
+ if (typeof breakpoint === 'boolean') {
16304
+ repsonsiveClassNames.push(`col${infix}`);
16305
+ }
16306
+ });
16307
+ return () => vue.h(props.component, {
16308
+ class: [
16309
+ props.animation ? `placeholder-${props.animation}` : 'placeholder',
16310
+ {
16311
+ [`bg-${props.color}`]: props.color,
16312
+ [`placeholder-${props.size}`]: props.size,
16313
+ },
16314
+ repsonsiveClassNames,
16315
+ ],
16316
+ }, slots.default && slots.default());
16317
+ },
16318
+ });
16319
+
16320
+ const CPlaceholderPlugin = {
16321
+ install: (app) => {
16322
+ app.component(CPlaceholder.name, CPlaceholder);
16323
+ },
16324
+ };
16325
+
16326
+ const CProgressBar = vue.defineComponent({
16327
+ name: 'CProgressBar',
16328
+ props: {
15742
16329
  /**
15743
- * Number of pages
16330
+ * Use to animate the stripes right to left via CSS3 animations.
15744
16331
  */
15745
- pages: {
15746
- type: Number,
15747
- default: 1000,
15748
- require: true,
16332
+ animated: {
16333
+ type: Boolean,
16334
+ required: false,
15749
16335
  },
15750
16336
  /**
15751
- * The content of 'previousButton' button
16337
+ * Sets the color context of the component to one of CoreUI’s themed colors.
15752
16338
  *
15753
- * @default '&lsaquo;'
16339
+ * @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
15754
16340
  */
15755
- previousButton: {
15756
- type: String,
15757
- default: '&lsaquo;',
15758
- require: false,
16341
+ color: Color,
16342
+ /**
16343
+ * The percent to progress the ProgressBar.
16344
+ */
16345
+ value: {
16346
+ type: Number,
16347
+ required: false,
16348
+ default: 0,
15759
16349
  },
15760
16350
  /**
15761
- * Size of pagination, valid values: 'sm', 'lg'
16351
+ * Set the progress bar variant to optional striped.
16352
+ *
16353
+ * @values 'striped'
15762
16354
  */
15763
- size: {
16355
+ variant: {
15764
16356
  type: String,
15765
16357
  default: undefined,
15766
- required: false,
16358
+ require: false,
15767
16359
  validator: (value) => {
15768
- return ['sm', 'lg'].includes(value);
15769
- },
15770
- },
15771
- },
15772
- emits: [
15773
- /**
15774
- * On active page change callback.
15775
- */
15776
- 'activePageChange',
15777
- ],
15778
- setup(props, { emit }) {
15779
- const activePage = vue.ref(props.activePage);
15780
- const limit = vue.ref(props.limit);
15781
- const pages = vue.ref(props.pages);
15782
- vue.watch(props, () => {
15783
- activePage.value = props.activePage;
15784
- limit.value = props.limit;
15785
- pages.value = props.pages;
15786
- });
15787
- const showDots = vue.computed(() => {
15788
- return props.dots && limit.value > 4 && limit.value < pages.value;
15789
- });
15790
- const maxPrevItems = vue.computed(() => {
15791
- return Math.floor((limit.value - 1) / 2);
15792
- });
15793
- const maxNextItems = vue.computed(() => {
15794
- return Math.ceil((limit.value - 1) / 2);
15795
- });
15796
- const beforeDots = vue.computed(() => {
15797
- return showDots.value && activePage.value > maxPrevItems.value + 1;
15798
- });
15799
- const afterDots = vue.computed(() => {
15800
- return showDots.value && activePage.value < pages.value - maxNextItems.value;
15801
- });
15802
- const computedLimit = vue.computed(() => {
15803
- return limit.value - (afterDots.value ? 1 : 0) - (beforeDots.value ? 1 : 0);
15804
- });
15805
- const range = vue.computed(() => {
15806
- return activePage.value + maxNextItems.value;
15807
- });
15808
- const lastItem = vue.computed(() => {
15809
- return range.value >= pages.value ? pages.value : range.value - (afterDots.value ? 1 : 0);
15810
- });
15811
- const itemsAmount = vue.computed(() => {
15812
- return pages.value < computedLimit.value ? pages.value : computedLimit.value;
15813
- });
15814
- const items = vue.computed(() => {
15815
- if (activePage.value - maxPrevItems.value <= 1) {
15816
- return Array.from({
15817
- length: itemsAmount.value,
15818
- }, (_v, i) => i + 1);
15819
- }
15820
- else {
15821
- return Array.from({
15822
- length: itemsAmount.value,
15823
- }, (_v, i) => {
15824
- return lastItem.value - i;
15825
- }).reverse();
15826
- }
15827
- });
15828
- const setPage = (number) => {
15829
- if (number !== activePage.value) {
15830
- activePage.value = number;
15831
- emit('activePageChange', number);
15832
- }
15833
- };
15834
- return () => vue.h(CPagination, {
15835
- align: props.align,
15836
- 'aria-label': 'pagination',
15837
- size: props.size,
15838
- }, {
15839
- default: () => [
15840
- props.doubleArrows &&
15841
- vue.h(CPaginationItem, {
15842
- onClick: () => {
15843
- activePage.value !== 1 && setPage(1);
15844
- },
15845
- 'aria-label': 'Go to first page',
15846
- ...(activePage.value === 1 && {
15847
- 'aria-disabled': true,
15848
- disabled: true,
15849
- }),
15850
- }, {
15851
- default: () => typeof props.firstButton === 'string'
15852
- ? vue.h('span', {
15853
- innerHTML: props.firstButton,
15854
- })
15855
- : props.firstButton,
15856
- }),
15857
- props.arrows &&
15858
- vue.h(CPaginationItem, {
15859
- onClick: () => {
15860
- activePage.value !== 1 && setPage(activePage.value - 1);
15861
- },
15862
- 'aria-label': 'Go to previous page',
15863
- ...(activePage.value === 1 && {
15864
- 'aria-disabled': true,
15865
- disabled: true,
15866
- }),
15867
- }, {
15868
- default: () => typeof props.previousButton === 'string'
15869
- ? vue.h('span', {
15870
- innerHTML: props.previousButton,
15871
- })
15872
- : props.previousButton,
15873
- }),
15874
- beforeDots.value &&
15875
- vue.h(CPaginationItem, {
15876
- role: 'separator',
15877
- disabled: true,
15878
- }, {
15879
- default: () => '...',
15880
- }),
15881
- items.value.map((i) => {
15882
- return vue.h(CPaginationItem, {
15883
- onClick: () => setPage(i),
15884
- 'aria-label': activePage.value === i ? `Current page ${i}` : `Go to page ${i}`,
15885
- active: activePage.value === i,
15886
- }, {
15887
- default: () => i,
15888
- });
15889
- }),
15890
- afterDots.value &&
15891
- vue.h(CPaginationItem, {
15892
- role: 'separator',
15893
- disabled: true,
15894
- }, {
15895
- default: () => '...',
15896
- }),
15897
- props.arrows &&
15898
- vue.h(CPaginationItem, {
15899
- onClick: () => {
15900
- activePage.value !== pages.value && setPage(activePage.value + 1);
15901
- },
15902
- 'aria-label': 'Go to next page',
15903
- ...(activePage.value === pages.value && {
15904
- 'aria-disabled': true,
15905
- disabled: true,
15906
- }),
15907
- }, {
15908
- default: () => typeof props.nextButton === 'string'
15909
- ? vue.h('span', {
15910
- innerHTML: props.nextButton,
15911
- })
15912
- : props.nextButton,
15913
- }),
15914
- props.doubleArrows &&
15915
- vue.h(CPaginationItem, {
15916
- onClick: () => {
15917
- activePage.value !== pages.value && setPage(pages.value);
15918
- },
15919
- 'aria-label': 'Go to last page',
15920
- ...(activePage.value === pages.value && {
15921
- 'aria-disabled': true,
15922
- disabled: true,
15923
- }),
15924
- }, {
15925
- default: () => typeof props.lastButton === 'string'
15926
- ? vue.h('span', {
15927
- innerHTML: props.lastButton,
15928
- })
15929
- : props.lastButton,
15930
- }),
15931
- ],
15932
- });
15933
- },
15934
- });
15935
-
15936
- const CPaginationPlugin = {
15937
- install: (app) => {
15938
- app.component(CPagination.name, CPagination);
15939
- app.component(CPaginationItem.name, CPaginationItem);
15940
- app.component(CSmartPagination.name, CSmartPagination);
15941
- },
15942
- };
15943
-
15944
- const BREAKPOINTS$1 = [
15945
- 'xxl',
15946
- 'xl',
15947
- 'lg',
15948
- 'md',
15949
- 'sm',
15950
- 'xs',
15951
- ];
15952
- const CPlaceholder = vue.defineComponent({
15953
- name: 'CPlaceholder',
15954
- props: {
15955
- /**
15956
- * Set animation type to better convey the perception of something being actively loaded.
15957
- *
15958
- * @values 'glow', 'wave'
15959
- */
15960
- animation: {
15961
- type: String,
15962
- default: undefined,
15963
- require: false,
15964
- validator: (value) => {
15965
- return ['glow', 'wave'].includes(value);
15966
- },
15967
- },
15968
- /**
15969
- * Sets the color context of the component to one of CoreUI’s themed colors.
15970
- *
15971
- * @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
15972
- */
15973
- color: Color,
15974
- /**
15975
- * Component used for the root node. Either a string to use a HTML element or a component.
15976
- */
15977
- component: {
15978
- type: String,
15979
- default: 'span',
15980
- required: false,
15981
- },
15982
- /**
15983
- * Size the component extra small, small, or large.
15984
- *
15985
- * @values 'xs', 'sm', 'lg'
15986
- */
15987
- size: {
15988
- type: String,
15989
- default: undefined,
15990
- required: false,
15991
- validator: (value) => {
15992
- return ['xs', 'sm', 'lg'].includes(value);
15993
- },
15994
- },
15995
- /**
15996
- * The number of columns on extra small devices (<576px).
15997
- */
15998
- xs: {
15999
- type: Number,
16000
- default: undefined,
16001
- require: false,
16002
- },
16003
- /**
16004
- * The number of columns on small devices (<768px).
16005
- */
16006
- sm: {
16007
- type: Number,
16008
- default: undefined,
16009
- require: false,
16010
- },
16011
- /**
16012
- * The number of columns on medium devices (<992px).
16013
- */
16014
- md: {
16015
- type: Number,
16016
- default: undefined,
16017
- require: false,
16018
- },
16019
- /**
16020
- * The number of columns on large devices (<1200px).
16021
- */
16022
- lg: {
16023
- type: Number,
16024
- default: undefined,
16025
- require: false,
16026
- },
16027
- /**
16028
- * The number of columns on X-Large devices (<1400px).
16029
- */
16030
- xl: {
16031
- type: Number,
16032
- default: undefined,
16033
- require: false,
16034
- },
16035
- /**
16036
- * The number of columns on XX-Large devices (≥1400px).
16037
- */
16038
- xxl: {
16039
- type: Number,
16040
- default: undefined,
16041
- require: false,
16042
- },
16043
- },
16044
- setup(props, { slots }) {
16045
- const repsonsiveClassNames = [];
16046
- BREAKPOINTS$1.forEach((bp) => {
16047
- const breakpoint = props[bp];
16048
- const infix = bp === 'xs' ? '' : `-${bp}`;
16049
- if (typeof breakpoint === 'number') {
16050
- repsonsiveClassNames.push(`col${infix}-${breakpoint}`);
16051
- }
16052
- if (typeof breakpoint === 'boolean') {
16053
- repsonsiveClassNames.push(`col${infix}`);
16054
- }
16055
- });
16056
- return () => vue.h(props.component, {
16057
- class: [
16058
- props.animation ? `placeholder-${props.animation}` : 'placeholder',
16059
- {
16060
- [`bg-${props.color}`]: props.color,
16061
- [`placeholder-${props.size}`]: props.size,
16062
- },
16063
- repsonsiveClassNames,
16064
- ],
16065
- }, slots.default && slots.default());
16066
- },
16067
- });
16068
-
16069
- const CPlaceholderPlugin = {
16070
- install: (app) => {
16071
- app.component(CPlaceholder.name, CPlaceholder);
16072
- },
16073
- };
16074
-
16075
- const CProgressBar = vue.defineComponent({
16076
- name: 'CProgressBar',
16077
- props: {
16078
- /**
16079
- * Use to animate the stripes right to left via CSS3 animations.
16080
- */
16081
- animated: {
16082
- type: Boolean,
16083
- required: false,
16084
- },
16085
- /**
16086
- * Sets the color context of the component to one of CoreUI’s themed colors.
16087
- *
16088
- * @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
16089
- */
16090
- color: Color,
16091
- /**
16092
- * The percent to progress the ProgressBar.
16093
- */
16094
- value: {
16095
- type: Number,
16096
- required: false,
16097
- default: 0,
16098
- },
16099
- /**
16100
- * Set the progress bar variant to optional striped.
16101
- *
16102
- * @values 'striped'
16103
- */
16104
- variant: {
16105
- type: String,
16106
- default: undefined,
16107
- require: false,
16108
- validator: (value) => {
16109
- return value === 'striped';
16360
+ return value === 'striped';
16110
16361
  },
16111
16362
  },
16112
16363
  },
@@ -16330,259 +16581,548 @@ const CPopover = vue.defineComponent({
16330
16581
  },
16331
16582
  });
16332
16583
 
16333
- const CPopoverPlugin = {
16584
+ const CPopoverPlugin = {
16585
+ install: (app) => {
16586
+ app.component(CPopover.name, CPopover);
16587
+ },
16588
+ };
16589
+
16590
+ const isOnMobile = (element) => Boolean(getComputedStyle(element).getPropertyValue('--cui-is-mobile'));
16591
+ const CSidebar = vue.defineComponent({
16592
+ name: 'CSidebar',
16593
+ props: {
16594
+ /**
16595
+ * Sets if the color of text should be colored for a light or dark dark background.
16596
+ *
16597
+ * @values 'dark', light'
16598
+ */
16599
+ colorScheme: {
16600
+ type: String,
16601
+ default: undefined,
16602
+ validator: (value) => {
16603
+ return ['dark', 'light'].includes(value);
16604
+ },
16605
+ },
16606
+ /**
16607
+ * Make sidebar narrow.
16608
+ */
16609
+ narrow: {
16610
+ type: Boolean,
16611
+ required: false,
16612
+ },
16613
+ /**
16614
+ * Set sidebar to overlaid variant.
16615
+ */
16616
+ overlaid: {
16617
+ type: Boolean,
16618
+ required: false,
16619
+ },
16620
+ /**
16621
+ * Components placement, there’s no default placement.
16622
+ * @values 'start', 'end'
16623
+ */
16624
+ placement: {
16625
+ type: String,
16626
+ default: undefined,
16627
+ validator: (value) => {
16628
+ return ['start', 'end'].includes(value);
16629
+ },
16630
+ },
16631
+ /**
16632
+ * Place sidebar in non-static positions.
16633
+ */
16634
+ position: {
16635
+ type: String,
16636
+ default: undefined,
16637
+ validator: (value) => {
16638
+ return ['fixed'].includes(value);
16639
+ },
16640
+ },
16641
+ /**
16642
+ * Size the component small, large, or extra large.
16643
+ */
16644
+ size: {
16645
+ type: String,
16646
+ default: undefined,
16647
+ validator: (value) => {
16648
+ return ['sm', 'lg', 'xl'].includes(value);
16649
+ },
16650
+ },
16651
+ /**
16652
+ * Expand narrowed sidebar on hover.
16653
+ */
16654
+ unfoldable: Boolean,
16655
+ /**
16656
+ * Toggle the visibility of sidebar component.
16657
+ */
16658
+ visible: Boolean,
16659
+ },
16660
+ emits: [
16661
+ /**
16662
+ * Callback fired when the component requests to be hidden.
16663
+ */
16664
+ 'hide',
16665
+ /**
16666
+ * Callback fired when the component requests to be shown.
16667
+ */
16668
+ 'show',
16669
+ /**
16670
+ * Event emitted after visibility of component changed.
16671
+ */
16672
+ 'visible-change',
16673
+ ],
16674
+ setup(props, { attrs, slots, emit }) {
16675
+ const mobile = vue.ref();
16676
+ const inViewport = vue.ref();
16677
+ const sidebarRef = vue.ref();
16678
+ const visible = vue.ref(props.visible);
16679
+ vue.watch(inViewport, () => {
16680
+ emit('visible-change', inViewport.value);
16681
+ inViewport.value ? emit('show') : emit('hide');
16682
+ });
16683
+ vue.watch(() => props.visible, () => (visible.value = props.visible));
16684
+ vue.watch(mobile, () => {
16685
+ if (mobile.value && visible.value)
16686
+ visible.value = false;
16687
+ });
16688
+ vue.onMounted(() => {
16689
+ mobile.value = isOnMobile(sidebarRef.value);
16690
+ inViewport.value = isVisible(sidebarRef.value);
16691
+ window.addEventListener('resize', () => handleResize());
16692
+ window.addEventListener('mouseup', handleClickOutside);
16693
+ window.addEventListener('keyup', handleKeyup);
16694
+ sidebarRef.value.addEventListener('mouseup', handleOnClick);
16695
+ sidebarRef.value.addEventListener('transitionend', () => {
16696
+ inViewport.value = isVisible(sidebarRef.value);
16697
+ });
16698
+ });
16699
+ vue.onBeforeUnmount(() => {
16700
+ window.removeEventListener('resize', () => handleResize());
16701
+ window.removeEventListener('mouseup', handleClickOutside);
16702
+ window.removeEventListener('keyup', handleKeyup);
16703
+ sidebarRef.value.removeEventListener('mouseup', handleOnClick);
16704
+ sidebarRef.value.removeEventListener('transitionend', () => {
16705
+ inViewport.value = isVisible(sidebarRef.value);
16706
+ });
16707
+ });
16708
+ const handleHide = () => {
16709
+ visible.value = false;
16710
+ emit('visible-change', false);
16711
+ };
16712
+ const handleResize = () => {
16713
+ mobile.value = isOnMobile(sidebarRef.value);
16714
+ inViewport.value = isVisible(sidebarRef.value);
16715
+ };
16716
+ const handleKeyup = (event) => {
16717
+ if (mobile.value && !sidebarRef.value.contains(event.target)) {
16718
+ handleHide();
16719
+ }
16720
+ };
16721
+ const handleClickOutside = (event) => {
16722
+ if (mobile.value && !sidebarRef.value.contains(event.target)) {
16723
+ handleHide();
16724
+ }
16725
+ };
16726
+ const handleOnClick = (event) => {
16727
+ const target = event.target;
16728
+ target &&
16729
+ target.classList.contains('nav-link') &&
16730
+ !target.classList.contains('nav-group-toggle') &&
16731
+ mobile.value &&
16732
+ handleHide();
16733
+ };
16734
+ return () => [
16735
+ vue.h('div', {
16736
+ class: [
16737
+ 'sidebar',
16738
+ {
16739
+ [`sidebar-${props.colorScheme}`]: props.colorScheme,
16740
+ 'sidebar-narrow': props.narrow,
16741
+ 'sidebar-overlaid': props.overlaid,
16742
+ [`sidebar-${props.placement}`]: props.placement,
16743
+ [`sidebar-${props.position}`]: props.position,
16744
+ [`sidebar-${props.size}`]: props.size,
16745
+ 'sidebar-narrow-unfoldable': props.unfoldable,
16746
+ show: visible.value === true && mobile.value,
16747
+ hide: visible.value === false && !mobile.value,
16748
+ },
16749
+ attrs.class,
16750
+ ],
16751
+ ref: sidebarRef,
16752
+ }, slots.default && slots.default()),
16753
+ mobile.value &&
16754
+ vue.h(CBackdrop, {
16755
+ class: 'sidebar-backdrop d-none',
16756
+ visible: props.visible,
16757
+ onClick: () => handleHide(),
16758
+ }),
16759
+ ];
16760
+ },
16761
+ });
16762
+
16763
+ const CSidebarBrand = vue.defineComponent({
16764
+ name: 'CSidebarBrand',
16765
+ setup(_, { slots }) {
16766
+ return () => vue.h('div', { class: 'sidebar-brand' }, slots.default && slots.default());
16767
+ },
16768
+ });
16769
+
16770
+ const CSidebarFooter = vue.defineComponent({
16771
+ name: 'CSidebarFooter',
16772
+ setup(_, { slots }) {
16773
+ return () => vue.h('div', { class: 'sidebar-footer' }, slots.default && slots.default());
16774
+ },
16775
+ });
16776
+
16777
+ const CSidebarHeader = vue.defineComponent({
16778
+ name: 'CSidebarHeader',
16779
+ setup(_, { slots }) {
16780
+ return () => vue.h('div', { class: 'sidebar-header' }, slots.default && slots.default());
16781
+ },
16782
+ });
16783
+
16784
+ const CSidebarNav = vue.defineComponent({
16785
+ name: 'CSidebarNav',
16786
+ setup(_, { slots }) {
16787
+ const visibleGroup = vue.ref();
16788
+ const handleVisibleChange = (visible, index) => {
16789
+ if (visible) {
16790
+ visibleGroup.value = index;
16791
+ }
16792
+ else {
16793
+ if (visibleGroup.value === index) {
16794
+ visibleGroup.value = 0;
16795
+ }
16796
+ }
16797
+ };
16798
+ const isVisible = (index) => Boolean(visibleGroup.value === index);
16799
+ return () => vue.h('ul', {
16800
+ class: 'sidebar-nav',
16801
+ }, slots.default &&
16802
+ slots.default().map((vnode, index) => {
16803
+ // @ts-expect-error name is defined in component
16804
+ if (vnode.type.name === 'CNavGroup') {
16805
+ return vue.h(vnode, {
16806
+ onVisibleChange: (visible) => handleVisibleChange(visible, index + 1),
16807
+ ...(visibleGroup.value && { visible: isVisible(index + 1) }),
16808
+ });
16809
+ }
16810
+ return vnode;
16811
+ }));
16812
+ },
16813
+ });
16814
+
16815
+ const CSidebarToggler = vue.defineComponent({
16816
+ name: 'CSidebarToggler',
16817
+ setup(_, { slots }) {
16818
+ return () => vue.h('button', { class: 'sidebar-toggler' }, slots.default && slots.default());
16819
+ },
16820
+ });
16821
+
16822
+ const CSidebarPlugin = {
16334
16823
  install: (app) => {
16335
- app.component(CPopover.name, CPopover);
16824
+ app.component(CSidebar.name, CSidebar);
16825
+ app.component(CSidebarBrand.name, CSidebarBrand);
16826
+ app.component(CSidebarFooter.name, CSidebarFooter);
16827
+ app.component(CSidebarHeader.name, CSidebarHeader);
16828
+ app.component(CSidebarNav.name, CSidebarNav);
16829
+ app.component(CSidebarToggler.name, CSidebarToggler);
16336
16830
  },
16337
16831
  };
16338
16832
 
16339
- const isOnMobile = (element) => Boolean(getComputedStyle(element).getPropertyValue('--cui-is-mobile'));
16340
- const isVisible = (element) => {
16341
- const rect = element.getBoundingClientRect();
16342
- return (rect.top >= 0 &&
16343
- rect.left >= 0 &&
16344
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
16345
- rect.right <= (window.innerWidth || document.documentElement.clientWidth));
16346
- };
16347
- const CSidebar = vue.defineComponent({
16348
- name: 'CSidebar',
16833
+ const CSmartPagination = vue.defineComponent({
16834
+ name: 'CSmartPagination',
16349
16835
  props: {
16350
16836
  /**
16351
- * Sets if the color of text should be colored for a light or dark dark background.
16837
+ * Horizontall align
16352
16838
  *
16353
- * @values 'dark', light'
16839
+ * @default 'start'
16354
16840
  */
16355
- colorScheme: {
16841
+ align: {
16356
16842
  type: String,
16357
- default: undefined,
16843
+ default: 'start',
16844
+ require: false,
16358
16845
  validator: (value) => {
16359
- return ['dark', 'light'].includes(value);
16846
+ return ['start', 'center', 'end'].includes(value);
16360
16847
  },
16361
16848
  },
16362
16849
  /**
16363
- * Make sidebar narrow.
16850
+ * Current page number
16851
+ *
16852
+ * @default 1
16364
16853
  */
16365
- narrow: {
16854
+ activePage: {
16855
+ type: Number,
16856
+ default: 1,
16857
+ require: false,
16858
+ },
16859
+ /**
16860
+ * Show/hide arrows
16861
+ *
16862
+ * @default true
16863
+ */
16864
+ arrows: {
16366
16865
  type: Boolean,
16367
- required: false,
16866
+ default: true,
16867
+ require: false,
16368
16868
  },
16369
16869
  /**
16370
- * Set sidebar to overlaid variant.
16870
+ * Show/hide dots
16871
+ *
16872
+ * @default true
16371
16873
  */
16372
- overlaid: {
16874
+ dots: {
16373
16875
  type: Boolean,
16374
- required: false,
16876
+ default: true,
16877
+ require: false,
16375
16878
  },
16376
16879
  /**
16377
- * Components placement, there’s no default placement.
16378
- * @values 'start', 'end'
16880
+ * Show double arrows buttons
16881
+ *
16882
+ * @default true
16379
16883
  */
16380
- placement: {
16381
- type: String,
16382
- default: undefined,
16383
- validator: (value) => {
16384
- return ['start', 'end'].includes(value);
16385
- },
16884
+ doubleArrows: {
16885
+ type: Boolean,
16886
+ default: true,
16887
+ require: false,
16386
16888
  },
16387
16889
  /**
16388
- * Place sidebar in non-static positions.
16890
+ * The content of 'firstButton' button
16891
+ *
16892
+ * @default '&laquo;'
16389
16893
  */
16390
- position: {
16894
+ firstButton: {
16391
16895
  type: String,
16392
- default: undefined,
16393
- validator: (value) => {
16394
- return ['fixed'].includes(value);
16395
- },
16896
+ default: '&laquo;',
16897
+ require: false,
16396
16898
  },
16397
16899
  /**
16398
- * Size the component small, large, or extra large.
16900
+ * The content of 'lastButton' button
16901
+ *
16902
+ * @default '&raquo;'
16399
16903
  */
16400
- size: {
16904
+ lastButton: {
16401
16905
  type: String,
16402
- default: undefined,
16403
- validator: (value) => {
16404
- return ['sm', 'lg', 'xl'].includes(value);
16405
- },
16906
+ default: '&raquo;',
16907
+ require: false,
16406
16908
  },
16407
16909
  /**
16408
- * Expand narrowed sidebar on hover.
16910
+ * Maximum items number
16911
+ *
16912
+ * @default 5
16409
16913
  */
16410
- unfoldable: Boolean,
16914
+ limit: {
16915
+ type: Number,
16916
+ default: 5,
16917
+ require: false,
16918
+ },
16411
16919
  /**
16412
- * Toggle the visibility of sidebar component.
16920
+ * The content of 'nextButton' button
16921
+ *
16922
+ * @default '&rsaquo;'
16413
16923
  */
16414
- visible: Boolean,
16415
- },
16416
- emits: [
16924
+ nextButton: {
16925
+ type: String,
16926
+ default: '&rsaquo;',
16927
+ require: false,
16928
+ },
16417
16929
  /**
16418
- * Callback fired when the component requests to be hidden.
16930
+ * Number of pages
16419
16931
  */
16420
- 'hide',
16932
+ pages: {
16933
+ type: Number,
16934
+ default: 1000,
16935
+ require: true,
16936
+ },
16421
16937
  /**
16422
- * Callback fired when the component requests to be shown.
16938
+ * The content of 'previousButton' button
16939
+ *
16940
+ * @default '&lsaquo;'
16423
16941
  */
16424
- 'show',
16942
+ previousButton: {
16943
+ type: String,
16944
+ default: '&lsaquo;',
16945
+ require: false,
16946
+ },
16425
16947
  /**
16426
- * Event emitted after visibility of component changed.
16948
+ * Size of pagination, valid values: 'sm', 'lg'
16427
16949
  */
16428
- 'visible-change',
16950
+ size: {
16951
+ type: String,
16952
+ default: undefined,
16953
+ required: false,
16954
+ validator: (value) => {
16955
+ return ['sm', 'lg'].includes(value);
16956
+ },
16957
+ },
16958
+ },
16959
+ emits: [
16960
+ /**
16961
+ * On active page change callback.
16962
+ */
16963
+ 'activePageChange',
16429
16964
  ],
16430
- setup(props, { attrs, slots, emit }) {
16431
- const mobile = vue.ref();
16432
- const inViewport = vue.ref();
16433
- const sidebarRef = vue.ref();
16434
- const visible = vue.ref(props.visible);
16435
- vue.watch(inViewport, () => {
16436
- emit('visible-change', inViewport.value);
16437
- inViewport.value ? emit('show') : emit('hide');
16965
+ setup(props, { emit }) {
16966
+ const activePage = vue.ref(props.activePage);
16967
+ const limit = vue.ref(props.limit);
16968
+ const pages = vue.ref(props.pages);
16969
+ vue.watch(props, () => {
16970
+ activePage.value = props.activePage;
16971
+ limit.value = props.limit;
16972
+ pages.value = props.pages;
16438
16973
  });
16439
- vue.watch(() => props.visible, () => (visible.value = props.visible));
16440
- vue.watch(mobile, () => {
16441
- if (mobile.value && visible.value)
16442
- visible.value = false;
16974
+ const showDots = vue.computed(() => {
16975
+ return props.dots && limit.value > 4 && limit.value < pages.value;
16976
+ });
16977
+ const maxPrevItems = vue.computed(() => {
16978
+ return Math.floor((limit.value - 1) / 2);
16979
+ });
16980
+ const maxNextItems = vue.computed(() => {
16981
+ return Math.ceil((limit.value - 1) / 2);
16982
+ });
16983
+ const beforeDots = vue.computed(() => {
16984
+ return showDots.value && activePage.value > maxPrevItems.value + 1;
16985
+ });
16986
+ const afterDots = vue.computed(() => {
16987
+ return showDots.value && activePage.value < pages.value - maxNextItems.value;
16988
+ });
16989
+ const computedLimit = vue.computed(() => {
16990
+ return limit.value - (afterDots.value ? 1 : 0) - (beforeDots.value ? 1 : 0);
16991
+ });
16992
+ const range = vue.computed(() => {
16993
+ return activePage.value + maxNextItems.value;
16443
16994
  });
16444
- vue.onMounted(() => {
16445
- mobile.value = isOnMobile(sidebarRef.value);
16446
- inViewport.value = isVisible(sidebarRef.value);
16447
- window.addEventListener('resize', () => handleResize());
16448
- window.addEventListener('mouseup', handleClickOutside);
16449
- window.addEventListener('keyup', handleKeyup);
16450
- sidebarRef.value.addEventListener('mouseup', handleOnClick);
16451
- sidebarRef.value.addEventListener('transitionend', () => {
16452
- inViewport.value = isVisible(sidebarRef.value);
16453
- });
16995
+ const lastItem = vue.computed(() => {
16996
+ return range.value >= pages.value ? pages.value : range.value - (afterDots.value ? 1 : 0);
16454
16997
  });
16455
- vue.onBeforeUnmount(() => {
16456
- window.removeEventListener('resize', () => handleResize());
16457
- window.removeEventListener('mouseup', handleClickOutside);
16458
- window.removeEventListener('keyup', handleKeyup);
16459
- sidebarRef.value.removeEventListener('mouseup', handleOnClick);
16460
- sidebarRef.value.removeEventListener('transitionend', () => {
16461
- inViewport.value = isVisible(sidebarRef.value);
16462
- });
16998
+ const itemsAmount = vue.computed(() => {
16999
+ return pages.value < computedLimit.value ? pages.value : computedLimit.value;
16463
17000
  });
16464
- const handleHide = () => {
16465
- visible.value = false;
16466
- emit('visible-change', false);
16467
- };
16468
- const handleResize = () => {
16469
- mobile.value = isOnMobile(sidebarRef.value);
16470
- inViewport.value = isVisible(sidebarRef.value);
16471
- };
16472
- const handleKeyup = (event) => {
16473
- if (mobile.value && !sidebarRef.value.contains(event.target)) {
16474
- handleHide();
16475
- }
16476
- };
16477
- const handleClickOutside = (event) => {
16478
- if (mobile.value && !sidebarRef.value.contains(event.target)) {
16479
- handleHide();
16480
- }
16481
- };
16482
- const handleOnClick = (event) => {
16483
- const target = event.target;
16484
- target &&
16485
- target.classList.contains('nav-link') &&
16486
- !target.classList.contains('nav-group-toggle') &&
16487
- mobile.value &&
16488
- handleHide();
16489
- };
16490
- return () => [
16491
- vue.h('div', {
16492
- class: [
16493
- 'sidebar',
16494
- {
16495
- [`sidebar-${props.colorScheme}`]: props.colorScheme,
16496
- 'sidebar-narrow': props.narrow,
16497
- 'sidebar-overlaid': props.overlaid,
16498
- [`sidebar-${props.placement}`]: props.placement,
16499
- [`sidebar-${props.position}`]: props.position,
16500
- [`sidebar-${props.size}`]: props.size,
16501
- 'sidebar-narrow-unfoldable': props.unfoldable,
16502
- show: visible.value === true && mobile.value,
16503
- hide: visible.value === false && !mobile.value,
16504
- },
16505
- attrs.class,
16506
- ],
16507
- ref: sidebarRef,
16508
- }, slots.default && slots.default()),
16509
- mobile.value &&
16510
- vue.h(CBackdrop, {
16511
- class: 'sidebar-backdrop d-none',
16512
- visible: props.visible,
16513
- onClick: () => handleHide(),
16514
- }),
16515
- ];
16516
- },
16517
- });
16518
-
16519
- const CSidebarBrand = vue.defineComponent({
16520
- name: 'CSidebarBrand',
16521
- setup(_, { slots }) {
16522
- return () => vue.h('div', { class: 'sidebar-brand' }, slots.default && slots.default());
16523
- },
16524
- });
16525
-
16526
- const CSidebarFooter = vue.defineComponent({
16527
- name: 'CSidebarFooter',
16528
- setup(_, { slots }) {
16529
- return () => vue.h('div', { class: 'sidebar-footer' }, slots.default && slots.default());
16530
- },
16531
- });
16532
-
16533
- const CSidebarHeader = vue.defineComponent({
16534
- name: 'CSidebarHeader',
16535
- setup(_, { slots }) {
16536
- return () => vue.h('div', { class: 'sidebar-header' }, slots.default && slots.default());
16537
- },
16538
- });
16539
-
16540
- const CSidebarNav = vue.defineComponent({
16541
- name: 'CSidebarNav',
16542
- setup(_, { slots }) {
16543
- const visibleGroup = vue.ref();
16544
- const handleVisibleChange = (visible, index) => {
16545
- if (visible) {
16546
- visibleGroup.value = index;
17001
+ const items = vue.computed(() => {
17002
+ if (activePage.value - maxPrevItems.value <= 1) {
17003
+ return Array.from({
17004
+ length: itemsAmount.value,
17005
+ }, (_v, i) => i + 1);
16547
17006
  }
16548
17007
  else {
16549
- if (visibleGroup.value === index) {
16550
- visibleGroup.value = 0;
16551
- }
17008
+ return Array.from({
17009
+ length: itemsAmount.value,
17010
+ }, (_v, i) => {
17011
+ return lastItem.value - i;
17012
+ }).reverse();
17013
+ }
17014
+ });
17015
+ const setPage = (number) => {
17016
+ if (number !== activePage.value) {
17017
+ activePage.value = number;
17018
+ emit('activePageChange', number);
16552
17019
  }
16553
17020
  };
16554
- const isVisible = (index) => Boolean(visibleGroup.value === index);
16555
- return () => vue.h('ul', {
16556
- class: 'sidebar-nav',
16557
- }, slots.default &&
16558
- slots.default().map((vnode, index) => {
16559
- // @ts-expect-error name is defined in component
16560
- if (vnode.type.name === 'CNavGroup') {
16561
- return vue.h(vnode, {
16562
- onVisibleChange: (visible) => handleVisibleChange(visible, index + 1),
16563
- ...(visibleGroup.value && { visible: isVisible(index + 1) }),
17021
+ return () => vue.h(CPagination, {
17022
+ align: props.align,
17023
+ 'aria-label': 'pagination',
17024
+ size: props.size,
17025
+ }, {
17026
+ default: () => [
17027
+ props.doubleArrows &&
17028
+ vue.h(CPaginationItem, {
17029
+ onClick: () => {
17030
+ activePage.value !== 1 && setPage(1);
17031
+ },
17032
+ 'aria-label': 'Go to first page',
17033
+ ...(activePage.value === 1 && {
17034
+ 'aria-disabled': true,
17035
+ disabled: true,
17036
+ }),
17037
+ }, {
17038
+ default: () => typeof props.firstButton === 'string'
17039
+ ? vue.h('span', {
17040
+ innerHTML: props.firstButton,
17041
+ })
17042
+ : props.firstButton,
17043
+ }),
17044
+ props.arrows &&
17045
+ vue.h(CPaginationItem, {
17046
+ onClick: () => {
17047
+ activePage.value !== 1 && setPage(activePage.value - 1);
17048
+ },
17049
+ 'aria-label': 'Go to previous page',
17050
+ ...(activePage.value === 1 && {
17051
+ 'aria-disabled': true,
17052
+ disabled: true,
17053
+ }),
17054
+ }, {
17055
+ default: () => typeof props.previousButton === 'string'
17056
+ ? vue.h('span', {
17057
+ innerHTML: props.previousButton,
17058
+ })
17059
+ : props.previousButton,
17060
+ }),
17061
+ beforeDots.value &&
17062
+ vue.h(CPaginationItem, {
17063
+ role: 'separator',
17064
+ disabled: true,
17065
+ }, {
17066
+ default: () => '...',
17067
+ }),
17068
+ items.value.map((i) => {
17069
+ return vue.h(CPaginationItem, {
17070
+ onClick: () => setPage(i),
17071
+ 'aria-label': activePage.value === i ? `Current page ${i}` : `Go to page ${i}`,
17072
+ active: activePage.value === i,
17073
+ }, {
17074
+ default: () => i,
16564
17075
  });
16565
- }
16566
- return vnode;
16567
- }));
16568
- },
16569
- });
16570
-
16571
- const CSidebarToggler = vue.defineComponent({
16572
- name: 'CSidebarToggler',
16573
- setup(_, { slots }) {
16574
- return () => vue.h('button', { class: 'sidebar-toggler' }, slots.default && slots.default());
17076
+ }),
17077
+ afterDots.value &&
17078
+ vue.h(CPaginationItem, {
17079
+ role: 'separator',
17080
+ disabled: true,
17081
+ }, {
17082
+ default: () => '...',
17083
+ }),
17084
+ props.arrows &&
17085
+ vue.h(CPaginationItem, {
17086
+ onClick: () => {
17087
+ activePage.value !== pages.value && setPage(activePage.value + 1);
17088
+ },
17089
+ 'aria-label': 'Go to next page',
17090
+ ...(activePage.value === pages.value && {
17091
+ 'aria-disabled': true,
17092
+ disabled: true,
17093
+ }),
17094
+ }, {
17095
+ default: () => typeof props.nextButton === 'string'
17096
+ ? vue.h('span', {
17097
+ innerHTML: props.nextButton,
17098
+ })
17099
+ : props.nextButton,
17100
+ }),
17101
+ props.doubleArrows &&
17102
+ vue.h(CPaginationItem, {
17103
+ onClick: () => {
17104
+ activePage.value !== pages.value && setPage(pages.value);
17105
+ },
17106
+ 'aria-label': 'Go to last page',
17107
+ ...(activePage.value === pages.value && {
17108
+ 'aria-disabled': true,
17109
+ disabled: true,
17110
+ }),
17111
+ }, {
17112
+ default: () => typeof props.lastButton === 'string'
17113
+ ? vue.h('span', {
17114
+ innerHTML: props.lastButton,
17115
+ })
17116
+ : props.lastButton,
17117
+ }),
17118
+ ],
17119
+ });
16575
17120
  },
16576
17121
  });
16577
17122
 
16578
- const CSidebarPlugin = {
17123
+ const CSmartPaginationPlugin = {
16579
17124
  install: (app) => {
16580
- app.component(CSidebar.name, CSidebar);
16581
- app.component(CSidebarBrand.name, CSidebarBrand);
16582
- app.component(CSidebarFooter.name, CSidebarFooter);
16583
- app.component(CSidebarHeader.name, CSidebarHeader);
16584
- app.component(CSidebarNav.name, CSidebarNav);
16585
- app.component(CSidebarToggler.name, CSidebarToggler);
17125
+ app.component(CSmartPagination.name, CSmartPagination);
16586
17126
  },
16587
17127
  };
16588
17128
 
@@ -16609,7 +17149,6 @@ const CTableBody = vue.defineComponent({
16609
17149
 
16610
17150
  const CTableCaption = vue.defineComponent({
16611
17151
  name: 'CTableCaption',
16612
- props: {},
16613
17152
  setup(_, { slots }) {
16614
17153
  return () => vue.h('caption', {}, slots.default && slots.default());
16615
17154
  },
@@ -17625,13 +18164,13 @@ const CIcon = vue.defineComponent({
17625
18164
  },
17626
18165
  });
17627
18166
 
17628
- const 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'/>"];
18167
+ 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'/>"];
17629
18168
 
17630
- const 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'/>"];
18169
+ 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'/>"];
17631
18170
 
17632
- const 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'/>"];
18171
+ 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'/>"];
17633
18172
 
17634
- const 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'/>"];
18173
+ 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'/>"];
17635
18174
 
17636
18175
  const CSmartTable = vue.defineComponent({
17637
18176
  name: 'CSmartTable',
@@ -17740,6 +18279,7 @@ const CSmartTable = vue.defineComponent({
17740
18279
  */
17741
18280
  itemsPerPage: {
17742
18281
  type: Number,
18282
+ default: 10,
17743
18283
  required: false,
17744
18284
  },
17745
18285
  /**
@@ -17788,7 +18328,7 @@ const CSmartTable = vue.defineComponent({
17788
18328
  * 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.
17789
18329
  */
17790
18330
  pagination: {
17791
- type: Boolean,
18331
+ type: [Boolean, Object],
17792
18332
  required: false,
17793
18333
  },
17794
18334
  /**
@@ -18275,12 +18815,14 @@ const CSmartTable = vue.defineComponent({
18275
18815
  }, [
18276
18816
  vue.h('div', {
18277
18817
  class: 'col',
18278
- }, props.pagination && numberOfPages.value > 1
18818
+ }, (props.pagination && numberOfPages.value > 1) || props.paginationProps
18279
18819
  ? vue.h(CSmartPagination, {
18280
- ...props.paginationProps,
18281
18820
  pages: numberOfPages.value,
18282
18821
  activePage: activePage.value,
18283
- onActivePageChange: handleActivePageChange,
18822
+ ...props.paginationProps,
18823
+ onActivePageChange: (page) => typeof props.pagination === 'object' && props.pagination.external
18824
+ ? emit('activePageChange', page)
18825
+ : handleActivePageChange(page),
18284
18826
  })
18285
18827
  : ''),
18286
18828
  vue.h('div', {
@@ -19409,7 +19951,6 @@ var Components = /*#__PURE__*/Object.freeze({
19409
19951
  CPaginationPlugin: CPaginationPlugin,
19410
19952
  CPagination: CPagination,
19411
19953
  CPaginationItem: CPaginationItem,
19412
- CSmartPagination: CSmartPagination,
19413
19954
  CPicker: CPicker,
19414
19955
  CPickerPlugin: CPickerPlugin,
19415
19956
  CPlaceholderPlugin: CPlaceholderPlugin,
@@ -19426,6 +19967,8 @@ var Components = /*#__PURE__*/Object.freeze({
19426
19967
  CSidebarHeader: CSidebarHeader,
19427
19968
  CSidebarNav: CSidebarNav,
19428
19969
  CSidebarToggler: CSidebarToggler,
19970
+ CSmartPaginationPlugin: CSmartPaginationPlugin,
19971
+ CSmartPagination: CSmartPagination,
19429
19972
  CSmartTablePlugin: CSmartTablePlugin,
19430
19973
  CSmartTable: CSmartTable,
19431
19974
  CSpinnerPlugin: CSpinnerPlugin,
@@ -19833,6 +20376,7 @@ exports.CSidebarNav = CSidebarNav;
19833
20376
  exports.CSidebarPlugin = CSidebarPlugin;
19834
20377
  exports.CSidebarToggler = CSidebarToggler;
19835
20378
  exports.CSmartPagination = CSmartPagination;
20379
+ exports.CSmartPaginationPlugin = CSmartPaginationPlugin;
19836
20380
  exports.CSmartTable = CSmartTable;
19837
20381
  exports.CSmartTablePlugin = CSmartTablePlugin;
19838
20382
  exports.CSpinner = CSpinner;