@coreui/react-pro 4.9.0-next.1 → 4.10.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 (186) hide show
  1. package/README.md +1 -1
  2. package/dist/components/conditional-portal/CConditionalPortal.d.ts +12 -0
  3. package/dist/components/conditional-portal/index.d.ts +2 -0
  4. package/dist/components/date-range-picker/CDateRangePicker.d.ts +6 -0
  5. package/dist/components/form/CFormCheck.d.ts +7 -1
  6. package/dist/components/form/CFormSwitch.d.ts +6 -0
  7. package/dist/components/index.d.ts +1 -0
  8. package/dist/components/table/CTableResponsiveWrapper.d.ts +0 -1
  9. package/dist/components/time-picker/CTimePicker.d.ts +6 -0
  10. package/dist/index.es.js +507 -728
  11. package/dist/index.es.js.map +1 -1
  12. package/dist/index.js +506 -726
  13. package/dist/index.js.map +1 -1
  14. package/package.json +11 -6
  15. package/src/components/accordion/CAccordion.tsx +7 -3
  16. package/src/components/accordion/CAccordionBody.tsx +1 -2
  17. package/src/components/accordion/CAccordionButton.tsx +1 -3
  18. package/src/components/accordion/CAccordionHeader.tsx +1 -3
  19. package/src/components/accordion/CAccordionItem.tsx +2 -4
  20. package/src/components/accordion/__tests__/__snapshots__/CAccordionBody.spec.tsx.snap +2 -2
  21. package/src/components/alert/CAlert.tsx +19 -27
  22. package/src/components/alert/CAlertHeading.tsx +1 -3
  23. package/src/components/alert/CAlertLink.tsx +1 -3
  24. package/src/components/alert/__tests__/__snapshots__/CAlert.spec.tsx.snap +1 -1
  25. package/src/components/avatar/CAvatar.tsx +14 -11
  26. package/src/components/backdrop/CBackdrop.tsx +9 -12
  27. package/src/components/badge/CBadge.tsx +19 -17
  28. package/src/components/breadcrumb/CBreadcrumb.tsx +1 -2
  29. package/src/components/breadcrumb/CBreadcrumbItem.tsx +12 -8
  30. package/src/components/button/CButton.tsx +7 -9
  31. package/src/components/button-group/CButtonGroup.tsx +9 -7
  32. package/src/components/button-group/CButtonToolbar.tsx +1 -3
  33. package/src/components/calendar/utils.ts +7 -9
  34. package/src/components/callout/CCallout.tsx +11 -9
  35. package/src/components/card/CCard.tsx +12 -10
  36. package/src/components/card/CCardBody.tsx +1 -3
  37. package/src/components/card/CCardFooter.tsx +1 -3
  38. package/src/components/card/CCardGroup.tsx +1 -3
  39. package/src/components/card/CCardHeader.tsx +1 -3
  40. package/src/components/card/CCardImage.tsx +5 -3
  41. package/src/components/card/CCardImageOverlay.tsx +1 -3
  42. package/src/components/card/CCardLink.tsx +1 -3
  43. package/src/components/card/CCardSubtitle.tsx +1 -3
  44. package/src/components/card/CCardText.tsx +1 -3
  45. package/src/components/card/CCardTitle.tsx +1 -3
  46. package/src/components/carousel/CCarousel.tsx +8 -8
  47. package/src/components/carousel/CCarouselCaption.tsx +1 -3
  48. package/src/components/carousel/CCarouselItem.tsx +11 -9
  49. package/src/components/close-button/CCloseButton.tsx +9 -10
  50. package/src/components/collapse/CCollapse.tsx +8 -20
  51. package/src/components/collapse/__tests__/CCollapse.spec.tsx +2 -3
  52. package/src/components/conditional-portal/CConditionalPortal.tsx +29 -0
  53. package/src/components/conditional-portal/index.ts +3 -0
  54. package/src/components/date-range-picker/CDateRangePicker.tsx +19 -11
  55. package/src/components/date-range-picker/utils.ts +2 -2
  56. package/src/components/dropdown/CDropdown.tsx +35 -30
  57. package/src/components/dropdown/CDropdownDivider.tsx +1 -3
  58. package/src/components/dropdown/CDropdownHeader.tsx +1 -3
  59. package/src/components/dropdown/CDropdownItem.tsx +6 -3
  60. package/src/components/dropdown/CDropdownItemPlain.tsx +1 -3
  61. package/src/components/dropdown/CDropdownMenu.tsx +27 -31
  62. package/src/components/dropdown/CDropdownToggle.tsx +29 -23
  63. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +2 -4
  64. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
  65. package/src/components/footer/CFooter.tsx +5 -3
  66. package/src/components/form/CForm.tsx +5 -2
  67. package/src/components/form/CFormCheck.tsx +87 -63
  68. package/src/components/form/CFormControlWrapper.tsx +3 -3
  69. package/src/components/form/CFormFeedback.tsx +11 -8
  70. package/src/components/form/CFormFloating.tsx +1 -2
  71. package/src/components/form/CFormInput.tsx +10 -12
  72. package/src/components/form/CFormLabel.tsx +1 -2
  73. package/src/components/form/CFormRange.tsx +1 -2
  74. package/src/components/form/CFormSelect.tsx +15 -10
  75. package/src/components/form/CFormSwitch.tsx +31 -20
  76. package/src/components/form/CFormText.tsx +1 -2
  77. package/src/components/form/CFormTextarea.tsx +13 -9
  78. package/src/components/form/CInputGroup.tsx +11 -8
  79. package/src/components/form/CInputGroupText.tsx +1 -2
  80. package/src/components/form/__tests__/CFormRange.spec.tsx +1 -1
  81. package/src/components/form/__tests__/__snapshots__/CForm.spec.tsx.snap +2 -6
  82. package/src/components/form/__tests__/__snapshots__/CFormRange.spec.tsx.snap +2 -2
  83. package/src/components/grid/CCol.tsx +8 -6
  84. package/src/components/grid/CContainer.tsx +8 -6
  85. package/src/components/grid/CRow.tsx +4 -3
  86. package/src/components/header/CHeader.tsx +12 -13
  87. package/src/components/header/CHeaderBrand.tsx +1 -3
  88. package/src/components/header/CHeaderBrand.tsx~HEAD +1 -3
  89. package/src/components/header/CHeaderDivider.tsx +1 -3
  90. package/src/components/header/CHeaderNav.tsx +6 -3
  91. package/src/components/header/CHeaderText.tsx +1 -3
  92. package/src/components/header/CHeaderToggler.tsx +2 -4
  93. package/src/components/image/CImage.tsx +17 -10
  94. package/src/components/image/__tests__/__snapshots__/CImage.spec.tsx.snap +1 -3
  95. package/src/components/index.ts +1 -0
  96. package/src/components/link/CLink.tsx +2 -4
  97. package/src/components/list-group/CListGroup.tsx +11 -10
  98. package/src/components/list-group/CListGroupItem.tsx +13 -12
  99. package/src/components/loading-button/CLoadingButton.tsx +1 -3
  100. package/src/components/modal/CModal.tsx +55 -70
  101. package/src/components/modal/CModalBody.tsx +1 -3
  102. package/src/components/modal/CModalContent.tsx +1 -3
  103. package/src/components/modal/CModalDialog.tsx +16 -14
  104. package/src/components/modal/CModalFooter.tsx +1 -3
  105. package/src/components/modal/CModalHeader.tsx +1 -2
  106. package/src/components/modal/CModalTitle.tsx +1 -3
  107. package/src/components/modal/__tests__/CModal.spec.tsx +19 -20
  108. package/src/components/multi-select/CMultiSelect.tsx +19 -19
  109. package/src/components/multi-select/utils.ts +3 -3
  110. package/src/components/nav/CNav.tsx +13 -10
  111. package/src/components/nav/CNavGroup.tsx +1 -3
  112. package/src/components/nav/CNavGroupItems.tsx +1 -2
  113. package/src/components/nav/CNavItem.tsx +8 -10
  114. package/src/components/nav/CNavLink.tsx +1 -2
  115. package/src/components/nav/CNavTitle.tsx +1 -2
  116. package/src/components/navbar/CNavbar.tsx +21 -22
  117. package/src/components/navbar/CNavbarBrand.tsx +2 -3
  118. package/src/components/navbar/CNavbarNav.tsx +6 -3
  119. package/src/components/navbar/CNavbarText.tsx +1 -3
  120. package/src/components/navbar/CNavbarToggler.tsx +2 -4
  121. package/src/components/offcanvas/COffcanvas.tsx +39 -66
  122. package/src/components/offcanvas/COffcanvasBody.tsx +1 -3
  123. package/src/components/offcanvas/COffcanvasHeader.tsx +1 -3
  124. package/src/components/offcanvas/COffcanvasTitle.tsx +1 -3
  125. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +7 -2
  126. package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +9 -4
  127. package/src/components/pagination/CPagination.tsx +12 -9
  128. package/src/components/pagination/CPaginationItem.tsx +12 -11
  129. package/src/components/pagination/__tests__/CPagination.spec.tsx +3 -3
  130. package/src/components/pagination/__tests__/CPaginationItem.spec.tsx +3 -3
  131. package/src/components/picker/CPicker.tsx +6 -6
  132. package/src/components/placeholder/CPlaceholder.tsx +13 -11
  133. package/src/components/popover/CPopover.tsx +22 -33
  134. package/src/components/progress/CProgress.tsx +12 -10
  135. package/src/components/progress/CProgressBar.tsx +9 -11
  136. package/src/components/sidebar/CSidebar.tsx +20 -18
  137. package/src/components/sidebar/CSidebarBrand.tsx +1 -2
  138. package/src/components/sidebar/CSidebarFooter.tsx +1 -2
  139. package/src/components/sidebar/CSidebarHeader.tsx +1 -2
  140. package/src/components/sidebar/CSidebarNav.tsx +2 -2
  141. package/src/components/sidebar/CSidebarToggler.tsx +1 -2
  142. package/src/components/smart-pagination/CSmartPagination.tsx +22 -20
  143. package/src/components/smart-table/CSmartTable.tsx +4 -8
  144. package/src/components/smart-table/utils.ts +3 -4
  145. package/src/components/spinner/CSpinner.tsx +11 -8
  146. package/src/components/table/CTable.tsx +20 -18
  147. package/src/components/table/CTableBody.tsx +12 -8
  148. package/src/components/table/CTableDataCell.tsx +14 -10
  149. package/src/components/table/CTableFoot.tsx +12 -8
  150. package/src/components/table/CTableHead.tsx +12 -8
  151. package/src/components/table/CTableHeaderCell.tsx +12 -8
  152. package/src/components/table/CTableResponsiveWrapper.tsx +2 -3
  153. package/src/components/table/CTableRow.tsx +14 -10
  154. package/src/components/table/__tests__/__snapshots__/CTable.spec.tsx.snap +1 -5
  155. package/src/components/table/utils.ts +2 -7
  156. package/src/components/tabs/CTabContent.tsx +1 -2
  157. package/src/components/tabs/CTabPane.tsx +17 -20
  158. package/src/components/tabs/__tests__/CTabPane.spec.tsx +2 -5
  159. package/src/components/tabs/__tests__/__snapshots__/CTabPane.spec.tsx.snap +1 -1
  160. package/src/components/time-picker/CTimePicker.tsx +21 -14
  161. package/src/components/toast/CToast.tsx +29 -42
  162. package/src/components/toast/CToastBody.tsx +1 -2
  163. package/src/components/toast/CToastClose.tsx +3 -1
  164. package/src/components/toast/CToastHeader.tsx +1 -2
  165. package/src/components/toast/CToaster.tsx +26 -26
  166. package/src/components/toast/__tests__/CToast.spec.tsx +2 -1
  167. package/src/components/toast/__tests__/__snapshots__/CToast.spec.tsx.snap +1 -66
  168. package/src/components/tooltip/CTooltip.tsx +21 -32
  169. package/src/components/virtual-scroller/CVirtualScroller.tsx +4 -6
  170. package/src/components/widgets/CWidgetStatsA.tsx +8 -6
  171. package/src/components/widgets/CWidgetStatsD.tsx +9 -10
  172. package/src/components/widgets/CWidgetStatsE.tsx +1 -3
  173. package/src/components/widgets/CWidgetStatsF.tsx +1 -4
  174. package/dist/components/Types.d.ts +0 -14
  175. package/dist/components/multi-select/CMultiSelectCleaner.d.ts +0 -2
  176. package/dist/components/multi-select/CMultiSelectSearchInput.d.ts +0 -5
  177. package/dist/components/pagination/CSmartPagination.d.ts +0 -80
  178. package/dist/components/time-picker/CTimePicker copy.d.ts +0 -46
  179. package/dist/utils/calendar.d.ts +0 -23
  180. package/dist/utils/getNextSibling.d.ts +0 -2
  181. package/dist/utils/getPreviousSibling.d.ts +0 -2
  182. package/dist/utils/hooks/index.d.ts +0 -3
  183. package/dist/utils/hooks/useForkedRef.d.ts +0 -7
  184. package/dist/utils/hooks/useStateWithCallback.d.ts +0 -2
  185. package/dist/utils/isVisible.d.ts +0 -2
  186. package/dist/utils/time.d.ts +0 -21
