@coreui/vue-pro 5.18.0 → 5.19.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 (422) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/carousel/CCarousel.d.ts +24 -2
  3. package/dist/cjs/components/carousel/CCarousel.js +51 -14
  4. package/dist/cjs/components/carousel/CCarousel.js.map +1 -1
  5. package/dist/cjs/components/carousel/CCarouselItem.js +3 -3
  6. package/dist/cjs/components/carousel/CCarouselItem.js.map +1 -1
  7. package/dist/cjs/components/chip/CChip.d.ts +97 -11
  8. package/dist/cjs/components/chip/CChip.js +107 -79
  9. package/dist/cjs/components/chip/CChip.js.map +1 -1
  10. package/dist/cjs/components/chip/const.d.ts +1 -0
  11. package/dist/cjs/components/chip/const.js +8 -0
  12. package/dist/cjs/components/chip/const.js.map +1 -0
  13. package/dist/cjs/components/chip-input/CChipInput.d.ts +30 -2
  14. package/dist/cjs/components/chip-input/CChipInput.js +108 -66
  15. package/dist/cjs/components/chip-input/CChipInput.js.map +1 -1
  16. package/dist/cjs/components/chip-set/CChipSet.d.ts +145 -0
  17. package/dist/cjs/components/chip-set/CChipSet.js +127 -0
  18. package/dist/cjs/components/chip-set/CChipSet.js.map +1 -0
  19. package/dist/cjs/components/chip-set/buildChips.d.ts +13 -0
  20. package/dist/cjs/components/chip-set/buildChips.js +19 -0
  21. package/dist/cjs/components/chip-set/buildChips.js.map +1 -0
  22. package/dist/cjs/components/chip-set/index.d.ts +2 -0
  23. package/dist/cjs/components/chip-set/useChipSet.d.ts +42 -0
  24. package/dist/cjs/components/chip-set/useChipSet.js +115 -0
  25. package/dist/cjs/components/chip-set/useChipSet.js.map +1 -0
  26. package/dist/cjs/components/collapse/CCollapse.js +2 -2
  27. package/dist/cjs/components/collapse/CCollapse.js.map +1 -1
  28. package/dist/cjs/components/dropdown/CDropdown.d.ts +24 -1
  29. package/dist/cjs/components/dropdown/CDropdown.js +34 -17
  30. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  31. package/dist/cjs/components/dropdown/CDropdownToggle.js +1 -1
  32. package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
  33. package/dist/cjs/components/focus-trap/CFocusTrap.js +4 -1
  34. package/dist/cjs/components/focus-trap/CFocusTrap.js.map +1 -1
  35. package/dist/cjs/components/form/CFormInput.d.ts +3 -0
  36. package/dist/cjs/components/form/CFormRange.d.ts +2 -2
  37. package/dist/cjs/components/form/CFormRange.js +2 -2
  38. package/dist/cjs/components/form/CFormRange.js.map +1 -1
  39. package/dist/cjs/components/grid/CContainer.js +3 -1
  40. package/dist/cjs/components/grid/CContainer.js.map +1 -1
  41. package/dist/cjs/components/index.d.ts +2 -0
  42. package/dist/cjs/components/index.js +30 -24
  43. package/dist/cjs/components/index.js.map +1 -1
  44. package/dist/cjs/components/modal/CModal.js +3 -2
  45. package/dist/cjs/components/modal/CModal.js.map +1 -1
  46. package/dist/cjs/components/modal/CModalHeader.js +6 -3
  47. package/dist/cjs/components/modal/CModalHeader.js.map +1 -1
  48. package/dist/cjs/components/multi-select/CMultiSelect.d.ts +206 -3
  49. package/dist/cjs/components/multi-select/CMultiSelect.js +304 -28
  50. package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
  51. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js +1 -2
  52. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  53. package/dist/cjs/components/multi-select/CMultiSelectOptions.d.ts +16 -1
  54. package/dist/cjs/components/multi-select/CMultiSelectOptions.js +59 -3
  55. package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
  56. package/dist/cjs/components/multi-select/CMultiSelectSelection.d.ts +9 -0
  57. package/dist/cjs/components/multi-select/CMultiSelectSelection.js +6 -1
  58. package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
  59. package/dist/cjs/components/multi-select/utils.js +0 -3
  60. package/dist/cjs/components/multi-select/utils.js.map +1 -1
  61. package/dist/cjs/components/nav/CNav.js +8 -1
  62. package/dist/cjs/components/nav/CNav.js.map +1 -1
  63. package/dist/cjs/components/nav/CNavGroup.d.ts +15 -7
  64. package/dist/cjs/components/nav/CNavGroup.js +113 -88
  65. package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
  66. package/dist/cjs/components/nav/CNavLink.js +11 -0
  67. package/dist/cjs/components/nav/CNavLink.js.map +1 -1
  68. package/dist/cjs/components/popover/CPopover.d.ts +24 -1
  69. package/dist/cjs/components/popover/CPopover.js +18 -1
  70. package/dist/cjs/components/popover/CPopover.js.map +1 -1
  71. package/dist/cjs/components/range-slider/CRangeSlider.d.ts +1 -1
  72. package/dist/cjs/components/search-button/CSearchButton.d.ts +63 -0
  73. package/dist/cjs/components/search-button/CSearchButton.js +125 -0
  74. package/dist/cjs/components/search-button/CSearchButton.js.map +1 -0
  75. package/dist/cjs/components/search-button/index.d.ts +6 -0
  76. package/dist/cjs/components/search-button/index.js +13 -0
  77. package/dist/cjs/components/search-button/index.js.map +1 -0
  78. package/dist/cjs/components/search-button/types.d.ts +10 -0
  79. package/dist/cjs/components/search-button/utils.d.ts +11 -0
  80. package/dist/cjs/components/search-button/utils.js +114 -0
  81. package/dist/cjs/components/search-button/utils.js.map +1 -0
  82. package/dist/cjs/components/sidebar/CSidebar.js +4 -3
  83. package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
  84. package/dist/cjs/components/sidebar/CSidebarNav.d.ts +32 -0
  85. package/dist/cjs/components/sidebar/CSidebarNav.js +28 -24
  86. package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
  87. package/dist/cjs/components/spinner/CSpinner.d.ts +4 -4
  88. package/dist/cjs/components/spinner/CSpinner.js +2 -2
  89. package/dist/cjs/components/spinner/CSpinner.js.map +1 -1
  90. package/dist/cjs/components/table/utils.js +4 -4
  91. package/dist/cjs/components/table/utils.js.map +1 -1
  92. package/dist/cjs/components/tabs/CTabList.js +8 -2
  93. package/dist/cjs/components/tabs/CTabList.js.map +1 -1
  94. package/dist/cjs/components/tabs/CTabs.js +1 -1
  95. package/dist/cjs/components/tabs/CTabs.js.map +1 -1
  96. package/dist/cjs/components/toast/CToast.js +12 -2
  97. package/dist/cjs/components/toast/CToast.js.map +1 -1
  98. package/dist/cjs/components/toast/CToastClose.d.ts +3 -2
  99. package/dist/cjs/components/toast/CToastClose.js +2 -3
  100. package/dist/cjs/components/toast/CToastClose.js.map +1 -1
  101. package/dist/cjs/components/tooltip/CTooltip.d.ts +24 -1
  102. package/dist/cjs/components/tooltip/CTooltip.js +18 -1
  103. package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
  104. package/dist/cjs/directives/v-c-popover.js +6 -3
  105. package/dist/cjs/directives/v-c-popover.js.map +1 -1
  106. package/dist/cjs/directives/v-c-tooltip.js +6 -3
  107. package/dist/cjs/directives/v-c-tooltip.js.map +1 -1
  108. package/dist/cjs/directives/v-c-visible.js +1 -1
  109. package/dist/cjs/directives/v-c-visible.js.map +1 -1
  110. package/dist/cjs/index.js +36 -30
  111. package/dist/cjs/index.js.map +1 -1
  112. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  113. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  114. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  115. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  116. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  117. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  118. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  119. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  120. package/dist/cjs/utils/index.d.ts +2 -1
  121. package/dist/cjs/utils/swipe.d.ts +26 -0
  122. package/dist/cjs/utils/swipe.js +94 -0
  123. package/dist/cjs/utils/swipe.js.map +1 -0
  124. package/dist/cjs/utils/transition.js.map +1 -1
  125. package/dist/esm/components/carousel/CCarousel.d.ts +24 -2
  126. package/dist/esm/components/carousel/CCarousel.js +52 -15
  127. package/dist/esm/components/carousel/CCarousel.js.map +1 -1
  128. package/dist/esm/components/carousel/CCarouselItem.js +3 -3
  129. package/dist/esm/components/carousel/CCarouselItem.js.map +1 -1
  130. package/dist/esm/components/chip/CChip.d.ts +97 -11
  131. package/dist/esm/components/chip/CChip.js +108 -80
  132. package/dist/esm/components/chip/CChip.js.map +1 -1
  133. package/dist/esm/components/chip/const.d.ts +1 -0
  134. package/dist/esm/components/chip/const.js +6 -0
  135. package/dist/esm/components/chip/const.js.map +1 -0
  136. package/dist/esm/components/chip-input/CChipInput.d.ts +30 -2
  137. package/dist/esm/components/chip-input/CChipInput.js +109 -67
  138. package/dist/esm/components/chip-input/CChipInput.js.map +1 -1
  139. package/dist/esm/components/chip-set/CChipSet.d.ts +145 -0
  140. package/dist/esm/components/chip-set/CChipSet.js +125 -0
  141. package/dist/esm/components/chip-set/CChipSet.js.map +1 -0
  142. package/dist/esm/components/chip-set/buildChips.d.ts +13 -0
  143. package/dist/esm/components/chip-set/buildChips.js +17 -0
  144. package/dist/esm/components/chip-set/buildChips.js.map +1 -0
  145. package/dist/esm/components/chip-set/index.d.ts +2 -0
  146. package/dist/esm/components/chip-set/useChipSet.d.ts +42 -0
  147. package/dist/esm/components/chip-set/useChipSet.js +112 -0
  148. package/dist/esm/components/chip-set/useChipSet.js.map +1 -0
  149. package/dist/esm/components/collapse/CCollapse.js +2 -2
  150. package/dist/esm/components/collapse/CCollapse.js.map +1 -1
  151. package/dist/esm/components/dropdown/CDropdown.d.ts +24 -1
  152. package/dist/esm/components/dropdown/CDropdown.js +34 -17
  153. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  154. package/dist/esm/components/dropdown/CDropdownToggle.js +1 -1
  155. package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
  156. package/dist/esm/components/focus-trap/CFocusTrap.js +4 -1
  157. package/dist/esm/components/focus-trap/CFocusTrap.js.map +1 -1
  158. package/dist/esm/components/form/CFormInput.d.ts +3 -0
  159. package/dist/esm/components/form/CFormRange.d.ts +2 -2
  160. package/dist/esm/components/form/CFormRange.js +2 -2
  161. package/dist/esm/components/form/CFormRange.js.map +1 -1
  162. package/dist/esm/components/grid/CContainer.js +3 -1
  163. package/dist/esm/components/grid/CContainer.js.map +1 -1
  164. package/dist/esm/components/index.d.ts +2 -0
  165. package/dist/esm/components/index.js +3 -0
  166. package/dist/esm/components/index.js.map +1 -1
  167. package/dist/esm/components/modal/CModal.js +3 -2
  168. package/dist/esm/components/modal/CModal.js.map +1 -1
  169. package/dist/esm/components/modal/CModalHeader.js +6 -3
  170. package/dist/esm/components/modal/CModalHeader.js.map +1 -1
  171. package/dist/esm/components/multi-select/CMultiSelect.d.ts +206 -3
  172. package/dist/esm/components/multi-select/CMultiSelect.js +305 -29
  173. package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
  174. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js +1 -2
  175. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  176. package/dist/esm/components/multi-select/CMultiSelectOptions.d.ts +16 -1
  177. package/dist/esm/components/multi-select/CMultiSelectOptions.js +59 -3
  178. package/dist/esm/components/multi-select/CMultiSelectOptions.js.map +1 -1
  179. package/dist/esm/components/multi-select/CMultiSelectSelection.d.ts +9 -0
  180. package/dist/esm/components/multi-select/CMultiSelectSelection.js +6 -1
  181. package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
  182. package/dist/esm/components/multi-select/utils.js +0 -3
  183. package/dist/esm/components/multi-select/utils.js.map +1 -1
  184. package/dist/esm/components/nav/CNav.js +8 -1
  185. package/dist/esm/components/nav/CNav.js.map +1 -1
  186. package/dist/esm/components/nav/CNavGroup.d.ts +15 -7
  187. package/dist/esm/components/nav/CNavGroup.js +114 -89
  188. package/dist/esm/components/nav/CNavGroup.js.map +1 -1
  189. package/dist/esm/components/nav/CNavLink.js +12 -1
  190. package/dist/esm/components/nav/CNavLink.js.map +1 -1
  191. package/dist/esm/components/popover/CPopover.d.ts +24 -1
  192. package/dist/esm/components/popover/CPopover.js +18 -1
  193. package/dist/esm/components/popover/CPopover.js.map +1 -1
  194. package/dist/esm/components/range-slider/CRangeSlider.d.ts +1 -1
  195. package/dist/esm/components/search-button/CSearchButton.d.ts +63 -0
  196. package/dist/esm/components/search-button/CSearchButton.js +123 -0
  197. package/dist/esm/components/search-button/CSearchButton.js.map +1 -0
  198. package/dist/esm/components/search-button/index.d.ts +6 -0
  199. package/dist/esm/components/search-button/index.js +10 -0
  200. package/dist/esm/components/search-button/index.js.map +1 -0
  201. package/dist/esm/components/search-button/types.d.ts +10 -0
  202. package/dist/esm/components/search-button/utils.d.ts +11 -0
  203. package/dist/esm/components/search-button/utils.js +103 -0
  204. package/dist/esm/components/search-button/utils.js.map +1 -0
  205. package/dist/esm/components/sidebar/CSidebar.js +4 -3
  206. package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
  207. package/dist/esm/components/sidebar/CSidebarNav.d.ts +32 -0
  208. package/dist/esm/components/sidebar/CSidebarNav.js +29 -25
  209. package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
  210. package/dist/esm/components/spinner/CSpinner.d.ts +4 -4
  211. package/dist/esm/components/spinner/CSpinner.js +2 -2
  212. package/dist/esm/components/spinner/CSpinner.js.map +1 -1
  213. package/dist/esm/components/table/utils.js +4 -4
  214. package/dist/esm/components/table/utils.js.map +1 -1
  215. package/dist/esm/components/tabs/CTabList.js +8 -2
  216. package/dist/esm/components/tabs/CTabList.js.map +1 -1
  217. package/dist/esm/components/tabs/CTabs.js +1 -1
  218. package/dist/esm/components/tabs/CTabs.js.map +1 -1
  219. package/dist/esm/components/toast/CToast.js +12 -2
  220. package/dist/esm/components/toast/CToast.js.map +1 -1
  221. package/dist/esm/components/toast/CToastClose.d.ts +3 -2
  222. package/dist/esm/components/toast/CToastClose.js +2 -3
  223. package/dist/esm/components/toast/CToastClose.js.map +1 -1
  224. package/dist/esm/components/tooltip/CTooltip.d.ts +24 -1
  225. package/dist/esm/components/tooltip/CTooltip.js +18 -1
  226. package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
  227. package/dist/esm/directives/v-c-popover.js +6 -3
  228. package/dist/esm/directives/v-c-popover.js.map +1 -1
  229. package/dist/esm/directives/v-c-tooltip.js +6 -3
  230. package/dist/esm/directives/v-c-tooltip.js.map +1 -1
  231. package/dist/esm/directives/v-c-visible.js +1 -1
  232. package/dist/esm/directives/v-c-visible.js.map +1 -1
  233. package/dist/esm/index.js +3 -0
  234. package/dist/esm/index.js.map +1 -1
  235. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  236. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  237. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  238. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  239. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  240. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  241. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  242. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  243. package/dist/esm/utils/index.d.ts +2 -1
  244. package/dist/esm/utils/swipe.d.ts +26 -0
  245. package/dist/esm/utils/swipe.js +90 -0
  246. package/dist/esm/utils/swipe.js.map +1 -0
  247. package/dist/esm/utils/transition.js.map +1 -1
  248. package/package.json +6 -6
  249. package/src/components/accordion/CAccordion.ts +2 -2
  250. package/src/components/accordion/CAccordionBody.ts +1 -1
  251. package/src/components/accordion/CAccordionButton.ts +1 -1
  252. package/src/components/accordion/CAccordionHeader.ts +2 -2
  253. package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.ts.snap +1 -1
  254. package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.ts.snap +1 -1
  255. package/src/components/alert/CAlert.ts +3 -3
  256. package/src/components/alert/CAlertHeading.ts +1 -1
  257. package/src/components/alert/CAlertLink.ts +1 -1
  258. package/src/components/autocomplete/__tests__/CAutocomplete.spec.ts +5 -1
  259. package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.ts +8 -5
  260. package/src/components/avatar/CAvatar.ts +1 -1
  261. package/src/components/backdrop/CBackdrop.ts +1 -1
  262. package/src/components/badge/CBadge.ts +1 -1
  263. package/src/components/breadcrumb/CBreadcrumb.ts +1 -1
  264. package/src/components/breadcrumb/CBreadcrumbItem.ts +1 -1
  265. package/src/components/button/CButton.ts +1 -1
  266. package/src/components/button/__tests__/CButton.spec.ts +0 -1
  267. package/src/components/button/__tests__/__snapshots__/CButton.spec.ts.snap +1 -1
  268. package/src/components/button-group/CButtonGroup.ts +1 -1
  269. package/src/components/callout/CCallout.ts +1 -1
  270. package/src/components/card/CCard.ts +1 -1
  271. package/src/components/card/CCardImage.ts +1 -1
  272. package/src/components/card/CCardLink.ts +1 -1
  273. package/src/components/carousel/CCarousel.ts +61 -22
  274. package/src/components/carousel/CCarouselCaption.ts +1 -1
  275. package/src/components/carousel/CCarouselItem.ts +5 -4
  276. package/src/components/carousel/__tests__/CCarousel.spec.ts +1 -1
  277. package/src/components/chip/CChip.ts +123 -101
  278. package/src/components/chip/__tests__/CChip.spec.ts +26 -0
  279. package/src/components/chip/const.ts +3 -0
  280. package/src/components/chip-input/CChipInput.ts +134 -82
  281. package/src/components/chip-input/__tests__/CChipInput.spec.ts +80 -4
  282. package/src/components/chip-input/__tests__/__snapshots__/CChipInput.spec.ts.snap +1 -1
  283. package/src/components/chip-set/CChipSet.ts +140 -0
  284. package/src/components/chip-set/__tests__/CChipSet.spec.ts +174 -0
  285. package/src/components/chip-set/buildChips.ts +29 -0
  286. package/src/components/chip-set/index.ts +3 -0
  287. package/src/components/chip-set/useChipSet.ts +168 -0
  288. package/src/components/collapse/CCollapse.ts +5 -5
  289. package/src/components/collapse/__tests__/CCollapse.spec.ts +48 -0
  290. package/src/components/collapse/__tests__/__snapshots__/CCollapse.spec.ts.snap +7 -0
  291. package/src/components/conditional-teleport/CConditionalTeleport.ts +3 -3
  292. package/src/components/conditional-teleport/__tests__/CConditionalTeleport.spec.ts +28 -0
  293. package/src/components/dropdown/CDropdown.ts +43 -23
  294. package/src/components/dropdown/CDropdownHeader.ts +1 -1
  295. package/src/components/dropdown/CDropdownItem.ts +1 -1
  296. package/src/components/dropdown/CDropdownMenu.ts +2 -2
  297. package/src/components/dropdown/CDropdownToggle.ts +4 -4
  298. package/src/components/dropdown/__tests__/CDropdown.spec.ts +1 -1
  299. package/src/components/dropdown/__tests__/CDropdownMenu.spec.ts +11 -7
  300. package/src/components/dropdown/__tests__/CDropdownPopperConfig.spec.ts +63 -0
  301. package/src/components/dropdown/__tests__/CDropdownToggle.spec.ts +0 -2
  302. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.ts.snap +1 -1
  303. package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.ts.snap +4 -0
  304. package/src/components/dropdown/utils.ts +2 -2
  305. package/src/components/focus-trap/CFocusTrap.ts +9 -6
  306. package/src/components/focus-trap/__tests__/CFocusTrap.spec.ts +42 -0
  307. package/src/components/footer/CFooter.ts +1 -1
  308. package/src/components/form/CForm.ts +1 -1
  309. package/src/components/form/CFormCheck.ts +5 -5
  310. package/src/components/form/CFormControlValidation.ts +3 -3
  311. package/src/components/form/CFormFeedback.ts +1 -1
  312. package/src/components/form/CFormFloating.ts +1 -1
  313. package/src/components/form/CFormInput.ts +2 -2
  314. package/src/components/form/CFormLabel.ts +1 -1
  315. package/src/components/form/CFormRange.ts +4 -4
  316. package/src/components/form/CFormSelect.ts +3 -3
  317. package/src/components/form/CFormSwitch.ts +2 -2
  318. package/src/components/form/CFormTextarea.ts +2 -2
  319. package/src/components/form/CInputGroup.ts +1 -1
  320. package/src/components/form/__tests__/CFormRange.spec.ts +2 -2
  321. package/src/components/form/__tests__/CFormText.spec.ts +1 -1
  322. package/src/components/form/__tests__/__snapshots__/CFormRange.spec.ts.snap +1 -1
  323. package/src/components/grid/CCol.ts +1 -1
  324. package/src/components/grid/CContainer.ts +4 -2
  325. package/src/components/grid/CRow.ts +1 -1
  326. package/src/components/header/CHeader.ts +2 -2
  327. package/src/components/header/CHeaderNav.ts +1 -1
  328. package/src/components/header/CHeaderToggler.ts +1 -1
  329. package/src/components/header/__tests__/CHeader.spec.ts +1 -2
  330. package/src/components/index.ts +2 -0
  331. package/src/components/link/CLink.ts +1 -1
  332. package/src/components/list-group/CListGroup.ts +1 -1
  333. package/src/components/list-group/CListGroupItem.ts +1 -1
  334. package/src/components/modal/CModal.ts +3 -2
  335. package/src/components/modal/CModalHeader.ts +10 -3
  336. package/src/components/modal/__tests__/__snapshots__/CModal.spec.ts.snap +9 -4
  337. package/src/components/multi-select/CMultiSelect.ts +380 -41
  338. package/src/components/multi-select/CMultiSelectNativeSelect.ts +1 -2
  339. package/src/components/multi-select/CMultiSelectOptions.ts +77 -3
  340. package/src/components/multi-select/CMultiSelectSelection.ts +6 -1
  341. package/src/components/nav/CNav.ts +9 -2
  342. package/src/components/nav/CNavGroup.ts +147 -99
  343. package/src/components/nav/CNavItem.ts +2 -2
  344. package/src/components/nav/CNavLink.ts +19 -2
  345. package/src/components/nav/__tests__/CNavGroup.spec.ts +188 -6
  346. package/src/components/nav/__tests__/CNavItem.spec.ts +6 -6
  347. package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.ts.snap +3 -7
  348. package/src/components/nav/__tests__/__snapshots__/CNavItem.spec.ts.snap +1 -5
  349. package/src/components/navbar/CNavbar.ts +2 -2
  350. package/src/components/navbar/CNavbarBrand.ts +1 -1
  351. package/src/components/navbar/CNavbarNav.ts +1 -1
  352. package/src/components/navbar/CNavbarToggler.ts +1 -1
  353. package/src/components/navbar/__tests__/CNavbar.spec.ts +1 -1
  354. package/src/components/pagination/CPagination.ts +2 -2
  355. package/src/components/pagination/CPaginationItem.ts +2 -2
  356. package/src/components/placeholder/CPlaceholder.ts +1 -1
  357. package/src/components/popover/CPopover.ts +27 -7
  358. package/src/components/popover/__tests__/CPopover.spec.ts +43 -0
  359. package/src/components/progress/CProgress.ts +2 -2
  360. package/src/components/progress/CProgressBar.ts +1 -1
  361. package/src/components/progress/CProgressStacked.ts +1 -1
  362. package/src/components/progress/__tests__/CProgressBar.spec.ts +0 -4
  363. package/src/components/search-button/CSearchButton.ts +163 -0
  364. package/src/components/search-button/__tests__/CSearchButton.spec.ts +128 -0
  365. package/src/components/search-button/__tests__/__snapshots__/CSearchButton.spec.ts.snap +13 -0
  366. package/src/components/search-button/index.ts +10 -0
  367. package/src/components/search-button/types.ts +10 -0
  368. package/src/components/search-button/utils.ts +140 -0
  369. package/src/components/sidebar/CSidebar.ts +9 -6
  370. package/src/components/sidebar/CSidebarBrand.ts +1 -1
  371. package/src/components/sidebar/CSidebarNav.ts +30 -28
  372. package/src/components/sidebar/__tests__/CSidebar.spec.ts +1 -1
  373. package/src/components/spinner/CSpinner.ts +6 -6
  374. package/src/components/spinner/__tests__/CSpinner.spec.ts +0 -1
  375. package/src/components/stepper/__tests__/CStepper.spec.ts +13 -8
  376. package/src/components/table/CTable.ts +16 -16
  377. package/src/components/table/CTableBody.ts +1 -1
  378. package/src/components/table/CTableDataCell.ts +1 -1
  379. package/src/components/table/CTableFoot.ts +1 -1
  380. package/src/components/table/CTableHead.ts +1 -1
  381. package/src/components/table/CTableHeaderCell.ts +1 -1
  382. package/src/components/table/CTableRow.ts +1 -1
  383. package/src/components/table/types.ts +1 -0
  384. package/src/components/table/utils.ts +4 -4
  385. package/src/components/tabs/CTab.ts +1 -1
  386. package/src/components/tabs/CTabList.ts +12 -5
  387. package/src/components/tabs/CTabPane.ts +3 -3
  388. package/src/components/tabs/CTabPanel.ts +5 -5
  389. package/src/components/tabs/CTabs.ts +2 -2
  390. package/src/components/tabs/__tests__/__snapshots__/CTabPane.spec.ts.snap +1 -1
  391. package/src/components/toast/CToast.ts +12 -4
  392. package/src/components/toast/CToastClose.ts +5 -6
  393. package/src/components/toast/CToaster.ts +1 -1
  394. package/src/components/toast/__tests__/CToaster.spec.ts +0 -2
  395. package/src/components/toast/__tests__/__snapshots__/CToastClose.spec.ts.snap +1 -1
  396. package/src/components/tooltip/CTooltip.ts +26 -6
  397. package/src/components/tooltip/__tests__/CTooltip.spec.ts +43 -0
  398. package/src/components/widgets/CWidgetStatsA.ts +4 -4
  399. package/src/components/widgets/CWidgetStatsB.ts +5 -5
  400. package/src/components/widgets/CWidgetStatsC.ts +5 -5
  401. package/src/components/widgets/CWidgetStatsD.ts +5 -5
  402. package/src/components/widgets/CWidgetStatsE.ts +4 -4
  403. package/src/components/widgets/CWidgetStatsF.ts +5 -5
  404. package/src/directives/__tests__/v-c-placeholder.spec.ts +33 -0
  405. package/src/directives/__tests__/v-c-popover.spec.ts +67 -0
  406. package/src/directives/__tests__/v-c-tooltip.spec.ts +66 -0
  407. package/src/directives/v-c-popover.ts +8 -5
  408. package/src/directives/v-c-tooltip.ts +8 -5
  409. package/src/directives/v-c-visible.ts +1 -1
  410. package/src/index.ts +1 -1
  411. package/src/utils/ComponentProps.ts +1 -0
  412. package/src/utils/__tests__/swipe.spec.ts +82 -0
  413. package/src/utils/getNextActiveElement.ts +1 -1
  414. package/src/utils/index.ts +2 -0
  415. package/src/utils/swipe.ts +114 -0
  416. package/src/utils/transition.ts +2 -2
  417. package/dist/cjs/components/collapse/__test__/CCollapse.spec.d.ts +0 -1
  418. package/dist/esm/components/collapse/__test__/CCollapse.spec.d.ts +0 -1
  419. package/src/components/accordion/__tests__/CAccordionCollapse.spec.ts +0 -28
  420. package/src/components/accordion/__tests__/__snapshots__/CAccordionCollapse.spec.ts.snap +0 -7
  421. package/src/components/collapse/__test__/CCollapse.spec.ts +0 -44
  422. package/src/components/collapse/__test__/__snapshots__/CCollapse.spec.ts.snap +0 -13
