@coreui/react-pro 5.24.1 → 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 (416) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/card/CCardImage.js.map +1 -1
  3. package/dist/cjs/components/carousel/CCarousel.js +44 -33
  4. package/dist/cjs/components/carousel/CCarousel.js.map +1 -1
  5. package/dist/cjs/components/carousel/CCarouselItem.js +19 -28
  6. package/dist/cjs/components/carousel/CCarouselItem.js.map +1 -1
  7. package/dist/cjs/components/chip/CChip.d.ts +12 -0
  8. package/dist/cjs/components/chip/CChip.js +16 -63
  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-set/CChipSet.d.ts +73 -0
  14. package/dist/cjs/components/chip-set/CChipSet.js +66 -0
  15. package/dist/cjs/components/chip-set/CChipSet.js.map +1 -0
  16. package/dist/cjs/components/chip-set/index.d.ts +2 -0
  17. package/dist/cjs/components/chip-set/useChipSet.d.ts +48 -0
  18. package/dist/cjs/components/chip-set/useChipSet.js +163 -0
  19. package/dist/cjs/components/chip-set/useChipSet.js.map +1 -0
  20. package/dist/cjs/components/chip-set/utils.d.ts +7 -0
  21. package/dist/cjs/components/chip-set/utils.js +18 -0
  22. package/dist/cjs/components/chip-set/utils.js.map +1 -0
  23. package/dist/cjs/components/collapse/CCollapse.js +14 -6
  24. package/dist/cjs/components/collapse/CCollapse.js.map +1 -1
  25. package/dist/cjs/components/conditional-portal/CConditionalPortal.js +3 -1
  26. package/dist/cjs/components/conditional-portal/CConditionalPortal.js.map +1 -1
  27. package/dist/cjs/components/date-picker/CDatePicker.d.ts +1 -1
  28. package/dist/cjs/components/date-picker/CDatePicker.js.map +1 -1
  29. package/dist/cjs/components/date-range-picker/CDateRangePicker.js +2 -0
  30. package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
  31. package/dist/cjs/components/dropdown/CDropdown.js +23 -30
  32. package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
  33. package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
  34. package/dist/cjs/components/form/CChipInput.d.ts +14 -2
  35. package/dist/cjs/components/form/CChipInput.js +77 -49
  36. package/dist/cjs/components/form/CChipInput.js.map +1 -1
  37. package/dist/cjs/components/form/CFormCheck.js.map +1 -1
  38. package/dist/cjs/components/form/CFormInput.js.map +1 -1
  39. package/dist/cjs/components/form/CFormSelect.js.map +1 -1
  40. package/dist/cjs/components/form/CFormTextarea.js.map +1 -1
  41. package/dist/cjs/components/form/CInputGroupText.js.map +1 -1
  42. package/dist/cjs/components/grid/CContainer.js +3 -1
  43. package/dist/cjs/components/grid/CContainer.js.map +1 -1
  44. package/dist/cjs/components/header/CHeaderBrand.js.map +1 -1
  45. package/dist/cjs/components/index.d.ts +2 -0
  46. package/dist/cjs/components/link/CLink.js +4 -2
  47. package/dist/cjs/components/link/CLink.js.map +1 -1
  48. package/dist/cjs/components/list-group/CListGroupItem.js.map +1 -1
  49. package/dist/cjs/components/modal/CModal.js +14 -2
  50. package/dist/cjs/components/modal/CModal.js.map +1 -1
  51. package/dist/cjs/components/multi-select/CMultiSelect.d.ts +73 -1
  52. package/dist/cjs/components/multi-select/CMultiSelect.js +157 -18
  53. package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
  54. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js +1 -1
  55. package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  56. package/dist/cjs/components/multi-select/CMultiSelectOptions.d.ts +3 -0
  57. package/dist/cjs/components/multi-select/CMultiSelectOptions.js +45 -2
  58. package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
  59. package/dist/cjs/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  60. package/dist/cjs/components/multi-select/CMultiSelectSelection.js +4 -3
  61. package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
  62. package/dist/cjs/components/multi-select/types.d.ts +12 -0
  63. package/dist/cjs/components/multi-select/utils.js +1 -4
  64. package/dist/cjs/components/multi-select/utils.js.map +1 -1
  65. package/dist/cjs/components/nav/CNav.js.map +1 -1
  66. package/dist/cjs/components/nav/CNavGroup.d.ts +13 -6
  67. package/dist/cjs/components/nav/CNavGroup.js +86 -23
  68. package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
  69. package/dist/cjs/components/nav/CNavGroupContext.d.ts +25 -0
  70. package/dist/cjs/components/nav/CNavGroupContext.js +13 -0
  71. package/dist/cjs/components/nav/CNavGroupContext.js.map +1 -0
  72. package/dist/cjs/components/nav/CNavLink.d.ts +1 -5
  73. package/dist/cjs/components/nav/CNavLink.js +21 -8
  74. package/dist/cjs/components/nav/CNavLink.js.map +1 -1
  75. package/dist/cjs/components/one-time-password-input/COneTimePassword.js +3 -3
  76. package/dist/cjs/components/one-time-password-input/COneTimePassword.js.map +1 -1
  77. package/dist/cjs/components/popover/CPopover.js +69 -24
  78. package/dist/cjs/components/popover/CPopover.js.map +1 -1
  79. package/dist/cjs/components/progress/CProgress.js.map +1 -1
  80. package/dist/cjs/components/rating/CRating.d.ts +1 -1
  81. package/dist/cjs/components/rating/CRating.js.map +1 -1
  82. package/dist/cjs/components/search-button/CSearchButton.d.ts +32 -0
  83. package/dist/cjs/components/search-button/CSearchButton.js +77 -0
  84. package/dist/cjs/components/search-button/CSearchButton.js.map +1 -0
  85. package/dist/cjs/components/search-button/index.d.ts +2 -0
  86. package/dist/cjs/components/search-button/types.d.ts +10 -0
  87. package/dist/cjs/components/search-button/utils.d.ts +11 -0
  88. package/dist/cjs/components/search-button/utils.js +115 -0
  89. package/dist/cjs/components/search-button/utils.js.map +1 -0
  90. package/dist/cjs/components/sidebar/CSidebar.js +40 -23
  91. package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
  92. package/dist/cjs/components/sidebar/CSidebarNav.d.ts +12 -0
  93. package/dist/cjs/components/sidebar/CSidebarNav.js +12 -36
  94. package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
  95. package/dist/cjs/components/smart-table/CSmartTable.js +2 -2
  96. package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
  97. package/dist/cjs/components/smart-table/CSmartTableInterface.d.ts +2 -2
  98. package/dist/cjs/components/table/CTableDataCell.js.map +1 -1
  99. package/dist/cjs/components/table/types.d.ts +2 -1
  100. package/dist/cjs/components/table/utils.js +4 -4
  101. package/dist/cjs/components/table/utils.js.map +1 -1
  102. package/dist/cjs/components/tabs/CTabPanel.js +3 -1
  103. package/dist/cjs/components/tabs/CTabPanel.js.map +1 -1
  104. package/dist/cjs/components/time-picker/CTimePicker.d.ts +1 -1
  105. package/dist/cjs/components/time-picker/CTimePicker.js +1 -1
  106. package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
  107. package/dist/cjs/components/tooltip/CTooltip.js +69 -24
  108. package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
  109. package/dist/cjs/components/virtual-scroller/CVirtualScroller.js +11 -8
  110. package/dist/cjs/components/virtual-scroller/CVirtualScroller.js.map +1 -1
  111. package/dist/cjs/helpers/polymorphicComponent.d.ts +1 -2
  112. package/dist/cjs/hooks/useDebouncedCallback.d.ts +1 -1
  113. package/dist/cjs/hooks/useDebouncedCallback.js +1 -1
  114. package/dist/cjs/hooks/useDebouncedCallback.js.map +1 -1
  115. package/dist/cjs/hooks/useForkedRef.d.ts +1 -1
  116. package/dist/cjs/hooks/useForkedRef.js +6 -3
  117. package/dist/cjs/hooks/useForkedRef.js.map +1 -1
  118. package/dist/cjs/hooks/usePopper.js +8 -6
  119. package/dist/cjs/hooks/usePopper.js.map +1 -1
  120. package/dist/cjs/index.js +4 -0
  121. package/dist/cjs/index.js.map +1 -1
  122. package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
  123. package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
  124. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  125. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  126. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  127. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  128. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  129. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  130. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  131. package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  132. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +4 -4
  133. package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  134. package/dist/cjs/utils/executeAfterTransition.js.map +1 -1
  135. package/dist/cjs/utils/index.d.ts +2 -1
  136. package/dist/cjs/utils/swipe.d.ts +26 -0
  137. package/dist/cjs/utils/swipe.js +94 -0
  138. package/dist/cjs/utils/swipe.js.map +1 -0
  139. package/dist/esm/components/card/CCardImage.js.map +1 -1
  140. package/dist/esm/components/carousel/CCarousel.js +44 -33
  141. package/dist/esm/components/carousel/CCarousel.js.map +1 -1
  142. package/dist/esm/components/carousel/CCarouselItem.js +19 -28
  143. package/dist/esm/components/carousel/CCarouselItem.js.map +1 -1
  144. package/dist/esm/components/chip/CChip.d.ts +12 -0
  145. package/dist/esm/components/chip/CChip.js +16 -63
  146. package/dist/esm/components/chip/CChip.js.map +1 -1
  147. package/dist/esm/components/chip/const.d.ts +1 -0
  148. package/dist/esm/components/chip/const.js +6 -0
  149. package/dist/esm/components/chip/const.js.map +1 -0
  150. package/dist/esm/components/chip-set/CChipSet.d.ts +73 -0
  151. package/dist/esm/components/chip-set/CChipSet.js +64 -0
  152. package/dist/esm/components/chip-set/CChipSet.js.map +1 -0
  153. package/dist/esm/components/chip-set/index.d.ts +2 -0
  154. package/dist/esm/components/chip-set/useChipSet.d.ts +48 -0
  155. package/dist/esm/components/chip-set/useChipSet.js +161 -0
  156. package/dist/esm/components/chip-set/useChipSet.js.map +1 -0
  157. package/dist/esm/components/chip-set/utils.d.ts +7 -0
  158. package/dist/esm/components/chip-set/utils.js +16 -0
  159. package/dist/esm/components/chip-set/utils.js.map +1 -0
  160. package/dist/esm/components/collapse/CCollapse.js +14 -6
  161. package/dist/esm/components/collapse/CCollapse.js.map +1 -1
  162. package/dist/esm/components/conditional-portal/CConditionalPortal.js +3 -1
  163. package/dist/esm/components/conditional-portal/CConditionalPortal.js.map +1 -1
  164. package/dist/esm/components/date-picker/CDatePicker.d.ts +1 -1
  165. package/dist/esm/components/date-picker/CDatePicker.js.map +1 -1
  166. package/dist/esm/components/date-range-picker/CDateRangePicker.js +2 -0
  167. package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
  168. package/dist/esm/components/dropdown/CDropdown.js +23 -30
  169. package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
  170. package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
  171. package/dist/esm/components/form/CChipInput.d.ts +14 -2
  172. package/dist/esm/components/form/CChipInput.js +78 -50
  173. package/dist/esm/components/form/CChipInput.js.map +1 -1
  174. package/dist/esm/components/form/CFormCheck.js.map +1 -1
  175. package/dist/esm/components/form/CFormInput.js.map +1 -1
  176. package/dist/esm/components/form/CFormSelect.js.map +1 -1
  177. package/dist/esm/components/form/CFormTextarea.js.map +1 -1
  178. package/dist/esm/components/form/CInputGroupText.js.map +1 -1
  179. package/dist/esm/components/grid/CContainer.js +3 -1
  180. package/dist/esm/components/grid/CContainer.js.map +1 -1
  181. package/dist/esm/components/header/CHeaderBrand.js.map +1 -1
  182. package/dist/esm/components/index.d.ts +2 -0
  183. package/dist/esm/components/link/CLink.js +4 -2
  184. package/dist/esm/components/link/CLink.js.map +1 -1
  185. package/dist/esm/components/list-group/CListGroupItem.js.map +1 -1
  186. package/dist/esm/components/modal/CModal.js +14 -2
  187. package/dist/esm/components/modal/CModal.js.map +1 -1
  188. package/dist/esm/components/multi-select/CMultiSelect.d.ts +73 -1
  189. package/dist/esm/components/multi-select/CMultiSelect.js +158 -19
  190. package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
  191. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js +1 -1
  192. package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
  193. package/dist/esm/components/multi-select/CMultiSelectOptions.d.ts +3 -0
  194. package/dist/esm/components/multi-select/CMultiSelectOptions.js +45 -2
  195. package/dist/esm/components/multi-select/CMultiSelectOptions.js.map +1 -1
  196. package/dist/esm/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  197. package/dist/esm/components/multi-select/CMultiSelectSelection.js +4 -3
  198. package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
  199. package/dist/esm/components/multi-select/types.d.ts +12 -0
  200. package/dist/esm/components/multi-select/utils.js +1 -4
  201. package/dist/esm/components/multi-select/utils.js.map +1 -1
  202. package/dist/esm/components/nav/CNav.js.map +1 -1
  203. package/dist/esm/components/nav/CNavGroup.d.ts +13 -6
  204. package/dist/esm/components/nav/CNavGroup.js +87 -24
  205. package/dist/esm/components/nav/CNavGroup.js.map +1 -1
  206. package/dist/esm/components/nav/CNavGroupContext.d.ts +25 -0
  207. package/dist/esm/components/nav/CNavGroupContext.js +11 -0
  208. package/dist/esm/components/nav/CNavGroupContext.js.map +1 -0
  209. package/dist/esm/components/nav/CNavLink.d.ts +1 -5
  210. package/dist/esm/components/nav/CNavLink.js +21 -8
  211. package/dist/esm/components/nav/CNavLink.js.map +1 -1
  212. package/dist/esm/components/one-time-password-input/COneTimePassword.js +3 -3
  213. package/dist/esm/components/one-time-password-input/COneTimePassword.js.map +1 -1
  214. package/dist/esm/components/popover/CPopover.js +69 -24
  215. package/dist/esm/components/popover/CPopover.js.map +1 -1
  216. package/dist/esm/components/progress/CProgress.js.map +1 -1
  217. package/dist/esm/components/rating/CRating.d.ts +1 -1
  218. package/dist/esm/components/rating/CRating.js.map +1 -1
  219. package/dist/esm/components/search-button/CSearchButton.d.ts +32 -0
  220. package/dist/esm/components/search-button/CSearchButton.js +75 -0
  221. package/dist/esm/components/search-button/CSearchButton.js.map +1 -0
  222. package/dist/esm/components/search-button/index.d.ts +2 -0
  223. package/dist/esm/components/search-button/types.d.ts +10 -0
  224. package/dist/esm/components/search-button/utils.d.ts +11 -0
  225. package/dist/esm/components/search-button/utils.js +104 -0
  226. package/dist/esm/components/search-button/utils.js.map +1 -0
  227. package/dist/esm/components/sidebar/CSidebar.js +40 -23
  228. package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
  229. package/dist/esm/components/sidebar/CSidebarNav.d.ts +12 -0
  230. package/dist/esm/components/sidebar/CSidebarNav.js +13 -37
  231. package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
  232. package/dist/esm/components/smart-table/CSmartTable.js +2 -2
  233. package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
  234. package/dist/esm/components/smart-table/CSmartTableInterface.d.ts +2 -2
  235. package/dist/esm/components/table/CTableDataCell.js.map +1 -1
  236. package/dist/esm/components/table/types.d.ts +2 -1
  237. package/dist/esm/components/table/utils.js +4 -4
  238. package/dist/esm/components/table/utils.js.map +1 -1
  239. package/dist/esm/components/tabs/CTabPanel.js +3 -1
  240. package/dist/esm/components/tabs/CTabPanel.js.map +1 -1
  241. package/dist/esm/components/time-picker/CTimePicker.d.ts +1 -1
  242. package/dist/esm/components/time-picker/CTimePicker.js +1 -1
  243. package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
  244. package/dist/esm/components/tooltip/CTooltip.js +69 -24
  245. package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
  246. package/dist/esm/components/virtual-scroller/CVirtualScroller.js +11 -8
  247. package/dist/esm/components/virtual-scroller/CVirtualScroller.js.map +1 -1
  248. package/dist/esm/helpers/polymorphicComponent.d.ts +1 -2
  249. package/dist/esm/hooks/useDebouncedCallback.d.ts +1 -1
  250. package/dist/esm/hooks/useDebouncedCallback.js +1 -1
  251. package/dist/esm/hooks/useDebouncedCallback.js.map +1 -1
  252. package/dist/esm/hooks/useForkedRef.d.ts +1 -1
  253. package/dist/esm/hooks/useForkedRef.js +6 -3
  254. package/dist/esm/hooks/useForkedRef.js.map +1 -1
  255. package/dist/esm/hooks/usePopper.js +9 -7
  256. package/dist/esm/hooks/usePopper.js.map +1 -1
  257. package/dist/esm/index.js +2 -0
  258. package/dist/esm/index.js.map +1 -1
  259. package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
  260. package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
  261. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
  262. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
  263. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
  264. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
  265. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
  266. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
  267. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
  268. package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
  269. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +4 -4
  270. package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
  271. package/dist/esm/utils/executeAfterTransition.js.map +1 -1
  272. package/dist/esm/utils/index.d.ts +2 -1
  273. package/dist/esm/utils/swipe.d.ts +26 -0
  274. package/dist/esm/utils/swipe.js +90 -0
  275. package/dist/esm/utils/swipe.js.map +1 -0
  276. package/package.json +8 -6
  277. package/src/components/autocomplete/CAutocompleteOptions.tsx +1 -1
  278. package/src/components/autocomplete/__tests__/CAutocomplete.spec.tsx +18 -16
  279. package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.tsx +37 -28
  280. package/src/components/autocomplete/__tests__/__snapshots__/CAutocomplete.spec.tsx.snap +129 -0
  281. package/src/components/autocomplete/__tests__/__snapshots__/CAutocompleteOptions.spec.tsx.snap +36 -0
  282. package/src/components/calendar/__tests__/CCalendar.spec.tsx +40 -45
  283. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +99 -75
  284. package/src/components/calendar/__tests__/utils.spec.tsx +8 -18
  285. package/src/components/card/CCardImage.tsx +3 -2
  286. package/src/components/carousel/CCarousel.tsx +48 -51
  287. package/src/components/carousel/CCarouselContext.ts +1 -1
  288. package/src/components/carousel/CCarouselItem.tsx +25 -26
  289. package/src/components/carousel/__tests__/CCarousel.spec.tsx +47 -4
  290. package/src/components/carousel/__tests__/CCarouselItem.spec.tsx +37 -0
  291. package/src/components/chip/CChip.tsx +45 -78
  292. package/src/components/chip/__tests__/CChip.spec.tsx +26 -19
  293. package/src/components/chip/const.ts +3 -0
  294. package/src/components/chip-set/CChipSet.tsx +183 -0
  295. package/src/components/chip-set/__tests__/CChipSet.spec.tsx +215 -0
  296. package/src/components/chip-set/__tests__/__snapshots__/CChipSet.spec.tsx.snap +22 -0
  297. package/src/components/chip-set/index.ts +3 -0
  298. package/src/components/chip-set/useChipSet.ts +243 -0
  299. package/src/components/chip-set/utils.ts +19 -0
  300. package/src/components/collapse/CCollapse.tsx +18 -6
  301. package/src/components/conditional-portal/CConditionalPortal.tsx +4 -2
  302. package/src/components/date-picker/CDatePicker.tsx +12 -13
  303. package/src/components/date-picker/__tests__/CDatePicker.spec.tsx +1 -1
  304. package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +12 -640
  305. package/src/components/date-range-picker/CDateRangePicker.tsx +2 -0
  306. package/src/components/date-range-picker/__tests__/CDateRangePicker.spec.tsx +1 -1
  307. package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +21 -1259
  308. package/src/components/dropdown/CDropdown.tsx +29 -34
  309. package/src/components/dropdown/CDropdownToggle.tsx +1 -1
  310. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +56 -1
  311. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +2 -2
  312. package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +1 -1
  313. package/src/components/focus-trap/__tests__/CFocusTrap.spec.tsx +1 -1
  314. package/src/components/form/CChipInput.tsx +105 -67
  315. package/src/components/form/CFormCheck.tsx +1 -2
  316. package/src/components/form/CFormInput.tsx +1 -2
  317. package/src/components/form/CFormSelect.tsx +1 -2
  318. package/src/components/form/CFormTextarea.tsx +1 -2
  319. package/src/components/form/CInputGroupText.tsx +3 -2
  320. package/src/components/form/__tests__/CChipInput.spec.tsx +67 -1
  321. package/src/components/form/__tests__/CFormInput.spec.tsx +17 -20
  322. package/src/components/form/__tests__/__snapshots__/CChipInput.spec.tsx.snap +7 -0
  323. package/src/components/form/__tests__/__snapshots__/CFormInput.spec.tsx.snap +12 -3
  324. package/src/components/grid/CContainer.tsx +3 -1
  325. package/src/components/header/CHeaderBrand.tsx +3 -2
  326. package/src/components/index.ts +2 -0
  327. package/src/components/link/CLink.tsx +7 -4
  328. package/src/components/list-group/CListGroupItem.tsx +3 -2
  329. package/src/components/loading-button/__tests__/CLoadingButton.spec.tsx +1 -1
  330. package/src/components/loading-button/__tests__/__snapshots__/CLoadingButton.spec.tsx.snap +4 -4
  331. package/src/components/modal/CModal.tsx +19 -2
  332. package/src/components/modal/__tests__/CModal.spec.tsx +43 -0
  333. package/src/components/multi-select/CMultiSelect.tsx +341 -46
  334. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
  335. package/src/components/multi-select/CMultiSelectOptions.tsx +74 -3
  336. package/src/components/multi-select/CMultiSelectSelection.tsx +5 -1
  337. package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +27 -69
  338. package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +4 -5
  339. package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
  340. package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +7 -24
  341. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +108 -61
  342. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -4
  343. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +7 -0
  344. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +16 -9
  345. package/src/components/multi-select/types.ts +14 -0
  346. package/src/components/nav/CNav.tsx +3 -2
  347. package/src/components/nav/CNavGroup.tsx +196 -105
  348. package/src/components/nav/CNavGroupContext.ts +27 -0
  349. package/src/components/nav/CNavLink.tsx +26 -12
  350. package/src/components/nav/__tests__/CNavGroup.spec.tsx +207 -4
  351. package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +3 -1
  352. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -0
  353. package/src/components/one-time-password-input/COneTimePassword.tsx +10 -11
  354. package/src/components/picker/__tests__/CPicker.spec.tsx +1 -1
  355. package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +2 -16
  356. package/src/components/popover/CPopover.tsx +71 -26
  357. package/src/components/popover/__tests__/CPopover.spec.tsx +85 -4
  358. package/src/components/progress/CProgress.tsx +1 -2
  359. package/src/components/rating/CRating.tsx +1 -0
  360. package/src/components/search-button/CSearchButton.tsx +195 -0
  361. package/src/components/search-button/__tests__/CSearchButton.spec.tsx +95 -0
  362. package/src/components/search-button/__tests__/__snapshots__/CSearchButton.spec.tsx.snap +87 -0
  363. package/src/components/search-button/index.ts +3 -0
  364. package/src/components/search-button/types.ts +10 -0
  365. package/src/components/search-button/utils.ts +140 -0
  366. package/src/components/sidebar/CSidebar.tsx +51 -26
  367. package/src/components/sidebar/CSidebarNav.tsx +39 -53
  368. package/src/components/sidebar/__tests__/CSidebar.spec.tsx +26 -0
  369. package/src/components/smart-table/CSmartTable.tsx +5 -4
  370. package/src/components/smart-table/CSmartTableInterface.tsx +2 -2
  371. package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +3 -2
  372. package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +7 -15
  373. package/src/components/stepper/__tests__/CStepper.spec.tsx +24 -21
  374. package/src/components/stepper/__tests__/__snapshots__/CStepper.spec.tsx.snap +295 -0
  375. package/src/components/table/CTableDataCell.tsx +2 -1
  376. package/src/components/table/types.ts +3 -1
  377. package/src/components/table/utils.ts +4 -4
  378. package/src/components/tabs/CTabPanel.tsx +3 -1
  379. package/src/components/tabs/CTabsContext.ts +1 -1
  380. package/src/components/tabs/__tests__/CTabContent.spec.tsx +1 -0
  381. package/src/components/tabs/__tests__/CTabPane.spec.tsx +1 -0
  382. package/src/components/time-picker/CTimePicker.tsx +6 -7
  383. package/src/components/time-picker/__tests__/CTimePicker.spec.tsx +10 -1
  384. package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +599 -315
  385. package/src/components/tooltip/CTooltip.tsx +72 -27
  386. package/src/components/tooltip/__tests__/CTooltip.spec.tsx +102 -1
  387. package/src/components/virtual-scroller/CVirtualScroller.tsx +13 -14
  388. package/src/helpers/polymorphicComponent.ts +1 -1
  389. package/src/hooks/useColorModes.ts +2 -2
  390. package/src/hooks/useDebouncedCallback.ts +7 -4
  391. package/src/hooks/useForkedRef.ts +20 -15
  392. package/src/hooks/usePopper.ts +13 -9
  393. package/src/utils/__tests__/swipe.spec.ts +82 -0
  394. package/src/utils/executeAfterTransition.ts +1 -1
  395. package/src/utils/index.ts +2 -0
  396. package/src/utils/mergeClassNames.ts +1 -1
  397. package/src/utils/swipe.ts +114 -0
  398. package/dist/cjs/components/accordion/CAccordionCollapse.d.ts +0 -3
  399. package/dist/cjs/components/sidebar/CSidebarNavContext.d.ts +0 -5
  400. package/dist/cjs/components/sidebar/CSidebarNavContext.js +0 -8
  401. package/dist/cjs/components/sidebar/CSidebarNavContext.js.map +0 -1
  402. package/dist/esm/components/accordion/CAccordionCollapse.d.ts +0 -3
  403. package/dist/esm/components/sidebar/CSidebarNavContext.d.ts +0 -5
  404. package/dist/esm/components/sidebar/CSidebarNavContext.js +0 -6
  405. package/dist/esm/components/sidebar/CSidebarNavContext.js.map +0 -1
  406. package/src/components/accordion/CAccordionCollapse.tsx +0 -20
  407. package/src/components/accordion/__tests__/CAccordionCollapse.spec.tsx +0 -10
  408. package/src/components/accordion/__tests__/__snapshots__/CAccordionCollapse.spec.tsx.snap +0 -11
  409. package/src/components/button/__tests__/__snapshots__/CButtonClose.spec.tsx.snap +0 -26
  410. package/src/components/calendar/__tests__/CCalendar.accessibility.spec.tsx +0 -595
  411. package/src/components/calendar/__tests__/CCalendar.comprehensive.spec.tsx +0 -402
  412. package/src/components/calendar/__tests__/CCalendar.edge-cases.spec.tsx +0 -416
  413. package/src/components/calendar/__tests__/CCalendar.interactions.spec.tsx +0 -593
  414. package/src/components/header/CHeaderBrand.tsx~HEAD +0 -36
  415. package/src/components/sidebar/CSidebarNavContext.ts +0 -8
  416. /package/src/components/calendar/__tests__/{test-setup.ts → setup.ts} +0 -0
