@coreui/react-pro 5.25.0 → 5.26.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 (291) hide show
  1. package/dist/cjs/components/card/CCardImage.js.map +1 -1
  2. package/dist/cjs/components/carousel/CCarousel.js +44 -33
  3. package/dist/cjs/components/carousel/CCarousel.js.map +1 -1
  4. package/dist/cjs/components/carousel/CCarouselItem.js +19 -28
  5. package/dist/cjs/components/carousel/CCarouselItem.js.map +1 -1
  6. package/dist/cjs/components/chip/CChip.d.ts +12 -0
  7. package/dist/cjs/components/chip/CChip.js +16 -63
  8. package/dist/cjs/components/chip/CChip.js.map +1 -1
  9. package/dist/cjs/components/chip/const.d.ts +1 -0
  10. package/dist/cjs/components/chip/const.js +8 -0
  11. package/dist/cjs/components/chip/const.js.map +1 -0
  12. package/dist/cjs/components/chip-set/CChipSet.d.ts +73 -0
  13. package/dist/cjs/components/chip-set/CChipSet.js +66 -0
  14. package/dist/cjs/components/chip-set/CChipSet.js.map +1 -0
  15. package/dist/cjs/components/chip-set/index.d.ts +2 -0
  16. package/dist/cjs/components/chip-set/useChipSet.d.ts +48 -0
  17. package/dist/cjs/components/chip-set/useChipSet.js +163 -0
  18. package/dist/cjs/components/chip-set/useChipSet.js.map +1 -0
  19. package/dist/cjs/components/chip-set/utils.d.ts +7 -0
  20. package/dist/cjs/components/chip-set/utils.js +18 -0
  21. package/dist/cjs/components/chip-set/utils.js.map +1 -0
  22. package/dist/cjs/components/collapse/CCollapse.js +14 -6
  23. package/dist/cjs/components/collapse/CCollapse.js.map +1 -1
  24. package/dist/cjs/components/conditional-portal/CConditionalPortal.js +3 -1
  25. package/dist/cjs/components/conditional-portal/CConditionalPortal.js.map +1 -1
  26. package/dist/cjs/components/dropdown/CDropdown.js +22 -29
  27. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  28. package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
  29. package/dist/cjs/components/form/CChipInput.d.ts +14 -2
  30. package/dist/cjs/components/form/CChipInput.js +77 -49
  31. package/dist/cjs/components/form/CChipInput.js.map +1 -1
  32. package/dist/cjs/components/form/CFormCheck.js.map +1 -1
  33. package/dist/cjs/components/form/CFormInput.js.map +1 -1
  34. package/dist/cjs/components/form/CFormSelect.js.map +1 -1
  35. package/dist/cjs/components/form/CFormTextarea.js.map +1 -1
  36. package/dist/cjs/components/form/CInputGroupText.js.map +1 -1
  37. package/dist/cjs/components/grid/CContainer.js +3 -1
  38. package/dist/cjs/components/grid/CContainer.js.map +1 -1
  39. package/dist/cjs/components/header/CHeaderBrand.js.map +1 -1
  40. package/dist/cjs/components/index.d.ts +1 -0
  41. package/dist/cjs/components/link/CLink.js +4 -2
  42. package/dist/cjs/components/link/CLink.js.map +1 -1
  43. package/dist/cjs/components/list-group/CListGroupItem.js.map +1 -1
  44. package/dist/cjs/components/modal/CModal.js +14 -2
  45. package/dist/cjs/components/modal/CModal.js.map +1 -1
  46. package/dist/cjs/components/multi-select/CMultiSelect.d.ts +73 -1
  47. package/dist/cjs/components/multi-select/CMultiSelect.js +157 -18
  48. package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
  49. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js +1 -1
  50. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  51. package/dist/cjs/components/multi-select/CMultiSelectOptions.d.ts +3 -0
  52. package/dist/cjs/components/multi-select/CMultiSelectOptions.js +45 -2
  53. package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
  54. package/dist/cjs/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  55. package/dist/cjs/components/multi-select/CMultiSelectSelection.js +4 -3
  56. package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
  57. package/dist/cjs/components/multi-select/types.d.ts +12 -0
  58. package/dist/cjs/components/multi-select/utils.js +1 -4
  59. package/dist/cjs/components/multi-select/utils.js.map +1 -1
  60. package/dist/cjs/components/nav/CNav.js.map +1 -1
  61. package/dist/cjs/components/nav/CNavGroup.d.ts +10 -5
  62. package/dist/cjs/components/nav/CNavGroup.js +83 -24
  63. package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
  64. package/dist/cjs/components/nav/CNavGroupContext.d.ts +25 -0
  65. package/dist/cjs/components/nav/CNavGroupContext.js +13 -0
  66. package/dist/cjs/components/nav/CNavGroupContext.js.map +1 -0
  67. package/dist/cjs/components/nav/CNavLink.d.ts +1 -5
  68. package/dist/cjs/components/nav/CNavLink.js +21 -8
  69. package/dist/cjs/components/nav/CNavLink.js.map +1 -1
  70. package/dist/cjs/components/popover/CPopover.js +57 -9
  71. package/dist/cjs/components/popover/CPopover.js.map +1 -1
  72. package/dist/cjs/components/progress/CProgress.js.map +1 -1
  73. package/dist/cjs/components/rating/CRating.d.ts +1 -1
  74. package/dist/cjs/components/rating/CRating.js.map +1 -1
  75. package/dist/cjs/components/sidebar/CSidebar.js +40 -23
  76. package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
  77. package/dist/cjs/components/sidebar/CSidebarNav.js +6 -35
  78. package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
  79. package/dist/cjs/components/table/CTableDataCell.js.map +1 -1
  80. package/dist/cjs/components/table/types.d.ts +2 -1
  81. package/dist/cjs/components/table/utils.js +4 -4
  82. package/dist/cjs/components/table/utils.js.map +1 -1
  83. package/dist/cjs/components/tabs/CTabPanel.js +3 -1
  84. package/dist/cjs/components/tabs/CTabPanel.js.map +1 -1
  85. package/dist/cjs/components/tooltip/CTooltip.js +57 -9
  86. package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
  87. package/dist/cjs/helpers/polymorphicComponent.d.ts +1 -2
  88. package/dist/cjs/hooks/useForkedRef.d.ts +1 -1
  89. package/dist/cjs/hooks/useForkedRef.js +6 -3
  90. package/dist/cjs/hooks/useForkedRef.js.map +1 -1
  91. package/dist/cjs/hooks/usePopper.js +8 -6
  92. package/dist/cjs/hooks/usePopper.js.map +1 -1
  93. package/dist/cjs/index.js +2 -0
  94. package/dist/cjs/index.js.map +1 -1
  95. package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
  96. package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
  97. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +3 -3
  98. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  99. package/dist/cjs/utils/executeAfterTransition.js.map +1 -1
  100. package/dist/cjs/utils/index.d.ts +2 -1
  101. package/dist/cjs/utils/swipe.d.ts +26 -0
  102. package/dist/cjs/utils/swipe.js +94 -0
  103. package/dist/cjs/utils/swipe.js.map +1 -0
  104. package/dist/esm/components/card/CCardImage.js.map +1 -1
  105. package/dist/esm/components/carousel/CCarousel.js +44 -33
  106. package/dist/esm/components/carousel/CCarousel.js.map +1 -1
  107. package/dist/esm/components/carousel/CCarouselItem.js +19 -28
  108. package/dist/esm/components/carousel/CCarouselItem.js.map +1 -1
  109. package/dist/esm/components/chip/CChip.d.ts +12 -0
  110. package/dist/esm/components/chip/CChip.js +16 -63
  111. package/dist/esm/components/chip/CChip.js.map +1 -1
  112. package/dist/esm/components/chip/const.d.ts +1 -0
  113. package/dist/esm/components/chip/const.js +6 -0
  114. package/dist/esm/components/chip/const.js.map +1 -0
  115. package/dist/esm/components/chip-set/CChipSet.d.ts +73 -0
  116. package/dist/esm/components/chip-set/CChipSet.js +64 -0
  117. package/dist/esm/components/chip-set/CChipSet.js.map +1 -0
  118. package/dist/esm/components/chip-set/index.d.ts +2 -0
  119. package/dist/esm/components/chip-set/useChipSet.d.ts +48 -0
  120. package/dist/esm/components/chip-set/useChipSet.js +161 -0
  121. package/dist/esm/components/chip-set/useChipSet.js.map +1 -0
  122. package/dist/esm/components/chip-set/utils.d.ts +7 -0
  123. package/dist/esm/components/chip-set/utils.js +16 -0
  124. package/dist/esm/components/chip-set/utils.js.map +1 -0
  125. package/dist/esm/components/collapse/CCollapse.js +14 -6
  126. package/dist/esm/components/collapse/CCollapse.js.map +1 -1
  127. package/dist/esm/components/conditional-portal/CConditionalPortal.js +3 -1
  128. package/dist/esm/components/conditional-portal/CConditionalPortal.js.map +1 -1
  129. package/dist/esm/components/dropdown/CDropdown.js +22 -29
  130. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  131. package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
  132. package/dist/esm/components/form/CChipInput.d.ts +14 -2
  133. package/dist/esm/components/form/CChipInput.js +78 -50
  134. package/dist/esm/components/form/CChipInput.js.map +1 -1
  135. package/dist/esm/components/form/CFormCheck.js.map +1 -1
  136. package/dist/esm/components/form/CFormInput.js.map +1 -1
  137. package/dist/esm/components/form/CFormSelect.js.map +1 -1
  138. package/dist/esm/components/form/CFormTextarea.js.map +1 -1
  139. package/dist/esm/components/form/CInputGroupText.js.map +1 -1
  140. package/dist/esm/components/grid/CContainer.js +3 -1
  141. package/dist/esm/components/grid/CContainer.js.map +1 -1
  142. package/dist/esm/components/header/CHeaderBrand.js.map +1 -1
  143. package/dist/esm/components/index.d.ts +1 -0
  144. package/dist/esm/components/link/CLink.js +4 -2
  145. package/dist/esm/components/link/CLink.js.map +1 -1
  146. package/dist/esm/components/list-group/CListGroupItem.js.map +1 -1
  147. package/dist/esm/components/modal/CModal.js +14 -2
  148. package/dist/esm/components/modal/CModal.js.map +1 -1
  149. package/dist/esm/components/multi-select/CMultiSelect.d.ts +73 -1
  150. package/dist/esm/components/multi-select/CMultiSelect.js +158 -19
  151. package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
  152. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js +1 -1
  153. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  154. package/dist/esm/components/multi-select/CMultiSelectOptions.d.ts +3 -0
  155. package/dist/esm/components/multi-select/CMultiSelectOptions.js +45 -2
  156. package/dist/esm/components/multi-select/CMultiSelectOptions.js.map +1 -1
  157. package/dist/esm/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  158. package/dist/esm/components/multi-select/CMultiSelectSelection.js +4 -3
  159. package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
  160. package/dist/esm/components/multi-select/types.d.ts +12 -0
  161. package/dist/esm/components/multi-select/utils.js +1 -4
  162. package/dist/esm/components/multi-select/utils.js.map +1 -1
  163. package/dist/esm/components/nav/CNav.js.map +1 -1
  164. package/dist/esm/components/nav/CNavGroup.d.ts +10 -5
  165. package/dist/esm/components/nav/CNavGroup.js +84 -25
  166. package/dist/esm/components/nav/CNavGroup.js.map +1 -1
  167. package/dist/esm/components/nav/CNavGroupContext.d.ts +25 -0
  168. package/dist/esm/components/nav/CNavGroupContext.js +11 -0
  169. package/dist/esm/components/nav/CNavGroupContext.js.map +1 -0
  170. package/dist/esm/components/nav/CNavLink.d.ts +1 -5
  171. package/dist/esm/components/nav/CNavLink.js +21 -8
  172. package/dist/esm/components/nav/CNavLink.js.map +1 -1
  173. package/dist/esm/components/popover/CPopover.js +57 -9
  174. package/dist/esm/components/popover/CPopover.js.map +1 -1
  175. package/dist/esm/components/progress/CProgress.js.map +1 -1
  176. package/dist/esm/components/rating/CRating.d.ts +1 -1
  177. package/dist/esm/components/rating/CRating.js.map +1 -1
  178. package/dist/esm/components/sidebar/CSidebar.js +40 -23
  179. package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
  180. package/dist/esm/components/sidebar/CSidebarNav.js +7 -36
  181. package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
  182. package/dist/esm/components/table/CTableDataCell.js.map +1 -1
  183. package/dist/esm/components/table/types.d.ts +2 -1
  184. package/dist/esm/components/table/utils.js +4 -4
  185. package/dist/esm/components/table/utils.js.map +1 -1
  186. package/dist/esm/components/tabs/CTabPanel.js +3 -1
  187. package/dist/esm/components/tabs/CTabPanel.js.map +1 -1
  188. package/dist/esm/components/tooltip/CTooltip.js +57 -9
  189. package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
  190. package/dist/esm/helpers/polymorphicComponent.d.ts +1 -2
  191. package/dist/esm/hooks/useForkedRef.d.ts +1 -1
  192. package/dist/esm/hooks/useForkedRef.js +6 -3
  193. package/dist/esm/hooks/useForkedRef.js.map +1 -1
  194. package/dist/esm/hooks/usePopper.js +9 -7
  195. package/dist/esm/hooks/usePopper.js.map +1 -1
  196. package/dist/esm/index.js +1 -0
  197. package/dist/esm/index.js.map +1 -1
  198. package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
  199. package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
  200. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +3 -3
  201. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  202. package/dist/esm/utils/executeAfterTransition.js.map +1 -1
  203. package/dist/esm/utils/index.d.ts +2 -1
  204. package/dist/esm/utils/swipe.d.ts +26 -0
  205. package/dist/esm/utils/swipe.js +90 -0
  206. package/dist/esm/utils/swipe.js.map +1 -0
  207. package/package.json +6 -6
  208. package/src/components/autocomplete/CAutocompleteOptions.tsx +1 -1
  209. package/src/components/card/CCardImage.tsx +3 -2
  210. package/src/components/carousel/CCarousel.tsx +48 -51
  211. package/src/components/carousel/CCarouselContext.ts +1 -1
  212. package/src/components/carousel/CCarouselItem.tsx +25 -26
  213. package/src/components/carousel/__tests__/CCarousel.spec.tsx +47 -4
  214. package/src/components/carousel/__tests__/CCarouselItem.spec.tsx +37 -0
  215. package/src/components/chip/CChip.tsx +45 -78
  216. package/src/components/chip/__tests__/CChip.spec.tsx +26 -19
  217. package/src/components/chip/const.ts +3 -0
  218. package/src/components/chip-set/CChipSet.tsx +183 -0
  219. package/src/components/chip-set/__tests__/CChipSet.spec.tsx +215 -0
  220. package/src/components/chip-set/__tests__/__snapshots__/CChipSet.spec.tsx.snap +22 -0
  221. package/src/components/chip-set/index.ts +3 -0
  222. package/src/components/chip-set/useChipSet.ts +243 -0
  223. package/src/components/chip-set/utils.ts +19 -0
  224. package/src/components/collapse/CCollapse.tsx +18 -6
  225. package/src/components/conditional-portal/CConditionalPortal.tsx +4 -2
  226. package/src/components/dropdown/CDropdown.tsx +28 -33
  227. package/src/components/dropdown/CDropdownToggle.tsx +1 -1
  228. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +55 -0
  229. package/src/components/focus-trap/__tests__/CFocusTrap.spec.tsx +1 -1
  230. package/src/components/form/CChipInput.tsx +105 -67
  231. package/src/components/form/CFormCheck.tsx +1 -2
  232. package/src/components/form/CFormInput.tsx +1 -2
  233. package/src/components/form/CFormSelect.tsx +1 -2
  234. package/src/components/form/CFormTextarea.tsx +1 -2
  235. package/src/components/form/CInputGroupText.tsx +3 -2
  236. package/src/components/form/__tests__/CChipInput.spec.tsx +67 -1
  237. package/src/components/form/__tests__/__snapshots__/CChipInput.spec.tsx.snap +7 -0
  238. package/src/components/grid/CContainer.tsx +3 -1
  239. package/src/components/header/CHeaderBrand.tsx +3 -2
  240. package/src/components/index.ts +1 -0
  241. package/src/components/link/CLink.tsx +7 -4
  242. package/src/components/list-group/CListGroupItem.tsx +3 -2
  243. package/src/components/modal/CModal.tsx +19 -2
  244. package/src/components/modal/__tests__/CModal.spec.tsx +43 -0
  245. package/src/components/multi-select/CMultiSelect.tsx +341 -46
  246. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
  247. package/src/components/multi-select/CMultiSelectOptions.tsx +74 -3
  248. package/src/components/multi-select/CMultiSelectSelection.tsx +5 -1
  249. package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +12 -8
  250. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +62 -45
  251. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -2
  252. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +1 -0
  253. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +5 -1
  254. package/src/components/multi-select/types.ts +14 -0
  255. package/src/components/nav/CNav.tsx +3 -2
  256. package/src/components/nav/CNavGroup.tsx +193 -107
  257. package/src/components/nav/CNavGroupContext.ts +27 -0
  258. package/src/components/nav/CNavLink.tsx +26 -12
  259. package/src/components/nav/__tests__/CNavGroup.spec.tsx +195 -20
  260. package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +2 -0
  261. package/src/components/popover/CPopover.tsx +59 -9
  262. package/src/components/popover/__tests__/CPopover.spec.tsx +76 -1
  263. package/src/components/progress/CProgress.tsx +1 -2
  264. package/src/components/rating/CRating.tsx +1 -0
  265. package/src/components/search-button/__tests__/CSearchButton.spec.tsx +2 -2
  266. package/src/components/sidebar/CSidebar.tsx +51 -26
  267. package/src/components/sidebar/CSidebarNav.tsx +12 -51
  268. package/src/components/sidebar/__tests__/CSidebar.spec.tsx +26 -0
  269. package/src/components/table/CTableDataCell.tsx +2 -1
  270. package/src/components/table/types.ts +3 -1
  271. package/src/components/table/utils.ts +4 -4
  272. package/src/components/tabs/CTabPanel.tsx +3 -1
  273. package/src/components/tabs/CTabsContext.ts +1 -1
  274. package/src/components/tooltip/CTooltip.tsx +59 -9
  275. package/src/components/tooltip/__tests__/CTooltip.spec.tsx +96 -1
  276. package/src/helpers/polymorphicComponent.ts +1 -1
  277. package/src/hooks/useColorModes.ts +2 -2
  278. package/src/hooks/useForkedRef.ts +20 -15
  279. package/src/hooks/usePopper.ts +13 -9
  280. package/src/utils/__tests__/swipe.spec.ts +82 -0
  281. package/src/utils/executeAfterTransition.ts +1 -1
  282. package/src/utils/index.ts +2 -0
  283. package/src/utils/mergeClassNames.ts +1 -1
  284. package/src/utils/swipe.ts +114 -0
  285. package/dist/cjs/components/sidebar/CSidebarNavContext.d.ts +0 -5
  286. package/dist/cjs/components/sidebar/CSidebarNavContext.js +0 -8
  287. package/dist/cjs/components/sidebar/CSidebarNavContext.js.map +0 -1
  288. package/dist/esm/components/sidebar/CSidebarNavContext.d.ts +0 -5
  289. package/dist/esm/components/sidebar/CSidebarNavContext.js +0 -6
  290. package/dist/esm/components/sidebar/CSidebarNavContext.js.map +0 -1
  291. package/src/components/sidebar/CSidebarNavContext.ts +0 -8
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'
1
+ import React, { forwardRef, HTMLAttributes, JSX, ReactNode } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
@@ -10,11 +10,14 @@ import type { Option, OptionsGroup } from './types'
10
10
 
