@coreui/react 4.1.0 → 4.2.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/accordion/index.d.ts +7 -0
- package/dist/components/alert/index.d.ts +4 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/backdrop/index.d.ts +2 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.d.ts +3 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button-group/index.d.ts +3 -0
- package/dist/components/callout/index.d.ts +2 -0
- package/dist/components/card/index.d.ts +12 -0
- package/dist/components/carousel/index.d.ts +4 -0
- package/dist/components/close-button/index.d.ts +2 -0
- package/dist/components/collapse/index.d.ts +2 -0
- package/dist/components/dropdown/CDropdown.d.ts +10 -1
- package/dist/components/dropdown/CDropdownToggle.d.ts +4 -0
- package/dist/components/dropdown/index.d.ts +8 -0
- package/dist/components/footer/index.d.ts +2 -0
- package/dist/components/form/CForm.d.ts +2 -2
- package/dist/components/form/CFormCheck.d.ts +2 -1
- package/dist/components/form/CFormControlValidation.d.ts +46 -0
- package/dist/components/form/CFormControlWrapper.d.ts +31 -0
- package/dist/components/form/CFormInput.d.ts +6 -9
- package/dist/components/form/CFormRange.d.ts +7 -1
- package/dist/components/form/CFormSelect.d.ts +3 -10
- package/dist/components/form/CFormTextarea.d.ts +2 -9
- package/dist/components/form/index.d.ts +14 -0
- package/dist/components/grid/index.d.ts +4 -0
- package/dist/components/header/index.d.ts +7 -0
- package/dist/components/image/index.d.ts +2 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/link/index.d.ts +2 -0
- package/dist/components/list-group/index.d.ts +3 -0
- package/dist/components/modal/CModal.d.ts +4 -0
- package/dist/components/modal/index.d.ts +8 -0
- package/dist/components/nav/index.d.ts +7 -0
- package/dist/components/navbar/index.d.ts +6 -0
- package/dist/components/offcanvas/index.d.ts +5 -0
- package/dist/components/pagination/index.d.ts +3 -0
- package/dist/components/placeholder/index.d.ts +2 -0
- package/dist/components/popover/CPopover.d.ts +4 -4
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/progress/index.d.ts +3 -0
- package/dist/components/sidebar/index.d.ts +7 -0
- package/dist/components/spinner/index.d.ts +2 -0
- package/dist/components/table/index.d.ts +9 -0
- package/dist/components/tabs/index.d.ts +3 -0
- package/dist/components/toast/index.d.ts +6 -0
- package/dist/components/tooltip/CTooltip.d.ts +7 -3
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/index.d.ts +0 -120
- package/dist/index.es.js +676 -559
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +676 -559
- package/dist/index.js.map +1 -1
- package/package.json +13 -12
- package/src/components/accordion/CAccordionButton.tsx +2 -1
- package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.tsx.snap +2 -0
- package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.tsx.snap +2 -0
- package/src/components/accordion/index.ts +15 -0
- package/src/components/alert/CAlert.tsx +14 -3
- package/src/components/alert/index.ts +5 -0
- package/src/components/avatar/index.ts +3 -0
- package/src/components/backdrop/CBackdrop.tsx +10 -3
- package/src/components/backdrop/index.ts +3 -0
- package/src/components/badge/index.ts +3 -0
- package/src/components/breadcrumb/index.ts +4 -0
- package/src/components/button/index.ts +3 -0
- package/src/components/button-group/index.ts +4 -0
- package/src/components/callout/index.ts +3 -0
- package/src/components/card/index.ts +25 -0
- package/src/components/carousel/index.ts +5 -0
- package/src/components/close-button/index.ts +3 -0
- package/src/components/collapse/CCollapse.tsx +1 -0
- package/src/components/collapse/index.ts +3 -0
- package/src/components/dropdown/CDropdown.tsx +19 -24
- package/src/components/dropdown/CDropdownItem.tsx +1 -1
- package/src/components/dropdown/CDropdownMenu.tsx +55 -3
- package/src/components/dropdown/CDropdownToggle.tsx +28 -5
- package/src/components/dropdown/index.ts +17 -0
- package/src/components/footer/index.ts +3 -0
- package/src/components/form/CForm.tsx +2 -2
- package/src/components/form/CFormCheck.tsx +32 -7
- package/src/components/form/CFormControlValidation.tsx +97 -0
- package/src/components/form/CFormControlWrapper.tsx +85 -0
- package/src/components/form/CFormInput.tsx +75 -19
- package/src/components/form/CFormRange.tsx +18 -4
- package/src/components/form/CFormSelect.tsx +60 -32
- package/src/components/form/CFormTextarea.tsx +45 -17
- package/src/components/form/index.ts +29 -0
- package/src/components/grid/index.ts +5 -0
- package/src/components/header/index.ts +8 -0
- package/src/components/image/index.ts +3 -0
- package/src/components/index.ts +35 -0
- package/src/components/link/index.ts +3 -0
- package/src/components/list-group/index.ts +4 -0
- package/src/components/modal/CModal.tsx +43 -19
- package/src/components/modal/__tests__/CModal.spec.tsx +1 -1
- package/src/components/modal/__tests__/__snapshots__/CModal.spec.tsx.snap +2 -10
- package/src/components/modal/index.ts +9 -0
- package/src/components/nav/CNavGroup.tsx +1 -0
- package/src/components/nav/index.ts +8 -0
- package/src/components/navbar/index.ts +7 -0
- package/src/components/offcanvas/COffcanvas.tsx +1 -0
- package/src/components/offcanvas/index.ts +6 -0
- package/src/components/pagination/index.ts +4 -0
- package/src/components/placeholder/index.ts +3 -0
- package/src/components/popover/CPopover.tsx +63 -61
- package/src/components/popover/index.ts +3 -0
- package/src/components/progress/index.ts +4 -0
- package/src/components/sidebar/index.ts +8 -0
- package/src/components/spinner/index.ts +3 -0
- package/src/components/table/index.ts +19 -0
- package/src/components/tabs/CTabPane.tsx +7 -3
- package/src/components/tabs/index.ts +4 -0
- package/src/components/toast/CToast.tsx +6 -1
- package/src/components/toast/index.ts +7 -0
- package/src/components/tooltip/CTooltip.tsx +65 -47
- package/src/components/tooltip/index.ts +3 -0
- package/src/index.ts +0 -242
- package/src/utils/hooks/useForkedRef.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreui/react",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "UI Components Library for React.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -35,24 +35,25 @@
|
|
|
35
35
|
"build": "rollup -c"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@popperjs/core": "^2.11.
|
|
39
|
-
"@rollup/plugin-commonjs": "^21.0.
|
|
40
|
-
"@rollup/plugin-node-resolve": "^13.
|
|
41
|
-
"@rollup/plugin-typescript": "^8.3.
|
|
42
|
-
"@testing-library/jest-dom": "^5.
|
|
43
|
-
"@testing-library/react": "^12.1.
|
|
44
|
-
"@types/react": "
|
|
45
|
-
"@types/react-dom": "^17.0.
|
|
38
|
+
"@popperjs/core": "^2.11.5",
|
|
39
|
+
"@rollup/plugin-commonjs": "^21.0.3",
|
|
40
|
+
"@rollup/plugin-node-resolve": "^13.1.3",
|
|
41
|
+
"@rollup/plugin-typescript": "^8.3.1",
|
|
42
|
+
"@testing-library/jest-dom": "^5.16.4",
|
|
43
|
+
"@testing-library/react": "^12.1.4",
|
|
44
|
+
"@types/react": "17.0.39",
|
|
45
|
+
"@types/react-dom": "^17.0.15",
|
|
46
46
|
"@types/react-transition-group": "^4.4.4",
|
|
47
47
|
"classnames": "^2.3.1",
|
|
48
|
-
"prop-types": "^15.
|
|
48
|
+
"prop-types": "^15.8.1",
|
|
49
49
|
"react": "^17.0.2",
|
|
50
50
|
"react-dom": "^17.0.2",
|
|
51
51
|
"react-popper": "^2.2.5",
|
|
52
52
|
"react-transition-group": "^4.4.2",
|
|
53
|
-
"rollup": "^2.
|
|
53
|
+
"rollup": "^2.70.1",
|
|
54
54
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
55
|
-
"
|
|
55
|
+
"tslib": "^2.4.0",
|
|
56
|
+
"typescript": "^4.6.3"
|
|
56
57
|
},
|
|
57
58
|
"peerDependencies": {
|
|
58
59
|
"react": "^17",
|
|
@@ -19,10 +19,11 @@ export const CAccordionButton = forwardRef<HTMLButtonElement, CAccordionButtonPr
|
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<button
|
|
22
|
+
type="button"
|
|
22
23
|
className={_className}
|
|
23
|
-
{...rest}
|
|
24
24
|
aria-expanded={!visible}
|
|
25
25
|
onClick={() => setVisible(!visible)}
|
|
26
|
+
{...rest}
|
|
26
27
|
ref={ref}
|
|
27
28
|
>
|
|
28
29
|
{children}
|
|
@@ -5,6 +5,7 @@ exports[`CAccordionButton customize 1`] = `
|
|
|
5
5
|
<button
|
|
6
6
|
aria-expanded="true"
|
|
7
7
|
class="accordion-button collapsed bazinga"
|
|
8
|
+
type="button"
|
|
8
9
|
>
|
|
9
10
|
Test
|
|
10
11
|
</button>
|
|
@@ -16,6 +17,7 @@ exports[`loads and displays CAccordionButton component 1`] = `
|
|
|
16
17
|
<button
|
|
17
18
|
aria-expanded="true"
|
|
18
19
|
class="accordion-button collapsed"
|
|
20
|
+
type="button"
|
|
19
21
|
>
|
|
20
22
|
Test
|
|
21
23
|
</button>
|
|
@@ -8,6 +8,7 @@ exports[`CAccordionHeader customize 1`] = `
|
|
|
8
8
|
<button
|
|
9
9
|
aria-expanded="true"
|
|
10
10
|
class="accordion-button collapsed"
|
|
11
|
+
type="button"
|
|
11
12
|
>
|
|
12
13
|
Test
|
|
13
14
|
</button>
|
|
@@ -23,6 +24,7 @@ exports[`loads and displays CAccordionHeader component 1`] = `
|
|
|
23
24
|
<button
|
|
24
25
|
aria-expanded="true"
|
|
25
26
|
class="accordion-button collapsed"
|
|
27
|
+
type="button"
|
|
26
28
|
>
|
|
27
29
|
Test
|
|
28
30
|
</button>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CAccordion } from './CAccordion'
|
|
2
|
+
import { CAccordionBody } from './CAccordionBody'
|
|
3
|
+
import { CAccordionButton } from './CAccordionButton'
|
|
4
|
+
import { CAccordionCollapse } from './CAccordionCollapse'
|
|
5
|
+
import { CAccordionHeader } from './CAccordionHeader'
|
|
6
|
+
import { CAccordionItem } from './CAccordionItem'
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
CAccordion,
|
|
10
|
+
CAccordionBody,
|
|
11
|
+
CAccordionButton,
|
|
12
|
+
CAccordionCollapse,
|
|
13
|
+
CAccordionHeader,
|
|
14
|
+
CAccordionItem,
|
|
15
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, HTMLAttributes, useEffect, useState } from 'react'
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, useEffect, useState, useRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { Transition } from 'react-transition-group'
|
|
@@ -6,6 +6,8 @@ import { Transition } from 'react-transition-group'
|
|
|
6
6
|
import { Colors, colorPropType } from '../Types'
|
|
7
7
|
import { CCloseButton } from '../close-button/CCloseButton'
|
|
8
8
|
|
|
9
|
+
import { useForkedRef } from '../../utils/hooks'
|
|
10
|
+
|
|
9
11
|
export interface CAlertProps extends HTMLAttributes<HTMLDivElement> {
|
|
10
12
|
/**
|
|
11
13
|
* A string of all className you want applied to the component.
|
|
@@ -49,6 +51,8 @@ export const CAlert = forwardRef<HTMLDivElement, CAlertProps>(
|
|
|
49
51
|
},
|
|
50
52
|
ref,
|
|
51
53
|
) => {
|
|
54
|
+
const alertRef = useRef<HTMLDivElement>(null)
|
|
55
|
+
const forkedRef = useForkedRef(ref, alertRef)
|
|
52
56
|
const [_visible, setVisible] = useState(visible)
|
|
53
57
|
|
|
54
58
|
useEffect(() => {
|
|
@@ -69,7 +73,14 @@ export const CAlert = forwardRef<HTMLDivElement, CAlertProps>(
|
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
return (
|
|
72
|
-
<Transition
|
|
76
|
+
<Transition
|
|
77
|
+
in={_visible}
|
|
78
|
+
mountOnEnter
|
|
79
|
+
nodeRef={alertRef}
|
|
80
|
+
onExit={onClose}
|
|
81
|
+
timeout={150}
|
|
82
|
+
unmountOnExit
|
|
83
|
+
>
|
|
73
84
|
{(state) => {
|
|
74
85
|
const transitionClass = getTransitionClass(state)
|
|
75
86
|
return (
|
|
@@ -77,7 +88,7 @@ export const CAlert = forwardRef<HTMLDivElement, CAlertProps>(
|
|
|
77
88
|
className={classNames(_className, transitionClass)}
|
|
78
89
|
role="alert"
|
|
79
90
|
{...rest}
|
|
80
|
-
ref={
|
|
91
|
+
ref={forkedRef}
|
|
81
92
|
>
|
|
82
93
|
{children}
|
|
83
94
|
{dismissible && <CCloseButton onClick={() => setVisible(false)} />}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import React, { forwardRef, HTMLAttributes } from 'react'
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, useRef } from 'react'
|
|
2
2
|
import { Transition } from 'react-transition-group'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
import classNames from 'classnames'
|
|
5
5
|
|
|
6
|
+
import { useForkedRef } from '../../utils/hooks'
|
|
7
|
+
|
|
6
8
|
export interface CBackdropProps extends HTMLAttributes<HTMLDivElement> {
|
|
7
9
|
/**
|
|
8
10
|
* A string of all className you want applied to the base component.
|
|
@@ -16,6 +18,9 @@ export interface CBackdropProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
16
18
|
|
|
17
19
|
export const CBackdrop = forwardRef<HTMLDivElement, CBackdropProps>(
|
|
18
20
|
({ className = 'modal-backdrop', visible, ...rest }, ref) => {
|
|
21
|
+
const backdropRef = useRef<HTMLDivElement>(null)
|
|
22
|
+
const forkedRef = useForkedRef(ref, backdropRef)
|
|
23
|
+
|
|
19
24
|
const _className = classNames(className, 'fade')
|
|
20
25
|
|
|
21
26
|
const getTransitionClass = (state: string) => {
|
|
@@ -23,10 +28,12 @@ export const CBackdrop = forwardRef<HTMLDivElement, CBackdropProps>(
|
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
return (
|
|
26
|
-
<Transition in={visible} mountOnEnter timeout={150} unmountOnExit>
|
|
31
|
+
<Transition in={visible} mountOnEnter nodeRef={backdropRef} timeout={150} unmountOnExit>
|
|
27
32
|
{(state) => {
|
|
28
33
|
const transitionClass = getTransitionClass(state)
|
|
29
|
-
return
|
|
34
|
+
return (
|
|
35
|
+
<div className={classNames(_className, transitionClass)} {...rest} ref={forkedRef} />
|
|
36
|
+
)
|
|
30
37
|
}}
|
|
31
38
|
</Transition>
|
|
32
39
|
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CCard } from './CCard'
|
|
2
|
+
import { CCardBody } from './CCardBody'
|
|
3
|
+
import { CCardFooter } from './CCardFooter'
|
|
4
|
+
import { CCardGroup } from './CCardGroup'
|
|
5
|
+
import { CCardHeader } from './CCardHeader'
|
|
6
|
+
import { CCardImage } from './CCardImage'
|
|
7
|
+
import { CCardImageOverlay } from './CCardImageOverlay'
|
|
8
|
+
import { CCardLink } from './CCardLink'
|
|
9
|
+
import { CCardSubtitle } from './CCardSubtitle'
|
|
10
|
+
import { CCardText } from './CCardText'
|
|
11
|
+
import { CCardTitle } from './CCardTitle'
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
CCard,
|
|
15
|
+
CCardBody,
|
|
16
|
+
CCardFooter,
|
|
17
|
+
CCardGroup,
|
|
18
|
+
CCardHeader,
|
|
19
|
+
CCardImage,
|
|
20
|
+
CCardImageOverlay,
|
|
21
|
+
CCardLink,
|
|
22
|
+
CCardSubtitle,
|
|
23
|
+
CCardText,
|
|
24
|
+
CCardTitle,
|
|
25
|
+
}
|
|
@@ -3,6 +3,7 @@ import React, {
|
|
|
3
3
|
ElementType,
|
|
4
4
|
forwardRef,
|
|
5
5
|
HTMLAttributes,
|
|
6
|
+
RefObject,
|
|
6
7
|
useEffect,
|
|
7
8
|
useRef,
|
|
8
9
|
useState,
|
|
@@ -33,6 +34,14 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
|
|
|
33
34
|
* @type 'start' | 'end' | { xs: 'start' | 'end' } | { sm: 'start' | 'end' } | { md: 'start' | 'end' } | { lg: 'start' | 'end' } | { xl: 'start' | 'end'} | { xxl: 'start' | 'end'}
|
|
34
35
|
*/
|
|
35
36
|
alignment?: Alignments
|
|
37
|
+
/**
|
|
38
|
+
* Configure the auto close behavior of the dropdown:
|
|
39
|
+
* - `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
|
|
40
|
+
* - `false` - the dropdown will be closed by clicking the toggle button and manually calling hide or toggle method. (Also will not be closed by pressing esc key)
|
|
41
|
+
* - `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
|
|
42
|
+
* - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
|
|
43
|
+
*/
|
|
44
|
+
autoClose?: 'inside' | 'outside' | boolean
|
|
36
45
|
/**
|
|
37
46
|
* A string of all className you want applied to the base component.
|
|
38
47
|
*/
|
|
@@ -80,6 +89,8 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
|
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
interface ContextProps extends CDropdownProps {
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
|
+
dropdownToggleRef: RefObject<any> | undefined
|
|
83
94
|
setVisible: React.Dispatch<React.SetStateAction<boolean | undefined>>
|
|
84
95
|
}
|
|
85
96
|
|
|
@@ -90,6 +101,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
90
101
|
{
|
|
91
102
|
children,
|
|
92
103
|
alignment,
|
|
104
|
+
autoClose = true,
|
|
93
105
|
className,
|
|
94
106
|
dark,
|
|
95
107
|
direction,
|
|
@@ -106,6 +118,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
106
118
|
) => {
|
|
107
119
|
const [_visible, setVisible] = useState(visible)
|
|
108
120
|
const dropdownRef = useRef<HTMLDivElement>(null)
|
|
121
|
+
const dropdownToggleRef = useRef(null)
|
|
109
122
|
const forkedRef = useForkedRef(ref, dropdownRef)
|
|
110
123
|
|
|
111
124
|
const Component = variant === 'nav-item' ? 'li' : component
|
|
@@ -117,8 +130,10 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
117
130
|
|
|
118
131
|
const contextValues = {
|
|
119
132
|
alignment,
|
|
133
|
+
autoClose,
|
|
120
134
|
dark,
|
|
121
135
|
direction: direction,
|
|
136
|
+
dropdownToggleRef,
|
|
122
137
|
placement: placement,
|
|
123
138
|
popper,
|
|
124
139
|
variant,
|
|
@@ -135,19 +150,6 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
135
150
|
className,
|
|
136
151
|
)
|
|
137
152
|
|
|
138
|
-
useEffect(() => {
|
|
139
|
-
_visible &&
|
|
140
|
-
setTimeout(() => {
|
|
141
|
-
window.addEventListener('click', handleClickOutside)
|
|
142
|
-
window.addEventListener('keyup', handleKeyup)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
return () => {
|
|
146
|
-
window.removeEventListener('click', handleClickOutside)
|
|
147
|
-
window.removeEventListener('keyup', handleKeyup)
|
|
148
|
-
}
|
|
149
|
-
}, [_visible])
|
|
150
|
-
|
|
151
153
|
useEffect(() => {
|
|
152
154
|
setVisible(visible)
|
|
153
155
|
}, [visible])
|
|
@@ -157,17 +159,6 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
157
159
|
!_visible && onHide && onHide()
|
|
158
160
|
}, [_visible])
|
|
159
161
|
|
|
160
|
-
const handleKeyup = (event: Event) => {
|
|
161
|
-
if (!dropdownRef.current?.contains(event.target as HTMLElement)) {
|
|
162
|
-
setVisible(false)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const handleClickOutside = (event: Event) => {
|
|
166
|
-
if (!dropdownRef.current?.contains(event.target as HTMLElement)) {
|
|
167
|
-
setVisible(false)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
162
|
const dropdownContent = () => {
|
|
172
163
|
return variant === 'input-group' ? (
|
|
173
164
|
<>{children}</>
|
|
@@ -203,6 +194,10 @@ CDropdown.propTypes = {
|
|
|
203
194
|
PropTypes.shape({ xl: alignmentDirection }),
|
|
204
195
|
PropTypes.shape({ xxl: alignmentDirection }),
|
|
205
196
|
]),
|
|
197
|
+
autoClose: PropTypes.oneOfType([
|
|
198
|
+
PropTypes.bool,
|
|
199
|
+
PropTypes.oneOf<'inside' | 'outside'>(['inside', 'outside']),
|
|
200
|
+
]),
|
|
206
201
|
children: PropTypes.node,
|
|
207
202
|
className: PropTypes.string,
|
|
208
203
|
component: PropTypes.elementType,
|
|
@@ -21,7 +21,7 @@ export const CDropdownItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, C
|
|
|
21
21
|
const _className = classNames('dropdown-item', className)
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<CLink component={component} {...rest}
|
|
24
|
+
<CLink className={_className} component={component} {...rest} ref={ref}>
|
|
25
25
|
{children}
|
|
26
26
|
</CLink>
|
|
27
27
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import React, { ElementType, FC, HTMLAttributes, useContext, useEffect, useRef } from 'react'
|
|
1
2
|
import PropTypes from 'prop-types'
|
|
2
|
-
import React, { ElementType, FC, HTMLAttributes, useContext } from 'react'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { Popper, PopperChildrenProps } from 'react-popper'
|
|
5
5
|
|
|
@@ -35,19 +35,69 @@ export const CDropdownMenu: FC<CDropdownMenuProps> = ({
|
|
|
35
35
|
component: Component = 'ul',
|
|
36
36
|
...rest
|
|
37
37
|
}) => {
|
|
38
|
-
const {
|
|
38
|
+
const {
|
|
39
|
+
alignment,
|
|
40
|
+
autoClose,
|
|
41
|
+
dark,
|
|
42
|
+
direction,
|
|
43
|
+
dropdownToggleRef,
|
|
44
|
+
placement,
|
|
45
|
+
popper,
|
|
46
|
+
visible,
|
|
47
|
+
setVisible,
|
|
48
|
+
} = useContext(CDropdownContext)
|
|
49
|
+
|
|
50
|
+
const dropdownMenuRef = useRef<HTMLDivElement>(null)
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
visible && window.addEventListener('mouseup', handleMouseUp)
|
|
54
|
+
visible && window.addEventListener('keyup', handleKeyup)
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('mouseup', handleMouseUp)
|
|
58
|
+
window.removeEventListener('keyup', handleKeyup)
|
|
59
|
+
}
|
|
60
|
+
}, [visible])
|
|
61
|
+
|
|
62
|
+
const handleKeyup = (event: KeyboardEvent) => {
|
|
63
|
+
if (autoClose === false) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (event.key === 'Escape') {
|
|
68
|
+
setVisible(false)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const handleMouseUp = (event: Event) => {
|
|
73
|
+
if (dropdownToggleRef && dropdownToggleRef.current.contains(event.target as HTMLElement)) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
autoClose === true ||
|
|
79
|
+
(autoClose === 'inside' && dropdownMenuRef.current?.contains(event.target as HTMLElement)) ||
|
|
80
|
+
(autoClose === 'outside' && !dropdownMenuRef.current?.contains(event.target as HTMLElement))
|
|
81
|
+
) {
|
|
82
|
+
setTimeout(() => setVisible(false), 1)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
}
|
|
39
86
|
|
|
40
87
|
let _placement: Placements = placement
|
|
41
88
|
|
|
42
89
|
if (direction === 'dropup') {
|
|
43
90
|
_placement = 'top-start'
|
|
44
91
|
}
|
|
92
|
+
|
|
45
93
|
if (direction === 'dropend') {
|
|
46
94
|
_placement = 'right-start'
|
|
47
95
|
}
|
|
96
|
+
|
|
48
97
|
if (direction === 'dropstart') {
|
|
49
98
|
_placement = 'left-start'
|
|
50
99
|
}
|
|
100
|
+
|
|
51
101
|
if (alignment === 'end') {
|
|
52
102
|
_placement = 'bottom-end'
|
|
53
103
|
}
|
|
@@ -101,7 +151,9 @@ export const CDropdownMenu: FC<CDropdownMenuProps> = ({
|
|
|
101
151
|
}
|
|
102
152
|
|
|
103
153
|
return popper && visible ? (
|
|
104
|
-
<Popper placement={_placement}>
|
|
154
|
+
<Popper innerRef={dropdownMenuRef} placement={_placement}>
|
|
155
|
+
{({ ref, style }) => dropdownMenuComponent(style, ref)}
|
|
156
|
+
</Popper>
|
|
105
157
|
) : (
|
|
106
158
|
dropdownMenuComponent()
|
|
107
159
|
)
|
|
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { Reference } from 'react-popper'
|
|
5
5
|
|
|
6
|
+
import { useForkedRef } from '../../utils/hooks'
|
|
7
|
+
|
|
6
8
|
import { Triggers, triggerPropType } from '../Types'
|
|
7
9
|
|
|
8
10
|
import { CButton, CButtonProps } from '../button/CButton'
|
|
@@ -13,6 +15,10 @@ export interface CDropdownToggleProps extends Omit<CButtonProps, 'type'> {
|
|
|
13
15
|
* Enables pseudo element caret on toggler.
|
|
14
16
|
*/
|
|
15
17
|
caret?: boolean
|
|
18
|
+
/**
|
|
19
|
+
* Create a custom toggler which accepts any content.
|
|
20
|
+
*/
|
|
21
|
+
custom?: boolean
|
|
16
22
|
/**
|
|
17
23
|
* Similarly, create split button dropdowns with virtually the same markup as single button dropdowns, but with the addition of `.dropdown-toggle-split` className for proper spacing around the dropdown caret.
|
|
18
24
|
*/
|
|
@@ -28,12 +34,13 @@ export interface CDropdownToggleProps extends Omit<CButtonProps, 'type'> {
|
|
|
28
34
|
export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
29
35
|
children,
|
|
30
36
|
caret = true,
|
|
37
|
+
custom,
|
|
31
38
|
className,
|
|
32
39
|
split,
|
|
33
40
|
trigger = 'click',
|
|
34
41
|
...rest
|
|
35
42
|
}) => {
|
|
36
|
-
const { popper, variant, visible, setVisible } = useContext(CDropdownContext)
|
|
43
|
+
const { dropdownToggleRef, popper, variant, visible, setVisible } = useContext(CDropdownContext)
|
|
37
44
|
const _className = classNames(
|
|
38
45
|
{
|
|
39
46
|
'dropdown-toggle': caret,
|
|
@@ -59,31 +66,47 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
|
59
66
|
const togglerProps = {
|
|
60
67
|
className: _className,
|
|
61
68
|
'aria-expanded': visible,
|
|
69
|
+
...(!rest.disabled && { ...triggers }),
|
|
62
70
|
...triggers,
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
// We use any because Toggler can be `a` as well as `button`.
|
|
66
74
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
75
|
const Toggler = (ref?: React.Ref<any>) => {
|
|
68
|
-
return
|
|
69
|
-
|
|
76
|
+
return custom && React.isValidElement(children) ? (
|
|
77
|
+
<>
|
|
78
|
+
{React.cloneElement(children, {
|
|
79
|
+
'aria-expanded': visible,
|
|
80
|
+
...(!rest.disabled && { ...triggers }),
|
|
81
|
+
ref: useForkedRef(ref, dropdownToggleRef),
|
|
82
|
+
})}
|
|
83
|
+
</>
|
|
84
|
+
) : variant === 'nav-item' ? (
|
|
85
|
+
<a href="#" {...togglerProps} ref={useForkedRef(ref, dropdownToggleRef)}>
|
|
70
86
|
{children}
|
|
71
87
|
</a>
|
|
72
88
|
) : (
|
|
73
|
-
<CButton
|
|
89
|
+
<CButton
|
|
90
|
+
type="button"
|
|
91
|
+
{...togglerProps}
|
|
92
|
+
tabIndex={0}
|
|
93
|
+
{...rest}
|
|
94
|
+
ref={useForkedRef(ref, dropdownToggleRef)}
|
|
95
|
+
>
|
|
74
96
|
{children}
|
|
75
97
|
{split && <span className="visually-hidden">Toggle Dropdown</span>}
|
|
76
98
|
</CButton>
|
|
77
99
|
)
|
|
78
100
|
}
|
|
79
101
|
|
|
80
|
-
return popper ? <Reference>{({ ref }) => Toggler(ref)}</Reference> : Toggler()
|
|
102
|
+
return popper ? <Reference>{({ ref }) => Toggler(ref)}</Reference> : Toggler(dropdownToggleRef)
|
|
81
103
|
}
|
|
82
104
|
|
|
83
105
|
CDropdownToggle.propTypes = {
|
|
84
106
|
caret: PropTypes.bool,
|
|
85
107
|
children: PropTypes.node,
|
|
86
108
|
className: PropTypes.string,
|
|
109
|
+
custom: PropTypes.bool,
|
|
87
110
|
split: PropTypes.bool,
|
|
88
111
|
trigger: triggerPropType,
|
|
89
112
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CDropdown } from './CDropdown'
|
|
2
|
+
import { CDropdownDivider } from './CDropdownDivider'
|
|
3
|
+
import { CDropdownHeader } from './CDropdownHeader'
|
|
4
|
+
import { CDropdownItem } from './CDropdownItem'
|
|
5
|
+
import { CDropdownItemPlain } from './CDropdownItemPlain'
|
|
6
|
+
import { CDropdownMenu } from './CDropdownMenu'
|
|
7
|
+
import { CDropdownToggle } from './CDropdownToggle'
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
CDropdown,
|
|
11
|
+
CDropdownDivider,
|
|
12
|
+
CDropdownHeader,
|
|
13
|
+
CDropdownItem,
|
|
14
|
+
CDropdownItemPlain,
|
|
15
|
+
CDropdownMenu,
|
|
16
|
+
CDropdownToggle,
|
|
17
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { forwardRef,
|
|
1
|
+
import React, { forwardRef, FormHTMLAttributes } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
-
export interface CFormProps extends
|
|
5
|
+
export interface CFormProps extends FormHTMLAttributes<HTMLFormElement> {
|
|
6
6
|
/**
|
|
7
7
|
* A string of all className you want applied to the component.
|
|
8
8
|
*/
|