@@ -1,16 +1,8 @@
1
- import React, {
2
- Children,
3
- forwardRef,
4
- HTMLAttributes,
5
- TouchEvent,
6
- useState,
7
- useEffect,
8
- useRef,
9
- } from 'react'
1
+ import React, { Children, forwardRef, HTMLAttributes, useState, useEffect, useRef } from 'react'
10
2
  import PropTypes from 'prop-types'
11
3
  import classNames from 'classnames'
12
4
 
13
- import { isInViewport } from '../../utils'
5
+ import { isInViewport, isRTL, Swipe } from '../../utils'
14
6
  import { useForkedRef } from '../../hooks'
15
7
 
16
8
  import { CCarouselContext } from './CCarouselContext'
@@ -95,27 +87,32 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
95
87
  const carouselRef = useRef<HTMLDivElement>(null)
96
88
  const forkedRef = useForkedRef(ref, carouselRef)
97
89
  const data = useRef<DataType>({}).current
90
+ const handleControlClickRef = useRef<(direction: string) => void>(() => undefined)
98
91
 
99
92
  const [active, setActive] = useState<number>(activeIndex)
100
93
  const [animating, setAnimating] = useState<boolean>(false)
101
94
  const [customInterval, setCustomInterval] = useState<boolean | number>()
