@coreui/react-pro 4.9.0-next.0 → 4.9.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 (239) hide show
  1. package/README.md +1 -1
  2. package/dist/components/alert/CAlert.d.ts +1 -1
  3. package/dist/components/avatar/CAvatar.d.ts +1 -1
  4. package/dist/components/badge/CBadge.d.ts +1 -1
  5. package/dist/components/button/CButton.d.ts +1 -1
  6. package/dist/components/calendar/utils.d.ts +0 -1
  7. package/dist/components/callout/CCallout.d.ts +1 -1
  8. package/dist/components/card/CCard.d.ts +1 -1
  9. package/dist/components/conditional-portal/CConditionalPortal.d.ts +12 -0
  10. package/dist/components/conditional-portal/index.d.ts +2 -0
  11. package/dist/components/date-range-picker/CDateRangePicker.d.ts +1 -1
  12. package/dist/components/date-range-picker/utils.d.ts +1 -0
  13. package/dist/components/dropdown/CDropdown.d.ts +1 -1
  14. package/dist/components/dropdown/CDropdownToggle.d.ts +1 -1
  15. package/dist/components/form/CFormCheck.d.ts +8 -2
  16. package/dist/components/form/CFormSwitch.d.ts +6 -0
  17. package/dist/components/index.d.ts +1 -0
  18. package/dist/components/list-group/CListGroupItem.d.ts +4 -5
  19. package/dist/components/multi-select/CMultiSelect.d.ts +1 -13
  20. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
  21. package/dist/components/multi-select/CMultiSelectOptions.d.ts +1 -1
  22. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
  23. package/dist/components/multi-select/types.d.ts +14 -0
  24. package/dist/components/multi-select/utils.d.ts +6 -0
  25. package/dist/components/navbar/CNavbar.d.ts +1 -1
  26. package/dist/components/picker/CPicker.d.ts +1 -1
  27. package/dist/components/placeholder/CPlaceholder.d.ts +1 -1
  28. package/dist/components/popover/CPopover.d.ts +1 -1
  29. package/dist/components/progress/CProgressBar.d.ts +1 -1
  30. package/dist/components/smart-table/CSmartTableHead.d.ts +1 -1
  31. package/dist/components/smart-table/CSmartTableInterface.d.ts +8 -0
  32. package/dist/components/smart-table/types.d.ts +1 -1
  33. package/dist/components/spinner/CSpinner.d.ts +1 -1
  34. package/dist/components/table/CTable.d.ts +2 -18
  35. package/dist/components/table/CTableBody.d.ts +1 -1
  36. package/dist/components/table/CTableDataCell.d.ts +1 -1
  37. package/dist/components/table/CTableFoot.d.ts +1 -1
  38. package/dist/components/table/CTableHead.d.ts +1 -1
  39. package/dist/components/table/CTableHeaderCell.d.ts +1 -1
  40. package/dist/components/table/CTableResponsiveWrapper.d.ts +0 -1
  41. package/dist/components/table/CTableRow.d.ts +1 -1
  42. package/dist/components/table/types.d.ts +17 -0
  43. package/dist/components/table/utils.d.ts +5 -0
  44. package/dist/components/toast/CToast.d.ts +1 -1
  45. package/dist/components/toast/CToastClose.d.ts +1 -1
  46. package/dist/components/tooltip/CTooltip.d.ts +1 -1
  47. package/dist/components/virtual-scroller/CVirtualScroller.d.ts +0 -8
  48. package/dist/components/widgets/CWidgetStatsA.d.ts +1 -1
  49. package/dist/components/widgets/CWidgetStatsB.d.ts +1 -1
  50. package/dist/components/widgets/CWidgetStatsC.d.ts +1 -1
  51. package/dist/components/widgets/CWidgetStatsD.d.ts +1 -1
  52. package/dist/components/widgets/CWidgetStatsF.d.ts +1 -1
  53. package/dist/index.es.js +696 -927
  54. package/dist/index.es.js.map +1 -1
  55. package/dist/index.js +695 -925
  56. package/dist/index.js.map +1 -1
  57. package/dist/props.d.ts +8 -0
  58. package/dist/types.d.ts +7 -0
  59. package/dist/utils/index.d.ts +1 -3
  60. package/package.json +11 -6
  61. package/src/components/accordion/CAccordion.tsx +7 -3
  62. package/src/components/accordion/CAccordionBody.tsx +2 -2
  63. package/src/components/accordion/CAccordionButton.tsx +1 -3
  64. package/src/components/accordion/CAccordionCollapse.tsx +1 -0
  65. package/src/components/accordion/CAccordionHeader.tsx +1 -3
  66. package/src/components/accordion/CAccordionItem.tsx +2 -4
  67. package/src/components/accordion/__tests__/__snapshots__/CAccordionBody.spec.tsx.snap +2 -2
  68. package/src/components/alert/CAlert.tsx +21 -28
  69. package/src/components/alert/CAlertHeading.tsx +1 -3
  70. package/src/components/alert/CAlertLink.tsx +1 -3
  71. package/src/components/alert/__tests__/__snapshots__/CAlert.spec.tsx.snap +1 -1
  72. package/src/components/avatar/CAvatar.tsx +16 -19
  73. package/src/components/backdrop/CBackdrop.tsx +10 -13
  74. package/src/components/badge/CBadge.tsx +21 -27
  75. package/src/components/breadcrumb/CBreadcrumb.tsx +1 -2
  76. package/src/components/breadcrumb/CBreadcrumbItem.tsx +12 -8
  77. package/src/components/button/CButton.tsx +10 -10
  78. package/src/components/button-group/CButtonGroup.tsx +9 -7
  79. package/src/components/button-group/CButtonToolbar.tsx +1 -3
  80. package/src/components/calendar/utils.ts +7 -55
  81. package/src/components/callout/CCallout.tsx +13 -10
  82. package/src/components/card/CCard.tsx +14 -11
  83. package/src/components/card/CCardBody.tsx +1 -3
  84. package/src/components/card/CCardFooter.tsx +1 -3
  85. package/src/components/card/CCardGroup.tsx +1 -3
  86. package/src/components/card/CCardHeader.tsx +1 -3
  87. package/src/components/card/CCardImage.tsx +5 -3
  88. package/src/components/card/CCardImageOverlay.tsx +1 -3
  89. package/src/components/card/CCardLink.tsx +1 -3
  90. package/src/components/card/CCardSubtitle.tsx +1 -3
  91. package/src/components/card/CCardText.tsx +1 -3
  92. package/src/components/card/CCardTitle.tsx +1 -3
  93. package/src/components/carousel/CCarousel.tsx +8 -8
  94. package/src/components/carousel/CCarouselCaption.tsx +1 -3
  95. package/src/components/carousel/CCarouselItem.tsx +11 -9
  96. package/src/components/close-button/CCloseButton.tsx +9 -10
  97. package/src/components/collapse/CCollapse.tsx +8 -20
  98. package/src/components/collapse/__tests__/CCollapse.spec.tsx +2 -3
  99. package/src/components/conditional-portal/CConditionalPortal.tsx +29 -0
  100. package/src/components/conditional-portal/index.ts +3 -0
  101. package/src/components/date-range-picker/CDateRangePicker.tsx +11 -13
  102. package/src/components/date-range-picker/utils.ts +49 -0
  103. package/src/components/dropdown/CDropdown.tsx +26 -23
  104. package/src/components/dropdown/CDropdownDivider.tsx +1 -3
  105. package/src/components/dropdown/CDropdownHeader.tsx +1 -3
  106. package/src/components/dropdown/CDropdownItem.tsx +7 -5
  107. package/src/components/dropdown/CDropdownItemPlain.tsx +1 -3
  108. package/src/components/dropdown/CDropdownMenu.tsx +29 -32
  109. package/src/components/dropdown/CDropdownToggle.tsx +34 -27
  110. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +2 -4
  111. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
  112. package/src/components/footer/CFooter.tsx +5 -3
  113. package/src/components/form/CForm.tsx +5 -2
  114. package/src/components/form/CFormCheck.tsx +90 -66
  115. package/src/components/form/CFormControlValidation.tsx +0 -1
  116. package/src/components/form/CFormControlWrapper.tsx +3 -4
  117. package/src/components/form/CFormFeedback.tsx +11 -8
  118. package/src/components/form/CFormFloating.tsx +1 -2
  119. package/src/components/form/CFormInput.tsx +18 -16
  120. package/src/components/form/CFormLabel.tsx +1 -2
  121. package/src/components/form/CFormRange.tsx +2 -4
  122. package/src/components/form/CFormSelect.tsx +16 -12
  123. package/src/components/form/CFormSwitch.tsx +31 -20
  124. package/src/components/form/CFormText.tsx +1 -2
  125. package/src/components/form/CFormTextarea.tsx +14 -11
  126. package/src/components/form/CInputGroup.tsx +11 -8
  127. package/src/components/form/CInputGroupText.tsx +1 -2
  128. package/src/components/form/__tests__/CFormRange.spec.tsx +1 -1
  129. package/src/components/form/__tests__/__snapshots__/CForm.spec.tsx.snap +2 -6
  130. package/src/components/form/__tests__/__snapshots__/CFormRange.spec.tsx.snap +2 -2
  131. package/src/components/grid/CCol.tsx +8 -6
  132. package/src/components/grid/CContainer.tsx +8 -6
  133. package/src/components/grid/CRow.tsx +4 -3
  134. package/src/components/header/CHeader.tsx +12 -13
  135. package/src/components/header/CHeaderBrand.tsx +1 -3
  136. package/src/components/header/CHeaderBrand.tsx~HEAD +1 -3
  137. package/src/components/header/CHeaderDivider.tsx +1 -3
  138. package/src/components/header/CHeaderNav.tsx +6 -3
  139. package/src/components/header/CHeaderText.tsx +1 -3
  140. package/src/components/header/CHeaderToggler.tsx +2 -4
  141. package/src/components/image/CImage.tsx +17 -10
  142. package/src/components/image/__tests__/__snapshots__/CImage.spec.tsx.snap +1 -3
  143. package/src/components/index.ts +1 -0
  144. package/src/components/link/CLink.tsx +2 -4
  145. package/src/components/list-group/CListGroup.tsx +11 -10
  146. package/src/components/list-group/CListGroupItem.tsx +21 -20
  147. package/src/components/list-group/CListGroupItem.tsx~HEAD +3 -1
  148. package/src/components/loading-button/CLoadingButton.tsx +1 -3
  149. package/src/components/modal/CModal.tsx +57 -72
  150. package/src/components/modal/CModalBody.tsx +1 -3
  151. package/src/components/modal/CModalContent.tsx +1 -3
  152. package/src/components/modal/CModalDialog.tsx +16 -14
  153. package/src/components/modal/CModalFooter.tsx +1 -3
  154. package/src/components/modal/CModalHeader.tsx +4 -4
  155. package/src/components/modal/CModalTitle.tsx +1 -3
  156. package/src/components/modal/__tests__/CModal.spec.tsx +19 -20
  157. package/src/components/multi-select/CMultiSelect.tsx +34 -93
  158. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
  159. package/src/components/multi-select/CMultiSelectOptions.tsx +2 -2
  160. package/src/components/multi-select/CMultiSelectSelection.tsx +1 -1
  161. package/src/components/multi-select/types.ts +15 -0
  162. package/src/components/multi-select/utils.ts +92 -0
  163. package/src/components/nav/CNav.tsx +13 -10
  164. package/src/components/nav/CNavGroup.tsx +1 -3
  165. package/src/components/nav/CNavGroupItems.tsx +1 -2
  166. package/src/components/nav/CNavItem.tsx +9 -10
  167. package/src/components/nav/CNavLink.tsx +4 -5
  168. package/src/components/nav/CNavTitle.tsx +1 -2
  169. package/src/components/navbar/CNavbar.tsx +23 -23
  170. package/src/components/navbar/CNavbarBrand.tsx +2 -3
  171. package/src/components/navbar/CNavbarNav.tsx +6 -3
  172. package/src/components/navbar/CNavbarText.tsx +1 -3
  173. package/src/components/navbar/CNavbarToggler.tsx +2 -4
  174. package/src/components/offcanvas/COffcanvas.tsx +42 -68
  175. package/src/components/offcanvas/COffcanvasBody.tsx +1 -3
  176. package/src/components/offcanvas/COffcanvasHeader.tsx +1 -3
  177. package/src/components/offcanvas/COffcanvasTitle.tsx +1 -3
  178. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +7 -2
  179. package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +9 -4
  180. package/src/components/pagination/CPagination.tsx +12 -9
  181. package/src/components/pagination/CPaginationItem.tsx +12 -11
  182. package/src/components/pagination/__tests__/CPagination.spec.tsx +3 -3
  183. package/src/components/pagination/__tests__/CPaginationItem.spec.tsx +3 -3
  184. package/src/components/picker/CPicker.tsx +7 -7
  185. package/src/components/placeholder/CPlaceholder.tsx +15 -12
  186. package/src/components/popover/CPopover.tsx +24 -34
  187. package/src/components/progress/CProgress.tsx +13 -10
  188. package/src/components/progress/CProgressBar.tsx +11 -12
  189. package/src/components/sidebar/CSidebar.tsx +22 -19
  190. package/src/components/sidebar/CSidebarBrand.tsx +1 -2
  191. package/src/components/sidebar/CSidebarFooter.tsx +1 -2
  192. package/src/components/sidebar/CSidebarHeader.tsx +1 -2
  193. package/src/components/sidebar/CSidebarNav.tsx +2 -2
  194. package/src/components/sidebar/CSidebarToggler.tsx +1 -2
  195. package/src/components/smart-pagination/CSmartPagination.tsx +22 -20
  196. package/src/components/smart-table/CSmartTable.tsx +5 -9
  197. package/src/components/smart-table/CSmartTableBody.tsx +82 -81
  198. package/src/components/smart-table/CSmartTableHead.tsx +5 -2
  199. package/src/components/smart-table/CSmartTableInterface.tsx +8 -0
  200. package/src/components/smart-table/{utils.tsx → utils.ts} +4 -5
  201. package/src/components/spinner/CSpinner.tsx +13 -9
  202. package/src/components/table/CTable.tsx +45 -77
  203. package/src/components/table/CTableBody.tsx +14 -9
  204. package/src/components/table/CTableDataCell.tsx +16 -11
  205. package/src/components/table/CTableFoot.tsx +14 -9
  206. package/src/components/table/CTableHead.tsx +14 -9
  207. package/src/components/table/CTableHeaderCell.tsx +14 -9
  208. package/src/components/table/CTableResponsiveWrapper.tsx +2 -3
  209. package/src/components/table/CTableRow.tsx +16 -11
  210. package/src/components/table/__tests__/__snapshots__/CTable.spec.tsx.snap +1 -5
  211. package/src/components/table/types.ts +20 -0
  212. package/src/components/table/utils.ts +24 -0
  213. package/src/components/tabs/CTabContent.tsx +1 -2
  214. package/src/components/tabs/CTabPane.tsx +18 -20
  215. package/src/components/tabs/__tests__/CTabPane.spec.tsx +2 -5
  216. package/src/components/tabs/__tests__/__snapshots__/CTabPane.spec.tsx.snap +1 -1
  217. package/src/components/time-picker/CTimePicker.tsx +14 -18
  218. package/src/components/toast/CToast.tsx +32 -45
  219. package/src/components/toast/CToastBody.tsx +1 -2
  220. package/src/components/toast/CToastClose.tsx +4 -2
  221. package/src/components/toast/CToastHeader.tsx +1 -2
  222. package/src/components/toast/CToaster.tsx +27 -26
  223. package/src/components/toast/__tests__/CToast.spec.tsx +2 -1
  224. package/src/components/toast/__tests__/__snapshots__/CToast.spec.tsx.snap +1 -66
  225. package/src/components/tooltip/CTooltip.tsx +24 -34
  226. package/src/components/virtual-scroller/CVirtualScroller.tsx +35 -60
  227. package/src/components/widgets/CWidgetStatsA.tsx +11 -9
  228. package/src/components/widgets/CWidgetStatsB.tsx +4 -4
  229. package/src/components/widgets/CWidgetStatsC.tsx +4 -4
  230. package/src/components/widgets/CWidgetStatsD.tsx +13 -15
  231. package/src/components/widgets/CWidgetStatsE.tsx +2 -5
  232. package/src/components/widgets/CWidgetStatsF.tsx +4 -8
  233. package/src/{components/Types.tsx → props.ts} +1 -68
  234. package/src/types.ts +68 -0
  235. package/src/utils/index.ts +1 -3
  236. package/src/components/multi-select/CMultiSelectCleaner.tsx +0 -18
  237. package/src/utils/getNextSibling.ts +0 -18
  238. package/src/utils/getPreviousSibling.ts +0 -18
  239. package/src/components/smart-table/{types.tsx → types.ts} +1 -1