@@ -49,7 +49,7 @@ const CLink = defineComponent({
49
49
  }),
50
50
  href: props.href,
51
51
  },
52
- slots.default && slots.default(),
52
+ slots.default && slots.default()
53
53
  )
54
54
  },
55
55
  })
@@ -46,7 +46,7 @@ const CListGroup = defineComponent({
46
46
  },
47
47
  ],
48
48
  },
49
- slots.default && slots.default(),
49
+ slots.default && slots.default()
50
50
  )
51
51
  },
52
52
  })
@@ -48,7 +48,7 @@ const CListGroupItem = defineComponent({
48
48
  ...(props.active && { 'aria-current': true }),
49
49
  ...(props.disabled && { 'aria-disabled': true }),
50
50
  },
51
- slots.default && slots.default(),
51
+ slots.default && slots.default()
52
52
  )
53
53
  },
54
54
  })
@@ -181,12 +181,13 @@ const CModal = defineComponent({
181
181
  }
182
182
 
183
183
  const handleAfterEnter = () => {
184
- props.focus && modalRef.value?.focus()
184
+ if (props.focus) {
185
+ modalRef.value?.focus()
186
+ }
185
187
  window.addEventListener('mousedown', handleMouseDown)
186
188
  window.addEventListener('keydown', handleKeyDown)
187
189
  }
188
190
 
189
- // eslint-disable-next-line unicorn/consistent-function-scoping
190
191
  const handleLeave = (el: RendererElement, done: () => void) => {
191
192
  executeAfterTransition(() => done(), el as HTMLElement)
192
193
  document.body.classList.remove('modal-open')
@@ -18,9 +18,16 @@ const CModalHeader = defineComponent({
18
18
  return () =>
19
19
  h('span', { class: 'modal-header' }, [
20
20
  slots.default && slots.default(),
21
- props.closeButton && h(CCloseButton, { onClick: () => {
22
- visible.value = false
23
- } }, ''),
21
+ props.closeButton &&
22
+ h(
23
+ CCloseButton,
24
+ {
25
+ onClick: () => {
26
+ visible.value = false
27
+ },
28
+ },
29
+ ''
30
+ ),
24
31
  ])
25
32
  },
26
33
  })
@@ -1,17 +1,21 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`Customize CModal component renders correctly 1`] = `
4
- "<transition-stub appear="false" persisted="false" css="false">
4
+ "<!--teleport start-->
5
+ <transition-stub appear="false" persisted="false" css="false">
5
6
  <div class="modal" aria-modal="true" role="dialog">
6
7
  <div class="modal-dialog modal-dialog-centered modal-fullscreen-lg-down modal-dialog-scrollable modal-lg">
7
8
  <div class="modal-content bazinga">Default slot</div>
8
9
  </div>
9
10
  </div>
10
- </transition-stub>"
11
+ </transition-stub>
12
+ <!---->
13
+ <!--teleport end-->"
11
14
  `;