102
95
  const [direction, setDirection] = useState<string>('next')
103
96
  const [itemsNumber, setItemsNumber] = useState<number>(0)
104
- const [touchPosition, setTouchPosition] = useState<number | null>(null)
105
97
  const [visible, setVisible] = useState<boolean>()
106
98
 
107
99
  useEffect(() => {
108
100
  setItemsNumber(Children.toArray(children).length)
109
- })
101
+ }, [children])
110
102
 
111
103
  useEffect(() => {
112
- visible && cycle()
104
+ if (visible) {
105
+ cycle()
106
+ }
113
107
  }, [visible])
114
108
 
115
109
  useEffect(() => {
116
- !animating && cycle()
117
- !animating && onSlid && onSlid(active, direction)
118
- animating && onSlide && onSlide(active, direction)
110
+ if (animating) {
111
+ onSlide?.(active, direction)
112
+ } else {
113
+ cycle()
114
+ onSlid?.(active, direction)
115
+ }
119
116
  }, [animating])
120
117
 
121
118
  useEffect(() => {
@@ -124,10 +121,34 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
124
121
  return () => {
125
122
  window.removeEventListener('scroll', handleScroll)
126
123
  }
127
- })
124
+ }, [])
125
+
126
+ useEffect(() => {
127
+ if (!touch || !carouselRef.current) {
128
+ return
129
+ }
130
+
131
+ const swipe = new Swipe(carouselRef.current, {
132
+ onLeft: () => handleControlClickRef.current(isRTL(carouselRef.current) ? 'prev' : 'next'),
133
+ onRight: () => handleControlClickRef.current(isRTL(carouselRef.current) ? 'next' : 'prev'),
134
+ })
135
+
136
+ return () => swipe.dispose()
137
+ }, [touch])
138
+
139
+ useEffect(() => {
140
+ return () => clearCycleTimeout()
141
+ }, [])
142
+
143
+ const clearCycleTimeout = () => {
144
+ if (data.timeout) {
145
+ clearTimeout(data.timeout)
146
+ data.timeout = null
147
+ }
148
+ }
128
149
 