@@ -0,0 +1,92 @@
1
+ import type { Option, SelectedOption } from './types'
2
+
3
+ export const filterOptionsList = (search: string, _options: Option[]) => {
4
+ return search.length > 0
5
+ ? _options &&
6
+ _options.reduce((acc: Option[], val: Option) => {
7
+ const options =
8
+ val.options &&
9
+ val.options.filter(
10
+ (element) =>
11
+ element.text && element.text.toLowerCase().includes(search.toLowerCase()),
12
+ )
13
+
14
+ if (
15
+ (val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
16
+ (options && options.length > 0)
17
+ ) {
18
+ acc.push(Object.assign({}, val, options && options.length > 0 && { options }))
19
+ }
20
+
21
+ return acc
22
+ }, [])
23
+ : _options
24
+ }
25
+
26
+ export const flattenArray = (options: Option[]): Option[] => {
27
+ return options.reduce((acc: Option[], val: Option) => {
28
+ return acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val)
29
+ }, [])
30
+ }
31
+
32
+ export const getNextSibling = (elem: HTMLElement, selector?: string) => {
33
+ // Get the next sibling element
34
+ let sibling = elem.nextElementSibling
35
+
36
+ // If there's no selector, return the first sibling
37
+ if (!selector) return sibling
38
+
39
+ // If the sibling matches our selector, use it
40
+ // If not, jump to the next sibling and continue the loop
41
+ while (sibling) {
42
+ if (sibling.matches(selector)) return sibling
43
+ sibling = sibling.nextElementSibling
44
+ }
45
+
46
+ return
47
+ }
48
+
49
+ export const getPreviousSibling = (elem: HTMLElement, selector?: string) => {
50
+ // Get the next sibling element
51
+ let sibling = elem.previousElementSibling
52
+
53
+ // If there's no selector, return the first sibling
54
+ if (!selector) return sibling
55
+
56
+ // If the sibling matches our selector, use it
57
+ // If not, jump to the next sibling and continue the loop
58
+ while (sibling) {
59
+ if (sibling.matches(selector)) return sibling
60
+ sibling = sibling.previousElementSibling
61
+ }
62
+
63
+ return
64
+ }
65
+
66
+ export const selectOptions = (
67
+ options: Option[],
68
+ selected: SelectedOption[],
69
+ deselected?: Option[],
70
+ ) => {
71
+ let _selected = [...selected, ...options]
72
+
73
+ if (deselected) {
74
+ _selected = _selected.filter(
75
+ (selectedOption) =>
76
+ !deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value),
77
+ )
78
+ }
79
+
80
+ const deduplicated = _selected.reduce((unique: Option[], option) => {
81
+ if (!unique.some((obj) => obj.value === option.value)) {
82
+ unique.push({
83
+ value: option.value,
84
+ text: option.text,
85
+ ...(option.disabled && { disabled: option.disabled }),
86
+ })
87
+ }
88
+ return unique
89
+ }, []) as SelectedOption[]
90
+
91
+ return deduplicated
92
+ }
@@ -24,17 +24,20 @@ export interface CNavProps
24
24
 