11
11
  export interface CMultiSelectOptionsProps extends HTMLAttributes<HTMLDivElement> {
12
12
  loading?: boolean
13
+ onGroupOnClick?: (group: OptionsGroup) => void
13
14
  onOptionOnClick?: (option: Option) => void
14
15
  options: (Option | OptionsGroup)[]
15
16
  optionsMaxHeight?: number | string
16
17
  optionsStyle?: 'checkbox' | 'text'
17
18
  optionsTemplate?: (option: Option) => ReactNode
19
+ optionsGroupsSelectable?: boolean
20
+ optionsGroupsStyle?: 'checkbox' | 'text'
18
21
  optionsGroupsTemplate?: (option: OptionsGroup) => ReactNode
19
22
  searchNoResultsLabel?: string | ReactNode
20
23
  selected: Option[]
@@ -26,12 +29,15 @@ export const CMultiSelectOptions = forwardRef<HTMLDivElement, CMultiSelectOption
26
29
  (
27
30
  {
28
31
  loading,
32
+ onGroupOnClick,
29
33
  onKeyDown,
30
34
  onOptionOnClick,
31
35
  options,
32
36
  optionsMaxHeight,
33
37
  optionsStyle,
34
38
  optionsTemplate,
39
+ optionsGroupsSelectable,
40
+ optionsGroupsStyle,
35
41
  optionsGroupsTemplate,
36
42
  searchNoResultsLabel,
37
43
  selected,
@@ -63,6 +69,44 @@ export const CMultiSelectOptions = forwardRef<HTMLDivElement, CMultiSelectOption
63
69
  }
64
70
  }
65
71
 
72
+ const handleGroupKeyDown = (
73
+ event: React.KeyboardEvent<HTMLDivElement>,
74
+ group: OptionsGroup
75
+ ) => {
76
+ if (event.code === 'Space' || event.key === 'Enter') {
77
+ event.preventDefault()
78
+ onGroupOnClick?.(group)
79
+ return
80
+ }
81
+
82
+ if (event.key === 'Down' || event.key === 'ArrowDown') {
83
+ event.preventDefault()
84
+ const next = getNextSibling(event.target as HTMLElement, '.form-multi-select-option')
85
+
86
+ next && (next as HTMLElement).focus()
87
+ }
88
+
89
+ if (event.key === 'Up' || event.key === 'ArrowUp') {
90
+ event.preventDefault()
91
+ const prev = getPreviousSibling(event.target as HTMLElement, '.form-multi-select-option')
92
+
93
+ prev && (prev as HTMLElement).focus()
94
+ }
95
+ }
96
+
97
+ const getGroupCheckboxState = (group: OptionsGroup) => {
98
+ const groupOptions = (group.options ?? []).filter((option) => !option.disabled)
99
+ const selectedCount = groupOptions.filter((option) =>
100
+ selected.some((_option) => _option.value === option.value)
101
+ ).length
102
+
103
+ if (groupOptions.length > 0 && selectedCount >= groupOptions.length) {
104
+ return 'all'
105
+ }
106
+
107
+ return selectedCount === 0 ? 'none' : 'indeterminate'
108
+ }
109
+
66
110
  const createOptions = (options: (Option | OptionsGroup)[]): JSX.Element | JSX.Element[] =>
67
111
  options.length > 0 ? (
68
112
  options.map((option: Option | OptionsGroup, index: number) =>
@@ -84,13 +128,37 @@ export const CMultiSelectOptions = forwardRef<HTMLDivElement, CMultiSelectOption
84
128
  {optionsTemplate ? optionsTemplate(option as Option) : option.label}
85
129
  </div>
86
130
  ) : (
87
- <div className="form-multi-select-optgroup-label" key={index}>
131
+ <div
132
+ className={classNames('form-multi-select-optgroup-label', {
133
+ 'form-multi-select-optgroup-label-with-checkbox':
134
+ optionsGroupsSelectable && optionsGroupsStyle === 'checkbox',
135
+ 'form-multi-selected':
136
+ optionsGroupsSelectable &&
137
+ optionsGroupsStyle === 'checkbox' &&
138
+ getGroupCheckboxState(option as OptionsGroup) === 'all',
139
+ 'form-multi-select-indeterminate':
140
+ optionsGroupsSelectable &&
141
+ optionsGroupsStyle === 'checkbox' &&
142
+ getGroupCheckboxState(option as OptionsGroup) === 'indeterminate',
143
+ })}
144
+ key={index}
145
+ {...(optionsGroupsSelectable &&
146
+ optionsGroupsStyle === 'checkbox' && {
147
+ onClick: () => onGroupOnClick?.(option as OptionsGroup),
148
+ onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) =>
149
+ handleGroupKeyDown(event, option as OptionsGroup),
150
+ tabIndex: 0,
151
+ role: 'button',
152
+ })}
153
+ >
88
154
  {optionsGroupsTemplate ? optionsGroupsTemplate(option as OptionsGroup) : option.label}
89
155
  </div>
90
156
  )
91
157
  )
