@@ -4,15 +4,13 @@ import React, {
44 SVGAttributes ,
55 useContext ,
66 useRef ,
7- useState ,
87 useEffect ,
98 useCallback ,
109} from 'react' ;
1110import classnames from 'classnames' ;
1211import svg4everybody from 'svg4everybody' ;
1312import { registerStyle , getAssetRoot } from './util' ;
1413import { ComponentSettingsContext } from './ComponentSettings' ;
15- import { useEventCallback } from './hooks' ;
1614import { createFC } from './common' ;
1715
1816svg4everybody ( ) ;
@@ -124,23 +122,19 @@ function useInitComponentStyle() {
124122
125123function getIconColor (
126124 fillColor : string | undefined ,
127- category : string | undefined ,
125+ category : IconCategory ,
128126 icon : string
129127) {
130128 /* eslint-disable no-unneeded-ternary */
131- return category === 'doctype'
132- ? null
133- : fillColor === 'none'
129+ return fillColor === 'none'
134130 ? null
135131 : fillColor
136132 ? fillColor
137133 : category === 'utility'
138134 ? null
139- : category === 'custom'
140- ? icon . replace ( / ^ c u s t o m / , 'custom-' )
141- : category === 'action' && / ^ n e w _ c u s t o m / . test ( icon )
135+ : category === 'action' && / ^ n e w _ c u s t o m / . test ( icon ) // not needed for the current SLDS2 icons
142136 ? icon . replace ( / ^ n e w _ c u s t o m / , 'custom-' )
143- : `${ category ?? '' } -${ ( icon ?? '' ) . replace ( / _ / g, '-' ) } ` ;
137+ : `${ category } -${ icon . replace ( / _ / g, '-' ) } ` ;
144138 /* eslint-enable no-unneeded-ternary */
145139}
146140
@@ -154,8 +148,15 @@ export type IconCategory =
154148 | 'standard'
155149 | 'utility' ;
156150export type IconSize = 'xx-small' | 'x-small' | 'small' | 'medium' | 'large' ;
157- export type IconContainer = boolean | 'default' | 'circle' ;
158- export type IconTextColor = 'default' | 'warning' | 'error' | null ;
151+ export type IconContainer = 'circle' ;
152+ export type IconTextColor =
153+ | 'default'
154+ | 'currentColor'
155+ | 'success'
156+ | 'warning'
157+ | 'error'
158+ | 'light'
159+ | null ;
159160
160161/**
161162 *
@@ -167,55 +168,56 @@ export type IconProps = {
167168 size ?: IconSize ;
168169 align ?: 'left' | 'right' ;
169170 container ?: IconContainer ;
170- color ?: string ;
171171 textColor ?: IconTextColor ;
172- tabIndex ?: number ;
173172 fillColor ?: string ;
173+ title ?: string ;
174+ flip ?: boolean ;
174175} & SVGAttributes < SVGElement > ;
175176
176177/**
177178 *
178179 */
179180type SvgIconProps = IconProps & {
180- iconColor : string | null ;
181+ iconColor ? : string | null ;
181182} ;
182183
183184/**
184185 *
185186 */
186- const SvgIcon = forwardRef (
187+ export const SvgIcon = forwardRef (
187188 ( props : SvgIconProps , ref : ForwardedRef < SVGSVGElement | null > ) => {
188189 const {
189190 className = '' ,
190191 category : category_ = 'utility' ,
191192 icon : icon_ ,
192- iconColor,
193+ iconColor = null ,
193194 size = '' ,
194195 align,
195- container,
196196 textColor = 'default' ,
197197 style,
198198 ...rprops
199199 } = props ;
200200 const { assetRoot = getAssetRoot ( ) } = useContext ( ComponentSettingsContext ) ;
201- const iconClassNames = classnames (
202- 'react-slds-icon' ,
203- {
204- 'slds-icon' : ! / s l d s - b u t t o n _ _ i c o n / . test ( className ) ,
205- [ `slds-icon_${ size } ` ] : / ^ ( x x - s m a l l | x - s m a l l | s m a l l | m e d i u m | l a r g e ) $ / . test (
206- size
207- ) ,
208- [ `slds-icon-text-${ textColor ?? 'default' } ` ] :
209- / ^ ( d e f a u l t | w a r n i n g | e r r o r ) $ / . test ( textColor ?? '' ) && ! iconColor ,
210- [ `slds-icon-${ iconColor ?? '' } ` ] : ! container && iconColor ,
211- 'slds-m-left_x-small' : align === 'right' ,
212- 'slds-m-right_x-small' : align === 'left' ,
213- } ,
214- className
215- ) ;
201+
202+ const inIcon = ! / s l d s - b u t t o n _ _ i c o n / . test ( className ) ;
203+ const iconOnlyClassNames = classnames ( 'react-slds-icon' , 'slds-icon' , {
204+ [ `slds-icon_${ size } ` ] : / ^ ( x x - s m a l l | x - s m a l l | s m a l l | m e d i u m | l a r g e ) $ / . test (
205+ size
206+ ) ,
207+ [ `slds-icon-text-${ textColor ?? 'default' } ` ] :
208+ / ^ ( d e f a u l t | s u c c e s s | w a r n i n g | e r r o r | l i g h t ) $ / . test ( textColor ?? '' ) &&
209+ ! iconColor ,
210+ 'slds-m-left_x-small' : align === 'right' ,
211+ 'slds-m-right_x-small' : align === 'left' ,
212+ } ) ;
213+
214+ const iconClassNames = classnames ( className , {
215+ [ iconOnlyClassNames ] : inIcon ,
216+ } ) ;
217+
216218 // icon and category prop should not include chars other than alphanumerics, underscore, and hyphen
217- const icon = ( icon_ ?? '' ) . replace ( / [ ^ \w - ] / g, '' ) ; // eslint-disable-line no-param-reassign
218- const category = ( category_ ?? '' ) . replace ( / [ ^ \w - ] / g, '' ) ; // eslint-disable-line no-param-reassign
219+ const icon = ( icon_ ?? '' ) . replace ( / [ ^ \w - ] / g, '' ) ;
220+ const category = ( category_ ?? '' ) . replace ( / [ ^ \w - ] / g, '' ) ;
219221 const iconUrl = `${ assetRoot } /icons/${ category } -sprite/svg/symbols.svg#${ icon } ` ;
220222 return (
221223 < svg
@@ -236,13 +238,19 @@ const SvgIcon = forwardRef(
236238 */
237239export const Icon = createFC < IconProps , { ICONS : typeof ICONS } > (
238240 ( props ) => {
239- const { container, containerClassName, fillColor, ...rprops } = props ;
241+ const {
242+ container,
243+ containerClassName : containerClassName_ ,
244+ fillColor,
245+ textColor = 'default' ,
246+ title,
247+ flip,
248+ ...rprops
249+ } = props ;
240250 let { category = 'utility' , icon } = props ;
241251
242252 useInitComponentStyle ( ) ;
243253
244- const iconContainerRef = useRef < HTMLSpanElement | null > ( null ) ;
245-
246254 const svgIconRef = useRef < SVGSVGElement | null > ( null ) ;
247255
248256 const svgIconRefCallback = useCallback (
@@ -255,72 +263,44 @@ export const Icon = createFC<IconProps, { ICONS: typeof ICONS }>(
255263 [ props . tabIndex ]
256264 ) ;
257265
258- const [ iconColor , setIconColor ] = useState < string | null > ( null ) ;
259-
260- const checkIconColor = useEventCallback ( ( ) => {
261- if (
262- fillColor ||
263- category === 'doctype' ||
264- ( ! fillColor && category === 'utility' ) ||
265- iconColor === 'standard-default'
266- ) {
267- return ;
268- }
269- const el = container ? iconContainerRef . current : svgIconRef . current ;
270- if ( ! el ) {
271- return ;
272- }
273- const bgColorStyle = getComputedStyle ( el ) . backgroundColor ;
274- // if no background color set to the icon
275- if (
276- bgColorStyle &&
277- / ^ ( t r a n s p a r e n t | r g b a \( 0 , \s * 0 , \s * 0 , \s * 0 \) ) $ / . test ( bgColorStyle )
278- ) {
279- setIconColor ( 'standard-default' ) ;
280- }
281- } ) ;
282-
283266 useEffect ( ( ) => {
284267 svgIconRefCallback ( svgIconRef . current ) ;
285268 } , [ svgIconRefCallback ] ) ;
286269
287- useEffect ( ( ) => {
288- checkIconColor ( ) ;
289- } , [ checkIconColor ] ) ;
290-
291270 if ( icon . indexOf ( ':' ) > 0 ) {
292271 [ category , icon ] = icon . split ( ':' ) as [ IconCategory , string ] ;
293272 }
294273
295- const fillIconColor =
296- iconColor || container ? getIconColor ( fillColor , category , icon ) : null ;
274+ const fillIconColor = getIconColor ( fillColor , category , icon ) ;
297275
298- const svgIcon = (
299- < SvgIcon
300- ref = { svgIconRefCallback }
301- { ...rprops }
302- { ...{
303- container,
304- category,
305- icon,
306- iconColor : fillIconColor ,
307- } }
308- />
276+ const containerClassName = classnames (
277+ containerClassName_ ,
278+ 'slds-icon_container' ,
279+ container === 'circle' ? 'slds-icon_container_circle' : null ,
280+ category === 'utility'
281+ ? `slds-icon-utility-${ icon . replace ( / _ / g, '-' ) } `
282+ : null ,
283+ fillIconColor ? `slds-icon-${ fillIconColor } ` : null ,
284+ {
285+ 'slds-current-color' : textColor === 'currentColor' ,
286+ 'slds-icon_flip' : flip ,
287+ }
288+ ) ;
289+
290+ return (
291+ < span className = { containerClassName } title = { title } >
292+ < SvgIcon
293+ ref = { svgIconRefCallback }
294+ { ...rprops }
295+ { ...{
296+ category,
297+ icon,
298+ iconColor : fillIconColor ,
299+ } }
300+ />
301+ { title ? < span className = 'slds-assistive-text' > { title } </ span > : null }
302+ </ span >
309303 ) ;
310- if ( container ) {
311- const ccontainerClassName = classnames (
312- containerClassName ,
313- 'slds-icon_container' ,
314- container === 'circle' ? 'slds-icon_container_circle' : null ,
315- fillIconColor ? `slds-icon-${ fillIconColor } ` : null
316- ) ;
317- return (
318- < span className = { ccontainerClassName } ref = { iconContainerRef } >
319- { svgIcon }
320- </ span >
321- ) ;
322- }
323- return svgIcon ;
324304 } ,
325305 { ICONS }
326306) ;
0 commit comments