@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,6 +1,7 @@
1
1
  import * as React from 'react'
2
2
  import { fireEvent, render } from '@testing-library/react'
3
3
  import '@testing-library/jest-dom'
4
+ import { CChip } from '../../chip'
4
5
  import { CChipInput } from '../index'
5
6
 
6
7
  test('loads and displays CChipInput component', async () => {
@@ -52,7 +53,9 @@ test('CChipInput removes chip via remove button', async () => {
52
53
 
53
54
  test('CChipInput selectable chips', async () => {
54
55
  const onSelect = jest.fn()
55
- const { container } = render(<CChipInput defaultValue={['React']} selectable onSelect={onSelect} />)
56
+ const { container } = render(
57
+ <CChipInput defaultValue={['React']} selectable onSelect={onSelect} />
58
+ )
56
59
 
57
60
  const chip = container.querySelector('.chip') as HTMLElement
58
61
  fireEvent.click(chip)
@@ -60,3 +63,66 @@ test('CChipInput selectable chips', async () => {
60
63
  expect(chip).toHaveClass('active')
61
64
  expect(onSelect).toHaveBeenCalledWith(['React'])
62
65
  })
66
+
67
+ test('CChipInput always renders a hidden input for form submission', async () => {
68
+ const { container } = render(<CChipInput defaultValue={['React']} />)
69
+
70
+ const hidden = container.querySelector('input[type="hidden"]')
71
+ expect(hidden).not.toBeNull()
72
+ expect(hidden).toHaveAttribute('name')
73
+ expect(hidden).toHaveValue('React')
74
+ })
75
+
76
+ test('CChipInput single selection deselects siblings', async () => {
77
+ const { container } = render(
78
+ <CChipInput defaultValue={['React', 'Vue']} selectable selectionMode="single" />
79
+ )
80
+
81
+ const chips = container.querySelectorAll<HTMLElement>('.chip')
82
+ fireEvent.click(chips[0])
83
+ fireEvent.click(chips[1])
84
+
85
+ expect(chips[0]).not.toHaveClass('active')
86
+ expect(chips[1]).toHaveClass('active')
87
+ })
88
+
89
+ test('CChipInput ArrowRight on the last chip moves focus to the input', async () => {
90
+ const { container } = render(<CChipInput defaultValue={['React', 'Vue']} />)
91
+
92
+ const chips = container.querySelectorAll<HTMLElement>('.chip')
93
+ const lastChip = chips[chips.length - 1]
94
+ const input = container.querySelector('.chip-input-field') as HTMLInputElement
95
+ lastChip.focus()
96
+
97
+ fireEvent.keyDown(lastChip, { key: 'ArrowRight' })
98
+ expect(input).toHaveFocus()
99
+ })
100
+
101
+ test('CChipInput ArrowLeft on the last chip moves focus to the input in RTL', async () => {
102
+ document.documentElement.dir = 'rtl'
103
+
104
+ const { container } = render(<CChipInput defaultValue={['React', 'Vue']} />)
105
+
106
+ const chips = container.querySelectorAll<HTMLElement>('.chip')
107
+ const lastChip = chips[chips.length - 1]
108
+ const input = container.querySelector('.chip-input-field') as HTMLInputElement
109
+ lastChip.focus()
110
+
111
+ fireEvent.keyDown(lastChip, { key: 'ArrowLeft' })
112
+ expect(input).toHaveFocus()
113
+
114
+ document.documentElement.dir = ''
115
+ })
116
+
117
+ test('CChipInput seeds initial chips from CChip children', () => {
118
+ const { container, getByText } = render(
119
+ <CChipInput>
120
+ <CChip value="React">React</CChip>
121
+ <CChip value="Vue">Vue</CChip>
122
+ </CChipInput>
123
+ )
124
+
125
+ expect(container.querySelectorAll('.chip')).toHaveLength(2)
126
+ expect(getByText('React')).toBeInTheDocument()
127
+ expect(getByText('Vue')).toBeInTheDocument()
128
+ })
@@ -8,6 +8,7 @@ exports[`loads and displays CChipInput component 1`] = `
8
8
  <span
9
9
  class="chip"
10
10
  data-coreui-chip-focusable="true"
11
+ data-coreui-chip-value="React"
11
12
  tabindex="0"
12
13
  >
13
14
  React
@@ -45,6 +46,7 @@ exports[`loads and displays CChipInput component 1`] = `
45
46
  <span
46
47
  class="chip"
47
48
  data-coreui-chip-focusable="true"
49
+ data-coreui-chip-value="TypeScript"
48
50
  tabindex="0"
49
51
  >
50
52
  TypeScript
@@ -86,6 +88,11 @@ exports[`loads and displays CChipInput component 1`] = `
86
88
  type="text"
87
89
  value=""
88
90
  />
91
+ <input
92
+ name=":r0:"
93
+ type="hidden"
94
+ value="React,TypeScript"
95
+ />
89
96
  </div>
90
97
  </div>
91
98
  `;
@@ -50,7 +50,9 @@ export const CContainer = forwardRef<HTMLDivElement, CContainerProps>(
50
50
  const breakpoint = rest[bp]
51
51
  delete rest[bp]
52
52
 
53
- breakpoint && repsonsiveClassNames.push(`container-${bp}`)
53
+ if (breakpoint) {
54
+ repsonsiveClassNames.push(`container-${bp}`)
55
+ }
54
56
  })
55
57
 
56
58
  return (
@@ -4,8 +4,9 @@ import classNames from 'classnames'
4
4
 
5
5
  import { PolymorphicRefForwardingComponent } from '../../helpers'
6
6
 
7
- export interface CHeaderBrandProps
8
- extends AnchorHTMLAttributes<HTMLAnchorElement | HTMLSpanElement> {
7
+ export interface CHeaderBrandProps extends AnchorHTMLAttributes<
8
+ HTMLAnchorElement | HTMLSpanElement
9
+ > {
9
10
  /**
10
11
  * Component used for the root node. Either a string to use a HTML element or a component.
11
12
  */
@@ -12,6 +12,7 @@ export * from './callout'
12
12
  export * from './card'
13
13
  export * from './carousel'
14
14
  export * from './chip'
15
+ export * from './chip-set'
15
16
  export * from './close-button'
16
17
  export * from './collapse'
17
18
  export * from './conditional-portal'
@@ -4,8 +4,10 @@ import classNames from 'classnames'
4
4
 
5
5
  import { PolymorphicRefForwardingComponent } from '../../helpers'
6
6
 
7
- export interface CLinkProps
8
- extends Omit<AllHTMLAttributes<HTMLButtonElement | HTMLAnchorElement>, 'as'> {
7
+ export interface CLinkProps extends Omit<
8
+ AllHTMLAttributes<HTMLButtonElement | HTMLAnchorElement>,
9
+ 'as'
10
+ > {
9
11
  /**
10
12
  * Toggle the active state for the component.
11
13
  */
@@ -40,8 +42,9 @@ export const CLink: PolymorphicRefForwardingComponent<'a', CLinkProps> = forward
40
42
  {...(Component === 'a' && disabled && { 'aria-disabled': true, tabIndex: -1 })}
41
43
  {...((Component === 'a' || Component === 'button') && {
42
44
  onClick: (event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {
43
- event.preventDefault
44
- !disabled && rest.onClick && rest.onClick(event)
45
+ if (!disabled) {
46
+ rest.onClick?.(event)
47
+ }
45
48
  },
46
49
  })}
47
50
  disabled={disabled}
@@ -8,8 +8,9 @@ import { PolymorphicRefForwardingComponent } from '../../helpers'
8
8
  import { colorPropType } from '../../props'
9
9
  import type { Colors } from '../../types'
10
10
 
11
- export interface CListGroupItemProps
12
- extends AnchorHTMLAttributes<HTMLLIElement | HTMLAnchorElement | HTMLButtonElement> {
11
+ export interface CListGroupItemProps extends AnchorHTMLAttributes<
12
+ HTMLLIElement | HTMLAnchorElement | HTMLButtonElement
13
+ > {
13
14
  /**
14
15
  * Toggle the active state for the component.
15
16
  */
@@ -120,6 +120,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
120
120
  ref
121
121
  ) => {
122
122
  const modalRef = useRef<HTMLDivElement>(null)
123
+ const mouseDownTarget = useRef<EventTarget | null>(null)
123
124
  const forkedRef = useForkedRef(ref, modalRef)
124
125
 
125
126
  const [_visible, setVisible] = useState(visible)
@@ -136,11 +137,13 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
136
137
 
137
138
  useEffect(() => {
138
139
  if (_visible) {
140
+ document.addEventListener('mousedown', handleMouseDown)
139
141
  document.addEventListener('mouseup', handleClickOutside)
140
142
  document.addEventListener('keydown', handleKeyDown)
141
143
  }
142
144
 
143
145
  return () => {
146
+ document.removeEventListener('mousedown', handleMouseDown)
144
147
  document.removeEventListener('mouseup', handleClickOutside)
145
148
  document.removeEventListener('keydown', handleKeyDown)
146
149
  }
@@ -155,8 +158,14 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
155
158
  }
156
159
 
157
160
  useLayoutEffect(() => {
161
+ if (!staticBackdrop) {
162
+ return
163
+ }
164
+
158
165
  onClosePrevented?.()
159
- setTimeout(() => setStaticBackdrop(false), duration)
166
+ const timeout = setTimeout(() => setStaticBackdrop(false), duration)
167
+
168
+ return () => clearTimeout(timeout)
160
169
  }, [staticBackdrop])
161
170
 
162
171
  // Set focus to modal after open
@@ -186,8 +195,16 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
186
195
  }
187
196
  }, [_visible])
188
197
 
198
+ const handleMouseDown = (event: Event) => {
199
+ mouseDownTarget.current = event.target
200
+ }
201
+
189
202
  const handleClickOutside = (event: Event) => {
190
- if (modalRef.current && modalRef.current == event.target) {
203
+ if (
204
+ modalRef.current &&
205
+ modalRef.current == event.target &&
206
+ mouseDownTarget.current == event.target
207
+ ) {
191
208
  handleDismiss()
192
209
  }
193
210
  }
@@ -48,6 +48,49 @@ test('CModal dialog close on press ESC', async () => {
48
48
  }
49
49
  })
50
50
 
51
+ test('CModal calls onClosePrevented only when closing is actually prevented', async () => {
52
+ const onClosePrevented = jest.fn()
53
+
54
+ render(
55
+ <CModal backdrop="static" onClosePrevented={onClosePrevented} portal={false} visible>
56
+ Test
57
+ </CModal>
58
+ )
59
+
60
+ expect(onClosePrevented).toHaveBeenCalledTimes(0)
61
+
62
+ const modal = screen.getByText('Test').closest('.modal') as HTMLElement
63
+ fireEvent.keyDown(modal, { key: 'Escape' })
64
+
65
+ await waitFor(() => {
66
+ expect(onClosePrevented).toHaveBeenCalledTimes(1)
67
+ expect(modal).toHaveClass('modal-static')
68
+ })
69
+ })
70
+
71
+ test('CModal does not close when a press started inside the dialog is released over the backdrop area', async () => {
72
+ const onClose = jest.fn()
73
+
74
+ render(
75
+ <CModal onClose={onClose} portal={false} visible>
76
+ <div data-testid="content">Test</div>
77
+ </CModal>
78
+ )
79
+
80
+ const modal = screen.getByText('Test').closest('.modal') as HTMLElement
81
+ const content = screen.getByTestId('content')
82
+
83
+ fireEvent.mouseDown(content)
84
+ fireEvent.mouseUp(modal)
85
+ expect(onClose).toHaveBeenCalledTimes(0)
86
+
87
+ fireEvent.mouseDown(modal)
88
+ fireEvent.mouseUp(modal)
89
+ await waitFor(() => {
90
+ expect(onClose).toHaveBeenCalledTimes(1)
91
+ })
92
+ })
93
+
51
94
  // test('CModal dialog closes when clicking outside the modal', async () => {
52
95
  // const onClose = jest.fn()
53
96