@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
@@ -22,10 +22,8 @@ export const CHeaderBrand = forwardRef<
22
22
  HTMLAnchorElement | HTMLLinkElement | HTMLSpanElement,
23
23
  CHeaderBrandProps
24
24
  >(({ children, component: Component = 'a', className, ...rest }, ref) => {
25
- const _className = classNames('header-brand', className)
26
-
27
25
  return (
28
- <Component className={_className} {...rest} ref={ref}>
26
+ <Component className={classNames('header-brand', className)} {...rest} ref={ref}>
29
27
  {children}
30
28
  </Component>
31
29
  )
@@ -16,10 +16,8 @@ export interface CHeaderBrandProps
16
16
 
17
17
  export const CHeaderBrand = forwardRef<HTMLAnchorElement | HTMLSpanElement, CHeaderBrandProps>(
18
18
  ({ children, component: Component = 'a', className, ...rest }, ref) => {
19
- const _className = classNames('header-brand', className)
20
-
21
19
  return (
22
- <Component className={_className} {...rest} ref={ref}>
20
+ <Component className={classNames('header-brand', className)} {...rest} ref={ref}>
23
21
  {children}
24
22
  </Component>
25
23
  )
@@ -11,9 +11,7 @@ export interface CHeaderDividerProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const CHeaderDivider = forwardRef<HTMLDivElement, CHeaderDividerProps>(
13
13
  ({ className, ...rest }, ref) => {
14
- const _className = classNames('header-divider', className)
15
-
16
- return <div className={_className} {...rest} ref={ref} />
14
+ return <div className={classNames('header-divider', className)} {...rest} ref={ref} />
17
15
  },
18
16
  )
19
17
 
@@ -15,10 +15,13 @@ export interface CHeaderNavProps extends HTMLAttributes<HTMLDivElement | HTMLULi
15
15
 
16
16
  export const CHeaderNav = forwardRef<HTMLDivElement | HTMLUListElement, CHeaderNavProps>(
17
17
  ({ children, component: Component = 'ul', className, ...rest }, ref) => {
18
- const _className = classNames('header-nav', className)
19
-
20
18
  return (
21
- <Component className={_className} role="navigation" {...rest} ref={ref}>
19
+ <Component
20
+ className={classNames('header-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 CHeaderTextProps extends HTMLAttributes<HTMLSpanElement> {
11
11
 
12
12
  export const CHeaderText = forwardRef<HTMLSpanElement, CHeaderTextProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('header-text', className)
15
-
16
14
  return (
17
- <span className={_className} {...rest} ref={ref}>
15
+ <span className={classNames('header-text', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </span>
20
18
  )
@@ -11,11 +11,9 @@ export interface CHeaderTogglerProps extends HTMLAttributes<HTMLButtonElement> {
11
11
 
12
12
  export const CHeaderToggler = forwardRef<HTMLButtonElement, CHeaderTogglerProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('header-toggler', className)
15
-
16
14
  return (
17
- <button type="button" className={_className} {...rest} ref={ref}>
18
- {children ? children : <span className="header-toggler-icon"></span>}
15
+ <button type="button" className={classNames('header-toggler', className)} {...rest} ref={ref}>
16
+ {children ?? <span className="header-toggler-icon"></span>}
19
17
  </button>
20
18
  )
21
19
  },
@@ -27,17 +27,24 @@ export interface CImageProps extends ImgHTMLAttributes<HTMLOrSVGImageElement> {
27
27
 
28
28
  export const CImage = forwardRef<HTMLImageElement, CImageProps>(
29
29
  ({ align, className, fluid, rounded, thumbnail, ...rest }, ref) => {
30
- const _className = classNames(
31
- {
32
- [`float-${align}`]: align && (align === 'start' || align === 'end'),
33
- 'd-block mx-auto': align && align === 'center',
34
- 'img-fluid': fluid,
35
- rounded: rounded,
36
- 'img-thumbnail': thumbnail,
37
- },
38
- className,
30
+ return (
31
+ <img
32
+ className={
33
+ classNames(
34
+ {
35
+ [`float-${align}`]: align && (align === 'start' || align === 'end'),
36
+ 'd-block mx-auto': align && align === 'center',
37
+ 'img-fluid': fluid,
38
+ rounded: rounded,
39
+ 'img-thumbnail': thumbnail,
40
+ },
41
+ className,
42
+ ) || undefined
43
+ }
44
+ {...rest}
45
+ ref={ref}
46
+ />
39
47
  )
40
- return <img className={_className} {...rest} ref={ref} />
41
48
  },
42
49
  )
43
50
 
@@ -18,8 +18,6 @@ exports[`CImage customize two 1`] = `
18
18
 
19
19
  exports[`loads and displays CImage component 1`] = `
20
20
  <div>
21
- <img
22
- class=""
23
- />
21
+ <img />
24
22
  </div>
25
23
  `;
@@ -11,6 +11,7 @@ export * from './card'
11
11
  export * from './carousel'
12
12
  export * from './close-button'
13
13
  export * from './collapse'
14
+ export * from './conditional-portal'
14
15
  export * from './date-picker'
15
16
  export * from './date-range-picker'
16
17
  export * from './dropdown'
@@ -27,12 +27,10 @@ export interface CLinkProps extends AllHTMLAttributes<HTMLButtonElement | HTMLAn
27
27
 
28
28
  export const CLink = forwardRef<HTMLButtonElement | HTMLAnchorElement, CLinkProps>(
29
29
  ({ children, active, className, component: Component = 'a', disabled, ...rest }, ref) => {
30
- // TODO: remove duplicated classes ex. `active active` in `<CListGroupItem>`
31
- const _className = classNames(className, { active, disabled })
32
-
33
30
  return (
34
31
  <Component
35
- className={_className}
32
+ // TODO: remove duplicated classes ex. `active active` in `<CListGroupItem>`
33
+ className={classNames(className, { active, disabled })}
36
34
  {...(active && { 'aria-current': 'page' })}
37
35
  {...(Component === 'a' && disabled && { 'aria-disabled': true, tabIndex: -1 })}
38
36
  {...((Component === 'a' || Component === 'button') && {
@@ -29,17 +29,18 @@ export interface CListGroupProps extends HTMLAttributes<HTMLDivElement | HTMLULi
29
29
 
30
30
  export const CListGroup = forwardRef<HTMLDivElement | HTMLUListElement, CListGroupProps>(
31
31
  ({ children, className, component: Component = 'ul', flush, layout }, ref) => {
32
- const _className = classNames(
33
- 'list-group',
34
- {
35
- 'list-group-flush': flush,
36
- [`list-group-${layout}`]: layout,
37
- },
38
- className,
39
- )
40
-
41
32
  return (
42
- <Component className={_className} ref={ref}>
33
+ <Component
34
+ className={classNames(
35
+ 'list-group',
36
+ {
37
+ 'list-group-flush': flush,
38
+ [`list-group-${layout}`]: layout,
39
+ },
40
+ className,
41
+ )}
42
+ ref={ref}
43
+ >
43
44
  {children}
44
45
  </Component>
45
46
  )
@@ -37,17 +37,6 @@ export const CListGroupItem = forwardRef<
37
37
  HTMLLIElement | HTMLAnchorElement | HTMLButtonElement,
38
38
  CListGroupItemProps
39
39
  >(({ children, active, className, disabled, color, component = 'li', ...rest }, ref) => {
40
- const _className = classNames(
41
- 'list-group-item',
42
- {
43
- [`list-group-item-${color}`]: color,
44
- 'list-group-item-action': component === 'a' || component === 'button',
45
- active,
46
- disabled,
47
- },
48
- className,
49
- )
50
-
51
40
  const Component = component === 'a' || component === 'button' ? CLink : component
52
41
 
53
42
  rest = {
@@ -63,7 +52,19 @@ export const CListGroupItem = forwardRef<
63
52
  }
64
53
 
65
54
  return (
66
- <Component className={_className} {...rest}>
55
+ <Component
56
+ className={classNames(
57
+ 'list-group-item',
58
+ {
59
+ [`list-group-item-${color}`]: color,
60
+ 'list-group-item-action': component === 'a' || component === 'button',
61
+ active,
62
+ disabled,
63
+ },
64
+ className,
65
+ )}
66
+ {...rest}
67
+ >
67
68
  {children}
68
69
  </Component>
69
70
  )
@@ -60,11 +60,9 @@ export const CLoadingButton = forwardRef<HTMLButtonElement, CLoadingButtonProps>
60
60
  }
61
61
  }
62
62
 
63
- const _className = classNames('btn-loading', _loading && 'is-loading', className)
64
-
65
63
  return (
66
64
  <CButton
67
- className={_className}
65
+ className={classNames('btn-loading', _loading && 'is-loading', className)}
68
66
  {...(disabledOnLoading && _loading && { disabled: true })}
69
67
  onClick={handleOnClick}
70
68
  {...rest}
@@ -2,18 +2,17 @@ import React, {
2
2
  createContext,
3
3
  forwardRef,
4
4
  HTMLAttributes,
5
- useCallback,
6
5
  useEffect,
7
6
  useLayoutEffect,
8
7
  useRef,
9
8
  useState,
10
9
  } from 'react'
11
- import { createPortal } from 'react-dom'
12
10
  import PropTypes from 'prop-types'
13
11
  import classNames from 'classnames'
14
12
  import { Transition } from 'react-transition-group'
15
13
 
16
14
  import { CBackdrop } from '../backdrop/CBackdrop'
15
+ import { CConditionalPortal } from '../conditional-portal'
17
16
  import { CModalContent } from './CModalContent'
18
17
  import { CModalDialog } from './CModalDialog'
19
18
 
@@ -119,22 +118,22 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
119
118
  const [_visible, setVisible] = useState(visible)
120
119
  const [staticBackdrop, setStaticBackdrop] = useState(false)
121
120
 
122
- useEffect(() => {
123
- setVisible(visible)
124
- }, [visible])
125
-
126
121
  const contextValues = {
127
122
  visible: _visible,
128
123
  setVisible,
129
124
  }
130
125
 
131
126
  useEffect(() => {
132
- modalRef.current && modalRef.current.addEventListener('click', handleClickOutside)
133
- modalRef.current && modalRef.current.addEventListener('keyup', handleKeyDown)
127
+ setVisible(visible)
128
+ }, [visible])
129
+
130
+ useEffect(() => {
131
+ document.addEventListener('click', handleClickOutside)
132
+ document.addEventListener('keydown', handleKeyDown)
134
133
 
135
134
  return () => {
136
- modalRef.current && modalRef.current.removeEventListener('click', handleClickOutside)
137
- modalRef.current && modalRef.current.removeEventListener('keyup', handleKeyDown)
135
+ document.removeEventListener('click', handleClickOutside)
136
+ document.removeEventListener('keydown', handleKeyDown)
138
137
  }
139
138
  }, [_visible])
140
139
 
@@ -142,6 +141,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
142
141
  if (backdrop === 'static') {
143
142
  return setStaticBackdrop(true)
144
143
  }
144
+
145
145
  return onClose && onClose()
146
146
  }
147
147
 
@@ -150,24 +150,6 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
150
150
  setTimeout(() => setStaticBackdrop(false), duration)
151
151
  }, [staticBackdrop])
152
152
 
153
- const getTransitionClass = (state: string) => {
154
- return state === 'entering'
155
- ? 'd-block'
156
- : state === 'entered'
157
- ? 'show d-block'
158
- : state === 'exiting'
159
- ? 'd-block'
160
- : ''
161
- }
162
- const _className = classNames(
163
- 'modal',
164
- {
165
- 'modal-static': staticBackdrop,
166
- fade: transition,
167
- },
168
- className,
169
- )
170
-
171
153
  // Set focus to modal after open
172
154
  useLayoutEffect(() => {
173
155
  if (_visible) {
@@ -182,7 +164,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
182
164
  () => {
183
165
  modalRef.current?.focus()
184
166
  },
185
- !transition ? 0 : duration,
167
+ transition ? duration : 0,
186
168
  )
187
169
  } else {
188
170
  document.body.classList.remove('modal-open')
@@ -210,37 +192,10 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
210
192
  }
211
193
  }
212
194
 
213
- const handleKeyDown = useCallback(
214
- (event: KeyboardEvent) => {
215
- if (event.key === 'Escape' && keyboard) {
216
- return handleDismiss()
217
- }
218
- },
219
- [modalRef, handleDismiss],
220
- )
221
-
222
- const modal = (ref?: React.Ref<HTMLDivElement>, transitionClass?: string) => {
223
- return (
224
- <CModalContext.Provider value={contextValues}>
225
- <div
226
- className={classNames(_className, transitionClass)}
227
- tabIndex={-1}
228
- role="dialog"
229
- ref={ref}
230
- >
231
- <CModalDialog
232
- alignment={alignment}
233
- fullscreen={fullscreen}
234
- scrollable={scrollable}
235
- size={size}
236
- >
237
- <CModalContent {...rest} ref={modalContentRef}>
238
- {children}
239
- </CModalContent>
240
- </CModalDialog>
241
- </div>
242
- </CModalContext.Provider>
243
- )
195
+ const handleKeyDown = (event: KeyboardEvent) => {
196
+ if (event.key === 'Escape' && keyboard) {
197
+ handleDismiss()
198
+ }
244
199
  }
245
200
 
246
201
  return (
@@ -252,18 +207,48 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
252
207
  onEnter={onShow}
253
208
  onExit={onClose}
254
209
  unmountOnExit={unmountOnClose}
255
- timeout={!transition ? 0 : duration}
210
+ timeout={transition ? duration : 0}
256
211
  >
257
- {(state) => {
258
- const transitionClass = getTransitionClass(state)
259
- return typeof window !== 'undefined' && portal
260
- ? createPortal(modal(forkedRef, transitionClass), document.body)
261
- : modal(forkedRef, transitionClass)
262
- }}
212
+ {(state) => (
213
+ <CConditionalPortal portal={portal}>
214
+ <CModalContext.Provider value={contextValues}>
215
+ <div
216
+ className={classNames(
217
+ 'modal',
218
+ {
219
+ 'modal-static': staticBackdrop,
220
+ fade: transition,
221
+ show: state === 'entered',
222
+ },
223
+ className,
224
+ )}
225
+ tabIndex={-1}
226
+ role="dialog"
227
+ style={{
228
+ ...(state !== 'exited' && { display: 'block' }),
229
+ }}
230
+ ref={forkedRef}
231
+ >
232
+ <CModalDialog
233
+ alignment={alignment}
234
+ fullscreen={fullscreen}
235
+ scrollable={scrollable}
236
+ size={size}
237
+ >
238
+ <CModalContent {...rest} ref={modalContentRef}>
239
+ {children}
240
+ </CModalContent>
241
+ </CModalDialog>
242
+ </div>
243
+ </CModalContext.Provider>
244
+ </CConditionalPortal>
245
+ )}
263
246
  </Transition>
264
- {typeof window !== 'undefined' && portal
265
- ? backdrop && createPortal(<CBackdrop visible={_visible} />, document.body)
266
- : backdrop && <CBackdrop visible={_visible} />}
247
+ {backdrop && (
248
+ <CConditionalPortal portal={portal}>
249
+ <CBackdrop visible={_visible} />
250
+ </CConditionalPortal>
251
+ )}
267
252
  </>
268
253
  )
269
254
  },
@@ -11,10 +11,8 @@ export interface CModalBodyProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const CModalBody = forwardRef<HTMLDivElement, CModalBodyProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('modal-body', className)
15
-
16
14
  return (
17
- <div className={_className} {...rest} ref={ref}>
15
+ <div className={classNames('modal-body', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </div>
20
18
  )
@@ -11,10 +11,8 @@ export interface CModalContentProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const CModalContent = forwardRef<HTMLDivElement, CModalContentProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('modal-content', className)
15
-
16
14
  return (
17
- <div className={_className} {...rest} ref={ref}>
15
+ <div className={classNames('modal-content', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </div>
20
18
  )
@@ -27,21 +27,23 @@ export interface CModalDialogProps extends HTMLAttributes<HTMLDivElement> {
27
27
 
28
28
  export const CModalDialog = forwardRef<HTMLDivElement, CModalDialogProps>(
29
29
  ({ children, alignment, className, fullscreen, scrollable, size, ...rest }, ref) => {
30
- const _className = classNames(
31
- 'modal-dialog',
32
- {
33
- 'modal-dialog-centered': alignment === 'center',
34
- [typeof fullscreen === 'boolean'
35
- ? 'modal-fullscreen'
36
- : `modal-fullscreen-${fullscreen}-down`]: fullscreen,
37
- 'modal-dialog-scrollable': scrollable,
38
- [`modal-${size}`]: size,
39
- },
40
- className,
41
- )
42
-
43
30
  return (
44
- <div className={_className} {...rest} ref={ref}>
31
+ <div
32
+ className={classNames(
33
+ 'modal-dialog',
34
+ {
35
+ 'modal-dialog-centered': alignment === 'center',
36
+ [typeof fullscreen === 'boolean'
37
+ ? 'modal-fullscreen'
38
+ : `modal-fullscreen-${fullscreen}-down`]: fullscreen,
39
+ 'modal-dialog-scrollable': scrollable,
40
+ [`modal-${size}`]: size,
41
+ },
42
+ className,
43
+ )}
44
+ {...rest}
45
+ ref={ref}
46
+ >
45
47
  {children}
46
48
  </div>
47
49
  )
@@ -11,10 +11,8 @@ export interface CModalFooterProps extends HTMLAttributes<HTMLDivElement> {
11
11
 
12
12
  export const CModalFooter = forwardRef<HTMLDivElement, CModalFooterProps>(
13
13
  ({ children, className, ...rest }, ref) => {
14
- const _className = classNames('modal-footer', className)
15
-
16
14
  return (
17
- <div className={_className} {...rest} ref={ref}>
15
+ <div className={classNames('modal-footer', className)} {...rest} ref={ref}>
18
16
  {children}
19
17
  </div>
20
18
  )
@@ -19,10 +19,9 @@ export interface CModalHeaderProps extends HTMLAttributes<HTMLDivElement> {
19
19
  export const CModalHeader = forwardRef<HTMLDivElement, CModalHeaderProps>(
20
20
  ({ children, className, closeButton = true, ...rest }, ref) => {
21
21
  const { setVisible } = useContext(CModalContext)
22
- const _className = classNames('modal-header', className)
23
22
 
24
23
  return (
25
- <div className={_className} {...rest} ref={ref}>
24
+ <div className={classNames('modal-header', className)} {...rest} ref={ref}>
26
25
  {children}
27
26
  {closeButton && <CCloseButton onClick={() => setVisible(false)} />}
28
27
  </div>
@@ -15,10 +15,8 @@ export interface CModalTitleProps extends HTMLAttributes<HTMLHeadingElement> {
15
15
 
16
16
  export const CModalTitle = forwardRef<HTMLHeadElement, CModalTitleProps>(
17
17
  ({ children, component: Component = 'h5', className, ...rest }, ref) => {
18
- const _className = classNames('modal-title', className)
19
-
20
18
  return (
21
- <Component className={_className} {...rest} ref={ref}>
19
+ <Component className={classNames('modal-title', className)} {...rest} ref={ref}>
22
20
  {children}
23
21
  </Component>
24
22
  )
@@ -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>