25
25
  export const CNav = forwardRef<HTMLDivElement | HTMLUListElement | HTMLOListElement, CNavProps>(
26
26
  ({ children, className, component: Component = 'ul', layout, variant, ...rest }, ref) => {
27
- const _className = classNames(
28
- 'nav',
29
- {
30
- [`nav-${layout}`]: layout,
31
- [`nav-${variant}`]: variant,
32
- },
33
- className,
34
- )
35
-
36
27
  return (
37
- <Component className={_className} role="navigation" {...rest} ref={ref}>
28
+ <Component
29
+ className={classNames(
30
+ 'nav',
31
+ {
32
+ [`nav-${layout}`]: layout,
33
+ [`nav-${variant}`]: variant,
34
+ },
35
+ className,
36
+ )}
37
+ role="navigation"
38
+ {...rest}
39
+ ref={ref}
40
+ >
38
41
  {children}
39
42
  </Component>
40
43
  )
@@ -95,10 +95,8 @@ export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
95
95
  exited: { height: height },
96
96
  }
97
97
 
98
- const _className = classNames('nav-group', { show: _visible }, className)
99
-
100
98
  return (
101
- <li className={_className} {...rest} ref={ref}>
99
+ <li className={classNames('nav-group', { show: _visible }, className)} {...rest} ref={ref}>
102
100
  {toggler && (
103
101
  <a className="nav-link nav-group-toggle" onClick={(event) => handleTogglerOnCLick(event)}>
104
102
  {toggler}
@@ -11,9 +11,8 @@ export interface CNavGroupItemsProps extends HTMLAttributes<HTMLUListElement> {
11
11
 
12
12
  export const CNavGroupItems = forwardRef<HTMLUListElement, CNavGroupItemsProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('nav-group-items', className)
15
14
  return (
16
- <ul className={_className} {...rest} ref={ref}>
15
+ <ul className={classNames('nav-group-items', className)} {...rest} ref={ref}>
17
16
  {children}
18
17
  </ul>
19
18
  )
@@ -1,21 +1,20 @@
1
1
  import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
+
4
5
  import { CNavLink, CNavLinkProps } from './CNavLink'
5
6
 
6
7
  export const CNavItem = forwardRef<HTMLLIElement, CNavLinkProps>(
7
8
  ({ children, className, ...rest }, ref) => {
8
- const _className = classNames('nav-item', className)
9
- if (rest.href || rest.to) {
10
- children = (
11
- <CNavLink className={className} {...rest}>
12
- {children}
13
- </CNavLink>
14
- )
15
- }
16
9
  return (
17
- <li className={_className} ref={ref}>
18
- {children}
10
+ <li className={classNames('nav-item', className)} ref={ref}>
11
+ {rest.href || rest.to ? (
12
+ <CNavLink className={className} {...rest}>
13
+ {children}
14
+ </CNavLink>
15
+ ) : (
16
+ children
17
+ )}
19
18
  </li>
20
19
  )
21
20
  },
@@ -2,10 +2,10 @@ import React, { ElementType, forwardRef, useContext, useEffect, useRef } from 'r
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
- import { useForkedRef } from '../../hooks'
6
-
7
- import { CNavContext } from '../sidebar/CSidebarNav'
8
5
  import { CLinkProps, CLink } from '../link/CLink'
6
+ import { CNavContext } from '../sidebar/CSidebarNav'
7
+
8
+ import { useForkedRef } from '../../hooks'
9
9
 
10
10
  export interface CNavLinkProps extends Omit<CLinkProps, 'idx'> {
11
11
  /**
@@ -42,7 +42,6 @@ export const CNavLink = forwardRef<
42
42
  const forkedRef = useForkedRef(ref, navLinkRef)
43
43
 
44
44
  const { setVisibleGroup } = useContext(CNavContext)
45
- const _className = classNames('nav-link', className)
46
45
 
47
46
  useEffect(() => {
48
47
  rest.active = navLinkRef.current?.classList.contains('active')
@@ -50,7 +49,7 @@ export const CNavLink = forwardRef<
50
49
  }, [rest.active, className])
51
50
 
52
51
  return (
53
- <CLink className={_className} {...rest} ref={forkedRef}>
52
+ <CLink className={classNames('nav-link', className)} {...rest} ref={forkedRef}>
54
53
  {children}
55
54
  </CLink>
56
55
  )
@@ -11,9 +11,8 @@ export interface CNavTitleProps extends HTMLAttributes<HTMLLIElement> {
11
11
 
12
12
  export const CNavTitle = forwardRef<HTMLLIElement, CNavTitleProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('nav-title', className)
15
14
  return (
16
- <li className={_className} {...rest} ref={ref}>
15
+ <li className={classNames('nav-title', className)} {...rest} ref={ref}>
17
16
  {children}
18
17
  </li>
19
18
  )
@@ -2,7 +2,8 @@ import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
- import { Colors, colorPropType } from '../Types'
5
+ import { colorPropType } from '../../props'
6
+ import type { Colors } from '../../types'
6
7
 
7
8
  export interface CNavbarProps extends HTMLAttributes<HTMLDivElement> {
8
9
  /**
@@ -52,29 +53,28 @@ export const CNavbar = forwardRef<HTMLDivElement, CNavbarProps>(
52
53
  },
53
54
  ref,
54
55
  ) => {
55
- const _className = classNames(
56
- 'navbar',
57
- {
58
- [`bg-${color}`]: color,
59
- [`navbar-${colorScheme}`]: colorScheme,
60
- [typeof expand === 'boolean' ? 'navbar-expand' : `navbar-expand-${expand}`]: expand,
61
- },
62
- placement,
63
- className,
64
- )
65
-
66
- let content
67
- if (container) {
68
- content = (
69
- <div className={`container${container !== true ? '-' + container : ''}`}>{children}</div>
70
- )
71
- } else {
72
- content = children
73
- }
74
-
75
56
  return (
76
- <Component className={_className} {...rest} ref={ref}>
77
- {content}
57
+ <Component
58
+ className={classNames(
59
+ 'navbar',
60
+ {
61
+ [`bg-${color}`]: color,
62
+ [`navbar-${colorScheme}`]: colorScheme,
63
+ [typeof expand === 'boolean' ? 'navbar-expand' : `navbar-expand-${expand}`]: expand,
64
+ },
65
+ placement,
66
+ className,
67
+ )}
68
+ {...rest}
69
+ ref={ref}
70
+ >
71
+ {container ? (
72
+ <div className={typeof container === 'string' ? `container-${container}` : 'container'}>
73
+ {children}
74
+ </div>
75
+ ) : (
76
+ <>{children}</>
77
+ )}
78
78
  </Component>
79
79
  )
80
80
  },
@@ -20,11 +20,10 @@ export interface CNavbarBrandProps extends HTMLAttributes<HTMLAnchorElement | HT
20
20
 
21
21
  export const CNavbarBrand = forwardRef<HTMLAnchorElement | HTMLSpanElement, CNavbarBrandProps>(
22
22
  ({ children, component, className, ...rest }, ref) => {
23
- const Component = component ? component : rest.href ? 'a' : 'span'
24
- const _className = classNames('navbar-brand', className)
23
+ const Component = component ?? (rest.href ? 'a' : 'span')
25
24
 
26
25
  return (
27
- <Component className={_className} {...rest} ref={ref}>
26
+ <Component className={classNames('navbar-brand', className)} {...rest} ref={ref}>
28
27
  {children}
29
28
  </Component>
30
29
  )
@@ -15,10 +15,13 @@ export interface CNavbarNavProps extends HTMLAttributes<HTMLDivElement | HTMLULi
15
15
 
16
16
  export const CNavbarNav = forwardRef<HTMLDivElement | HTMLUListElement, CNavbarNavProps>(
17
17
  ({ children, component: Component = 'ul', className, ...rest }, ref) => {
18
- const _className = classNames('navbar-nav', className)
19
-
20
18
  return (
21
- <Component className={_className} role="navigation" {...rest} ref={ref}>
19
+ <Component
20
+ className={classNames('navbar-nav', className)}
21
+ role="navigation"
22
+ {...rest}
23
+ ref={ref}
24
+ >
22
25
  {children}
23
26
  </Component>
24
27
  )
@@ -11,10 +11,8 @@ export interface CNavbarTextProps extends HTMLAttributes<HTMLSpanElement> {
11
11
 
12
12
  export const CNavbarText = forwardRef<HTMLSpanElement, CNavbarTextProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('navbar-text', className)
15
-
16
14
  return (
17
- <span className={_className} {...rest} ref={ref}>
15
+ <span className={classNames('navbar-text', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </span>
20
18
  )
@@ -11,11 +11,9 @@ export interface CNavbarTogglerProps extends HTMLAttributes<HTMLButtonElement> {
11
11
 
12
12
  export const CNavbarToggler = forwardRef<HTMLButtonElement, CNavbarTogglerProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('navbar-toggler', className)
15
-
16
14
  return (
17
- <button type="button" className={_className} {...rest} ref={ref}>
18
- {children ? children : <span className="navbar-toggler-icon"></span>}
15
+ <button type="button" className={classNames('navbar-toggler', className)} {...rest} ref={ref}>
16
+ {children ?? <span className="navbar-toggler-icon"></span>}
19
17
  </button>
20
18
  )
21
19
  },
@@ -1,11 +1,12 @@
1
+ import React, { forwardRef, HTMLAttributes, useEffect, useRef, useState } from 'react'
1
2
  import PropTypes from 'prop-types'
2
- import React, { forwardRef, HTMLAttributes, useCallback, useEffect, useRef, useState } from 'react'
3
- import { createPortal } from 'react-dom'
4
- import { Transition } from 'react-transition-group'
5
3
  import classNames from 'classnames'
4
+ import { Transition } from 'react-transition-group'
6
5
 
7
- import { useForkedRef } from '../../hooks'
8
6
  import { CBackdrop } from '../backdrop/CBackdrop'
7
+ import { CConditionalPortal } from '../conditional-portal'
8
+
9
+ import { useForkedRef } from '../../hooks'
9
10
 
10
11
  export interface COffcanvasProps extends HTMLAttributes<HTMLDivElement> {
11
12
  /**
@@ -93,24 +94,6 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
93
94
  }
94
95
  }, [_visible])
95
96
 
96
- const getTransitionClass = (state: string) => {
97
- return state === 'entering'
98
- ? 'showing'
99
- : state === 'entered'
100
- ? 'show'
101
- : state === 'exiting'
102
- ? 'show hiding'
103
- : ''
104
- }
105
-
106
- const _className = classNames(
107
- {
108
- [`offcanvas${typeof responsive !== 'boolean' ? '-' + responsive : ''}`]: responsive,
109
- [`offcanvas-${placement}`]: placement,
110
- },
111
- className,
112
- )
113
-
114
97
  const handleDismiss = () => {
115
98
  setVisible(false)
116
99
  }
@@ -121,30 +104,10 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
121
104
  }
122
105
  }
123
106
 
124
- const handleKeyDown = useCallback(
125
- (event: React.KeyboardEvent<HTMLDivElement>) => {
126
- if (event.key === 'Escape' && keyboard) {
127
- return handleDismiss()
128
- }
129
- },
130
- [ref, handleDismiss],
131
- )
132
-
133
- const offcanvas = (ref: React.Ref<HTMLDivElement>, state: string) => {
134
- return (
135
- <>
136
- <div
137
- className={classNames(_className, getTransitionClass(state))}
138
- role="dialog"
139
- tabIndex={-1}
140
- onKeyDown={handleKeyDown}
141
- {...rest}
142
- ref={ref}
143
- >
144
- {children}
145
- </div>
146
- </>
147
- )
107
+ const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
108
+ if (event.key === 'Escape' && keyboard) {
109
+ return handleDismiss()
110
+ }
148
111
  }
149
112
 
150
113
  return (
@@ -157,29 +120,40 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
157
120
  onExit={onHide}
158
121
  timeout={300}
159
122
  >
160
- {(state) => {
161
- return typeof window !== 'undefined' && portal
162
- ? createPortal(offcanvas(forkedRef, state), document.body)
163
- : offcanvas(forkedRef, state)
164
- }}
123
+ {(state) => (
124
+ <CConditionalPortal portal={portal}>
125
+ <div
126
+ className={classNames(
127
+ {
128
+ [`offcanvas${typeof responsive === 'string' ? '-' + responsive : ''}`]:
129
+ responsive,
130
+ [`offcanvas-${placement}`]: placement,
131
+ showing: state === 'entering',
132
+ show: state === 'entered',
133
+ 'show hiding': state === 'exiting',
134
+ },
135
+ className,
136
+ )}
137
+ role="dialog"
138
+ tabIndex={-1}
139
+ onKeyDown={handleKeyDown}
140
+ {...rest}
141
+ ref={forkedRef}
142
+ >
143
+ {children}
144
+ </div>
145
+ </CConditionalPortal>
146
+ )}
165
147
  </Transition>
166
- {typeof window !== 'undefined' && portal
167
- ? backdrop &&
168
- createPortal(
169
- <CBackdrop
170
- className="offcanvas-backdrop"
171
- onClick={handleBackdropDismiss}
172
- visible={_visible}
173
- />,
174
- document.body,
175
- )
176
- : backdrop && (
177
- <CBackdrop
178
- className="offcanvas-backdrop"
179
- onClick={handleBackdropDismiss}
180
- visible={_visible}
181
- />
182
- )}
148
+ {backdrop && (
149
+ <CConditionalPortal portal={portal}>
150
+ <CBackdrop
151
+ className="offcanvas-backdrop"
152
+ onClick={handleBackdropDismiss}
153
+ visible={_visible}
154
+ />
155
+ </CConditionalPortal>
156
+ )}
183
157
  </>
184
158
  )
185
159
  },
@@ -11,10 +11,8 @@ export interface COffcanvasBodyProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const COffcanvasBody = forwardRef<HTMLDivElement, COffcanvasBodyProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('offcanvas-body', className)
15
-
16
14
  return (
17
- <div className={_className} {...rest} ref={ref}>
15
+ <div className={classNames('offcanvas-body', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </div>
20
18
  )
@@ -11,10 +11,8 @@ export interface COffcanvasHeaderProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const COffcanvasHeader = forwardRef<HTMLDivElement, COffcanvasHeaderProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('offcanvas-header', className)
15
-
16
14
  return (
17
- <div className={_className} {...rest} ref={ref}>
15
+ <div className={classNames('offcanvas-header', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </div>
20
18
  )
@@ -15,10 +15,8 @@ export interface COffcanvasTitleProps extends HTMLAttributes<HTMLHeadingElement>
15
15
 
16
16
  export const COffcanvasTitle = forwardRef<HTMLHeadingElement, COffcanvasTitleProps>(
17
17
  ({ children, component: Component = 'h5', className, ...rest }, ref) => {
18
- const _className = classNames('offcanvas-title', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('offcanvas-title', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -29,7 +29,7 @@ test('COffcanvas customize one', async () => {
29
29
  })
30
30
 
31
31
  test('COffcanvas customize and event on click backdrop', async () => {
32
- jest.useFakeTimers()
32
+ // jest.useFakeTimers()
33
33
  const onHide = jest.fn()
34
34
  const { container } = render(
35
35
  <COffcanvas
@@ -56,11 +56,13 @@ test('COffcanvas customize and event on click backdrop', async () => {
56
56
  fireEvent.click(backdrop)
57
57
  }
58
58
  expect(onHide).toHaveBeenCalledTimes(1)
59
+ expect(container.firstChild).toHaveClass('show')
60
+ expect(container.firstChild).toHaveClass('hiding')
61
+ await new Promise((r) => setTimeout(r, 1000))
59
62
  expect(container.firstChild).not.toHaveClass('show')
60
63
  })
61
64
 
62
65
  test('COffcanvas customize and event on keypress', async () => {
63
- jest.useFakeTimers()
64
66
  const onHide = jest.fn()
65
67
  const { container } = render(
66
68
  <COffcanvas
@@ -93,5 +95,8 @@ test('COffcanvas customize and event on keypress', async () => {
93
95
  })
94
96
  }
95
97
  expect(onHide).toHaveBeenCalledTimes(1)
98
+ expect(container.firstChild).toHaveClass('show')
99
+ expect(container.firstChild).toHaveClass('hiding')
100
+ await new Promise((r) => setTimeout(r, 1000))
96
101
  expect(container.firstChild).not.toHaveClass('show')
97
102
  })
@@ -5,7 +5,6 @@ exports[`COffcanvas customize and event on click backdrop 1`] = `
5
5
  <div
6
6
  class="offcanvas offcanvas-end show bazinga"
7
7
  role="dialog"
8
- style="visibility: visible;"
9
8
  tabindex="-1"
10
9
  >
11
10
  Test
@@ -21,7 +20,6 @@ exports[`COffcanvas customize and event on keypress 1`] = `
21
20
  <div
22
21
  class="offcanvas offcanvas-end show bazinga"
23
22
  role="dialog"
24
- style="visibility: visible;"
25
23
  tabindex="-1"
26
24
  >
27
25
  Test
@@ -37,7 +35,6 @@ exports[`COffcanvas customize one 1`] = `
37
35
  <div
38
36
  class="offcanvas offcanvas-start bazinga"
39
37
  role="dialog"
40
- style="visibility: hidden;"
41
38
  tabindex="-1"
42
39
  >
43
40
  Test
@@ -45,4 +42,12 @@ exports[`COffcanvas customize one 1`] = `
45
42
  </div>
46
43
  `;
47
44
 
48
- exports[`loads and displays COffcanvas component 1`] = `<div />`;
45
+ exports[`loads and displays COffcanvas component 1`] = `
46
+ <div>
47
+ <div
48
+ class="offcanvas offcanvas-top"
49
+ role="dialog"
50
+ tabindex="-1"
51
+ />
52
+ </div>
53
+ `;
@@ -19,17 +19,20 @@ export interface CPaginationProps extends HTMLAttributes<HTMLUListElement> {
19
19
 
20
20
  export const CPagination = forwardRef<HTMLUListElement, CPaginationProps>(
21
21
  ({ children, align, className, size, ...rest }, ref) => {
22
- const _className = classNames(
23
- 'pagination',
24
- {
25
- [`justify-content-${align}`]: align,
26
- [`pagination-${size}`]: size,
27
- },
28
- className,
29
- )
30
22
  return (
31
23
  <nav ref={ref} {...rest}>
32
- <ul className={_className}>{children}</ul>
24
+ <ul
25
+ className={classNames(
26
+ 'pagination',
27
+ {
28
+ [`justify-content-${align}`]: align,
29
+ [`pagination-${size}`]: size,
30
+ },
31
+ className,
32
+ )}
33
+ >
34
+ {children}
35
+ </ul>
33
36
  </nav>
34
37
  )
35
38
  },
@@ -21,19 +21,20 @@ export interface CPaginationItemProps extends HTMLAttributes<HTMLAnchorElement>
21
21
 
22
22
  export const CPaginationItem = forwardRef<HTMLAnchorElement, CPaginationItemProps>(
23
23
  ({ children, className, component, ...rest }, ref) => {
24
- const _className = classNames(
25
- 'page-item',
26
- {
27
- active: rest.active,
28
- disabled: rest.disabled,
29
- },
30
- className,
31
- )
32
-
33
- const Component = component ? component : rest.active ? 'span' : 'a'
24
+ const Component = component ?? (rest.active ? 'span' : 'a')
34
25
 
35
26
  return (
36
- <li className={_className} {...(rest.active && { 'aria-current': 'page' })}>
27
+ <li
28
+ className={classNames(
29
+ 'page-item',
30
+ {
31
+ active: rest.active,
32
+ disabled: rest.disabled,
33
+ },
34
+ className,
35
+ )}
36
+ {...(rest.active && { 'aria-current': 'page' })}
37
+ >
37
38
  {Component === 'a' ? (
38
39
  <CLink className="page-link" component={Component} {...rest} ref={ref}>
39
40
  {children}
@@ -16,13 +16,13 @@ test('CPagination customize', async () => {
16
16
  )
17
17
  expect(container).toMatchSnapshot()
18
18
  let element = container.firstChild
19
- if (element !== null) {
19
+ if (element === null) {
20
+ expect(true).toBe(false)
21
+ } else {
20
22
  element = element.firstChild
21
23
  expect(element).toHaveClass('bazinga')
22
24
  expect(element).toHaveClass('pagination')
23
25
  expect(element).toHaveClass('pagination-lg')
24
- } else {
25
- expect(true).toBe(false)
26
26
  }
27
27
  })
28
28