@@ -26,7 +26,6 @@ test('CModal customize', async () => {
26
26
  })
27
27
 
28
28
  test('CModal dialog close on press ESC', async () => {
29
- jest.useFakeTimers()
30
29
  const onClose = jest.fn()
31
30
  render(
32
31
  <CModal onClose={onClose} portal={false} visible>
@@ -36,32 +35,32 @@ test('CModal dialog close on press ESC', async () => {
36
35
  expect(onClose).toHaveBeenCalledTimes(0)
37
36
  const modal = document.querySelector('.modal')
38
37
  if (modal !== null) {
39
- fireEvent.keyUp(modal, {
38
+ fireEvent.keyDown(modal, {
40
39
  key: 'Escape',
41
40
  code: 'Escape',
42
41
  keyCode: 27,
43
42
  charCode: 27,
44
43
  })
45
44
  }
45
+ await new Promise((r) => setTimeout(r, 1000))
46
+ console.log(modal)
47
+ expect(onClose).toHaveBeenCalledTimes(1)
48
+ })
49
+
50
+ test('CModal dialog close on backdrop', async () => {
51
+ jest.useFakeTimers()
52
+ const onClose = jest.fn()
53
+ render(
54
+ <CModal onClose={onClose} portal={false} visible={true}>
55
+ Test
56
+ </CModal>,
57
+ )
58
+ expect(onClose).toHaveBeenCalledTimes(0)
59
+ const backdrop = document.querySelector('.modal-backdrop')
60
+ if (backdrop !== null) {
61
+ fireEvent.click(backdrop)
62
+ }
46
63
  jest.runAllTimers()
47
64
  expect(onClose).toHaveBeenCalledTimes(1)
48
65
  jest.useRealTimers()
49
66
  })
50
-
51
- // test('CModal dialog close on backdrop', async () => {
52
- // jest.useFakeTimers()
53
- // const onClose = jest.fn()
54
- // render(
55
- // <CModal onClose={onClose} portal={false} visible={true}>
56
- // Test
57
- // </CModal>,
58
- // )
59
- // expect(onClose).toHaveBeenCalledTimes(0)
60
- // const backdrop = document.querySelector('.modal-backdrop')
61
- // if (backdrop !== null) {
62
- // fireEvent.click(backdrop)
63
- // }
64
- // jest.runAllTimers()
65
- // expect(onClose).toHaveBeenCalledTimes(1)
66
- // jest.useRealTimers()
67
- // })
@@ -191,20 +191,6 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
191
191
  nativeSelectRef.current.dispatchEvent(new Event('change', { bubbles: true }))
192
192
  }, [JSON.stringify(selected)])
193
193
 
194
- const _className = classNames(
195
- 'form-multi-select',
196
- {
197
- 'form-multi-select-with-cleaner': cleaner,
198
- [`form-multi-select-${size}`]: size,
199
- show: _visible,
200
- 'form-multi-select-selection-tags': multiple && selectionType === 'tags',
201
- disabled,
202
- 'is-invalid': invalid,
203
- 'is-valid': valid,
204
- },
205
- className,
206
- )
207
-
208
194
  useEffect(() => {
209
195
  isInitialMount.current = false
210
196
  }, [])
@@ -219,7 +205,9 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
219
205
  }
220
206
 
221
207
  const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
222
- if (_search.length) return
208
+ if (_search.length > 0) {
209
+ return
210
+ }
223
211
 
224
212
  if (event.key === 'Backspace' || event.key === 'Delete') {
225
213
  const last = selected.filter((option: Option) => !option.disabled).pop()
@@ -284,7 +272,19 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
284
272
  ref={nativeSelectRef}
285
273
  />
286
274
  <CPicker
287
- className={_className}
275
+ className={classNames(
276
+ 'form-multi-select',
277
+ {
278
+ 'form-multi-select-with-cleaner': cleaner,
279
+ [`form-multi-select-${size}`]: size,
280
+ show: _visible,
281
+ 'form-multi-select-selection-tags': multiple && selectionType === 'tags',
282
+ disabled,
283
+ 'is-invalid': invalid,
284
+ 'is-valid': valid,
285
+ },
286
+ className,
287
+ )}
288
288
  disabled={disabled}
289
289
  id={id}
290
290
  onHide={() => setVisible(false)}
@@ -317,14 +317,14 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
317
317
  onChange={(event) => handleSearchChange(event)}
318
318
  onKeyDown={(event) => handleSearchKeyDown(event)}
319
319
  {...(selected.length === 0 && { placeholder: placeholder })}
320
- {...(selected.length &&
320
+ {...(selected.length > 0 &&
321
321
  selectionType === 'counter' && {
322
322
  placeholder: `${selected.length} ${selectionTypeCounterText}`,
323
323
  })}
324
- {...(selected.length &&
324
+ {...(selected.length > 0 &&
325
325
  !multiple && { placeholder: selected.map((option) => option.text)[0] })}
326
326
  {...(multiple &&
327
- selected.length &&
327
+ selected.length > 0 &&
328
328
  selectionType !== 'counter' && { size: _search.length + 2 })}
329
329
  ref={searchRef}
330
330
  ></input>
@@ -1,7 +1,7 @@
1
1
  import type { Option, SelectedOption } from './types'
2
2
 
3
3
  export const filterOptionsList = (search: string, _options: Option[]) => {
4
- return search.length
4
+ return search.length > 0
5
5
  ? _options &&
6
6
  _options.reduce((acc: Option[], val: Option) => {
7
7
  const options =
@@ -13,9 +13,9 @@ export const filterOptionsList = (search: string, _options: Option[]) => {
13
13
 
14
14
  if (
15
15
  (val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
16
- (options && options.length)
16
+ (options && options.length > 0)
17
17
  ) {
18
- acc.push(Object.assign({}, val, options && options.length && { options }))
18
+ acc.push(Object.assign({}, val, options && options.length > 0 && { options }))
19
19
  }
20
20
 
21
21
  return acc
@@ -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
  )
@@ -6,17 +6,15 @@ import { CNavLink, CNavLinkProps } from './CNavLink'
6
6
 
7
7
  export const CNavItem = forwardRef<HTMLLIElement, CNavLinkProps>(
8
8
  ({ children, className, ...rest }, ref) => {
9
- const _className = classNames('nav-item', className)
10
- if (rest.href || rest.to) {
11
- children = (
12
- <CNavLink className={className} {...rest}>
13
- {children}
14
- </CNavLink>
15
- )
16
- }
17
9
  return (
18
- <li className={_className} ref={ref}>
19
- {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
+ )}
20
18
  </li>
21
19
  )
22
20
  },
@@ -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
  )
@@ -53,29 +53,28 @@ export const CNavbar = forwardRef<HTMLDivElement, CNavbarProps>(
53
53
  },
54
54
  ref,
55
55
  ) => {
56
- const _className = classNames(
57
- 'navbar',
58
- {
59
- [`bg-${color}`]: color,
60
- [`navbar-${colorScheme}`]: colorScheme,
61
- [typeof expand === 'boolean' ? 'navbar-expand' : `navbar-expand-${expand}`]: expand,
62
- },
63
- placement,
64
- className,
65
- )
66
-
67
- let content
68
- if (container) {
69
- content = (
70
- <div className={`container${container !== true ? '-' + container : ''}`}>{children}</div>
71
- )
72
- } else {
73
- content = children
74
- }
75
-
76
56
  return (
77
- <Component className={_className} {...rest} ref={ref}>
78
- {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
+ )}
79
78
  </Component>
80
79
  )
81
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,10 +1,10 @@
1
- import React, { forwardRef, HTMLAttributes, useCallback, useEffect, useRef, useState } from 'react'
2
- import { createPortal } from 'react-dom'
1
+ import React, { forwardRef, HTMLAttributes, useEffect, useRef, useState } from 'react'
3
2
  import PropTypes from 'prop-types'
4
3
  import classNames from 'classnames'
5
4
  import { Transition } from 'react-transition-group'
6
5
 
7
6
  import { CBackdrop } from '../backdrop/CBackdrop'
7
+ import { CConditionalPortal } from '../conditional-portal'
8
8
 
9
9
  import { useForkedRef } from '../../hooks'
10
10
 
@@ -94,24 +94,6 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
94
94
  }
95
95
  }, [_visible])
96
96
 
97
- const getTransitionClass = (state: string) => {
98
- return state === 'entering'
99
- ? 'showing'
100
- : state === 'entered'
101
- ? 'show'
102
- : state === 'exiting'
103
- ? 'show hiding'
104
- : ''
105
- }
106
-
107
- const _className = classNames(
108
- {
109
- [`offcanvas${typeof responsive !== 'boolean' ? '-' + responsive : ''}`]: responsive,
110
- [`offcanvas-${placement}`]: placement,
111
- },
112
- className,
113
- )
114
-
115
97
  const handleDismiss = () => {
116
98
  setVisible(false)
117
99
  }
@@ -122,30 +104,10 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
122
104
  }
123
105
  }
124
106
 
125
- const handleKeyDown = useCallback(
126
- (event: React.KeyboardEvent<HTMLDivElement>) => {
127
- if (event.key === 'Escape' && keyboard) {
128
- return handleDismiss()
129
- }
130
- },
131
- [ref, handleDismiss],
132
- )
133
-
134
- const offcanvas = (ref: React.Ref<HTMLDivElement>, state: string) => {
135
- return (
136
- <>
137
- <div
138
- className={classNames(_className, getTransitionClass(state))}
139
- role="dialog"
140
- tabIndex={-1}
141
- onKeyDown={handleKeyDown}
142
- {...rest}
143
- ref={ref}
144
- >
145
- {children}
146
- </div>
147
- </>
148
- )
107
+ const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
108
+ if (event.key === 'Escape' && keyboard) {
109
+ return handleDismiss()
110
+ }
149
111
  }
150
112
 
151
113
  return (
@@ -158,29 +120,40 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
158
120
  onExit={onHide}
159
121
  timeout={300}
160
122
  >
161
- {(state) => {
162
- return typeof window !== 'undefined' && portal
163
- ? createPortal(offcanvas(forkedRef, state), document.body)
164
- : offcanvas(forkedRef, state)
165
- }}
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
+ )}
166
147
  </Transition>
167
- {typeof window !== 'undefined' && portal
168
- ? backdrop &&
169
- createPortal(
170
- <CBackdrop
171
- className="offcanvas-backdrop"
172
- onClick={handleBackdropDismiss}
173
- visible={_visible}
174
- />,
175
- document.body,
176
- )
177
- : backdrop && (
178
- <CBackdrop
179
- className="offcanvas-backdrop"
180
- onClick={handleBackdropDismiss}
181
- visible={_visible}
182
- />
183
- )}
148
+ {backdrop && (
149
+ <CConditionalPortal portal={portal}>
150
+ <CBackdrop
151
+ className="offcanvas-backdrop"
152
+ onClick={handleBackdropDismiss}
153
+ visible={_visible}
154
+ />
155
+ </CConditionalPortal>
156
+ )}
184
157
  </>
185
158
  )
186
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
  },