@coreui/react-pro 4.9.0-next.1 → 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 (171) 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/form/CFormCheck.d.ts +7 -1
  5. package/dist/components/form/CFormSwitch.d.ts +6 -0
  6. package/dist/components/index.d.ts +1 -0
  7. package/dist/components/table/CTableResponsiveWrapper.d.ts +0 -1
  8. package/dist/index.es.js +498 -720
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/index.js +497 -718
  11. package/dist/index.js.map +1 -1
  12. package/package.json +11 -6
  13. package/src/components/accordion/CAccordion.tsx +7 -3
  14. package/src/components/accordion/CAccordionBody.tsx +1 -2
  15. package/src/components/accordion/CAccordionButton.tsx +1 -3
  16. package/src/components/accordion/CAccordionHeader.tsx +1 -3
  17. package/src/components/accordion/CAccordionItem.tsx +2 -4
  18. package/src/components/accordion/__tests__/__snapshots__/CAccordionBody.spec.tsx.snap +2 -2
  19. package/src/components/alert/CAlert.tsx +19 -27
  20. package/src/components/alert/CAlertHeading.tsx +1 -3
  21. package/src/components/alert/CAlertLink.tsx +1 -3
  22. package/src/components/alert/__tests__/__snapshots__/CAlert.spec.tsx.snap +1 -1
  23. package/src/components/avatar/CAvatar.tsx +14 -11
  24. package/src/components/backdrop/CBackdrop.tsx +9 -12
  25. package/src/components/badge/CBadge.tsx +19 -17
  26. package/src/components/breadcrumb/CBreadcrumb.tsx +1 -2
  27. package/src/components/breadcrumb/CBreadcrumbItem.tsx +12 -8
  28. package/src/components/button/CButton.tsx +7 -9
  29. package/src/components/button-group/CButtonGroup.tsx +9 -7
  30. package/src/components/button-group/CButtonToolbar.tsx +1 -3
  31. package/src/components/calendar/utils.ts +7 -9
  32. package/src/components/callout/CCallout.tsx +11 -9
  33. package/src/components/card/CCard.tsx +12 -10
  34. package/src/components/card/CCardBody.tsx +1 -3
  35. package/src/components/card/CCardFooter.tsx +1 -3
  36. package/src/components/card/CCardGroup.tsx +1 -3
  37. package/src/components/card/CCardHeader.tsx +1 -3
  38. package/src/components/card/CCardImage.tsx +5 -3
  39. package/src/components/card/CCardImageOverlay.tsx +1 -3
  40. package/src/components/card/CCardLink.tsx +1 -3
  41. package/src/components/card/CCardSubtitle.tsx +1 -3
  42. package/src/components/card/CCardText.tsx +1 -3
  43. package/src/components/card/CCardTitle.tsx +1 -3
  44. package/src/components/carousel/CCarousel.tsx +8 -8
  45. package/src/components/carousel/CCarouselCaption.tsx +1 -3
  46. package/src/components/carousel/CCarouselItem.tsx +11 -9
  47. package/src/components/close-button/CCloseButton.tsx +9 -10
  48. package/src/components/collapse/CCollapse.tsx +8 -20
  49. package/src/components/collapse/__tests__/CCollapse.spec.tsx +2 -3
  50. package/src/components/conditional-portal/CConditionalPortal.tsx +29 -0
  51. package/src/components/conditional-portal/index.ts +3 -0
  52. package/src/components/date-range-picker/CDateRangePicker.tsx +9 -11
  53. package/src/components/date-range-picker/utils.ts +2 -2
  54. package/src/components/dropdown/CDropdown.tsx +24 -22
  55. package/src/components/dropdown/CDropdownDivider.tsx +1 -3
  56. package/src/components/dropdown/CDropdownHeader.tsx +1 -3
  57. package/src/components/dropdown/CDropdownItem.tsx +6 -3
  58. package/src/components/dropdown/CDropdownItemPlain.tsx +1 -3
  59. package/src/components/dropdown/CDropdownMenu.tsx +27 -31
  60. package/src/components/dropdown/CDropdownToggle.tsx +29 -23
  61. package/src/components/dropdown/__tests__/CDropdown.spec.tsx +2 -4
  62. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
  63. package/src/components/footer/CFooter.tsx +5 -3
  64. package/src/components/form/CForm.tsx +5 -2
  65. package/src/components/form/CFormCheck.tsx +87 -63
  66. package/src/components/form/CFormControlWrapper.tsx +3 -3
  67. package/src/components/form/CFormFeedback.tsx +11 -8
  68. package/src/components/form/CFormFloating.tsx +1 -2
  69. package/src/components/form/CFormInput.tsx +10 -12
  70. package/src/components/form/CFormLabel.tsx +1 -2
  71. package/src/components/form/CFormRange.tsx +1 -2
  72. package/src/components/form/CFormSelect.tsx +15 -10
  73. package/src/components/form/CFormSwitch.tsx +31 -20
  74. package/src/components/form/CFormText.tsx +1 -2
  75. package/src/components/form/CFormTextarea.tsx +13 -9
  76. package/src/components/form/CInputGroup.tsx +11 -8
  77. package/src/components/form/CInputGroupText.tsx +1 -2
  78. package/src/components/form/__tests__/CFormRange.spec.tsx +1 -1
  79. package/src/components/form/__tests__/__snapshots__/CForm.spec.tsx.snap +2 -6
  80. package/src/components/form/__tests__/__snapshots__/CFormRange.spec.tsx.snap +2 -2
  81. package/src/components/grid/CCol.tsx +8 -6
  82. package/src/components/grid/CContainer.tsx +8 -6
  83. package/src/components/grid/CRow.tsx +4 -3
  84. package/src/components/header/CHeader.tsx +12 -13
  85. package/src/components/header/CHeaderBrand.tsx +1 -3
  86. package/src/components/header/CHeaderBrand.tsx~HEAD +1 -3
  87. package/src/components/header/CHeaderDivider.tsx +1 -3
  88. package/src/components/header/CHeaderNav.tsx +6 -3
  89. package/src/components/header/CHeaderText.tsx +1 -3
  90. package/src/components/header/CHeaderToggler.tsx +2 -4
  91. package/src/components/image/CImage.tsx +17 -10
  92. package/src/components/image/__tests__/__snapshots__/CImage.spec.tsx.snap +1 -3
  93. package/src/components/index.ts +1 -0
  94. package/src/components/link/CLink.tsx +2 -4
  95. package/src/components/list-group/CListGroup.tsx +11 -10
  96. package/src/components/list-group/CListGroupItem.tsx +13 -12
  97. package/src/components/loading-button/CLoadingButton.tsx +1 -3
  98. package/src/components/modal/CModal.tsx +55 -70
  99. package/src/components/modal/CModalBody.tsx +1 -3
  100. package/src/components/modal/CModalContent.tsx +1 -3
  101. package/src/components/modal/CModalDialog.tsx +16 -14
  102. package/src/components/modal/CModalFooter.tsx +1 -3
  103. package/src/components/modal/CModalHeader.tsx +1 -2
  104. package/src/components/modal/CModalTitle.tsx +1 -3
  105. package/src/components/modal/__tests__/CModal.spec.tsx +19 -20
  106. package/src/components/multi-select/CMultiSelect.tsx +19 -19
  107. package/src/components/multi-select/utils.ts +3 -3
  108. package/src/components/nav/CNav.tsx +13 -10
  109. package/src/components/nav/CNavGroup.tsx +1 -3
  110. package/src/components/nav/CNavGroupItems.tsx +1 -2
  111. package/src/components/nav/CNavItem.tsx +8 -10
  112. package/src/components/nav/CNavLink.tsx +1 -2
  113. package/src/components/nav/CNavTitle.tsx +1 -2
  114. package/src/components/navbar/CNavbar.tsx +21 -22
  115. package/src/components/navbar/CNavbarBrand.tsx +2 -3
  116. package/src/components/navbar/CNavbarNav.tsx +6 -3
  117. package/src/components/navbar/CNavbarText.tsx +1 -3
  118. package/src/components/navbar/CNavbarToggler.tsx +2 -4
  119. package/src/components/offcanvas/COffcanvas.tsx +39 -66
  120. package/src/components/offcanvas/COffcanvasBody.tsx +1 -3
  121. package/src/components/offcanvas/COffcanvasHeader.tsx +1 -3
  122. package/src/components/offcanvas/COffcanvasTitle.tsx +1 -3
  123. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +7 -2
  124. package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +9 -4
  125. package/src/components/pagination/CPagination.tsx +12 -9
  126. package/src/components/pagination/CPaginationItem.tsx +12 -11
  127. package/src/components/pagination/__tests__/CPagination.spec.tsx +3 -3
  128. package/src/components/pagination/__tests__/CPaginationItem.spec.tsx +3 -3
  129. package/src/components/picker/CPicker.tsx +6 -6
  130. package/src/components/placeholder/CPlaceholder.tsx +13 -11
  131. package/src/components/popover/CPopover.tsx +22 -33
  132. package/src/components/progress/CProgress.tsx +12 -10
  133. package/src/components/progress/CProgressBar.tsx +9 -11
  134. package/src/components/sidebar/CSidebar.tsx +20 -18
  135. package/src/components/sidebar/CSidebarBrand.tsx +1 -2
  136. package/src/components/sidebar/CSidebarFooter.tsx +1 -2
  137. package/src/components/sidebar/CSidebarHeader.tsx +1 -2
  138. package/src/components/sidebar/CSidebarNav.tsx +2 -2
  139. package/src/components/sidebar/CSidebarToggler.tsx +1 -2
  140. package/src/components/smart-pagination/CSmartPagination.tsx +22 -20
  141. package/src/components/smart-table/CSmartTable.tsx +4 -8
  142. package/src/components/smart-table/utils.ts +3 -4
  143. package/src/components/spinner/CSpinner.tsx +11 -8
  144. package/src/components/table/CTable.tsx +20 -18
  145. package/src/components/table/CTableBody.tsx +12 -8
  146. package/src/components/table/CTableDataCell.tsx +14 -10
  147. package/src/components/table/CTableFoot.tsx +12 -8
  148. package/src/components/table/CTableHead.tsx +12 -8
  149. package/src/components/table/CTableHeaderCell.tsx +12 -8
  150. package/src/components/table/CTableResponsiveWrapper.tsx +2 -3
  151. package/src/components/table/CTableRow.tsx +14 -10
  152. package/src/components/table/__tests__/__snapshots__/CTable.spec.tsx.snap +1 -5
  153. package/src/components/table/utils.ts +2 -7
  154. package/src/components/tabs/CTabContent.tsx +1 -2
  155. package/src/components/tabs/CTabPane.tsx +17 -20
  156. package/src/components/tabs/__tests__/CTabPane.spec.tsx +2 -5
  157. package/src/components/tabs/__tests__/__snapshots__/CTabPane.spec.tsx.snap +1 -1
  158. package/src/components/time-picker/CTimePicker.tsx +12 -14
  159. package/src/components/toast/CToast.tsx +29 -42
  160. package/src/components/toast/CToastBody.tsx +1 -2
  161. package/src/components/toast/CToastClose.tsx +3 -1
  162. package/src/components/toast/CToastHeader.tsx +1 -2
  163. package/src/components/toast/CToaster.tsx +26 -26
  164. package/src/components/toast/__tests__/CToast.spec.tsx +2 -1
  165. package/src/components/toast/__tests__/__snapshots__/CToast.spec.tsx.snap +1 -66
  166. package/src/components/tooltip/CTooltip.tsx +21 -32
  167. package/src/components/virtual-scroller/CVirtualScroller.tsx +4 -6
  168. package/src/components/widgets/CWidgetStatsA.tsx +8 -6
  169. package/src/components/widgets/CWidgetStatsD.tsx +9 -10
  170. package/src/components/widgets/CWidgetStatsE.tsx +1 -3
  171. package/src/components/widgets/CWidgetStatsF.tsx +1 -4
