Skip to content

Commit cfbff31

Browse files
committed
refactor: improve syntax
1 parent 141d8a2 commit cfbff31

File tree

3 files changed

+125
-140
lines changed

3 files changed

+125
-140
lines changed

src/CIcon.css

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,77 @@
1-
.c-icon {
1+
.icon {
22
display: inline-block;
33
color: inherit;
44
text-align: center;
55
fill: currentColor;
66
}
77

8-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size) {
8+
.icon:not(.icon-c-s):not(.icon-custom-size) {
99
width: 1rem;
1010
height: 1rem;
1111
font-size: 1rem;
1212
}
1313

14-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-2xl {
14+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-2xl {
1515
width: 2rem;
1616
height: 2rem;
1717
font-size: 2rem;
1818
}
1919

20-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-3xl {
20+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-3xl {
2121
width: 3rem;
2222
height: 3rem;
2323
font-size: 3rem;
2424
}
2525

26-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-4xl {
26+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-4xl {
2727
width: 4rem;
2828
height: 4rem;
2929
font-size: 4rem;
3030
}
3131

32-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-5xl {
32+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-5xl {
3333
width: 5rem;
3434
height: 5rem;
3535
font-size: 5rem;
3636
}
3737

38-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-6xl {
38+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-6xl {
3939
width: 6rem;
4040
height: 6rem;
4141
font-size: 6rem;
4242
}
4343

44-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-7xl {
44+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-7xl {
4545
width: 7rem;
4646
height: 7rem;
4747
font-size: 7rem;
4848
}
4949

50-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-8xl {
50+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-8xl {
5151
width: 8rem;
5252
height: 8rem;
5353
font-size: 8rem;
5454
}
5555

56-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-9xl {
56+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-9xl {
5757
width: 9rem;
5858
height: 9rem;
5959
font-size: 9rem;
6060
}
6161

62-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-xl {
62+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-xl {
6363
width: 1.5rem;
6464
height: 1.5rem;
6565
font-size: 1.5rem;
6666
}
6767

68-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-lg {
68+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-lg {
6969
width: 1.25rem;
7070
height: 1.25rem;
7171
font-size: 1.25rem;
7272
}
7373

74-
.c-icon:not(.c-icon-c-s):not(.c-icon-custom-size).c-icon-sm {
74+
.icon:not(.icon-c-s):not(.icon-custom-size).icon-sm {
7575
width: 0.875rem;
7676
height: 0.875rem;
7777
font-size: 0.875rem;

src/CIcon.tsx

Lines changed: 110 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import React, { DOMAttributes, FC, useState, useMemo } from 'react'
1+
import PropTypes from 'prop-types'
2+
import React, { DOMAttributes, forwardRef, useState, useMemo } from 'react'
23
import classNames from 'classnames'
34
import './CIcon.css'
45

5-
export interface CIconProps extends DOMAttributes<SVGSVGElement|HTMLImageElement> {
6+
export interface CIconProps extends DOMAttributes<SVGSVGElement> {
67
/**
78
* A string of all className you want applied to the component. [docs]
89
*/
@@ -18,15 +19,23 @@ export interface CIconProps extends DOMAttributes<SVGSVGElement|HTMLImageElement
1819
/**
1920
* Size of the icon. Available sizes: 'sm', 'lg', 'xl', '2xl'...'9xl', 'custom', 'custom-size'. [docs]
2021
*/
21-
size?: 'custom'|'custom-size'|'sm'|'lg'|'xl'|'2xl'|'3xl'|'4xl'|'5xl'|'6xl'|'7xl'|'8xl'|'9xl'
22+
size?:
23+
| 'custom-size'
24+
| 'sm'
25+
| 'lg'
26+
| 'xl'
27+
| '2xl'
28+
| '3xl'
29+
| '4xl'
30+
| '5xl'
31+
| '6xl'
32+
| '7xl'
33+
| '8xl'
34+
| '9xl'
2235
/**
2336
* Use for replacing default CIcon component classes. Prop is overriding the 'size' prop. [docs]
2437
*/
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
38+
customClassName?: string | object | Array<string>
3039
/**
3140
* If defined component will be rendered using 'use' tag. [docs]
3241
*/
@@ -35,8 +44,8 @@ export interface CIconProps extends DOMAttributes<SVGSVGElement|HTMLImageElement
3544
* Title tag content. [docs]
3645
*/
3746
title?: string
38-
width?: string
39-
height?: string
47+
// width?: string
48+
// height?: string
4049
}
4150

4251
let warned = {}
@@ -48,127 +57,106 @@ const colog = (msg: string, icon?: string) => {
4857
}
4958

5059
const toCamelCase = (str: string) => {
51-
return str.replace(/([-_][a-z0-9])/ig, ($1) => {
52-
return $1.toUpperCase()
53-
}).replace(/-/ig, '')
60+
return str
61+
.replace(/([-_][a-z0-9])/gi, ($1) => {
62+
return $1.toUpperCase()
63+
})
64+
.replace(/-/gi, '')
5465
}
5566

56-
//component - CoreUI / CIcon
57-
const CIcon: FC<CIconProps> = ({
58-
className,
59-
name,
60-
content,
61-
customClasses,
62-
size,
63-
src,
64-
title,
65-
use,
66-
...rest
67-
}) => {
68-
69-
const [change, setChange] = useState(0)
70-
71-
useMemo(() => setChange(change + 1), [name, JSON.stringify(content)])
72-
73-
const iconName = useMemo(() => ( name && name.includes('-') ) ? toCamelCase(name) : name, [change])
74-
75-
const titleCode = title ? `<title>${title}</title>` : ''
76-
77-
const code = useMemo(() => {
78-
if (content) {
79-
return content
80-
} else if (name && React['icons']) {
81-
return React['icons'][iconName] ? React['icons'][iconName] :
82-
colog(`CIcon component: icon name '${iconName}' does not exist in React.icons object. ` +
83-
`To use icons by 'name' prop you need to make them available globally ` +
84-
`by adding them to React.icons object. CIcon component docs: https://coreui.io/react/docs/components/CIcon \n`,
85-
iconName
86-
)
87-
}
88-
}, [change])
67+
export const CIcon = forwardRef<SVGSVGElement, CIconProps>(
68+
({ className, name, content, customClassName, size, title, use, ...rest }, ref) => {
69+
const [change, setChange] = useState(0)
8970

90-
const iconCode = useMemo(()=>{
91-
return Array.isArray(code) ? code[1] || code[0] : code
92-
}, [change])
71+
useMemo(() => setChange(change + 1), [name, JSON.stringify(content)])
9372

94-
const scale = (()=>{
95-
return Array.isArray(code) && code.length > 1 ? code[0] : '64 64'
96-
})()
73+
const iconName = useMemo(
74+
() => (name && name.includes('-') ? toCamelCase(name) : name),
75+
[change],
76+
)
9777

98-
const viewBox = (()=>{
99-
return rest['viewBox'] || `0 0 ${scale}`
100-
})()
78+
const titleCode = title ? `<title>${title}</title>` : ''
79+
80+
const code = useMemo(() => {
81+
if (content) {
82+
return content
83+
} else if (name && React['icons']) {
84+
return React['icons'][iconName]
85+
? React['icons'][iconName]
86+
: colog(
87+
`CIcon component: icon name '${iconName}' does not exist in React.icons object. ` +
88+
`To use icons by 'name' prop you need to make them available globally ` +
89+
`by adding them to React.icons object. CIcon component docs: https://coreui.io/react/docs/components/CIcon \n`,
90+
iconName,
91+
)
92+
}
93+
}, [change])
10194

102-
// render
95+
const iconCode = useMemo(() => {
96+
return Array.isArray(code) ? code[1] || code[0] : code
97+
}, [change])
10398

104-
let classes
99+
const scale = (() => {
100+
return Array.isArray(code) && code.length > 1 ? code[0] : '64 64'
101+
})()
105102

106-
if (customClasses) {
107-
classes = classNames(
108-
customClasses
109-
)
110-
}
111-
else
112-
{
113-
const computedSize = (()=>{
114-
const addCustom = !size && (rest['width'] || rest['height'])
115-
return size === 'custom' || addCustom ? 'custom-size' : size
103+
const viewBox = (() => {
104+
return rest['viewBox'] || `0 0 ${scale}`
116105
})()
117-
classes = classNames(
118-
'c-icon',
119-
computedSize && `c-icon-${computedSize}`,
120-
className
121-
)
122-
}
123-
//const classes = customClasses || computedClasses
124-
125-
// let restImg: HTMLAttributes<HTMLImageElement> = {}
126-
// if (src && !use) {
127-
// restImg = rest as HTMLAttributes<HTMLImageElement>
128-
// }
129-
130-
return (
131-
<React.Fragment>
132-
{ !src && !use &&
133-
<svg
134-
{...rest}
135-
xmlns="http://www.w3.org/2000/svg"
136-
viewBox={viewBox}
137-
className={classes}
138-
role="img"
139-
dangerouslySetInnerHTML={{__html: titleCode + iconCode}}
140-
/>
141-
}
142-
{ src && !use &&
143-
<img
144-
{...rest}
145-
className={className}
146-
src={src}
147-
role="img"
148-
/>
149-
}
150-
{ !src && use &&
151-
<svg
152-
{...rest}
153-
xmlns="http://www.w3.org/2000/svg"
154-
className={classes}
155-
role="img"
156-
>
157-
<use href={use}></use>
158-
</svg>
159-
}
160-
</React.Fragment>
161-
)
162106

107+
// render
108+
109+
const _className = customClassName
110+
? classNames(customClassName)
111+
: classNames(
112+
'icon',
113+
{
114+
[`icon-${size}`]: size,
115+
[`icon-custom-size`]: rest['height'] || rest['width']
116+
},
117+
className,
118+
)
119+
120+
colog('@coreui/icons-react: Please use default export since named exports are deprecated')
121+
return use ? (
122+
<svg xmlns="http://www.w3.org/2000/svg" className={_className} role="img" {...rest} ref={ref}>
123+
<use href={use}></use>
124+
</svg>
125+
) : (
126+
<svg
127+
xmlns="http://www.w3.org/2000/svg"
128+
viewBox={viewBox}
129+
className={_className}
130+
role="img"
131+
dangerouslySetInnerHTML={{ __html: titleCode + iconCode }}
132+
{...rest}
133+
ref={ref}
134+
/>
135+
)
136+
},
137+
)
138+
139+
CIcon.propTypes = {
140+
className: PropTypes.any,
141+
content: PropTypes.any,
142+
customClassName: PropTypes.any,
143+
name: PropTypes.string,
144+
size: PropTypes.oneOf([
145+
'custom-size',
146+
'sm',
147+
'lg',
148+
'xl',
149+
'2xl',
150+
'3xl',
151+
'4xl',
152+
'5xl',
153+
'6xl',
154+
'7xl',
155+
'8xl',
156+
'9xl',
157+
]),
158+
title: PropTypes.any,
159+
use: PropTypes.any,
163160
}
164161

165-
export default CIcon
166-
167-
//
168-
169-
export const CIconWarn: FC<CIconProps> = (props) => {
170-
colog(
171-
'@coreui/icons-react: Please use default export since named exports are deprecated'
172-
)
173-
return <CIcon {...props}/>
174-
}
162+
CIcon.displayName = 'CIcon'

src/index.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import {default as CIcon, CIconWarn} from './CIcon'
1+
import { CIcon } from './CIcon'
22

33
export default CIcon
44

5-
export {
6-
CIconWarn as CIcon,
7-
CIconWarn as CIconRaw
8-
}
5+
// export { CIconWarning as CIcon, CIconWarning as CIconRaw }

0 commit comments

Comments
 (0)