12
15
 
13
16
  exports[`Loads and display CModal component renders correctly 1`] = `
14
- "<transition-stub appear="false" persisted="false" css="false">
17
+ "<!--teleport start-->
18
+ <transition-stub appear="false" persisted="false" css="false">
15
19
  <div class="modal fade" aria-modal="true" role="dialog">
16
20
  <div class="modal-dialog modal-fullscreen">
17
21
  <div class="modal-content">Default slot</div>
@@ -20,5 +24,6 @@ exports[`Loads and display CModal component renders correctly 1`] = `
20
24
  </transition-stub>
21
25
  <transition-stub appear="false" persisted="false" css="true" class="modal-backdrop">
22
26
  <div class="fade"></div>
23
- </transition-stub>"
27
+ </transition-stub>
28
+ <!--teleport end-->"
24
29
  `;
@@ -48,6 +48,24 @@ const CMultiSelect = defineComponent({
48
48
  type: String,
49
49
  default: 'Toggle dropdown',
50
50
  },
51
+ /**
52
+ * Accessible label for the search input (when `search` is enabled).
53
+ *
54
+ * @since 5.19.0
55
+ */
56
+ ariaSearchLabel: {
57
+ type: String,
58
+ default: 'Search',
59
+ },
60
+ /**
61
+ * Accessible label prefix for a tag's delete button (selection type `tags`). The selected option's label is appended, so screen readers announce e.g. "Remove Angular".
62
+ *
63
+ * @since 5.19.0
64
+ */
65
+ ariaTagDeleteLabel: {
66
+ type: String,
67
+ default: 'Remove',
68
+ },
51
69
  /**
52
70
  * Enables selection cleaner element.
53
71
  *
@@ -72,6 +90,24 @@ const CMultiSelect = defineComponent({
72
90
  * @since 4.9.0
73
91
  */
74
92
  clearSearchOnSelect: Boolean,
93
+ /**
94
+ * Sets the select all button label shown once everything is selected. The button is a toggle: it shows `selectAllLabel` (and selects all) until everything is selected, then shows `deselectAllLabel` (and deselects all).
95
+ *
96
+ * @since 5.19.0
97
+ */
98
+ deselectAllLabel: {
99
+ type: String,
100
+ default: 'Deselect all',
101
+ },
102
+ /**
103
+ * Sets the deselect filtered button label (used with `selectAllMode="filtered"`).
104
+ *
105
+ * @since 5.19.0
106
+ */
107
+ deselectFilteredLabel: {
108
+ type: String,
109
+ default: 'Deselect filtered',
110
+ },
75
111
  /**
76
112
  * Toggle the disabled state for the component.
77
113
  */
@@ -141,6 +177,26 @@ const CMultiSelect = defineComponent({
141
177
  type: Array as PropType<(Option | OptionsGroup)[]>,
142
178
  default: () => [],
143
179
  },
180
+ /**
181
+ * Makes each options group label a toggle that selects or deselects all options in that group. With `optionsGroupsStyle="checkbox"` (and `multiple`) the label shows a tri-state checkbox indicator (`none` / `all` / `indeterminate`) reflecting the group's selection.
182
+ *
183
+ * @since 5.19.0
184
+ */
185
+ optionsGroupsSelectable: Boolean,
186
+ /**
187
+ * Sets the options group label style when `optionsGroupsSelectable` is enabled.
188
+ *
189
+ * @values 'checkbox', 'text'
190
+ * @default 'checkbox'
191
+ * @since 5.19.0
192
+ */
193
+ optionsGroupsStyle: {
194
+ type: String,
195
+ default: 'checkbox',
196
+ validator: (value: string) => {
197
+ return ['checkbox', 'text'].includes(value)
198
+ },
199
+ },
144
200
  /**
145
201
  * Sets maxHeight of options list.
146
202
  *
@@ -239,11 +295,57 @@ const CMultiSelect = defineComponent({
239
295
  /**
240
296
  * Sets the select all button label.
241
297
  *
242
- * @default 'Select all options'
298
+ * @default 'Select all'
243
299
  */
244
300
  selectAllLabel: {
245
301
  type: String,
246
- default: 'Select all options',
302
+ default: 'Select all',
303
+ },
304
+ /**
305
+ * Determines what the select all button operates on: all options (`'all'`) or only the currently filtered (search-visible) options (`'filtered'`).
306
+ *
307
+ * @values 'all', 'filtered'
308
+ * @default 'all'
309
+ * @since 5.19.0
310
+ */
311
+ selectAllMode: {
312
+ type: String,
313
+ default: 'all',
314
+ validator: (value: string) => {
315
+ return ['all', 'filtered'].includes(value)
316
+ },
317
+ },
318
+ /**
319
+ * Sets the select all button style. With `'checkbox'` (and `multiple`), the button shows a tri-state checkbox indicator (`none` / `all` / `indeterminate`) and toggles between selecting and deselecting.
320
+ *
321
+ * @values 'checkbox', 'text'
322
+ * @default 'checkbox'
323
+ * @since 5.19.0
324
+ */
325
+ selectAllStyle: {
326
+ type: String,
327
+ default: 'checkbox',
328
+ validator: (value: string) => {
329
+ return ['checkbox', 'text'].includes(value)
330
+ },
331
+ },
332
+ /**
333
+ * Sets the select filtered button label (used with `selectAllMode="filtered"`).
334
+ *
335
+ * @since 5.19.0
336
+ */
337
+ selectFilteredLabel: {
338
+ type: String,
339
+ default: 'Select filtered',
340
+ },
341
+ /**
342
+ * Sets the maximum number of options that can be selected. The select all button stays enabled and selects options up to the limit, then toggles to deselect all once the limit is reached. The `selectionLimit` event fires when a user tries to select more options than allowed.
343
+ *
344
+ * @since 5.19.0
345
+ */
346
+ selectionLimit: {
347
+ type: Number,
348
+ default: null,
247
349
  },
248
350
  /**
249
351
  * Sets the selection style.
@@ -349,6 +451,12 @@ const CMultiSelect = defineComponent({
349
451
  * The callback is fired when the Multi Select component requests to be hidden.
350
452
  */
351
453
  'hide',
454
+ /**
455
+ * Execute a function when the user tries to select more options than allowed by `selectionLimit`.
456
+ *
457
+ * @since 5.19.0
458
+ */
459
+ 'selectionLimit',
352
460
  /**
353
461
  * The callback is fired when the Multi Select component requests to be shown.
354
462
  */
@@ -376,14 +484,22 @@ const CMultiSelect = defineComponent({
376
484
 
377
485
  provide('nativeSelectRef', nativeSelectRef)
378
486
 
379
- const filteredOptions = computed(() =>
380
- flattenOptionsArray(
381
- isExternalSearch(props.search)
382
- ? [...props.options, ...filterOptionsList(searchValue.value, userOptions.value)]
383
- : filterOptionsList(searchValue.value, [...props.options, ...userOptions.value]),
384
- true
385
- )
386
- )
487
+ const filteredOptions = computed(() => {
488
+ const source = isExternalSearch(props.search)
489
+ ? [...props.options, ...filterOptionsList(searchValue.value, userOptions.value)]
490
+ : filterOptionsList(searchValue.value, [...props.options, ...userOptions.value])
491
+
492
+ const flattened: (Option | OptionsGroup)[] = []
493
+ for (const option of source) {
494
+ if (Array.isArray((option as OptionsGroup).options)) {
495
+ flattened.push(option, ...((option as OptionsGroup).options as Option[]))
496
+ } else {
497
+ flattened.push(option)
498
+ }
499
+ }
500
+
501
+ return flattened
502
+ })
387
503
 
388
504
  const flattenedOptions = computed(() => {
389
505
  return flattenOptionsArray(props.options).map((option) => {
@@ -418,6 +534,107 @@ const CMultiSelect = defineComponent({
418
534
  return searchRef.value && createOption(String(searchValue.value), flattenedOptions.value)
419
535
  })
420
536
 
537
+ const selectableOptions = computed(() =>
538
+ flattenOptionsArray([...props.options, ...userOptions.value]).filter(
539
+ (option) => !option.disabled,
540
+ ),
541
+ )
542
+
543
+ const filteredSelectableOptions = computed(() =>
544
+ flattenOptionsArray(
545
+ isExternalSearch(props.search)
546
+ ? [...props.options, ...filterOptionsList(searchValue.value, userOptions.value)]
547
+ : filterOptionsList(searchValue.value, [...props.options, ...userOptions.value]),
548
+ ).filter((option) => !option.disabled),
549
+ )
550
+
551
+ const hasSelectionLimit = computed(
552
+ () => props.multiple && typeof props.selectionLimit === 'number',
553
+ )
554
+ const isSelectionLimitReached = computed(
555
+ () => hasSelectionLimit.value && selected.value.length >= (props.selectionLimit as number),
556
+ )
557
+ const selectableTarget = (total: number) =>
558
+ hasSelectionLimit.value ? Math.min(total, props.selectionLimit as number) : total
559
+
560
+ const selectAllScope = computed(() => {
561
+ const selectedValues = new Set(selected.value.map((option) => option.value))
562
+ const countSelected = (scope: (Option | OptionsGroup)[]) =>
563
+ scope.filter((option) => 'value' in option && selectedValues.has(option.value)).length
564
+
565
+ return props.selectAllMode === 'filtered'
566
+ ? {
567
+ selected: countSelected(filteredSelectableOptions.value),
568
+ total: filteredSelectableOptions.value.length,
569
+ }
570
+ : { selected: countSelected(selectableOptions.value), total: selectableOptions.value.length }
571
+ })
572
+
573
+ const isAllSelected = computed(() => {
574
+ const target = selectableTarget(selectAllScope.value.total)
575
+ return target > 0 && selectAllScope.value.selected >= target
576
+ })
577
+
578
+ const selectAllCheckboxState = computed(() =>
579
+ isAllSelected.value
580
+ ? 'all'
581
+ : selectAllScope.value.selected === 0
582
+ ? 'none'
583
+ : 'indeterminate',
584
+ )
585
+
586
+ const isFilteredScopeNarrowed = computed(
587
+ () =>
588
+ props.selectAllMode === 'filtered' &&
589
+ filteredSelectableOptions.value.length < selectableOptions.value.length,
590
+ )
591
+
592
+ const selectAllButtonLabel = computed(() =>
593
+ isFilteredScopeNarrowed.value
594
+ ? isAllSelected.value
595
+ ? props.deselectFilteredLabel
596
+ : props.selectFilteredLabel
597
+ : isAllSelected.value
598
+ ? props.deselectAllLabel
599
+ : props.selectAllLabel,
600
+ )
601
+
602
+ const headerState = computed(() => {
603
+ const selectedValues = new Set(selected.value.map((option) => option.value))
604
+ return {
605
+ selected: selected.value.length,
606
+ total: selectableOptions.value.length,
607
+ filtered: filteredSelectableOptions.value.length,
608
+ filteredSelected: filteredSelectableOptions.value.filter((option) =>
609
+ selectedValues.has(option.value),
610
+ ).length,
611
+ }
612
+ })
613
+
614
+ const selectWithLimit = (scope: (Option | OptionsGroup)[]) => {
615
+ if (!hasSelectionLimit.value) {
616
+ selected.value = selectOptions(props.multiple, scope, selected.value)
617
+ return
618
+ }
619
+
620
+ const remaining = (props.selectionLimit as number) - selected.value.length
621
+
622
+ if (remaining <= 0) {
623
+ emit('selectionLimit', props.selectionLimit)
624
+ return
625
+ }
626
+
627
+ const selectedValues = new Set(selected.value.map((option) => option.value))
628
+ const toAdd = scope.filter(
629
+ (option) => 'value' in option && !selectedValues.has(option.value),
630
+ )
631
+ selected.value = selectOptions(props.multiple, toAdd.slice(0, remaining), selected.value)
632
+
633
+ if (toAdd.length > remaining) {
634
+ emit('selectionLimit', props.selectionLimit)
635
+ }
636
+ }
637
+
421
638
  watch(
422
639
  flattenedOptions,
423
640
  () => {
@@ -481,6 +698,19 @@ const CMultiSelect = defineComponent({
481
698
  }
482
699
 
483
700
  emit('hide')
701
+
702
+ const active = document.activeElement
703
+ const wrapper = multiSelectRef.value as HTMLElement | null
704
+ const menu = dropdownMenuElement.value as HTMLElement | null
705
+
706
+ if (wrapper?.contains(active) || menu?.contains(active)) {
707
+ if (props.search && searchRef.value) {
708
+ searchRef.value.focus()
709
+ } else {
710
+ ;(dropdownRefElement.value as HTMLElement | null)?.focus()
711
+ }
712
+ }
713
+
484
714
  searchValue.value = ''
485
715
  if (searchRef.value) {
486
716
  searchRef.value.value = ''
@@ -582,6 +812,36 @@ const CMultiSelect = defineComponent({
582
812
  }
583
813
  }
584
814
 
815
+ const handleNativeSelectKeyDown = (event: KeyboardEvent) => {
816
+ if (event.key === 'Tab' || event.key === 'Escape') {
817
+ return
818
+ }
819
+
820
+ event.preventDefault()
821
+
822
+ const isPrintable =
823
+ event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey
824
+
825
+ if (
826
+ !isOpen.value &&
827
+ (event.key === 'Enter' || event.key === 'ArrowDown' || (props.search && isPrintable))
828
+ ) {
829
+ openDropdown()
830
+ }
831
+
832
+ if (props.search && searchRef.value) {
833
+ searchRef.value.focus()
834
+
835
+ if (isPrintable) {
836
+ const nextValue = searchRef.value.value + event.key
837
+ searchRef.value.value = nextValue
838
+ searchValue.value = nextValue.toLowerCase()
839
+ }
840
+ } else {
841
+ ;(dropdownRefElement.value as HTMLElement | null)?.focus()
842
+ }
843
+ }
844
+
585
845
  const handleGlobalSearch = (event: KeyboardEvent) => {
586
846
  if (
587
847
  isGlobalSearch(props.search) &&
@@ -604,6 +864,13 @@ const CMultiSelect = defineComponent({
604
864
  return
605
865
  }
606
866
 
867
+ const alreadySelected = selected.value.some((_option) => _option.value === option.value)
868
+
869
+ if (!alreadySelected && isSelectionLimitReached.value) {
870
+ emit('selectionLimit', props.selectionLimit)
871
+ return
872
+ }
873
+
607
874
  if (option.custom && !userOptions.value.some((_option) => _option.value === option.value)) {
608
875
  userOptions.value = [...userOptions.value, option]
609
876
  }
@@ -616,7 +883,7 @@ const CMultiSelect = defineComponent({
616
883
  }
617
884
  }
618
885
 
619
- if (selected.value.some((_option) => _option.value === option.value)) {
886
+ if (alreadySelected) {
620
887
  selected.value = selected.value.filter((_option) => _option.value !== option.value)
621
888
  } else {
622
889
  selected.value = [...selected.value, option] as SelectedOption[]
@@ -624,20 +891,57 @@ const CMultiSelect = defineComponent({
624
891
  }
625
892
 
626
893
  const handleSelectAll = () => {
627
- selected.value = selectOptions(
628
- props.multiple,
629
- [
630
- ...flattenedOptions.value.filter((option: Option | OptionsGroup) => !option.disabled),
631
- ...userOptions.value,
632
- ],
633
- selected.value
634
- )
894
+ selectWithLimit(selectableOptions.value)
635
895
  }
636
896
 
637
897
  const handleDeselectAll = () => {
638
898
  selected.value = selected.value.filter((option) => option.disabled)
639
899
  }
640
900
 
901
+ const handleSelectFiltered = () => {
902
+ selectWithLimit(filteredSelectableOptions.value)
903
+ }
904
+
905
+ const handleDeselectFiltered = () => {
906
+ const filteredValues = new Set(
907
+ filteredSelectableOptions.value.map((option) => option.value),
908
+ )
909
+ selected.value = selected.value.filter(
910
+ (option) => option.disabled || !filteredValues.has(option.value),
911
+ )
912
+ }
913
+
914
+ const handleSelectAllToggle = () => {
915
+ if (props.selectAllMode === 'filtered') {
916
+ isAllSelected.value ? handleDeselectFiltered() : handleSelectFiltered()
917
+ } else {
918
+ isAllSelected.value ? handleDeselectAll() : handleSelectAll()
919
+ }
920
+ }
921
+
922
+ const handleGroupClick = (group: OptionsGroup) => {
923
+ const selectedValues = new Set(selected.value.map((option) => option.value))
924
+ const groupOptions = (group.options ?? []).filter((option) => !option.disabled)
925
+ const allSelected =
926
+ groupOptions.length > 0 && groupOptions.every((option) => selectedValues.has(option.value))
927
+
928
+ if (allSelected) {
929
+ const groupValues = new Set(groupOptions.map((option) => option.value))
930
+ selected.value = selected.value.filter(
931
+ (option) => option.disabled || !groupValues.has(option.value),
932
+ )
933
+ } else {
934
+ selectWithLimit(groupOptions)
935
+ }
936
+ }
937
+
938
+ const headerActions = {
939
+ selectAll: handleSelectAll,
940
+ deselectAll: handleDeselectAll,
941
+ selectFiltered: handleSelectFiltered,
942
+ deselectFiltered: handleDeselectFiltered,
943
+ }
944
+
641
945
  return () => [
642
946
  h(
643
947
  CFormControlWrapper,
@@ -657,17 +961,6 @@ const CMultiSelect = defineComponent({
657
961
  },
658
962
  {
659
963
  default: () => [
660
- h(CMultiSelectNativeSelect, {
661
- id: props.id ?? uniqueId,
662
- multiple: props.multiple,
663
- name: props.name ?? uniqueId,
664
- options: selected.value,
665
- required: props.required,
666
- value: props.multiple
667
- ? selected.value.map((option: SelectedOption) => option.value.toString())
668
- : selected.value.map((option: SelectedOption) => option.value)[0],
669
- onChange: () => emit('change', selected.value),
670
- }),
671
964
  h(
672
965
  'div',
673
966
  {
@@ -685,11 +978,25 @@ const CMultiSelect = defineComponent({
685
978
  role: 'combobox',
686
979
  'aria-haspopup': 'listbox',
687
980
  'aria-expanded': isOpen.value,
981
+ 'aria-controls': `multi-select-listbox-${uniqueId}`,
688
982
  ...(props.teleport && { 'aria-owns': `multi-select-listbox-${uniqueId}` }),
983
+ ...(props.disabled && { 'aria-disabled': true }),
689
984
  ref: multiSelectRef,
690
985
  },
691
986
  {
692
987
  default: () => [
988
+ h(CMultiSelectNativeSelect, {
989
+ id: props.id ?? uniqueId,
990
+ multiple: props.multiple,
991
+ name: props.name ?? uniqueId,
992
+ options: selected.value,
993
+ required: props.required,
994
+ value: props.multiple
995
+ ? selected.value.map((option: SelectedOption) => option.value.toString())
996
+ : selected.value.map((option: SelectedOption) => option.value)[0],
997
+ onChange: () => emit('change', selected.value),
998
+ onKeydown: handleNativeSelectKeyDown,
999
+ }),
693
1000
  h(
694
1001
  'div',
695
1002
  {
@@ -708,6 +1015,7 @@ const CMultiSelect = defineComponent({
708
1015
  h(
709
1016
  CMultiSelectSelection,
710
1017
  {
1018
+ ariaTagDeleteLabel: props.ariaTagDeleteLabel,
711
1019
  disabled: props.disabled,
712
1020
  multiple: props.multiple,
713
1021
  placeholder: props.placeholder,
@@ -728,6 +1036,9 @@ const CMultiSelect = defineComponent({
728
1036
  id: `search-${props.id ?? uniqueId}`,
729
1037
  name: `search-${props.name ?? uniqueId}`,
730
1038
  autocomplete: 'off',
1039
+ 'aria-label': props.ariaSearchLabel,
1040
+ 'aria-autocomplete': 'list',
1041
+ 'aria-controls': `multi-select-listbox-${uniqueId}`,
731
1042
  onInput: (event: InputEvent) => handleSearchChange(event),
732
1043
  onKeydown: (event: KeyboardEvent) => handleSearchKeyDown(event),
733
1044
  ...(selected.value.length === 0 && {
@@ -822,24 +1133,52 @@ const CMultiSelect = defineComponent({
822
1133
  },
823
1134
  {
824
1135
  default: () => [
825
- props.multiple &&
826
- props.selectAll &&
827
- h(
828
- 'button',
829
- {
830
- class: 'form-multi-select-all',
831
- onClick: () => handleSelectAll(),
832
- type: 'button',
833
- },
834
- props.selectAllLabel
835
- ),
1136
+ (slots.header || (props.multiple && props.selectAll)) &&
1137
+ h('div', { class: 'form-multi-select-dropdown-header' }, [
1138
+ slots.header
1139
+ ? h(
1140
+ 'div',
1141
+ {
1142
+ onClick: (event: MouseEvent) => event.stopPropagation(),
1143
+ },
1144
+ slots.header({
1145
+ state: headerState.value,
1146
+ actions: headerActions,
1147
+ }),
1148
+ )
1149
+ : h(
1150
+ 'button',
1151
+ {
1152
+ class: [
1153
+ 'form-multi-select-all',
1154
+ {
1155
+ 'form-multi-select-all-with-checkbox':
1156
+ props.selectAllStyle === 'checkbox',
1157
+ 'form-multi-selected':
1158
+ props.selectAllStyle === 'checkbox' &&
1159
+ selectAllCheckboxState.value === 'all',
1160
+ 'form-multi-select-indeterminate':
1161
+ props.selectAllStyle === 'checkbox' &&
1162
+ selectAllCheckboxState.value === 'indeterminate',
1163
+ },
1164
+ ],
1165
+ onClick: () => handleSelectAllToggle(),
1166
+ type: 'button',
1167
+ },
1168
+ selectAllButtonLabel.value,
1169
+ ),
1170
+ ]),
836
1171
  h(CMultiSelectOptions, {
837
1172
  loading: props.loading,
1173
+ onGroupClick: (group: OptionsGroup) => handleGroupClick(group),
838
1174
  onOptionClick: (option: Option) => handleOnOptionClick(option),
839
1175
  options:
840
1176
  filteredOptions.value.length === 0 && props.allowCreateOptions
841
1177
  ? userOption.value || []
842
1178
  : filteredOptions.value,
1179
+ optionsGroupsSelectable:
1180
+ props.optionsGroupsSelectable && props.multiple,
1181
+ optionsGroupsStyle: props.optionsGroupsStyle,
843
1182
  optionsMaxHeight: props.optionsMaxHeight,
844
1183
  optionsStyle: props.optionsStyle,
845
1184
  scopedSlots: slots,
@@ -38,13 +38,12 @@ const CMultiSelectNativeSelect = defineComponent({
38
38
  h(
39
39
  'select',
40
40
  {
41
- className: 'multi-select-new',
41
+ className: 'form-multi-select',
42
42
  id: props.id,
43
43
  ...(props.id && !props.name && { name: `${props.id}-multi-select` }), // TODO: remove in v6
44
44
  ...(props.name && { name: props.name }), // TODO: change to `name: props.name` in v6
45
45
  multiple: props.multiple,
46
46
  tabIndex: '-1',
47
- style: { display: 'none' },
48
47
  required: props.required,
49
48
  value: props.value,
50
49
  ref: nativeSelectRef,