@coreui/react-pro 4.9.0-next.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/alert/CAlert.d.ts +1 -1
- package/dist/components/avatar/CAvatar.d.ts +1 -1
- package/dist/components/badge/CBadge.d.ts +1 -1
- package/dist/components/button/CButton.d.ts +1 -1
- package/dist/components/calendar/utils.d.ts +0 -1
- package/dist/components/callout/CCallout.d.ts +1 -1
- package/dist/components/card/CCard.d.ts +1 -1
- package/dist/components/conditional-portal/CConditionalPortal.d.ts +12 -0
- package/dist/components/conditional-portal/index.d.ts +2 -0
- package/dist/components/date-range-picker/CDateRangePicker.d.ts +1 -1
- package/dist/components/date-range-picker/utils.d.ts +1 -0
- package/dist/components/dropdown/CDropdown.d.ts +1 -1
- package/dist/components/dropdown/CDropdownToggle.d.ts +1 -1
- package/dist/components/form/CFormCheck.d.ts +8 -2
- package/dist/components/form/CFormSwitch.d.ts +6 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/list-group/CListGroupItem.d.ts +4 -5
- package/dist/components/multi-select/CMultiSelect.d.ts +1 -13
- package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
- package/dist/components/multi-select/CMultiSelectOptions.d.ts +1 -1
- package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
- package/dist/components/multi-select/types.d.ts +14 -0
- package/dist/components/multi-select/utils.d.ts +6 -0
- package/dist/components/navbar/CNavbar.d.ts +1 -1
- package/dist/components/picker/CPicker.d.ts +1 -1
- package/dist/components/placeholder/CPlaceholder.d.ts +1 -1
- package/dist/components/popover/CPopover.d.ts +1 -1
- package/dist/components/progress/CProgressBar.d.ts +1 -1
- package/dist/components/smart-table/CSmartTableHead.d.ts +1 -1
- package/dist/components/smart-table/CSmartTableInterface.d.ts +8 -0
- package/dist/components/smart-table/types.d.ts +1 -1
- package/dist/components/spinner/CSpinner.d.ts +1 -1
- package/dist/components/table/CTable.d.ts +2 -18
- package/dist/components/table/CTableBody.d.ts +1 -1
- package/dist/components/table/CTableDataCell.d.ts +1 -1
- package/dist/components/table/CTableFoot.d.ts +1 -1
- package/dist/components/table/CTableHead.d.ts +1 -1
- package/dist/components/table/CTableHeaderCell.d.ts +1 -1
- package/dist/components/table/CTableResponsiveWrapper.d.ts +0 -1
- package/dist/components/table/CTableRow.d.ts +1 -1
- package/dist/components/table/types.d.ts +17 -0
- package/dist/components/table/utils.d.ts +5 -0
- package/dist/components/toast/CToast.d.ts +1 -1
- package/dist/components/toast/CToastClose.d.ts +1 -1
- package/dist/components/tooltip/CTooltip.d.ts +1 -1
- package/dist/components/virtual-scroller/CVirtualScroller.d.ts +0 -8
- package/dist/components/widgets/CWidgetStatsA.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsB.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsC.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsD.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsF.d.ts +1 -1
- package/dist/index.es.js +696 -927
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +695 -925
- package/dist/index.js.map +1 -1
- package/dist/props.d.ts +8 -0
- package/dist/types.d.ts +7 -0
- package/dist/utils/index.d.ts +1 -3
- package/package.json +11 -6
- package/src/components/accordion/CAccordion.tsx +7 -3
- package/src/components/accordion/CAccordionBody.tsx +2 -2
- package/src/components/accordion/CAccordionButton.tsx +1 -3
- package/src/components/accordion/CAccordionCollapse.tsx +1 -0
- package/src/components/accordion/CAccordionHeader.tsx +1 -3
- package/src/components/accordion/CAccordionItem.tsx +2 -4
- package/src/components/accordion/__tests__/__snapshots__/CAccordionBody.spec.tsx.snap +2 -2
- package/src/components/alert/CAlert.tsx +21 -28
- package/src/components/alert/CAlertHeading.tsx +1 -3
- package/src/components/alert/CAlertLink.tsx +1 -3
- package/src/components/alert/__tests__/__snapshots__/CAlert.spec.tsx.snap +1 -1
- package/src/components/avatar/CAvatar.tsx +16 -19
- package/src/components/backdrop/CBackdrop.tsx +10 -13
- package/src/components/badge/CBadge.tsx +21 -27
- package/src/components/breadcrumb/CBreadcrumb.tsx +1 -2
- package/src/components/breadcrumb/CBreadcrumbItem.tsx +12 -8
- package/src/components/button/CButton.tsx +10 -10
- package/src/components/button-group/CButtonGroup.tsx +9 -7
- package/src/components/button-group/CButtonToolbar.tsx +1 -3
- package/src/components/calendar/utils.ts +7 -55
- package/src/components/callout/CCallout.tsx +13 -10
- package/src/components/card/CCard.tsx +14 -11
- package/src/components/card/CCardBody.tsx +1 -3
- package/src/components/card/CCardFooter.tsx +1 -3
- package/src/components/card/CCardGroup.tsx +1 -3
- package/src/components/card/CCardHeader.tsx +1 -3
- package/src/components/card/CCardImage.tsx +5 -3
- package/src/components/card/CCardImageOverlay.tsx +1 -3
- package/src/components/card/CCardLink.tsx +1 -3
- package/src/components/card/CCardSubtitle.tsx +1 -3
- package/src/components/card/CCardText.tsx +1 -3
- package/src/components/card/CCardTitle.tsx +1 -3
- package/src/components/carousel/CCarousel.tsx +8 -8
- package/src/components/carousel/CCarouselCaption.tsx +1 -3
- package/src/components/carousel/CCarouselItem.tsx +11 -9
- package/src/components/close-button/CCloseButton.tsx +9 -10
- package/src/components/collapse/CCollapse.tsx +8 -20
- package/src/components/collapse/__tests__/CCollapse.spec.tsx +2 -3
- package/src/components/conditional-portal/CConditionalPortal.tsx +29 -0
- package/src/components/conditional-portal/index.ts +3 -0
- package/src/components/date-range-picker/CDateRangePicker.tsx +11 -13
- package/src/components/date-range-picker/utils.ts +49 -0
- package/src/components/dropdown/CDropdown.tsx +26 -23
- package/src/components/dropdown/CDropdownDivider.tsx +1 -3
- package/src/components/dropdown/CDropdownHeader.tsx +1 -3
- package/src/components/dropdown/CDropdownItem.tsx +7 -5
- package/src/components/dropdown/CDropdownItemPlain.tsx +1 -3
- package/src/components/dropdown/CDropdownMenu.tsx +29 -32
- package/src/components/dropdown/CDropdownToggle.tsx +34 -27
- package/src/components/dropdown/__tests__/CDropdown.spec.tsx +2 -4
- package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
- package/src/components/footer/CFooter.tsx +5 -3
- package/src/components/form/CForm.tsx +5 -2
- package/src/components/form/CFormCheck.tsx +90 -66
- package/src/components/form/CFormControlValidation.tsx +0 -1
- package/src/components/form/CFormControlWrapper.tsx +3 -4
- package/src/components/form/CFormFeedback.tsx +11 -8
- package/src/components/form/CFormFloating.tsx +1 -2
- package/src/components/form/CFormInput.tsx +18 -16
- package/src/components/form/CFormLabel.tsx +1 -2
- package/src/components/form/CFormRange.tsx +2 -4
- package/src/components/form/CFormSelect.tsx +16 -12
- package/src/components/form/CFormSwitch.tsx +31 -20
- package/src/components/form/CFormText.tsx +1 -2
- package/src/components/form/CFormTextarea.tsx +14 -11
- package/src/components/form/CInputGroup.tsx +11 -8
- package/src/components/form/CInputGroupText.tsx +1 -2
- package/src/components/form/__tests__/CFormRange.spec.tsx +1 -1
- package/src/components/form/__tests__/__snapshots__/CForm.spec.tsx.snap +2 -6
- package/src/components/form/__tests__/__snapshots__/CFormRange.spec.tsx.snap +2 -2
- package/src/components/grid/CCol.tsx +8 -6
- package/src/components/grid/CContainer.tsx +8 -6
- package/src/components/grid/CRow.tsx +4 -3
- package/src/components/header/CHeader.tsx +12 -13
- package/src/components/header/CHeaderBrand.tsx +1 -3
- package/src/components/header/CHeaderBrand.tsx~HEAD +1 -3
- package/src/components/header/CHeaderDivider.tsx +1 -3
- package/src/components/header/CHeaderNav.tsx +6 -3
- package/src/components/header/CHeaderText.tsx +1 -3
- package/src/components/header/CHeaderToggler.tsx +2 -4
- package/src/components/image/CImage.tsx +17 -10
- package/src/components/image/__tests__/__snapshots__/CImage.spec.tsx.snap +1 -3
- package/src/components/index.ts +1 -0
- package/src/components/link/CLink.tsx +2 -4
- package/src/components/list-group/CListGroup.tsx +11 -10
- package/src/components/list-group/CListGroupItem.tsx +21 -20
- package/src/components/list-group/CListGroupItem.tsx~HEAD +3 -1
- package/src/components/loading-button/CLoadingButton.tsx +1 -3
- package/src/components/modal/CModal.tsx +57 -72
- package/src/components/modal/CModalBody.tsx +1 -3
- package/src/components/modal/CModalContent.tsx +1 -3
- package/src/components/modal/CModalDialog.tsx +16 -14
- package/src/components/modal/CModalFooter.tsx +1 -3
- package/src/components/modal/CModalHeader.tsx +4 -4
- package/src/components/modal/CModalTitle.tsx +1 -3
- package/src/components/modal/__tests__/CModal.spec.tsx +19 -20
- package/src/components/multi-select/CMultiSelect.tsx +34 -93
- package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
- package/src/components/multi-select/CMultiSelectOptions.tsx +2 -2
- package/src/components/multi-select/CMultiSelectSelection.tsx +1 -1
- package/src/components/multi-select/types.ts +15 -0
- package/src/components/multi-select/utils.ts +92 -0
- package/src/components/nav/CNav.tsx +13 -10
- package/src/components/nav/CNavGroup.tsx +1 -3
- package/src/components/nav/CNavGroupItems.tsx +1 -2
- package/src/components/nav/CNavItem.tsx +9 -10
- package/src/components/nav/CNavLink.tsx +4 -5
- package/src/components/nav/CNavTitle.tsx +1 -2
- package/src/components/navbar/CNavbar.tsx +23 -23
- package/src/components/navbar/CNavbarBrand.tsx +2 -3
- package/src/components/navbar/CNavbarNav.tsx +6 -3
- package/src/components/navbar/CNavbarText.tsx +1 -3
- package/src/components/navbar/CNavbarToggler.tsx +2 -4
- package/src/components/offcanvas/COffcanvas.tsx +42 -68
- package/src/components/offcanvas/COffcanvasBody.tsx +1 -3
- package/src/components/offcanvas/COffcanvasHeader.tsx +1 -3
- package/src/components/offcanvas/COffcanvasTitle.tsx +1 -3
- package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +7 -2
- package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +9 -4
- package/src/components/pagination/CPagination.tsx +12 -9
- package/src/components/pagination/CPaginationItem.tsx +12 -11
- package/src/components/pagination/__tests__/CPagination.spec.tsx +3 -3
- package/src/components/pagination/__tests__/CPaginationItem.spec.tsx +3 -3
- package/src/components/picker/CPicker.tsx +7 -7
- package/src/components/placeholder/CPlaceholder.tsx +15 -12
- package/src/components/popover/CPopover.tsx +24 -34
- package/src/components/progress/CProgress.tsx +13 -10
- package/src/components/progress/CProgressBar.tsx +11 -12
- package/src/components/sidebar/CSidebar.tsx +22 -19
- package/src/components/sidebar/CSidebarBrand.tsx +1 -2
- package/src/components/sidebar/CSidebarFooter.tsx +1 -2
- package/src/components/sidebar/CSidebarHeader.tsx +1 -2
- package/src/components/sidebar/CSidebarNav.tsx +2 -2
- package/src/components/sidebar/CSidebarToggler.tsx +1 -2
- package/src/components/smart-pagination/CSmartPagination.tsx +22 -20
- package/src/components/smart-table/CSmartTable.tsx +5 -9
- package/src/components/smart-table/CSmartTableBody.tsx +82 -81
- package/src/components/smart-table/CSmartTableHead.tsx +5 -2
- package/src/components/smart-table/CSmartTableInterface.tsx +8 -0
- package/src/components/smart-table/{utils.tsx → utils.ts} +4 -5
- package/src/components/spinner/CSpinner.tsx +13 -9
- package/src/components/table/CTable.tsx +45 -77
- package/src/components/table/CTableBody.tsx +14 -9
- package/src/components/table/CTableDataCell.tsx +16 -11
- package/src/components/table/CTableFoot.tsx +14 -9
- package/src/components/table/CTableHead.tsx +14 -9
- package/src/components/table/CTableHeaderCell.tsx +14 -9
- package/src/components/table/CTableResponsiveWrapper.tsx +2 -3
- package/src/components/table/CTableRow.tsx +16 -11
- package/src/components/table/__tests__/__snapshots__/CTable.spec.tsx.snap +1 -5
- package/src/components/table/types.ts +20 -0
- package/src/components/table/utils.ts +24 -0
- package/src/components/tabs/CTabContent.tsx +1 -2
- package/src/components/tabs/CTabPane.tsx +18 -20
- package/src/components/tabs/__tests__/CTabPane.spec.tsx +2 -5
- package/src/components/tabs/__tests__/__snapshots__/CTabPane.spec.tsx.snap +1 -1
- package/src/components/time-picker/CTimePicker.tsx +14 -18
- package/src/components/toast/CToast.tsx +32 -45
- package/src/components/toast/CToastBody.tsx +1 -2
- package/src/components/toast/CToastClose.tsx +4 -2
- package/src/components/toast/CToastHeader.tsx +1 -2
- package/src/components/toast/CToaster.tsx +27 -26
- package/src/components/toast/__tests__/CToast.spec.tsx +2 -1
- package/src/components/toast/__tests__/__snapshots__/CToast.spec.tsx.snap +1 -66
- package/src/components/tooltip/CTooltip.tsx +24 -34
- package/src/components/virtual-scroller/CVirtualScroller.tsx +35 -60
- package/src/components/widgets/CWidgetStatsA.tsx +11 -9
- package/src/components/widgets/CWidgetStatsB.tsx +4 -4
- package/src/components/widgets/CWidgetStatsC.tsx +4 -4
- package/src/components/widgets/CWidgetStatsD.tsx +13 -15
- package/src/components/widgets/CWidgetStatsE.tsx +2 -5
- package/src/components/widgets/CWidgetStatsF.tsx +4 -8
- package/src/{components/Types.tsx → props.ts} +1 -68
- package/src/types.ts +68 -0
- package/src/utils/index.ts +1 -3
- package/src/components/multi-select/CMultiSelectCleaner.tsx +0 -18
- package/src/utils/getNextSibling.ts +0 -18
- package/src/utils/getPreviousSibling.ts +0 -18
- package/src/components/smart-table/{types.tsx → types.ts} +1 -1
|
@@ -2,23 +2,22 @@ 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
|
-
import { useForkedRef } from '../../hooks'
|
|
17
|
-
|
|
18
14
|
import { CBackdrop } from '../backdrop/CBackdrop'
|
|
15
|
+
import { CConditionalPortal } from '../conditional-portal'
|
|
19
16
|
import { CModalContent } from './CModalContent'
|
|
20
17
|
import { CModalDialog } from './CModalDialog'
|
|
21
18
|
|
|
19
|
+
import { useForkedRef } from '../../hooks'
|
|
20
|
+
|
|
22
21
|
export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
|
|
23
22
|
/**
|
|
24
23
|
* Align the modal in the center or top of the screen.
|
|
@@ -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
|
-
|
|
133
|
-
|
|
127
|
+
setVisible(visible)
|
|
128
|
+
}, [visible])
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
document.addEventListener('click', handleClickOutside)
|
|
132
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
134
133
|
|
|
135
134
|
return () => {
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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 =
|
|
214
|
-
(event
|
|
215
|
-
|
|
216
|
-
|
|
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={
|
|
210
|
+
timeout={transition ? duration : 0}
|
|
256
211
|
>
|
|
257
|
-
{(state) =>
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
{
|
|
265
|
-
|
|
266
|
-
|
|
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={
|
|
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={
|
|
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
|
|
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={
|
|
15
|
+
<div className={classNames('modal-footer', className)} {...rest} ref={ref}>
|
|
18
16
|
{children}
|
|
19
17
|
</div>
|
|
20
18
|
)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { forwardRef, HTMLAttributes, useContext } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import { CModalContext } from './CModal'
|
|
4
|
-
import { CCloseButton } from '../close-button/CCloseButton'
|
|
5
3
|
import classNames from 'classnames'
|
|
6
4
|
|
|
5
|
+
import { CCloseButton } from '../close-button/CCloseButton'
|
|
6
|
+
import { CModalContext } from './CModal'
|
|
7
|
+
|
|
7
8
|
export interface CModalHeaderProps extends HTMLAttributes<HTMLDivElement> {
|
|
8
9
|
/**
|
|
9
10
|
* A string of all className you want applied to the base component.
|
|
@@ -18,10 +19,9 @@ export interface CModalHeaderProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
18
19
|
export const CModalHeader = forwardRef<HTMLDivElement, CModalHeaderProps>(
|
|
19
20
|
({ children, className, closeButton = true, ...rest }, ref) => {
|
|
20
21
|
const { setVisible } = useContext(CModalContext)
|
|
21
|
-
const _className = classNames('modal-header', className)
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<div className={
|
|
24
|
+
<div className={classNames('modal-header', className)} {...rest} ref={ref}>
|
|
25
25
|
{children}
|
|
26
26
|
{closeButton && <CCloseButton onClick={() => setVisible(false)} />}
|
|
27
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={
|
|
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.
|
|
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
|
-
// })
|
|
@@ -16,11 +16,13 @@ import PropTypes from 'prop-types'
|
|
|
16
16
|
import { CFormControlWrapper, CFormControlWrapperProps } from './../form/CFormControlWrapper'
|
|
17
17
|
import { CPicker } from '../picker/CPicker'
|
|
18
18
|
|
|
19
|
-
import { CMultiSelectCleaner } from './CMultiSelectCleaner'
|
|
20
19
|
import { CMultiSelectNativeSelect } from './CMultiSelectNativeSelect'
|
|
21
20
|
import { CMultiSelectOptions } from './CMultiSelectOptions'
|
|
22
21
|
import { CMultiSelectSelection } from './CMultiSelectSelection'
|
|
23
22
|
|
|
23
|
+
import { filterOptionsList, flattenArray, selectOptions } from './utils'
|
|
24
|
+
import type { Option, SelectedOption } from './types'
|
|
25
|
+
|
|
24
26
|
export interface CMultiSelectProps
|
|
25
27
|
extends Omit<CFormControlWrapperProps, 'floatingClassName' | 'floatingLabel'>,
|
|
26
28
|
Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
@@ -113,29 +115,6 @@ export interface CMultiSelectProps
|
|
|
113
115
|
visibleItems?: number
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
export interface Option {
|
|
117
|
-
disabled?: boolean
|
|
118
|
-
label?: string
|
|
119
|
-
options?: Option[]
|
|
120
|
-
selected?: boolean
|
|
121
|
-
// TODO: change to label
|
|
122
|
-
text?: string
|
|
123
|
-
value?: number | string
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export interface SelectedOption {
|
|
127
|
-
disabled?: boolean
|
|
128
|
-
text: string
|
|
129
|
-
value: number | string
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const flattenArray = (options: Option[]): Option[] =>
|
|
133
|
-
options.reduce(
|
|
134
|
-
(acc: Option[], val: Option) =>
|
|
135
|
-
acc.concat(Array.isArray(val.options) ? flattenArray(val.options) : val),
|
|
136
|
-
[],
|
|
137
|
-
)
|
|
138
|
-
|
|
139
118
|
export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
140
119
|
(
|
|
141
120
|
{
|
|
@@ -181,30 +160,6 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
181
160
|
const [_visible, setVisible] = useState(visible)
|
|
182
161
|
const [selected, setSelected] = useState<SelectedOption[]>([])
|
|
183
162
|
|
|
184
|
-
const selectOptions = (options: Option[], deselected?: Option[]) => {
|
|
185
|
-
let _selected = [...selected, ...options]
|
|
186
|
-
|
|
187
|
-
if (deselected) {
|
|
188
|
-
_selected = _selected.filter(
|
|
189
|
-
(selectedOption) =>
|
|
190
|
-
!deselected.some((deselectedOption) => deselectedOption.value === selectedOption.value),
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const deduplicated = _selected.reduce((unique: Option[], option) => {
|
|
195
|
-
if (!unique.some((obj) => obj.value === option.value)) {
|
|
196
|
-
unique.push({
|
|
197
|
-
value: option.value,
|
|
198
|
-
text: option.text,
|
|
199
|
-
...(option.disabled && { disabled: option.disabled }),
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
return unique
|
|
203
|
-
}, []) as SelectedOption[]
|
|
204
|
-
|
|
205
|
-
setSelected(deduplicated)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
163
|
useMemo(() => {
|
|
209
164
|
setOptions(options)
|
|
210
165
|
const _selected =
|
|
@@ -227,7 +182,7 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
227
182
|
return
|
|
228
183
|
})
|
|
229
184
|
|
|
230
|
-
_selected && selectOptions(_selected, deselected)
|
|
185
|
+
_selected && setSelected(selectOptions(_selected, selected, deselected))
|
|
231
186
|
}, [JSON.stringify(options)])
|
|
232
187
|
|
|
233
188
|
useEffect(() => {
|
|
@@ -236,47 +191,10 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
236
191
|
nativeSelectRef.current.dispatchEvent(new Event('change', { bubbles: true }))
|
|
237
192
|
}, [JSON.stringify(selected)])
|
|
238
193
|
|
|
239
|
-
const _className = classNames(
|
|
240
|
-
'form-multi-select',
|
|
241
|
-
{
|
|
242
|
-
'form-multi-select-with-cleaner': cleaner,
|
|
243
|
-
[`form-multi-select-${size}`]: size,
|
|
244
|
-
show: _visible,
|
|
245
|
-
'form-multi-select-selection-tags': multiple && selectionType === 'tags',
|
|
246
|
-
disabled,
|
|
247
|
-
'is-invalid': invalid,
|
|
248
|
-
'is-valid': valid,
|
|
249
|
-
},
|
|
250
|
-
className,
|
|
251
|
-
)
|
|
252
|
-
|
|
253
194
|
useEffect(() => {
|
|
254
195
|
isInitialMount.current = false
|
|
255
196
|
}, [])
|
|
256
197
|
|
|
257
|
-
const filterOptionsList = (search: string, options: Option[]) => {
|
|
258
|
-
return search.length
|
|
259
|
-
? options &&
|
|
260
|
-
options.reduce((acc: Option[], val: Option) => {
|
|
261
|
-
const options =
|
|
262
|
-
val.options &&
|
|
263
|
-
val.options.filter(
|
|
264
|
-
(element) =>
|
|
265
|
-
element.text && element.text.toLowerCase().includes(search.toLowerCase()),
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
if (
|
|
269
|
-
(val.text && val.text.toLowerCase().includes(search.toLowerCase())) ||
|
|
270
|
-
(options && options.length)
|
|
271
|
-
) {
|
|
272
|
-
acc.push(Object.assign({}, val, options && options.length && { options }))
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return acc
|
|
276
|
-
}, [])
|
|
277
|
-
: _options
|
|
278
|
-
}
|
|
279
|
-
|
|
280
198
|
const handleSearchChange = (event: FormEvent<HTMLInputElement>) => {
|
|
281
199
|
const target = event.target as HTMLInputElement
|
|
282
200
|
if (search !== 'external') {
|
|
@@ -287,7 +205,9 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
287
205
|
}
|
|
288
206
|
|
|
289
207
|
const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
|
290
|
-
if (_search.length)
|
|
208
|
+
if (_search.length > 0) {
|
|
209
|
+
return
|
|
210
|
+
}
|
|
291
211
|
|
|
292
212
|
if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
293
213
|
const last = selected.filter((option: Option) => !option.disabled).pop()
|
|
@@ -315,7 +235,12 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
315
235
|
}
|
|
316
236
|
|
|
317
237
|
const handleSelectAll = () => {
|
|
318
|
-
|
|
238
|
+
setSelected(
|
|
239
|
+
selectOptions(
|
|
240
|
+
flattenArray(options).filter((option: Option) => !option.disabled),
|
|
241
|
+
selected,
|
|
242
|
+
),
|
|
243
|
+
)
|
|
319
244
|
}
|
|
320
245
|
|
|
321
246
|
const handleDeselectAll = () => {
|
|
@@ -347,7 +272,19 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
347
272
|
ref={nativeSelectRef}
|
|
348
273
|
/>
|
|
349
274
|
<CPicker
|
|
350
|
-
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
|
+
)}
|
|
351
288
|
disabled={disabled}
|
|
352
289
|
id={id}
|
|
353
290
|
onHide={() => setVisible(false)}
|
|
@@ -366,7 +303,11 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
366
303
|
selectionTypeCounterText={selectionTypeCounterText}
|
|
367
304
|
/>
|
|
368
305
|
{multiple && cleaner && selected.length > 0 && (
|
|
369
|
-
<
|
|
306
|
+
<button
|
|
307
|
+
type="button"
|
|
308
|
+
className="form-multi-select-selection-cleaner"
|
|
309
|
+
onClick={() => handleDeselectAll()}
|
|
310
|
+
></button>
|
|
370
311
|
)}
|
|
371
312
|
{search && (
|
|
372
313
|
<input
|
|
@@ -376,14 +317,14 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
376
317
|
onChange={(event) => handleSearchChange(event)}
|
|
377
318
|
onKeyDown={(event) => handleSearchKeyDown(event)}
|
|
378
319
|
{...(selected.length === 0 && { placeholder: placeholder })}
|
|
379
|
-
{...(selected.length &&
|
|
320
|
+
{...(selected.length > 0 &&
|
|
380
321
|
selectionType === 'counter' && {
|
|
381
322
|
placeholder: `${selected.length} ${selectionTypeCounterText}`,
|
|
382
323
|
})}
|
|
383
|
-
{...(selected.length &&
|
|
324
|
+
{...(selected.length > 0 &&
|
|
384
325
|
!multiple && { placeholder: selected.map((option) => option.text)[0] })}
|
|
385
326
|
{...(multiple &&
|
|
386
|
-
selected.length &&
|
|
327
|
+
selected.length > 0 &&
|
|
387
328
|
selectionType !== 'counter' && { size: _search.length + 2 })}
|
|
388
329
|
ref={searchRef}
|
|
389
330
|
></input>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, HTMLAttributes } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
|
|
4
|
-
import { Option } from './
|
|
4
|
+
import type { Option } from './types'
|
|
5
5
|
|
|
6
6
|
export interface CMultiSelectNativeSelectProps
|
|
7
7
|
extends Omit<HTMLAttributes<HTMLSelectElement>, 'options'> {
|
|
@@ -2,10 +2,10 @@ import React, { forwardRef, Fragment, HTMLAttributes, ReactNode } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
-
import { Option } from './CMultiSelect'
|
|
6
5
|
import { CVirtualScroller } from './../virtual-scroller'
|
|
7
6
|
|
|
8
|
-
import { getNextSibling, getPreviousSibling } from '
|
|
7
|
+
import { getNextSibling, getPreviousSibling } from './utils'
|
|
8
|
+
import type { Option } from './types'
|
|
9
9
|
|
|
10
10
|
export interface CMultiSelectOptionsProps extends HTMLAttributes<HTMLDivElement> {
|
|
11
11
|
handleOptionOnClick?: (option: Option) => void
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, HTMLAttributes } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
|
|
4
|
-
import type { SelectedOption } from './
|
|
4
|
+
import type { SelectedOption } from './types'
|
|
5
5
|
|
|
6
6
|
export interface CMultiSelectSelectionProps extends HTMLAttributes<HTMLSpanElement> {
|
|
7
7
|
multiple?: boolean
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Option = {
|
|
2
|
+
disabled?: boolean
|
|
3
|
+
label?: string
|
|
4
|
+
options?: Option[]
|
|
5
|
+
order?: number
|
|
6
|
+
selected?: boolean
|
|
7
|
+
text: string
|
|
8
|
+
value: number | string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type SelectedOption = {
|
|
12
|
+
disabled?: boolean
|
|
13
|
+
text: string
|
|
14
|
+
value: number | string
|
|
15
|
+
}
|