Skip to content

Commit 31bfa1b

Browse files
author
Tomasz John
committed
- update: new ts version of CIcon
1 parent fa81d2e commit 31bfa1b

File tree

1 file changed

+82
-55
lines changed

1 file changed

+82
-55
lines changed

src/CIcon.tsx

Lines changed: 82 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,84 @@
1-
import React, { useMemo, useState } from 'react'
2-
import PropTypes from 'prop-types'
1+
import React, { HTMLAttributes, FC, useState, useMemo } from 'react'
32
import classNames from 'classnames'
43
import './CIcon.css'
54

5+
export interface CIconProps extends HTMLAttributes<SVGSVGElement> {
6+
/**
7+
* A string of all className you want applied to the component. [docs]
8+
*/
9+
className?: string
10+
/**
11+
* Name of the icon placed in React object. [docs]
12+
*/
13+
name?: string
14+
/**
15+
* Icon SVG content. [docs]
16+
*/
17+
content?: string | Array<string>
18+
/**
19+
* Size of the icon. Available sizes: 'sm', 'lg', 'xl', '2xl'...'9xl', 'custom', 'custom-size'. [docs]
20+
*/
21+
size?: 'custom'|'custom-size'|'sm'|'lg'|'xl'|'2xl'|'3xl'|'4xl'|'5xl'|'6xl'|'7xl'|'8xl'|'9xl'
22+
/**
23+
* Use for replacing default CIcon component classes. Prop is overriding the 'size' prop. [docs]
24+
*/
25+
customClasses?: string | object | Array<string>
26+
/**
27+
* Link to the icon. If defined component will be rendered as 'img' tag. [docs]
28+
*/
29+
src?: string
30+
/**
31+
* If defined component will be rendered using 'use' tag. [docs]
32+
*/
33+
use?: string
34+
/**
35+
* Title tag content. [docs]
36+
*/
37+
title?: string
38+
}
39+
640
let warned = {}
7-
const colog = (msg, icon) => {
8-
if (!warned[icon] && process && process.env && process.env.NODE_ENV === 'development') {
41+
const colog = (msg: string, icon?: string) => {
42+
if (icon && !warned[icon] && process && process.env && process.env.NODE_ENV === 'development') {
943
warned[icon] = true
1044
console.error(msg)
1145
}
1246
}
1347

14-
const toCamelCase = (str) => {
48+
const toCamelCase = (str: string) => {
1549
return str.replace(/([-_][a-z0-9])/ig, ($1) => {
1650
return $1.toUpperCase()
1751
}).replace(/-/ig, '')
1852
}
1953

2054
//component - CoreUI / CIcon
21-
const CIcon = props => {
22-
23-
const {
24-
className,
25-
name,
26-
content,
27-
customClasses,
28-
size,
29-
src,
30-
title,
31-
use,
32-
...attributes
33-
} = props
55+
const CIcon: FC<CIconProps> = ({
56+
className,
57+
name,
58+
content,
59+
customClasses,
60+
size,
61+
src,
62+
title,
63+
use,
64+
...rest
65+
}) => {
3466

3567
const [change, setChange] = useState(0)
3668

37-
useMemo(() => setChange(change + 1), [name, JSON.stringify[content]])
69+
useMemo(() => setChange(change + 1), [name, JSON.stringify(content)])
3870

39-
const iconName = useMemo(()=>{
40-
const iconNameIsKebabCase = name && name.includes('-')
41-
return iconNameIsKebabCase ? toCamelCase(name) : name
42-
}, [change])
71+
const iconName = useMemo(() => ( name && name.includes('-') ) ? toCamelCase(name) : name, [change])
4372

4473
const titleCode = title ? `<title>${title}</title>` : ''
4574

4675
const code = useMemo(() => {
4776
if (content) {
4877
return content
49-
} else if (name && React.icons) {
50-
return React.icons[iconName] ? React.icons[iconName] :
78+
} else if (name && React['icons']) {
79+
return React['icons'][iconName] ? React['icons'][iconName] :
5180
colog(`CIcon component: icon name '${iconName}' does not exist in React.icons object. ` +
52-
`To use icons by 'name' prop you need to make them available globally ` +
81+
`To use icons by 'name' prop you need to make them available globally ` +
5382
`by adding them to React.icons object. CIcon component docs: https://coreui.io/react/docs/components/CIcon \n`,
5483
iconName
5584
)
@@ -65,28 +94,38 @@ const CIcon = props => {
6594
})()
6695

6796
const viewBox = (()=>{
68-
return attributes.viewBox || `0 0 ${scale}`
97+
return rest['viewBox'] || `0 0 ${scale}`
6998
})()
7099

71-
const computedSize = (()=>{
72-
const addCustom = !size && (attributes.width || attributes.height)
73-
return size === 'custom' || addCustom ? 'custom-size' : size
74-
})()
100+
// render
75101

76-
//render
77-
const computedClasses = classNames(
78-
'c-icon',
79-
computedSize && `c-icon-${computedSize}`,
80-
className
81-
)
102+
let classes
82103

83-
const classes = customClasses || computedClasses
104+
if (customClasses) {
105+
classes = classNames(
106+
customClasses
107+
)
108+
}
109+
else
110+
{
111+
const computedSize = (()=>{
112+
const addCustom = !size && (rest['width'] || rest['height'])
113+
return size === 'custom' || addCustom ? 'custom-size' : size
114+
})()
115+
classes = classNames(
116+
'c-icon',
117+
computedSize && `c-icon-${computedSize}`,
118+
className
119+
)
120+
}
121+
122+
//const classes = customClasses || computedClasses
84123

85124
return (
86125
<React.Fragment>
87126
{ !src && !use &&
88127
<svg
89-
{...attributes}
128+
{...rest}
90129
xmlns="http://www.w3.org/2000/svg"
91130
viewBox={viewBox}
92131
className={classes}
@@ -96,15 +135,14 @@ const CIcon = props => {
96135
}
97136
{ src && !use &&
98137
<img
99-
{...attributes}
100138
className={className}
101139
src={src}
102140
role="img"
103141
/>
104142
}
105143
{ !src && use &&
106144
<svg
107-
{...attributes}
145+
{...rest}
108146
xmlns="http://www.w3.org/2000/svg"
109147
className={classes}
110148
role="img"
@@ -114,25 +152,14 @@ const CIcon = props => {
114152
}
115153
</React.Fragment>
116154
)
117-
}
118155

119-
CIcon.propTypes = {
120-
className: PropTypes.string,
121-
name: PropTypes.string,
122-
content: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
123-
size: PropTypes.oneOf([
124-
'custom', 'custom-size', 'sm', 'lg', 'xl',
125-
'2xl', '3xl', '4xl', '5xl', '6xl', '7xl', '8xl', '9xl'
126-
]),
127-
customClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object]),
128-
src: PropTypes.string,
129-
title: PropTypes.string,
130-
use: PropTypes.string
131156
}
132157

133158
export default CIcon
134159

135-
export const CIconWarn = props => {
160+
//
161+
162+
export const CIconWarn: FC<CIconProps> = (props) => {
136163
colog(
137164
'@coreui/icons-react: Please use default export since named exports are deprecated'
138165
)

0 commit comments

Comments
 (0)