@coreui/react 4.0.0 → 4.1.1
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 +157 -0
- package/dist/components/accordion/CAccordionCollapse.d.ts +1 -1
- package/dist/components/collapse/CCollapse.d.ts +4 -0
- package/dist/components/form/CFormCheck.d.ts +4 -0
- package/dist/components/form/CFormLabel.d.ts +2 -2
- package/dist/components/form/CFormSelect.d.ts +13 -0
- package/dist/components/placeholder/CPlaceholder.d.ts +51 -0
- package/dist/components/popover/CPopover.d.ts +2 -2
- package/dist/components/tooltip/CTooltip.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.es.js +291 -181
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +291 -180
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/src/components/accordion/CAccordionCollapse.tsx +1 -1
- package/src/components/collapse/CCollapse.tsx +36 -3
- package/src/components/form/CFormCheck.tsx +30 -3
- package/src/components/form/CFormLabel.tsx +2 -2
- package/src/components/form/CFormSelect.tsx +28 -2
- package/src/components/form/__tests__/CFormLabel.spec.tsx +8 -0
- package/src/components/form/__tests__/__snapshots__/CFormLabel.spec.tsx.snap +11 -0
- package/src/components/grid/CCol.tsx +8 -8
- package/src/components/grid/CContainer.tsx +3 -3
- package/src/components/grid/CRow.tsx +6 -6
- package/src/components/offcanvas/COffcanvas.tsx +15 -2
- package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -1
- package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +2 -2
- package/src/components/placeholder/CPlaceholder.tsx +114 -0
- package/src/components/placeholder/__tests__/CPlaceholder.spec.tsx +21 -0
- package/src/components/placeholder/__tests__/__snapshots__/CPlaceholder.spec.tsx.snap +17 -0
- package/src/components/popover/CPopover.tsx +4 -4
- package/src/components/tooltip/CTooltip.tsx +2 -2
- package/src/index.ts +2 -0
- 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.1.1",
|
|
4
4
|
"description": "UI Components Library for React.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"main": "dist/index.js",
|
|
27
27
|
"module": "dist/index.es.js",
|
|
28
28
|
"jsnext:main": "dist/index.es.js",
|
|
29
|
-
"
|
|
29
|
+
"types": "dist/index.d.ts",
|
|
30
30
|
"files": [
|
|
31
31
|
"dist/",
|
|
32
32
|
"src/"
|
|
@@ -35,24 +35,24 @@
|
|
|
35
35
|
"build": "rollup -c"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@popperjs/core": "^2.
|
|
38
|
+
"@popperjs/core": "^2.11.0",
|
|
39
39
|
"@rollup/plugin-commonjs": "^21.0.1",
|
|
40
|
-
"@rollup/plugin-node-resolve": "^13.
|
|
40
|
+
"@rollup/plugin-node-resolve": "^13.1.1",
|
|
41
41
|
"@rollup/plugin-typescript": "^8.3.0",
|
|
42
|
-
"@testing-library/jest-dom": "^5.
|
|
42
|
+
"@testing-library/jest-dom": "^5.16.1",
|
|
43
43
|
"@testing-library/react": "^12.1.2",
|
|
44
|
-
"@types/react": "^17.0.
|
|
45
|
-
"@types/react-dom": "^17.0.
|
|
46
|
-
"@types/react-transition-group": "^4.4.
|
|
44
|
+
"@types/react": "^17.0.37",
|
|
45
|
+
"@types/react-dom": "^17.0.11",
|
|
46
|
+
"@types/react-transition-group": "^4.4.4",
|
|
47
47
|
"classnames": "^2.3.1",
|
|
48
48
|
"prop-types": "^15.7.2",
|
|
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.61.1",
|
|
54
54
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
55
|
-
"typescript": "^4.
|
|
55
|
+
"typescript": "^4.5.4"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"react": "^17",
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { CCollapse, CCollapseProps } from '../collapse/CCollapse'
|
|
4
4
|
|
|
5
|
-
export const CAccordionCollapse = forwardRef<HTMLDivElement, CCollapseProps
|
|
5
|
+
export const CAccordionCollapse = forwardRef<HTMLDivElement, Omit<CCollapseProps, 'horizontal'>>(
|
|
6
6
|
({ children, ...props }, ref) => {
|
|
7
7
|
return (
|
|
8
8
|
<CCollapse className="accordion-collapse" {...props} ref={ref}>
|
|
@@ -10,6 +10,10 @@ export interface CCollapseProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
10
10
|
* A string of all className you want applied to the base component.
|
|
11
11
|
*/
|
|
12
12
|
className?: string
|
|
13
|
+
/**
|
|
14
|
+
* Set horizontal collapsing to transition the width instead of height.
|
|
15
|
+
*/
|
|
16
|
+
horizontal?: boolean
|
|
13
17
|
/**
|
|
14
18
|
* Callback fired when the component requests to be hidden.
|
|
15
19
|
*/
|
|
@@ -25,8 +29,9 @@ export interface CCollapseProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
|
|
28
|
-
({ children, className, onHide, onShow, visible, ...rest }, ref) => {
|
|
32
|
+
({ children, className, horizontal, onHide, onShow, visible, ...rest }, ref) => {
|
|
29
33
|
const [height, setHeight] = useState<number>()
|
|
34
|
+
const [width, setWidth] = useState<number>()
|
|
30
35
|
const collapseRef = useRef<HTMLDivElement>(null)
|
|
31
36
|
const forkedRef = useForkedRef(ref, collapseRef)
|
|
32
37
|
|
|
@@ -42,27 +47,53 @@ export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
|
|
|
42
47
|
|
|
43
48
|
const onEntering = () => {
|
|
44
49
|
onShow && onShow()
|
|
50
|
+
|
|
51
|
+
if (horizontal) {
|
|
52
|
+
collapseRef.current && setWidth(collapseRef.current.scrollWidth)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
45
55
|
collapseRef.current && setHeight(collapseRef.current.scrollHeight)
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
const onEntered = () => {
|
|
59
|
+
if (horizontal) {
|
|
60
|
+
setWidth(0)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
49
63
|
setHeight(0)
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
const onExit = () => {
|
|
67
|
+
if (horizontal) {
|
|
68
|
+
collapseRef.current && setWidth(collapseRef.current.scrollWidth)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
53
71
|
collapseRef.current && setHeight(collapseRef.current.scrollHeight)
|
|
54
72
|
}
|
|
55
73
|
|
|
56
74
|
const onExiting = () => {
|
|
57
75
|
onHide && onHide()
|
|
76
|
+
if (horizontal) {
|
|
77
|
+
setWidth(0)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
58
80
|
setHeight(0)
|
|
59
81
|
}
|
|
60
82
|
|
|
61
83
|
const onExited = () => {
|
|
84
|
+
if (horizontal) {
|
|
85
|
+
setWidth(0)
|
|
86
|
+
return
|
|
87
|
+
}
|
|
62
88
|
setHeight(0)
|
|
63
89
|
}
|
|
64
90
|
|
|
65
|
-
const _className = classNames(
|
|
91
|
+
const _className = classNames(
|
|
92
|
+
{
|
|
93
|
+
'collapse-horizontal': horizontal,
|
|
94
|
+
},
|
|
95
|
+
className,
|
|
96
|
+
)
|
|
66
97
|
|
|
67
98
|
return (
|
|
68
99
|
<CSSTransition
|
|
@@ -77,10 +108,11 @@ export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
|
|
|
77
108
|
{(state) => {
|
|
78
109
|
const transitionClass = getTransitionClass(state)
|
|
79
110
|
const currentHeight = height === 0 ? null : { height }
|
|
111
|
+
const currentWidth = width === 0 ? null : { width }
|
|
80
112
|
return (
|
|
81
113
|
<div
|
|
82
114
|
className={classNames(_className, transitionClass)}
|
|
83
|
-
style={{ ...currentHeight }}
|
|
115
|
+
style={{ ...currentHeight, ...currentWidth }}
|
|
84
116
|
{...rest}
|
|
85
117
|
ref={forkedRef}
|
|
86
118
|
>
|
|
@@ -96,6 +128,7 @@ export const CCollapse = forwardRef<HTMLDivElement, CCollapseProps>(
|
|
|
96
128
|
CCollapse.propTypes = {
|
|
97
129
|
children: PropTypes.node,
|
|
98
130
|
className: PropTypes.string,
|
|
131
|
+
horizontal: PropTypes.bool,
|
|
99
132
|
onHide: PropTypes.func,
|
|
100
133
|
onShow: PropTypes.func,
|
|
101
134
|
visible: PropTypes.bool,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { forwardRef, InputHTMLAttributes, ReactNode } from 'react'
|
|
1
|
+
import React, { forwardRef, InputHTMLAttributes, ReactNode, useEffect, useRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
+
import { useForkedRef } from '../../utils/hooks'
|
|
5
6
|
import { Colors, Shapes } from '../Types'
|
|
6
7
|
|
|
7
8
|
import { CFormLabel } from './CFormLabel'
|
|
@@ -46,6 +47,10 @@ export interface CFormCheckProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
46
47
|
* The id global attribute defines an identifier (ID) that must be unique in the whole document.
|
|
47
48
|
*/
|
|
48
49
|
id?: string
|
|
50
|
+
/**
|
|
51
|
+
* Input Checkbox indeterminate Property.
|
|
52
|
+
*/
|
|
53
|
+
indeterminate?: boolean
|
|
49
54
|
/**
|
|
50
55
|
* Group checkboxes or radios on the same horizontal row by adding.
|
|
51
56
|
*/
|
|
@@ -70,9 +75,30 @@ export interface CFormCheckProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
|
70
75
|
|
|
71
76
|
export const CFormCheck = forwardRef<HTMLInputElement, CFormCheckProps>(
|
|
72
77
|
(
|
|
73
|
-
{
|
|
78
|
+
{
|
|
79
|
+
className,
|
|
80
|
+
button,
|
|
81
|
+
hitArea,
|
|
82
|
+
id,
|
|
83
|
+
indeterminate,
|
|
84
|
+
inline,
|
|
85
|
+
invalid,
|
|
86
|
+
label,
|
|
87
|
+
type = 'checkbox',
|
|
88
|
+
valid,
|
|
89
|
+
...rest
|
|
90
|
+
},
|
|
74
91
|
ref,
|
|
75
92
|
) => {
|
|
93
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
94
|
+
const forkedRef = useForkedRef(ref, inputRef)
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (inputRef.current && indeterminate) {
|
|
98
|
+
inputRef.current.indeterminate = indeterminate
|
|
99
|
+
}
|
|
100
|
+
}, [indeterminate])
|
|
101
|
+
|
|
76
102
|
const _className = classNames(
|
|
77
103
|
'form-check',
|
|
78
104
|
{
|
|
@@ -102,7 +128,7 @@ export const CFormCheck = forwardRef<HTMLInputElement, CFormCheckProps>(
|
|
|
102
128
|
)
|
|
103
129
|
|
|
104
130
|
const formControl = () => {
|
|
105
|
-
return <input type={type} className={inputClassName} id={id} {...rest} ref={
|
|
131
|
+
return <input type={type} className={inputClassName} id={id} {...rest} ref={forkedRef} />
|
|
106
132
|
}
|
|
107
133
|
|
|
108
134
|
const formLabel = () => {
|
|
@@ -141,6 +167,7 @@ CFormCheck.propTypes = {
|
|
|
141
167
|
className: PropTypes.string,
|
|
142
168
|
hitArea: PropTypes.oneOf(['full']),
|
|
143
169
|
id: PropTypes.string,
|
|
170
|
+
indeterminate: PropTypes.bool,
|
|
144
171
|
inline: PropTypes.bool,
|
|
145
172
|
invalid: PropTypes.bool,
|
|
146
173
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { forwardRef,
|
|
1
|
+
import React, { forwardRef, AllHTMLAttributes } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
-
export interface CFormLabelProps extends
|
|
5
|
+
export interface CFormLabelProps extends AllHTMLAttributes<HTMLLabelElement> {
|
|
6
6
|
/**
|
|
7
7
|
* A string of all className you want applied to the component.
|
|
8
8
|
*/
|
|
@@ -2,6 +2,11 @@ import React, { ChangeEventHandler, forwardRef, InputHTMLAttributes } from 'reac
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
+
type Option = {
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
label?: string
|
|
8
|
+
value?: string
|
|
9
|
+
}
|
|
5
10
|
export interface CFormSelectProps extends Omit<InputHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
6
11
|
/**
|
|
7
12
|
* A string of all className you want applied to the component.
|
|
@@ -19,6 +24,13 @@ export interface CFormSelectProps extends Omit<InputHTMLAttributes<HTMLSelectEle
|
|
|
19
24
|
* Method called immediately after the `value` prop changes.
|
|
20
25
|
*/
|
|
21
26
|
onChange?: ChangeEventHandler<HTMLSelectElement>
|
|
27
|
+
/**
|
|
28
|
+
* Options list of the select component. Available keys: `label`, `value`, `disabled`.
|
|
29
|
+
* Examples:
|
|
30
|
+
* - `options={[{ value: 'js', label: 'JavaScript' }, { value: 'html', label: 'HTML', disabled: true }]}`
|
|
31
|
+
* - `options={['js', 'html']}`
|
|
32
|
+
*/
|
|
33
|
+
options?: Option[] | string[]
|
|
22
34
|
/**
|
|
23
35
|
* Size the component small or large.
|
|
24
36
|
*/
|
|
@@ -36,7 +48,7 @@ export interface CFormSelectProps extends Omit<InputHTMLAttributes<HTMLSelectEle
|
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
export const CFormSelect = forwardRef<HTMLSelectElement, CFormSelectProps>(
|
|
39
|
-
({ children, className, htmlSize, invalid, size, valid, ...rest }, ref) => {
|
|
51
|
+
({ children, className, htmlSize, invalid, options, size, valid, ...rest }, ref) => {
|
|
40
52
|
const _className = classNames(
|
|
41
53
|
'form-select',
|
|
42
54
|
{
|
|
@@ -48,7 +60,20 @@ export const CFormSelect = forwardRef<HTMLSelectElement, CFormSelectProps>(
|
|
|
48
60
|
)
|
|
49
61
|
return (
|
|
50
62
|
<select className={_className} size={htmlSize} {...rest} ref={ref}>
|
|
51
|
-
{
|
|
63
|
+
{options
|
|
64
|
+
? options.map((option, index) => {
|
|
65
|
+
return (
|
|
66
|
+
<option
|
|
67
|
+
{...(typeof option === 'object' &&
|
|
68
|
+
option.disabled && { disabled: option.disabled })}
|
|
69
|
+
{...(typeof option === 'object' && option.value && { value: option.value })}
|
|
70
|
+
key={index}
|
|
71
|
+
>
|
|
72
|
+
{typeof option === 'string' ? option : option.label}
|
|
73
|
+
</option>
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
: children}
|
|
52
77
|
</select>
|
|
53
78
|
)
|
|
54
79
|
},
|
|
@@ -59,6 +84,7 @@ CFormSelect.propTypes = {
|
|
|
59
84
|
className: PropTypes.string,
|
|
60
85
|
htmlSize: PropTypes.number,
|
|
61
86
|
invalid: PropTypes.bool,
|
|
87
|
+
options: PropTypes.array,
|
|
62
88
|
size: PropTypes.oneOf(['sm', 'lg']),
|
|
63
89
|
valid: PropTypes.bool,
|
|
64
90
|
}
|
|
@@ -15,3 +15,11 @@ test('CFormLabel customize className', async () => {
|
|
|
15
15
|
expect(container.firstChild).toHaveClass('form-label')
|
|
16
16
|
expect(container.firstChild).toHaveTextContent('Test')
|
|
17
17
|
})
|
|
18
|
+
|
|
19
|
+
test('CFormLabel customize htmlFor', async () => {
|
|
20
|
+
const { container } = render(<CFormLabel htmlFor="bazinga">Test</CFormLabel>)
|
|
21
|
+
expect(container).toMatchSnapshot()
|
|
22
|
+
expect(container.firstChild).toHaveAttribute('for', 'bazinga')
|
|
23
|
+
expect(container.firstChild).toHaveClass('form-label')
|
|
24
|
+
expect(container.firstChild).toHaveTextContent('Test')
|
|
25
|
+
})
|
|
@@ -10,6 +10,17 @@ exports[`CFormLabel customize className 1`] = `
|
|
|
10
10
|
</div>
|
|
11
11
|
`;
|
|
12
12
|
|
|
13
|
+
exports[`CFormLabel customize htmlFor 1`] = `
|
|
14
|
+
<div>
|
|
15
|
+
<label
|
|
16
|
+
class="form-label"
|
|
17
|
+
for="bazinga"
|
|
18
|
+
>
|
|
19
|
+
Test
|
|
20
|
+
</label>
|
|
21
|
+
</div>
|
|
22
|
+
`;
|
|
23
|
+
|
|
13
24
|
exports[`loads and displays CFormLabel component 1`] = `
|
|
14
25
|
<div>
|
|
15
26
|
<label
|
|
@@ -66,7 +66,7 @@ const BREAKPOINTS = [
|
|
|
66
66
|
|
|
67
67
|
export const CCol = forwardRef<HTMLDivElement, CColProps>(
|
|
68
68
|
({ children, className, ...rest }, ref) => {
|
|
69
|
-
const
|
|
69
|
+
const repsonsiveClassNames: string[] = []
|
|
70
70
|
|
|
71
71
|
BREAKPOINTS.forEach((bp) => {
|
|
72
72
|
const breakpoint = rest[bp]
|
|
@@ -75,34 +75,34 @@ export const CCol = forwardRef<HTMLDivElement, CColProps>(
|
|
|
75
75
|
const infix = bp === 'xs' ? '' : `-${bp}`
|
|
76
76
|
|
|
77
77
|
if (typeof breakpoint === 'number' || typeof breakpoint === 'string') {
|
|
78
|
-
|
|
78
|
+
repsonsiveClassNames.push(`col${infix}-${breakpoint}`)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
if (typeof breakpoint === 'boolean') {
|
|
82
|
-
|
|
82
|
+
repsonsiveClassNames.push(`col${infix}`)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
if (breakpoint && typeof breakpoint === 'object') {
|
|
86
86
|
if (typeof breakpoint.span === 'number' || typeof breakpoint.span === 'string') {
|
|
87
|
-
|
|
87
|
+
repsonsiveClassNames.push(`col${infix}-${breakpoint.span}`)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
if (typeof breakpoint.span === 'boolean') {
|
|
91
|
-
|
|
91
|
+
repsonsiveClassNames.push(`col${infix}`)
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
if (typeof breakpoint.order === 'number' || typeof breakpoint.order === 'string') {
|
|
95
|
-
|
|
95
|
+
repsonsiveClassNames.push(`order${infix}-${breakpoint.order}`)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
if (typeof breakpoint.offset === 'number') {
|
|
99
|
-
|
|
99
|
+
repsonsiveClassNames.push(`offset${infix}-${breakpoint.offset}`)
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
})
|
|
103
103
|
|
|
104
104
|
const _className = classNames(
|
|
105
|
-
|
|
105
|
+
repsonsiveClassNames.length ? repsonsiveClassNames : 'col',
|
|
106
106
|
className,
|
|
107
107
|
)
|
|
108
108
|
|
|
@@ -44,17 +44,17 @@ const BREAKPOINTS = [
|
|
|
44
44
|
|
|
45
45
|
export const CContainer = forwardRef<HTMLDivElement, CContainerProps>(
|
|
46
46
|
({ children, className, ...rest }, ref) => {
|
|
47
|
-
const
|
|
47
|
+
const repsonsiveClassNames: string[] = []
|
|
48
48
|
|
|
49
49
|
BREAKPOINTS.forEach((bp) => {
|
|
50
50
|
const breakpoint = rest[bp]
|
|
51
51
|
delete rest[bp]
|
|
52
52
|
|
|
53
|
-
breakpoint &&
|
|
53
|
+
breakpoint && repsonsiveClassNames.push(`container-${bp}`)
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
const _className = classNames(
|
|
57
|
-
|
|
57
|
+
repsonsiveClassNames.length ? repsonsiveClassNames : 'container',
|
|
58
58
|
className,
|
|
59
59
|
)
|
|
60
60
|
|
|
@@ -63,7 +63,7 @@ const BREAKPOINTS = [
|
|
|
63
63
|
|
|
64
64
|
export const CRow = forwardRef<HTMLDivElement, CRowProps>(
|
|
65
65
|
({ children, className, ...rest }, ref) => {
|
|
66
|
-
const
|
|
66
|
+
const repsonsiveClassNames: string[] = []
|
|
67
67
|
|
|
68
68
|
BREAKPOINTS.forEach((bp) => {
|
|
69
69
|
const breakpoint = rest[bp]
|
|
@@ -73,21 +73,21 @@ export const CRow = forwardRef<HTMLDivElement, CRowProps>(
|
|
|
73
73
|
|
|
74
74
|
if (typeof breakpoint === 'object') {
|
|
75
75
|
if (breakpoint.cols) {
|
|
76
|
-
|
|
76
|
+
repsonsiveClassNames.push(`row-cols${infix}-${breakpoint.cols}`)
|
|
77
77
|
}
|
|
78
78
|
if (typeof breakpoint.gutter === 'number') {
|
|
79
|
-
|
|
79
|
+
repsonsiveClassNames.push(`g${infix}-${breakpoint.gutter}`)
|
|
80
80
|
}
|
|
81
81
|
if (typeof breakpoint.gutterX === 'number') {
|
|
82
|
-
|
|
82
|
+
repsonsiveClassNames.push(`gx${infix}-${breakpoint.gutterX}`)
|
|
83
83
|
}
|
|
84
84
|
if (typeof breakpoint.gutterY === 'number') {
|
|
85
|
-
|
|
85
|
+
repsonsiveClassNames.push(`gy${infix}-${breakpoint.gutterY}`)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
})
|
|
89
89
|
|
|
90
|
-
const _className = classNames('row',
|
|
90
|
+
const _className = classNames('row', repsonsiveClassNames, className)
|
|
91
91
|
|
|
92
92
|
return (
|
|
93
93
|
<div className={_className} ref={ref}>
|
|
@@ -150,8 +150,21 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
150
150
|
</Transition>
|
|
151
151
|
{typeof window !== 'undefined' && portal
|
|
152
152
|
? backdrop &&
|
|
153
|
-
createPortal(
|
|
154
|
-
|
|
153
|
+
createPortal(
|
|
154
|
+
<CBackdrop
|
|
155
|
+
className="offcanvas-backdrop"
|
|
156
|
+
onClick={handleDismiss}
|
|
157
|
+
visible={_visible}
|
|
158
|
+
/>,
|
|
159
|
+
document.body,
|
|
160
|
+
)
|
|
161
|
+
: backdrop && (
|
|
162
|
+
<CBackdrop
|
|
163
|
+
className="offcanvas-backdrop"
|
|
164
|
+
onClick={handleDismiss}
|
|
165
|
+
visible={_visible}
|
|
166
|
+
/>
|
|
167
|
+
)}
|
|
155
168
|
</>
|
|
156
169
|
)
|
|
157
170
|
},
|
|
@@ -51,7 +51,7 @@ test('COffcanvas customize and event on click backdrop', async () => {
|
|
|
51
51
|
expect(container.firstChild).toHaveClass('show')
|
|
52
52
|
expect(container.firstChild).toHaveTextContent('Test')
|
|
53
53
|
expect(onHide).toHaveBeenCalledTimes(0)
|
|
54
|
-
const backdrop = document.querySelector('.
|
|
54
|
+
const backdrop = document.querySelector('.offcanvas-backdrop')
|
|
55
55
|
if (backdrop !== null) {
|
|
56
56
|
fireEvent.click(backdrop)
|
|
57
57
|
}
|
|
@@ -11,7 +11,7 @@ exports[`COffcanvas customize and event on click backdrop 1`] = `
|
|
|
11
11
|
Test
|
|
12
12
|
</div>
|
|
13
13
|
<div
|
|
14
|
-
class="
|
|
14
|
+
class="offcanvas-backdrop fade show"
|
|
15
15
|
/>
|
|
16
16
|
</div>
|
|
17
17
|
`;
|
|
@@ -27,7 +27,7 @@ exports[`COffcanvas customize and event on keypress 1`] = `
|
|
|
27
27
|
Test
|
|
28
28
|
</div>
|
|
29
29
|
<div
|
|
30
|
-
class="
|
|
30
|
+
class="offcanvas-backdrop fade show"
|
|
31
31
|
/>
|
|
32
32
|
</div>
|
|
33
33
|
`;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React, { ElementType, forwardRef, HTMLAttributes } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import classNames from 'classnames'
|
|
4
|
+
|
|
5
|
+
import { Colors, colorPropType } from '../Types'
|
|
6
|
+
|
|
7
|
+
export interface CPlaceholderProps extends HTMLAttributes<HTMLSpanElement> {
|
|
8
|
+
/**
|
|
9
|
+
* Set animation type to better convey the perception of something being actively loaded.
|
|
10
|
+
*/
|
|
11
|
+
animation?: 'glow' | 'wave'
|
|
12
|
+
/**
|
|
13
|
+
* A string of all className you want applied to the component.
|
|
14
|
+
*/
|
|
15
|
+
className?: string
|
|
16
|
+
/**
|
|
17
|
+
* Sets the color context of the component to one of CoreUI’s themed colors.
|
|
18
|
+
*
|
|
19
|
+
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
|
|
20
|
+
*/
|
|
21
|
+
color?: Colors
|
|
22
|
+
/**
|
|
23
|
+
* Component used for the root node. Either a string to use a HTML element or a component.
|
|
24
|
+
*/
|
|
25
|
+
component?: string | ElementType
|
|
26
|
+
/**
|
|
27
|
+
* Size the component extra small, small, or large.
|
|
28
|
+
*/
|
|
29
|
+
size?: 'xs' | 'sm' | 'lg'
|
|
30
|
+
/**
|
|
31
|
+
* The number of columns on extra small devices (<576px).
|
|
32
|
+
*/
|
|
33
|
+
xs?: number
|
|
34
|
+
/**
|
|
35
|
+
* The number of columns on small devices (<768px).
|
|
36
|
+
*/
|
|
37
|
+
sm?: number
|
|
38
|
+
/**
|
|
39
|
+
* The number of columns on medium devices (<992px).
|
|
40
|
+
*/
|
|
41
|
+
md?: number
|
|
42
|
+
/**
|
|
43
|
+
* The number of columns on large devices (<1200px).
|
|
44
|
+
*/
|
|
45
|
+
lg?: number
|
|
46
|
+
/**
|
|
47
|
+
* The number of columns on X-Large devices (<1400px).
|
|
48
|
+
*/
|
|
49
|
+
xl?: number
|
|
50
|
+
/**
|
|
51
|
+
* The number of columns on XX-Large devices (≥1400px).
|
|
52
|
+
*/
|
|
53
|
+
xxl?: number
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const BREAKPOINTS = [
|
|
57
|
+
'xxl' as const,
|
|
58
|
+
'xl' as const,
|
|
59
|
+
'lg' as const,
|
|
60
|
+
'md' as const,
|
|
61
|
+
'sm' as const,
|
|
62
|
+
'xs' as const,
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
export const CPlaceholder = forwardRef<HTMLSpanElement, CPlaceholderProps>(
|
|
66
|
+
(
|
|
67
|
+
{ children, animation, className, color, component: Component = 'span', size, ...rest },
|
|
68
|
+
ref,
|
|
69
|
+
) => {
|
|
70
|
+
const repsonsiveClassNames: string[] = []
|
|
71
|
+
|
|
72
|
+
BREAKPOINTS.forEach((bp) => {
|
|
73
|
+
const breakpoint = rest[bp]
|
|
74
|
+
delete rest[bp]
|
|
75
|
+
|
|
76
|
+
const infix = bp === 'xs' ? '' : `-${bp}`
|
|
77
|
+
|
|
78
|
+
if (typeof breakpoint === 'number') {
|
|
79
|
+
repsonsiveClassNames.push(`col${infix}-${breakpoint}`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (typeof breakpoint === 'boolean') {
|
|
83
|
+
repsonsiveClassNames.push(`col${infix}`)
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const _className = classNames(
|
|
88
|
+
animation ? `placeholder-${animation}` : 'placeholder',
|
|
89
|
+
{
|
|
90
|
+
[`bg-${color}`]: color,
|
|
91
|
+
[`placeholder-${size}`]: size,
|
|
92
|
+
},
|
|
93
|
+
repsonsiveClassNames,
|
|
94
|
+
className,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Component className={_className} {...rest} ref={ref}>
|
|
99
|
+
{children}
|
|
100
|
+
</Component>
|
|
101
|
+
)
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
CPlaceholder.propTypes = {
|
|
106
|
+
animation: PropTypes.oneOf(['glow', 'wave']),
|
|
107
|
+
children: PropTypes.node,
|
|
108
|
+
className: PropTypes.string,
|
|
109
|
+
color: colorPropType,
|
|
110
|
+
component: PropTypes.elementType,
|
|
111
|
+
size: PropTypes.oneOf(['xs', 'sm', 'lg']),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
CPlaceholder.displayName = 'CPlaceholder'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom/extend-expect'
|
|
4
|
+
import { CPlaceholder } from '../../../index'
|
|
5
|
+
|
|
6
|
+
test('loads and displays CPlaceholder component', async () => {
|
|
7
|
+
const { container } = render(<CPlaceholder color="primary" />)
|
|
8
|
+
expect(container).toMatchSnapshot()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('CPlaceholder customize', async () => {
|
|
12
|
+
const { container } = render(
|
|
13
|
+
<CPlaceholder animation="glow" className="bazinga" color="secondary" size="lg" sm={7} />,
|
|
14
|
+
)
|
|
15
|
+
expect(container).toMatchSnapshot()
|
|
16
|
+
expect(container.firstChild).toHaveClass('bazinga')
|
|
17
|
+
expect(container.firstChild).toHaveClass('bg-secondary')
|
|
18
|
+
expect(container.firstChild).toHaveClass('col-sm-7')
|
|
19
|
+
expect(container.firstChild).toHaveClass('placeholder-lg')
|
|
20
|
+
expect(container.firstChild).toHaveClass('placeholder-glow')
|
|
21
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`CPlaceholder customize 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<span
|
|
6
|
+
class="placeholder-glow bg-secondary placeholder-lg col-sm-7 bazinga"
|
|
7
|
+
/>
|
|
8
|
+
</div>
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
exports[`loads and displays CPlaceholder component 1`] = `
|
|
12
|
+
<div>
|
|
13
|
+
<span
|
|
14
|
+
class="placeholder bg-primary"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
`;
|