92
158
  ) : (
93
- <div className="form-multi-select-options-empty">{searchNoResultsLabel}</div>
159
+ <div className="form-multi-select-options-empty" role="status">
160
+ {searchNoResultsLabel}
161
+ </div>
94
162
  )
95
163
 
96
164
  return (
@@ -124,11 +192,14 @@ export const CMultiSelectOptions = forwardRef<HTMLDivElement, CMultiSelectOption
124
192
 
125
193
  CMultiSelectOptions.propTypes = {
126
194
  loading: PropTypes.bool,
195
+ onGroupOnClick: PropTypes.func,
127
196
  onOptionOnClick: PropTypes.func,
128
197
  options: PropTypes.array.isRequired,
129
198
  optionsMaxHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
130
199
  optionsStyle: PropTypes.oneOf(['checkbox', 'text']),
131
200
  optionsTemplate: PropTypes.func,
201
+ optionsGroupsSelectable: PropTypes.bool,
202
+ optionsGroupsStyle: PropTypes.oneOf(['checkbox', 'text']),
132
203
  optionsGroupsTemplate: PropTypes.func,
133
204
  searchNoResultsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
134
205
  virtualScroller: PropTypes.bool,
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types'
6
6
  import type { Search, SelectedOption } from './types'
7
7
 
8
8
  export interface CMultiSelectSelectionProps extends HTMLAttributes<HTMLSpanElement> {
9
+ ariaTagDeleteLabel?: string
9
10
  disabled?: boolean
10
11
  multiple?: boolean
11
12
  onRemove?: (option: SelectedOption) => void
@@ -19,6 +20,7 @@ export interface CMultiSelectSelectionProps extends HTMLAttributes<HTMLSpanEleme
19
20
  export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSelectionProps>(
20
21
  (
21
22
  {
23
+ ariaTagDeleteLabel = 'Remove',
22
24
  children,
23
25
  disabled,
24
26
  multiple,
@@ -36,6 +38,7 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
36
38
  className={classNames('form-multi-select-selection', {
37
39
  'form-multi-select-selection-tags': multiple && selectionType === 'tags',
38
40
  })}
41
+ aria-live="polite"
39
42
  ref={ref}
40
43
  >
41
44
  {multiple && selectionType === 'counter' && !search && selected.length === 0 && placeholder}
@@ -55,7 +58,7 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
55
58
  <button
56
59
  className="form-multi-select-tag-delete"
57
60
  type="button"
58
- aria-label="Close"
61
+ aria-label={`${ariaTagDeleteLabel} ${option.label}`.trim()}
59
62
  onClick={() => onRemove?.(option)}
60
63
  />
61
64
  )}
@@ -80,6 +83,7 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
80
83
  )
81
84
 
82
85
  CMultiSelectSelection.propTypes = {
86
+ ariaTagDeleteLabel: PropTypes.string,
83
87
  children: PropTypes.node,
84
88
  disabled: PropTypes.bool,
85
89
  multiple: PropTypes.bool,
@@ -68,16 +68,20 @@ test('CMultiSelect customize', async () => {
68
68
  />,
69
69
  )
70
70
  expect(container).toMatchSnapshot()
71
- expect(container.firstChild).toHaveAttribute('multiple', '')
72
- expect(container.firstChild).toHaveAttribute('style', 'display: none;')
73
- expect(container.firstChild).toHaveAttribute('tabindex', '-1')
74
- if (container.firstChild === null) {
71
+ const nativeSelect = container.querySelector('select')
72
+ expect(nativeSelect).toBeInTheDocument()
73
+ expect(nativeSelect).toHaveAttribute('multiple', '')
74
+ expect(nativeSelect).not.toHaveStyle('display: none')
75
+ expect(nativeSelect).toHaveAttribute('tabindex', '-1')
76
+ expect(nativeSelect).toHaveClass('form-multi-select')
77
+ expect(nativeSelect?.parentElement).toHaveClass('form-multi-select')
78
+ if (nativeSelect === null) {
75
79
  expect(true).toBe(false)
76
80
  } else {
77
- expect(container.firstChild.firstChild).toHaveAttribute('value', '1')
78
- expect(container.firstChild.firstChild).toHaveTextContent('Bootstrap')
79
- expect(container.firstChild.lastChild).toHaveAttribute('value', '6')
80
- expect(container.firstChild.lastChild).toHaveTextContent('Node.js')
81
+ expect(nativeSelect.firstChild).toHaveAttribute('value', '1')
82
+ expect(nativeSelect.firstChild).toHaveTextContent('Bootstrap')
83
+ expect(nativeSelect.lastChild).toHaveAttribute('value', '6')
84
+ expect(nativeSelect.lastChild).toHaveTextContent('Node.js')
81
85
  }
82
86
  expect(container.lastChild).toHaveClass('form-multi-select')
83
87
  expect(container.lastChild).toHaveClass('show')
@@ -2,41 +2,42 @@
2
2
 
3
3
  exports[`CMultiSelect customize 1`] = `
4
4
  <div>
5
- <select
6
- id=":r1:"
7
- multiple=""
8
- name=":r1:"
9
- style="display: none;"
10
- tabindex="-1"
11
- >
12
- <option
13
- value="1"
14
- >
15
- Bootstrap
16
- </option>
17
- <option
18
- value="3"
19
- >
20
- Vue.js
21
- </option>
22
- <option
23
- disabled=""
24
- value="6"
25
- >
26
- Node.js
27
- </option>
28
- </select>
29
5
  <div
30
- aria-expanded="true"
31
6
  class="form-multi-select show bazinga"
32
7
  >
8
+ <select
9
+ class="form-multi-select"
10
+ id=":r1:"
11
+ multiple=""
12
+ name=":r1:"
13
+ tabindex="-1"
14
+ >
15
+ <option
16
+ value="1"
17
+ >
18
+ Bootstrap
19
+ </option>
20
+ <option
21
+ value="3"
22
+ >
23
+ Vue.js
24
+ </option>
25
+ <option
26
+ disabled=""
27
+ value="6"
28
+ >
29
+ Node.js
30
+ </option>
31
+ </select>
33
32
  <div
33
+ aria-controls="multiselect-listbox-:r1:"
34
34
  aria-expanded="true"
35
35
  aria-haspopup="listbox"
36
36
  class="form-multi-select-input-group"
37
37
  role="combobox"
38
38
  >
39
39
  <span
40
+ aria-live="polite"
40
41
  class="form-multi-select-selection form-multi-select-selection-tags"
41
42
  >
42
43
  <span
@@ -44,7 +45,7 @@ exports[`CMultiSelect customize 1`] = `
44
45
  >
45
46
  Bootstrap
46
47
  <button
47
- aria-label="Close"
48
+ aria-label="Remove Bootstrap"
48
49
  class="form-multi-select-tag-delete"
49
50
  type="button"
50
51
  />
@@ -54,7 +55,7 @@ exports[`CMultiSelect customize 1`] = `
54
55
  >
55
56
  Vue.js
56
57
  <button
57
- aria-label="Close"
58
+ aria-label="Remove Vue.js"
58
59
  class="form-multi-select-tag-delete"
59
60
  type="button"
60
61
  />
@@ -65,6 +66,9 @@ exports[`CMultiSelect customize 1`] = `
65
66
  Node.js
66
67
  </span>
67
68
  <input
69
+ aria-autocomplete="list"
70
+ aria-controls="multiselect-listbox-:r1:"
71
+ aria-label="Search"
68
72
  autocomplete="off"
69
73
  class="form-multi-select-search"
70
74
  id="search:r1:"
@@ -95,12 +99,16 @@ exports[`CMultiSelect customize 1`] = `
95
99
  role="listbox"
96
100
  style="position: absolute; left: 0px; top: 0px; margin: 0px;"
97
101
  >
98
- <button
99
- class="form-multi-select-all"
100
- type="button"
102
+ <div
103
+ class="form-multi-select-dropdown-header"
101
104
  >
102
- selectAllLabel
103
- </button>
105
+ <button
106
+ class="form-multi-select-all form-multi-select-all-with-checkbox form-multi-select-indeterminate"
107
+ type="button"
108
+ >
109
+ selectAllLabel
110
+ </button>
111
+ </div>
104
112
  <div
105
113
  class="form-multi-select-options"
106
114
  style="max-height: 150px; overflow: scroll;"
@@ -181,27 +189,31 @@ exports[`CMultiSelect customize 1`] = `
181
189
 
182
190
  exports[`loads and displays CMultiSelect component 1`] = `
183
191
  <div>
184
- <select
185
- id=":r0:"
186
- multiple=""
187
- name=":r0:"
188
- style="display: none;"
189
- tabindex="-1"
190
- />
191
192
  <div
192
- aria-expanded="false"
193
193
  class="form-multi-select"
194
194
  >
195
+ <select
196
+ class="form-multi-select"
197
+ id=":r0:"
198
+ multiple=""
199
+ name=":r0:"
200
+ tabindex="-1"
201
+ />
195
202
  <div
203
+ aria-controls="multiselect-listbox-:r0:"
196
204
  aria-expanded="false"
197
205
  aria-haspopup="listbox"
198
206
  class="form-multi-select-input-group"
199
207
  role="combobox"
200
208
  >
201
209
  <span
210
+ aria-live="polite"
202
211
  class="form-multi-select-selection form-multi-select-selection-tags"
203
212
  >
204
213
  <input
214
+ aria-autocomplete="list"
215
+ aria-controls="multiselect-listbox-:r0:"
216
+ aria-label="Search"
205
217
  autocomplete="off"
206
218
  class="form-multi-select-search"
207
219
  id="search:r0:"
@@ -226,17 +238,22 @@ exports[`loads and displays CMultiSelect component 1`] = `
226
238
  id="multiselect-listbox-:r0:"
227
239
  role="listbox"
228
240
  >
229
- <button
230
- class="form-multi-select-all"
231
- type="button"
241
+ <div
242
+ class="form-multi-select-dropdown-header"
232
243
  >
233
- Select all options
234
- </button>
244
+ <button
245
+ class="form-multi-select-all form-multi-select-all-with-checkbox"
246
+ type="button"
247
+ >
248
+ Select all
249
+ </button>
250
+ </div>
235
251
  <div
236
252
  class="form-multi-select-options"
237
253
  >
238
254
  <div
239
255
  class="form-multi-select-options-empty"
256
+ role="status"
240
257
  >
241
258
  No results found
242
259
  </div>
@@ -3,8 +3,8 @@
3
3
  exports[`CMultiSelectNativeSelect customize 1`] = `
4
4
  <div>
5
5
  <select
6
+ class="form-multi-select"
6
7
  multiple=""
7
- style="display: none;"
8
8
  tabindex="-1"
9
9
  >
10
10
  <option
@@ -30,7 +30,7 @@ exports[`CMultiSelectNativeSelect customize 1`] = `
30
30
  exports[`loads and displays CMultiSelectNativeSelect component 1`] = `
31
31
  <div>
32
32
  <select
33
- style="display: none;"
33
+ class="form-multi-select"
34
34
  tabindex="-1"
35
35
  />
36
36
  </div>
@@ -36,6 +36,7 @@ exports[`loads and displays CMultiSelectOptions component 1`] = `
36
36
  >
37
37
  <div
38
38
  class="form-multi-select-options-empty"
39
+ role="status"
39
40
  >
40
41
  some no result label
41
42
  </div>
@@ -3,6 +3,7 @@
3
3
  exports[`CMultiSelectSelection customize counter 1`] = `
4
4
  <div>
5
5
  <span
6
+ aria-live="polite"
6
7
  class="form-multi-select-selection"
7
8
  >
8
9
  2 text
@@ -13,6 +14,7 @@ exports[`CMultiSelectSelection customize counter 1`] = `
13
14
  exports[`CMultiSelectSelection customize tags 1`] = `
14
15
  <div>
15
16
  <span
17
+ aria-live="polite"
16
18
  class="form-multi-select-selection form-multi-select-selection-tags"
17
19
  >
18
20
  <span
@@ -20,7 +22,7 @@ exports[`CMultiSelectSelection customize tags 1`] = `
20
22
  >
21
23
  text1
22
24
  <button
23
- aria-label="Close"
25
+ aria-label="Remove text1"
24
26
  class="form-multi-select-tag-delete"
25
27
  type="button"
26
28
  />
@@ -37,6 +39,7 @@ exports[`CMultiSelectSelection customize tags 1`] = `
37
39
  exports[`CMultiSelectSelection customize text 1`] = `
38
40
  <div>
39
41
  <span
42
+ aria-live="polite"
40
43
  class="form-multi-select-selection"
41
44
  >
42
45
  <span>
@@ -55,6 +58,7 @@ exports[`CMultiSelectSelection customize text 1`] = `
55
58
  exports[`loads and displays CMultiSelectSelection component 1`] = `
56
59
  <div>
57
60
  <span
61
+ aria-live="polite"
58
62
  class="form-multi-select-selection"
59
63
  />
60
64
  </div>
@@ -28,3 +28,17 @@ export type SelectedOption = {
28
28
  value: number | string
29
29
  [key: string]: number | string | any
30
30
  }
31
+
32
+ export type SelectionState = {
33
+ selected: number
34
+ total: number
35
+ filtered: number
36
+ filteredSelected: number
37
+ }
38
+
39
+ export type SelectionActions = {
40
+ selectAll: () => void
41
+ deselectAll: () => void
42
+ selectFiltered: () => void
43
+ deselectFiltered: () => void
44
+ }
@@ -4,8 +4,9 @@ import classNames from 'classnames'
4
4
 
5
5
  import { PolymorphicRefForwardingComponent } from '../../helpers'
6
6
 
7
- export interface CNavProps
8
- extends HTMLAttributes<HTMLDivElement | HTMLUListElement | HTMLOListElement> {
7
+ export interface CNavProps extends HTMLAttributes<
8
+ HTMLDivElement | HTMLUListElement | HTMLOListElement
9
+ > {
9
10
  /**
10
11
  * Component used for the root node. Either a string to use a HTML element or a component.
11
12
  */