129
150
  const cycle = () => {
130
- _pause()
151
+ clearCycleTimeout()
131
152
  if (!wrap && active === itemsNumber - 1) {
132
153
  return
133
154
  }
@@ -139,7 +160,7 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
139
160
  )
140
161
  }
141
162
  }
142
- const _pause = () => pause && data.timeout && clearTimeout(data.timeout)
163
+ const _pause = () => pause && clearCycleTimeout()
143
164
 
144
165
  const nextItemWhenVisible = () => {
145
166
  // Don't call next when the page isn't visible
@@ -158,11 +179,12 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
158
179
  }
159
180
  setDirection(direction)
160
181
  if (direction === 'next') {
161
- active === itemsNumber - 1 ? setActive(0) : setActive(active + 1)
182
+ setActive(active === itemsNumber - 1 ? 0 : active + 1)
162
183
  } else {
163
- active === 0 ? setActive(itemsNumber - 1) : setActive(active - 1)
184
+ setActive(active === 0 ? itemsNumber - 1 : active - 1)
164
185
  }
165
186
  }
187
+ handleControlClickRef.current = handleControlClick
166
188
 
167
189
  const handleIndicatorClick = (index: number) => {
168
190
  if (active === index) {
@@ -189,32 +211,6 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
189
211
  }
190
212
  }