@@ -14,10 +14,8 @@ export interface CCardSubtitleProps extends HTMLAttributes<HTMLHeadingElement> {
14
14
  }
15
15
  export const CCardSubtitle = forwardRef<HTMLHeadingElement, CCardSubtitleProps>(
16
16
  ({ children, component: Component = 'h6', className, ...rest }, ref) => {
17
- const _className = classNames('card-subtitle', className)
18
-
19
17
  return (
20
- <Component className={_className} {...rest} ref={ref}>
18
+ <Component className={classNames('card-subtitle', className)} {...rest} ref={ref}>
21
19
  {children}
22
20
  </Component>
23
21
  )
@@ -15,10 +15,8 @@ export interface CCardTextProps extends HTMLAttributes<HTMLParagraphElement> {
15
15
 
16
16
  export const CCardText = forwardRef<HTMLParagraphElement, CCardTextProps>(
17
17
  ({ children, component: Component = 'p', className, ...rest }, ref) => {
18
- const _className = classNames('card-text', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('card-text', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -15,10 +15,8 @@ export interface CCardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
15
15
 
16
16
  export const CCardTitle = forwardRef<HTMLHeadingElement, CCardTitleProps>(
17
17
  ({ children, component: Component = 'h5', className, ...rest }, ref) => {
18
- const _className = classNames('card-title', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('card-title', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -132,13 +132,6 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
132
132
  }
133
133
  })
134
134
 
135
- const _className = classNames(
136
- 'carousel slide',
137
- transition === 'crossfade' && 'carousel-fade',
138
- dark && 'carousel-dark',
139
- className,
140
- )
141
-
142
135
  const cycle = () => {
143
136
  _pause()
144
137
  if (!wrap && active === itemsNumber - 1) {
@@ -230,7 +223,14 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
230
223
 
231
224
  return (
232
225
  <div
233
- className={_className}
226
+ className={classNames(
227
+ 'carousel slide',
228
+ {
229
+ 'carousel-dark': dark,
230
+ 'carousel-fade': transition === 'crossfade',
231
+ },
232
+ className,
233
+ )}
234
234
  onMouseEnter={_pause}
235
235
  onMouseLeave={cycle}
236
236
  {...(touch && { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove })}
@@ -11,9 +11,7 @@ export interface CCarouselCaptionProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const CCarouselCaption = forwardRef<HTMLDivElement, CCarouselCaptionProps>(
13
13
  ({ className, ...rest }, ref) => {
14
- const _className = classNames('carousel-caption', className)
15
-
16
- return <div className={_className} {...rest} ref={ref} />
14
+ return <div className={classNames('carousel-caption', className)} {...rest} ref={ref} />
17
15
  },
18
16
  )
19
17
 
@@ -94,16 +94,18 @@ export const CCarouselItem = forwardRef<HTMLDivElement, CCarouselItemProps>(
94
94
  }
95
95
  })
96
96
 
97
- const _className = classNames(
98
- 'carousel-item',
99
- activeClassName,
100
- directionClassName,
101
- orderClassName,
102
- className,
103
- )
104
-
105
97
  return (
106
- <div className={_className} ref={forkedRef} {...rest}>
98
+ <div
99
+ className={classNames(
100
+ 'carousel-item',
101
+ activeClassName,
102
+ directionClassName,
103
+ orderClassName,
104
+ className,
105
+ )}
106
+ ref={forkedRef}
107
+ {...rest}
108
+ >
107
109
  {children}
108
110
  </div>
109
111
  )
@@ -19,19 +19,18 @@ export interface CCloseButtonProps extends HTMLAttributes<HTMLButtonElement> {
19
19
 
20
20
  export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
21
21
  ({ className, disabled, white, ...rest }, ref) => {
22
- const _className = classNames(
23
- 'btn',
24
- 'btn-close',
25
- {
26
- 'btn-close-white': white,
27
- },
28
- disabled,
29
- className,
30
- )
31
22
  return (
32
23
  <button
33
24
  type="button"
34
- className={_className}
25
+ className={classNames(
26
+ 'btn',
27
+ 'btn-close',
28
+ {
29
+ 'btn-close-white': white,
30
+ },
31
+ disabled,
32
+ className,
33
+ )}
35
34
  aria-label="Close"
36
35
  disabled={disabled}
37
36
  {...rest}
@@ -30,20 +30,11 @@ export interface CCollapseProps extends HTMLAttributes<HTMLDivElement> {
30
30
 
31
31
  export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
32
32
  ({ children, className, horizontal, onHide, onShow, visible, ...rest }, ref) => {
33
- const [height, setHeight] = useState<number>()
34
- const [width, setWidth] = useState<number>()
35
33
  const collapseRef = useRef<HTMLDivElement>(null)
36
34
  const forkedRef = useForkedRef(ref, collapseRef)
37
35
 
38
- const getTransitionClass = (state: string) => {
39
- return state === 'entering'
40
- ? 'collapsing'
41
- : state === 'entered'
42
- ? 'collapse show'
43
- : state === 'exiting'
44
- ? 'collapsing'
45
- : 'collapse'
46
- }
36
+ const [height, setHeight] = useState<number>()
37
+ const [width, setWidth] = useState<number>()
47
38
 
48
39
  const onEntering = () => {
49
40
  onShow && onShow()
@@ -88,13 +79,6 @@ export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
88
79
  setHeight(0)
89
80
  }
90
81
 
91
- const _className = classNames(
92
- {
93
- 'collapse-horizontal': horizontal,
94
- },
95
- className,
96
- )
97
-
98
82
  return (
99
83
  <CSSTransition
100
84
  in={visible}
@@ -107,12 +91,16 @@ export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
107
91
  timeout={350}
108
92
  >
109
93
  {(state) => {
110
- const transitionClass = getTransitionClass(state)
111
94
  const currentHeight = height === 0 ? null : { height }
112
95
  const currentWidth = width === 0 ? null : { width }
113
96
  return (
114
97
  <div
115
- className={classNames(_className, transitionClass)}
98
+ className={classNames(className, {
99
+ 'collapse-horizontal': horizontal,
100
+ collapsing: state === 'entering' || state === 'exiting',
101
+ 'collapse show': state === 'entered',
102
+ collapse: state === 'exited',
103
+ })}
116
104
  style={{ ...currentHeight, ...currentWidth }}
117
105
  {...rest}
118
106
  ref={forkedRef}
@@ -15,7 +15,6 @@ test('CCollapse customize', async () => {
15
15
  })
16
16
 
17
17
  test('CCollapse use case test', async () => {
18
- jest.useFakeTimers()
19
18
  const { rerender } = render(<CCollapse visible={false}>Test</CCollapse>)
20
19
  expect(screen.getByText('Test')).toHaveClass('collapse')
21
20
  expect(screen.getByText('Test')).not.toHaveClass('show')
@@ -24,7 +23,7 @@ test('CCollapse use case test', async () => {
24
23
  expect(screen.getByText('Test')).not.toHaveClass('collapse')
25
24
  expect(screen.getByText('Test')).not.toHaveClass('show')
26
25
  expect(screen.getByText('Test')).toHaveClass('collapsing')
27
- jest.runAllTimers()
26
+ await new Promise((r) => setTimeout(r, 1000))
28
27
  expect(screen.getByText('Test')).toHaveClass('collapse')
29
28
  expect(screen.getByText('Test')).toHaveClass('show')
30
29
  expect(screen.getByText('Test')).not.toHaveClass('collapsing')
@@ -32,7 +31,7 @@ test('CCollapse use case test', async () => {
32
31
  expect(screen.getByText('Test')).not.toHaveClass('collapse')
33
32
  expect(screen.getByText('Test')).not.toHaveClass('show')
34
33
  expect(screen.getByText('Test')).toHaveClass('collapsing')
35
- jest.runAllTimers()
34
+ await new Promise((r) => setTimeout(r, 1000))
36
35
  expect(screen.getByText('Test')).toHaveClass('collapse')
37
36
  expect(screen.getByText('Test')).not.toHaveClass('show')
38
37
  expect(screen.getByText('Test')).not.toHaveClass('collapsing')
@@ -0,0 +1,29 @@
1
+ import React, { FC, ReactNode } from 'react'
2
+ import { createPortal } from 'react-dom'
3
+ import PropTypes from 'prop-types'
4
+
5
+ export interface CConditionalPortalProps {
6
+ /**
7
+ * @ignore
8
+ */
9
+ children: ReactNode
10
+ /**
11
+ * Render some children into a different part of the DOM
12
+ */
13
+ portal: boolean
14
+ }
15
+
16
+ export const CConditionalPortal: FC<CConditionalPortalProps> = ({ children, portal }) => {
17
+ return typeof window !== 'undefined' && portal ? (
18
+ createPortal(children, document.body)
19
+ ) : (
20
+ <>{children}</>
21
+ )
22
+ }
23
+
24
+ CConditionalPortal.propTypes = {
25
+ children: PropTypes.node,
26
+ portal: PropTypes.bool.isRequired,
27
+ }
28
+
29
+ CConditionalPortal.displayName = 'CConditionalPortal'
@@ -0,0 +1,3 @@
1
+ import { CConditionalPortal } from './CConditionalPortal'
2
+
3
+ export { CConditionalPortal }
@@ -304,15 +304,6 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
304
304
  setEndDate(null)
305
305
  }
306
306
 
307
- const _className = classNames(
308
- 'date-picker',
309
- {
310
- 'is-invalid': invalid,
311
- 'is-valid': valid,
312
- },
313
- className,
314
- )
315
-
316
307
  const InputGroup = () => (
317
308
  <CInputGroup className="picker-input-group" size={size}>
318
309
  <CFormInput
@@ -409,7 +400,14 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
409
400
  valid={valid}
410
401
  >
411
402
  <CPicker
412
- className={_className}
403
+ className={classNames(
404
+ 'date-picker',
405
+ {
406
+ 'is-invalid': invalid,
407
+ 'is-valid': valid,
408
+ },
409
+ className,
410
+ )}
413
411
  disabled={disabled}
414
412
  footer={footer || timepicker}
415
413
  footerContent={
@@ -431,7 +429,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
431
429
  )
432
430
  }
433
431
  id={id}
434
- toggler={toggler ? toggler : InputGroup()}
432
+ toggler={toggler ?? InputGroup()}
435
433
  onCancel={() => {
436
434
  handleStartDateChange(initialStartDate)
437
435
  handleEndDateChange(initialEndDate)
@@ -1,5 +1,5 @@
1
1
  export const getLocalDateFromString = (string: string, locale: string, time?: boolean) => {
2
- if (!isNaN(Date.parse(string))) {
2
+ if (!Number.isNaN(Date.parse(string))) {
3
3
  return new Date(Date.parse(string))
4
4
  }
5
5
 
@@ -19,7 +19,7 @@ export const getLocalDateFromString = (string: string, locale: string, time?: bo
19
19
  .replace('PM', '(?<ampm>[A-Z]{2})')
20
20
  }
21
21
 
22
- const rgx = RegExp(`${regex}`)
22
+ const rgx = new RegExp(`${regex}`)
23
23
  const partials = string.match(rgx)
24
24
 
25
25
  if (partials === null) return
@@ -115,10 +115,10 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
115
115
  },
116
116
  ref,
117
117
  ) => {
118
- const [_visible, setVisible] = useState(visible)
119
118
  const dropdownRef = useRef<HTMLDivElement>(null)
120
119
  const dropdownToggleRef = useRef(null)
121
120
  const forkedRef = useForkedRef(ref, dropdownRef)
121
+ const [_visible, setVisible] = useState(visible)
122
122
 
123
123
  const Component = variant === 'nav-item' ? 'li' : component
124
124
 
@@ -140,19 +140,6 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
140
140
  setVisible,
141
141
  }
142
142
 
143
- const _className = classNames(
144
- variant === 'nav-item' ? 'nav-item dropdown' : variant,
145
- {
146
- show: _visible,
147
- },
148
- direction === 'center'
149
- ? 'dropdown-center'
150
- : direction === 'dropup-center'
151
- ? 'dropup dropup-center'
152
- : direction,
153
- className,
154
- )
155
-
156
143
  useEffect(() => {
157
144
  setVisible(visible)
158
145
  }, [visible])
@@ -162,23 +149,38 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
162
149
  !_visible && onHide && onHide()
163
150
  }, [_visible])
164
151
 
165
- const dropdownContent = () => {
152
+ const DropdownContent = () => {
166
153
  return variant === 'input-group' ? (
167
154
  <>{children}</>
168
155
  ) : (
169
- <Component className={_className} {...rest} ref={forkedRef}>
156
+ <Component
157
+ className={classNames(
158
+ variant === 'nav-item' ? 'nav-item dropdown' : variant,
159
+ {
160
+ 'dropdown-center': direction === 'center',
161
+ 'dropup dropup-center': direction === 'dropup-center',
162
+ direction: direction && direction !== 'center' && direction !== 'dropup-center',
163
+ show: _visible,
164
+ },
165
+ className,
166
+ )}
167
+ {...rest}
168
+ ref={forkedRef}
169
+ >
170
170
  {children}
171
171
  </Component>
172
172
  )
173
173
  }
174
174
 
175
- return popper ? (
176
- <CDropdownContext.Provider value={contextValues}>
177
- <Manager>{dropdownContent()}</Manager>
178
- </CDropdownContext.Provider>
179
- ) : (
175
+ return (
180
176
  <CDropdownContext.Provider value={contextValues}>
181
- {dropdownContent()}
177
+ {popper ? (
178
+ <Manager>
179
+ <DropdownContent />
180
+ </Manager>
181
+ ) : (
182
+ <DropdownContent />
183
+ )}
182
184
  </CDropdownContext.Provider>
183
185
  )
184
186
  },
@@ -11,9 +11,7 @@ export interface CDropdownDividerProps extends HTMLAttributes<HTMLHRElement> {
11
11
 
12
12
  export const CDropdownDivider = forwardRef<HTMLHRElement, CDropdownDividerProps>(
13
13
  ({ className, ...rest }, ref) => {
14
- const _className = classNames('dropdown-divider', className)
15
-
16
- return <hr className={_className} {...rest} ref={ref} />
14
+ return <hr className={classNames('dropdown-divider', className)} {...rest} ref={ref} />
17
15
  },
18
16
  )
19
17
 
@@ -15,10 +15,8 @@ export interface CDropdownHeaderProps extends HTMLAttributes<HTMLHeadingElement>
15
15
 
16
16
  export const CDropdownHeader = forwardRef<HTMLHeadingElement, CDropdownHeaderProps>(
17
17
  ({ children, className, component: Component = 'h6', ...rest }, ref) => {
18
- const _className = classNames('dropdown-header', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('dropdown-header', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -17,10 +17,13 @@ export interface CDropdownItemProps extends CLinkProps {
17
17
 
18
18
  export const CDropdownItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, CDropdownItemProps>(
19
19
  ({ children, className, component = 'a', ...rest }, ref) => {
20
- const _className = classNames('dropdown-item', className)
21
-
22
20
  return (
23
- <CLink className={_className} component={component} {...rest} ref={ref}>
21
+ <CLink
22
+ className={classNames('dropdown-item', className)}
23
+ component={component}
24
+ {...rest}
25
+ ref={ref}
26
+ >
24
27
  {children}
25
28
  </CLink>
26
29
  )
@@ -15,10 +15,8 @@ export interface CDropdownItemPlainProps extends HTMLAttributes<HTMLSpanElement>
15
15
 
16
16
  export const CDropdownItemPlain = forwardRef<HTMLSpanElement, CDropdownItemPlainProps>(
17
17
  ({ children, className, component: Component = 'span', ...rest }, ref) => {
18
- const _className = classNames('dropdown-item-text', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('dropdown-item-text', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -126,39 +126,35 @@ export const CDropdownMenu: FC<CDropdownMenuProps> = ({
126
126
  return classNames
127
127
  }
128
128
 
129
- const _className = classNames(
130
- 'dropdown-menu',
131
- {
132
- 'dropdown-menu-dark': dark,
133
- show: visible,
134
- },
135
- alignment && alignmentClassNames(alignment),
136
- className,
129
+ const dropdownMenuComponent = (style?: React.CSSProperties, ref?: React.Ref<HTMLDivElement>) => (
130
+ <Component
131
+ className={classNames(
132
+ 'dropdown-menu',
133
+ {
134
+ 'dropdown-menu-dark': dark,
135
+ show: visible,
136
+ },
137
+ alignment && alignmentClassNames(alignment),
138
+ className,
139
+ )}
140
+ ref={ref}
141
+ style={style}
142
+ role="menu"
143
+ aria-hidden={!visible}
144
+ {...(!popper && { 'data-coreui-popper': 'static' })}
145
+ {...rest}
146
+ >
147
+ {Component === 'ul'
148
+ ? React.Children.map(children, (child, index) => {
149
+ if (React.isValidElement(child)) {
150
+ return <li key={index}>{React.cloneElement(child)}</li>
151
+ }
152
+ return
153
+ })
154
+ : children}
155
+ </Component>
137
156
  )
138
157
 
139
- const dropdownMenuComponent = (style?: React.CSSProperties, ref?: React.Ref<HTMLDivElement>) => {
140
- return (
141
- <Component
142
- className={_className}
143
- ref={ref}
144
- style={style}
145
- role="menu"
146
- aria-hidden={!visible}
147
- {...(!popper && { 'data-coreui-popper': 'static' })}
148
- {...rest}
149
- >
150
- {Component === 'ul'
151
- ? React.Children.map(children, (child, index) => {
152
- if (React.isValidElement(child)) {
153
- return <li key={index}>{React.cloneElement(child)}</li>
154
- }
155
- return
156
- })
157
- : children}
158
- </Component>
159
- )
160
- }
161
-
162
158
  return popper && visible ? (
163
159
  <Popper innerRef={dropdownMenuRef} placement={_placement}>
164
160
  {({ ref, style }) => dropdownMenuComponent(style, ref)}
@@ -42,14 +42,6 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
42
42
  ...rest
43
43
  }) => {
44
44
  const { dropdownToggleRef, popper, variant, visible, setVisible } = useContext(CDropdownContext)
45
- const _className = classNames(
46
- {
47
- 'dropdown-toggle': caret,
48
- 'dropdown-toggle-split': split,
49
- 'nav-link': variant === 'nav-item',
50
- },
51
- className,
52
- )
53
45
 
54
46
  const triggers = {
55
47
  ...((trigger === 'click' || trigger.includes('click')) && {
@@ -65,28 +57,42 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
65
57
  }
66
58
 
67
59
  const togglerProps = {
68
- className: _className,
60
+ className: classNames(
61
+ {
62
+ 'dropdown-toggle': caret,
63
+ 'dropdown-toggle-split': split,
64
+ 'nav-link': variant === 'nav-item',
65
+ },
66
+ className,
67
+ ),
69
68
  'aria-expanded': visible,
70
69
  ...(!rest.disabled && { ...triggers }),
71
- ...triggers,
72
70
  }
73
71
 
74
72
  // We use any because Toggler can be `a` as well as `button`.
75
73
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
74
  const Toggler = (ref?: React.Ref<any>) => {
77
- return custom && React.isValidElement(children) ? (
78
- <>
79
- {React.cloneElement(children as React.ReactElement<any>, {
80
- 'aria-expanded': visible,
81
- ...(!rest.disabled && { ...triggers }),
82
- ref: useForkedRef(ref, dropdownToggleRef),
83
- })}
84
- </>
85
- ) : variant === 'nav-item' ? (
86
- <a href="#" {...togglerProps} ref={useForkedRef(ref, dropdownToggleRef)}>
87
- {children}
88
- </a>
89
- ) : (
75
+ if (custom && React.isValidElement(children)) {
76
+ return (
77
+ <>
78
+ {React.cloneElement(children as React.ReactElement<any>, {
79
+ 'aria-expanded': visible,
80
+ ...(!rest.disabled && { ...triggers }),
81
+ ref: useForkedRef(ref, dropdownToggleRef),
82
+ })}
83
+ </>
84
+ )
85
+ }
86
+
87
+ if (variant === 'nav-item') {
88
+ return (
89
+ <a href="#" {...togglerProps} ref={useForkedRef(ref, dropdownToggleRef)}>
90
+ {children}
91
+ </a>
92
+ )
93
+ }
94
+
95
+ return (
90
96
  <CButton
91
97
  type="button"
92
98
  {...togglerProps}
@@ -54,7 +54,6 @@ test('CDropdown change visible prop', async () => {
54
54
  })
55
55
 
56
56
  test('CDropdown click', async () => {
57
- jest.useFakeTimers()
58
57
  render(
59
58
  <CDropdown>
60
59
  <CDropdownToggle>Test</CDropdownToggle>
@@ -71,10 +70,9 @@ test('CDropdown click', async () => {
71
70
  }
72
71
  jest.runAllTimers()
73
72
  expect(screen.getByText('Test').closest('div')).toHaveClass('show')
74
- fireEvent.click(document) //click outside
73
+ fireEvent.mouseUp(document.body) //click outside
74
+ await new Promise((r) => setTimeout(r, 1000))
75
75
  expect(screen.getByText('Test').closest('div')).not.toHaveClass('show')
76
- jest.runAllTimers()
77
- jest.useRealTimers()
78
76
  })
79
77
 
80
78
  test('CDropdown example', async () => {
@@ -3,7 +3,7 @@
3
3
  exports[`CDropdown customize 1`] = `
4
4
  <div>
5
5
  <li
6
- class="nav-item dropdown show dropstart bazinga"
6
+ class="nav-item dropdown dropstart show bazinga"
7
7
  >
8
8
  Test
9
9
  </li>
@@ -15,10 +15,12 @@ export interface CFooterProps extends HTMLAttributes<HTMLDivElement> {
15
15
 
16
16
  export const CFooter = forwardRef<HTMLDivElement, CFooterProps>(
17
17
  ({ children, className, position, ...rest }, ref) => {
18
- const _className = classNames('footer', { [`footer-${position}`]: position }, className)
19
-
20
18
  return (
21
- <div className={_className} {...rest} ref={ref}>
19
+ <div
20
+ className={classNames('footer', { [`footer-${position}`]: position }, className)}
21
+ {...rest}
22
+ ref={ref}
23
+ >
22
24
  {children}
23
25
  </div>
24
26
  )
@@ -15,9 +15,12 @@ export interface CFormProps extends FormHTMLAttributes<HTMLFormElement> {
15
15
 
16
16
  export const CForm = forwardRef<HTMLFormElement, CFormProps>(
17
17
  ({ children, className, validated, ...rest }, ref) => {
18
- const _className = classNames({ 'was-validated': validated }, className)
19
18
  return (
20
- <form className={_className} {...rest} ref={ref}>
19
+ <form
20
+ className={classNames({ 'was-validated': validated }, className) || undefined}
21
+ {...rest}
22
+ ref={ref}
23
+ >
21
24
  {children}
22
25
  </form>
23
26
  )