191
213
 
192
- const handleTouchMove = (e: TouchEvent) => {
193
- const touchDown = touchPosition
194
-
195
- if (touchDown === null) {
196
- return
197
- }
198
-
199
- const currentTouch = e.touches[0].clientX
200
- const diff = touchDown - currentTouch
201
-
202
- if (diff > 5) {
203
- handleControlClick('next')
204
- }
205
-
206
- if (diff < -5) {
207
- handleControlClick('prev')
208
- }
209
-
210
- setTouchPosition(null)
211
- }
212
-
213
- const handleTouchStart = (e: TouchEvent) => {
214
- const touchDown = e.touches[0].clientX
215
- setTouchPosition(touchDown)
216
- }
217
-
218
214
  return (
219
215
  <div
220
216
  className={classNames(
@@ -227,7 +223,6 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
227
223
  {...(dark && { 'data-coreui-theme': 'dark' })}
228
224
  onMouseEnter={_pause}
229
225
  onMouseLeave={cycle}
230
- {...(touch && { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove })}
231
226
  {...rest}
232
227
  ref={forkedRef}
233
228
  >
@@ -244,7 +239,9 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
244
239
  <button
245
240
  key={`indicator${index}`}
246
241
  onClick={() => {
247
- !animating && handleIndicatorClick(index)
242
+ if (!animating) {
243
+ handleIndicatorClick(index)
244
+ }
248
245
  }}
249
246
  className={classNames({
250
247
  active: active === index,
@@ -260,8 +257,8 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
260
257
  <div className="carousel-inner">
261
258
  {Children.map(children, (child, index) => {
262
259
  if (React.isValidElement(child)) {
263
- return React.cloneElement(child as React.ReactElement<any>, {
264
- active: active === index ? true : false,
260
+ return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {
261
+ active: active === index,
265
262
  direction: direction,
266
263
  key: index,
267
264
  })
@@ -5,4 +5,4 @@ export interface CCarouselContextProps {
5
5
  setCustomInterval: (a: boolean | number) => void
6
6
  }
7
7
 
8
- export const CCarouselContext = createContext({} as CCarouselContextProps)
8
+ export const CCarouselContext = createContext({} as CCarouselContextProps)
@@ -64,37 +64,36 @@ export const CCarouselItem = forwardRef<HTMLDivElement, CCarouselItemProps>(
64
64
  }, [active])
65
65
 
66
66
  useEffect(() => {
67
- carouselItemRef.current?.addEventListener('transitionstart', () => {
68
- active && setAnimating(true)
69
- })
70
- carouselItemRef.current?.addEventListener('transitionend', () => {
71
- active && setAnimating(false)
72
- setDirectionClassName('')
73
- setOrderClassName('')
67
+ const element = carouselItemRef.current
68
+
69
+ if (!element) {
70
+ return
71
+ }
72
+
73
+ const handleTransitionStart = () => {
74
74
  if (active) {
75
- setActiveClassName('active')
75
+ setAnimating(true)
76
76
  }
77
- if (!active) {
78
- setActiveClassName('')
77
+ }
78
+
79
+ const handleTransitionEnd = () => {
80
+ if (active) {
81
+ setAnimating(false)
79
82
  }
80
- })
83
+
84
+ setDirectionClassName('')
85
+ setOrderClassName('')
86
+ setActiveClassName(active ? 'active' : '')
87
+ }
88
+
89
+ element.addEventListener('transitionstart', handleTransitionStart)
90
+ element.addEventListener('transitionend', handleTransitionEnd)
91
+
81
92
  return () => {
82
- carouselItemRef.current?.removeEventListener('transitionstart', () => {
83
- active && setAnimating(true)
84
- })
85
- carouselItemRef.current?.removeEventListener('transitionend', () => {
86
- active && setAnimating(false)
87
- setDirectionClassName('')
88
- setOrderClassName('')
89
- if (active) {
90
- setActiveClassName('active')
91
- }
92
- if (!active) {
93
- setActiveClassName('')
94
- }
95
- })
93
+ element.removeEventListener('transitionstart', handleTransitionStart)
94
+ element.removeEventListener('transitionend', handleTransitionEnd)
96
95
  }
97
- })
96
+ }, [active])
98
97
 
99
98
  return (
100
99
  <div
@@ -59,6 +59,49 @@ test('loads and displays CCarousel component', async () => {
59
59
  expect(container).toMatchSnapshot()
60
60
  })
61
61
 
62
+ test('CCarousel does not stack cycle timeouts when pause is disabled', async () => {
63
+ jest.useFakeTimers()
64
+
65
+ render(
66
+ <CCarousel interval={1000} pause={false}>
67
+ <CCarouselItem>Item-1</CCarouselItem>
68
+ <CCarouselItem>Item-2</CCarouselItem>
69
+ <CCarouselItem>Item-3</CCarouselItem>
70
+ </CCarousel>
71
+ )
72
+
73
+ const carousel = document.querySelector('.carousel') as HTMLElement
74
+ const baseTimerCount = jest.getTimerCount()
75
+
76
+ fireEvent.mouseLeave(carousel)
77
+ fireEvent.mouseLeave(carousel)
78
+ fireEvent.mouseLeave(carousel)
79
+
80
+ expect(jest.getTimerCount()).toBe(baseTimerCount)
81
+
82
+ jest.useRealTimers()
83
+ })
84
+
85
+ test('CCarousel clears the pending cycle timeout on unmount', async () => {
86
+ jest.useFakeTimers()
87
+
88
+ const { unmount } = render(
89
+ <CCarousel interval={1000}>
90
+ <CCarouselItem>Item-1</CCarouselItem>
91
+ <CCarouselItem>Item-2</CCarouselItem>
92
+ </CCarousel>
93
+ )
94
+
95
+ const baseTimerCount = jest.getTimerCount()
96
+ expect(baseTimerCount).toBeGreaterThan(0)
97
+
98
+ unmount()
99
+
100
+ expect(jest.getTimerCount()).toBe(baseTimerCount - 1)
101
+
102
+ jest.useRealTimers()
103
+ })
104
+
62
105
  test('CCarousel click on indicator', async () => {
63
106
  const { container } = render(
64
107
  <CCarousel controls indicators>
@@ -86,7 +129,7 @@ test('CCarousel click on indicator', async () => {
86
129
 
87
130
  // click
88
131
  const ci = document.querySelector('.carousel-indicators')
89
- ci && fireEvent.click(ci.children[1])
132
+ fireEvent.click(ci!.children[1])
90
133
  fireEvent.transitionEnd(item1)
91
134
  fireEvent.transitionEnd(item2)
92
135
 
@@ -94,7 +137,7 @@ test('CCarousel click on indicator', async () => {
94
137
  expect(item2).toHaveClass('active')
95
138
 
96
139
  // goback-click
97
- ci && fireEvent.click(ci.children[0])
140
+ fireEvent.click(ci!.children[0])
98
141
  fireEvent.transitionEnd(item1)
99
142
  fireEvent.transitionEnd(item2)
100
143
 
@@ -130,7 +173,7 @@ test('CCarousel click on button', async () => {
130
173
 
131
174
  // click
132
175
  const buttonNext = document.querySelector('.carousel-control-next')
133
- buttonNext && fireEvent.click(buttonNext)
176
+ fireEvent.click(buttonNext!)
134
177
  fireEvent.transitionEnd(item1)
135
178
  fireEvent.transitionEnd(item2)
136
179
 
@@ -139,7 +182,7 @@ test('CCarousel click on button', async () => {
139
182
 
140
183
  // goback-click
141
184
  const buttonPrev = document.querySelector('.carousel-control-prev')
142
- buttonPrev && fireEvent.click(buttonPrev)
185
+ fireEvent.click(buttonPrev!)
143
186
  fireEvent.transitionEnd(item1)
144
187
  fireEvent.transitionEnd(item2)
145
188
 
@@ -0,0 +1,37 @@
1
+ import React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import '@testing-library/jest-dom'
4
+ import { CCarousel, CCarouselItem } from '../index'
5
+
6
+ const isTransition = (type: string) => type === 'transitionstart' || type === 'transitionend'
7
+
8
+ test('CCarouselItem removes the exact transition listener references on cleanup', async () => {
9
+ const addSpy = jest.spyOn(HTMLElement.prototype, 'addEventListener')
10
+ const removeSpy = jest.spyOn(HTMLElement.prototype, 'removeEventListener')
11
+
12
+ const { container, unmount } = render(
13
+ <CCarousel>
14
+ <CCarouselItem>Item-1</CCarouselItem>
15
+ <CCarouselItem>Item-2</CCarouselItem>
16
+ </CCarousel>
17
+ )
18
+ const items = new Set<EventTarget>(container.querySelectorAll('.carousel-item'))
19
+ unmount()
20
+
21
+ const handlersOn = (spy: jest.SpyInstance) =>
22
+ spy.mock.calls
23
+ .map((args, index) => ({ args, context: spy.mock.contexts[index] }))
24
+ .filter(({ args, context }) => isTransition(args[0]) && items.has(context as EventTarget))
25
+ .map(({ args }) => args[1])
26
+
27
+ const added = handlersOn(addSpy)
28
+ const removed = handlersOn(removeSpy)
29
+
30
+ expect(added.length).toBeGreaterThan(0)
31
+ for (const handler of added) {
32
+ expect(removed).toContain(handler)
33
+ }
34
+
35
+ addSpy.mockRestore()
36
+ removeSpy.mockRestore()
37
+ })
@@ -49,6 +49,10 @@ export interface CChipProps extends HTMLAttributes<HTMLSpanElement | HTMLButtonE
49
49
  * Disables the React Chip component and removes interactive behavior.
50
50
  */
51
51
  disabled?: boolean
52
+ /**
53
+ * Turns the React Chip component into a filter chip. A filter chip is selectable and shows a leading check icon while selected.
54
+ */
55
+ filter?: boolean
52
56
  /**
53
57
  * Callback fired when the React Chip component becomes deselected.
54
58
  */
@@ -84,18 +88,24 @@ export interface CChipProps extends HTMLAttributes<HTMLSpanElement | HTMLButtonE
84
88
  * Controls the selected state of a selectable React Chip component.
85
89
  */
86
90
  selected?: boolean
91
+ /**
92
+ * Replaces the default selected icon shown by a filter React Chip component with a custom icon node.
93
+ */
94
+ selectedIcon?: ReactNode
87
95
  /**
88
96
  * Sets the size of the React Chip component to small or large.
89
97
  */
90
98
  size?: 'sm' | 'lg'
99
+ /**
100
+ * Sets the value associated with the React Chip component, used by `CChipSet` to track selection.
101
+ */
102
+ value?: string
91
103
  /**
92
104
  * Sets the visual variant of the React Chip component to outline style.
93
105
  */
94
106
  variant?: 'outline'
95
107
  }
96
108
 
97
- const SELECTOR_FOCUSABLE_ITEMS = '[data-coreui-chip-focusable="true"]:not(.disabled)'
98
-
99
109
  export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forwardRef<
100
110
  HTMLSpanElement | HTMLButtonElement,
101
111
  CChipProps
@@ -110,6 +120,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
110
120
  clickable,
111
121
  color,
112
122
  disabled,
123
+ filter,
113
124
  onClick,
114
125
  onDeselect,
115
126
  onKeyDown,
@@ -120,13 +131,17 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
120
131
  removeIcon,
121
132
  selectable,
122
133
  selected,
134
+ selectedIcon,
123
135
  size,
124
136
  tabIndex,
137
+ value,
125
138
  variant,
126
139
  ...rest
127
140
  },
128
141
  ref
129
142
  ) => {
143
+ // A filter chip is selectable by definition.
144
+ const isSelectable = Boolean(selectable || filter)
130
145
  const chipRef = useRef<HTMLSpanElement | HTMLButtonElement>(null)
131
146
  const forkedRef = useForkedRef(ref, chipRef)
132
147
  const isSelectedControlled = selected !== undefined
@@ -140,47 +155,15 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
140
155
  }, [isSelectedControlled, selected])
141
156
 
142
157
  const isFocusable = useMemo(
143
- () => Boolean(!disabled && (selectable || removable)),
144
- [disabled, selectable, removable]
158
+ () => Boolean(!disabled && (isSelectable || removable)),
159
+ [disabled, isSelectable, removable]
145
160
  )
146
161
 
147
- const getFocusableSibling = (shouldGetNext: boolean) => {
148
- const currentElement = chipRef.current
149
- if (!currentElement?.parentElement) {
150
- return null
151
- }
152
-
153
- const chips = Array.from(
154
- currentElement.parentElement.querySelectorAll<HTMLElement>(SELECTOR_FOCUSABLE_ITEMS)
155
- )
156
-
157
- const index = chips.indexOf(currentElement as unknown as HTMLElement)
158
- if (index === -1 || chips.length <= 1) {
159
- return null
160
- }
161
-
162
- const targetIndex = shouldGetNext ? index + 1 : index - 1
163
- return chips[targetIndex] ?? null
164
- }
165
-
166
- const navigateToEdge = (targetIndex: 0 | -1) => {
167
- const currentElement = chipRef.current
168
- if (!currentElement?.parentElement) {
169
- return
170
- }
171
-
172
- const chips = Array.from(
173
- currentElement.parentElement.querySelectorAll<HTMLElement>(SELECTOR_FOCUSABLE_ITEMS)
174
- )
175
- const edgeChip = targetIndex === -1 ? chips[chips.length - 1] : chips[0]
176
- edgeChip?.focus()
177
- }
178
-
179
162
  const setSelectableState = (
180
163
  nextSelected: boolean,
181
164
  event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>
182
165
  ) => {
183
- if (!selectable || disabled || nextSelected === selectedState) {
166
+ if (!isSelectable || disabled || nextSelected === selectedState) {
184
167
  return
185
168
  }
186
169
 
@@ -219,7 +202,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
219
202
  return
220
203
  }
221
204
 
222
- if (selectable) {
205
+ if (isSelectable) {
223
206
  toggleSelectedState(event)
224
207
  }
225
208
 
@@ -236,7 +219,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
236
219
  case 'Enter':
237
220
  case ' ':
238
221
  case 'Spacebar': {
239
- if (selectable) {
222
+ if (isSelectable) {
240
223
  event.preventDefault()
241
224
  toggleSelectedState(event)
242
225
  }
@@ -247,45 +230,11 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
247
230
  case 'Delete': {
248
231
  if (removable) {
249
232
  event.preventDefault()
250
- const sibling = getFocusableSibling(false) || getFocusableSibling(true)
251
- sibling?.focus()
252
233
  handleRemove(event)
253
234
  }
254
235
  break
255
236
  }
256
237
 
257
- case 'ArrowLeft': {
258
- event.preventDefault()
259
- const sibling = getFocusableSibling(false)
260
- sibling?.focus()
261
- if (selectedState && event.shiftKey) {
262
- sibling?.dispatchEvent(new CustomEvent('coreui-chip-select'))
263
- }
264
- break
265
- }
266
-
267
- case 'ArrowRight': {
268
- event.preventDefault()
269
- const sibling = getFocusableSibling(true)
270
- sibling?.focus()
271
- if (selectedState && event.shiftKey) {
272
- sibling?.dispatchEvent(new CustomEvent('coreui-chip-select'))
273
- }
274
- break
275
- }
276
-
277
- case 'Home': {
278
- event.preventDefault()
279
- navigateToEdge(0)
280
- break
281
- }
282
-
283
- case 'End': {
284
- event.preventDefault()
285
- navigateToEdge(-1)
286
- break
287
- }
288
-
289
238
  // No default
290
239
  }
291
240
 
@@ -297,18 +246,19 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
297
246
  className={classNames(
298
247
  'chip',
299
248
  {
300
- active: selectable ? selectedState : active,
249
+ active: isSelectable ? selectedState : active,
301
250
  disabled,
302
251
  [`chip-${color}`]: color,
303
252
  [`chip-${size}`]: size,
304
- 'chip-clickable': clickable || selectable || Boolean(onClick),
253
+ 'chip-clickable': clickable || isSelectable || Boolean(onClick),
305
254
  'chip-outline': variant === 'outline',
306
255
  },
307
256
  className
308
257
  )}
309
258
  data-coreui-chip-focusable={isFocusable || undefined}
259
+ data-coreui-chip-value={value}
310
260
  {...(disabled && { 'aria-disabled': true })}
311
- {...(selectable && { 'aria-selected': selectedState })}
261
+ {...(isSelectable && { 'aria-selected': selectedState })}
312
262
  {...(isFocusable && tabIndex === undefined && { tabIndex: 0 })}
313
263
  onClick={handleClick}
314
264
  onKeyDown={handleKeyDown}
@@ -316,15 +266,29 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
316
266
  {...rest}
317
267
  ref={forkedRef}
318
268
  >
269
+ {filter && selectedState && (
270
+ <span className="chip-check" aria-hidden="true">
271
+ {selectedIcon ?? (
272
+ <svg
273
+ xmlns="http://www.w3.org/2000/svg"
274
+ width="16"
275
+ height="16"
276
+ viewBox="0 0 512 512"
277
+ fill="currentColor"
278
+ >
279
+ <path d="M425.373 89.373 196 318.745 86.627 209.373l-45.254 45.254L196 409.255l274.627-274.628z" />
280
+ </svg>
281
+ )}
282
+ </span>
283
+ )}
319
284
  {children}
320
- {removable && (
285
+ {removable && !disabled && (
321
286
  <button
322
287
  type="button"
323
288
  className="chip-remove"
324
289
  aria-label={ariaRemoveLabel}
325
290
  onClick={handleRemoveClick}
326
291
  tabIndex={-1}
327
- disabled={disabled}
328
292
  >
329
293
  {removeIcon ?? (
330
294
  <svg
@@ -357,6 +321,7 @@ CChip.propTypes = {
357
321
  clickable: PropTypes.bool,
358
322
  color: colorPropType,
359
323
  disabled: PropTypes.bool,
324
+ filter: PropTypes.bool,
360
325
  onDeselect: PropTypes.func,
361
326
  onRemove: PropTypes.func,
362
327
  onSelect: PropTypes.func,
@@ -365,7 +330,9 @@ CChip.propTypes = {
365
330
  removeIcon: PropTypes.node,
366
331
  selectable: PropTypes.bool,
367
332
  selected: PropTypes.bool,
333
+ selectedIcon: PropTypes.node,
368
334
  size: PropTypes.oneOf(['sm', 'lg']),
335
+ value: PropTypes.string,
369
336
  variant: PropTypes.oneOf(['outline']),
370
337
  }
371
338
 
@@ -55,7 +55,7 @@ test('CChip selectable', async () => {
55
55
  const { getByText } = render(
56
56
  <CChip selectable={true} onSelect={onSelect} onDeselect={onDeselect}>
57
57
  Selectable
58
- </CChip>,
58
+ </CChip>
59
59
  )
60
60
  const chip = getByText('Selectable')
61
61
 
@@ -71,28 +71,35 @@ test('CChip selectable', async () => {
71
71
  expect(onDeselect).toHaveBeenCalledTimes(1)
72
72
  })
73
73
 
74
- test('CChip keyboard navigation', async () => {
75
- const { getByText } = render(
76
- <div>
77
- <CChip selectable={true}>First</CChip>
78
- <CChip selectable={true}>Second</CChip>
79
- <CChip selectable={true}>Third</CChip>
80
- </div>,
74
+ test('CChip filter shows a check icon while selected and implies selectable', async () => {
75
+ const onSelect = jest.fn()
76
+ const { getByText, container } = render(
77
+ <CChip filter={true} onSelect={onSelect}>
78
+ Filter
79
+ </CChip>
81
80
  )
81
+ const chip = getByText('Filter')
82
82
 
83
- const first = getByText('First')
84
- const second = getByText('Second')
85
- const third = getByText('Third')
83
+ expect(chip).toHaveAttribute('aria-selected', 'false')
84
+ expect(container.querySelector('.chip-check')).not.toBeInTheDocument()
86
85
 
87
- first.focus()
88
- fireEvent.keyDown(first, { key: 'ArrowRight' })
89
- expect(second).toHaveFocus()
86
+ fireEvent.click(chip)
87
+ expect(chip).toHaveClass('active')
88
+ expect(onSelect).toHaveBeenCalledTimes(1)
89
+ expect(container.querySelector('.chip-check')).toBeInTheDocument()
90
+
91
+ fireEvent.click(chip)
92
+ expect(container.querySelector('.chip-check')).not.toBeInTheDocument()
93
+ })
90
94
 
91
- fireEvent.keyDown(second, { key: 'End' })
92
- expect(third).toHaveFocus()
95
+ test('CChip filter renders a custom selectedIcon', async () => {
96
+ const { container } = render(
97
+ <CChip filter={true} selected={true} selectedIcon={<span data-testid="custom-check" />}>
98
+ Filter
99
+ </CChip>
100
+ )
93
101
 
94
- fireEvent.keyDown(third, { key: 'Home' })
95
- expect(first).toHaveFocus()
102
+ expect(container.querySelector('.chip-check [data-testid="custom-check"]')).toBeInTheDocument()
96
103
  })
97
104
 
98
105
  test('CChip delete triggers remove callback', async () => {
@@ -103,7 +110,7 @@ test('CChip delete triggers remove callback', async () => {
103
110
  First
104
111
  </CChip>
105
112
  <CChip removable={true}>Second</CChip>
106
- </div>,
113
+ </div>
107
114
  )
108
115
 
109
116
  const first = getByText('First')