IconBase.tsx131 lines · main
1'use client'
2
3import React from 'react'
4
5import styleHandler from '../../lib/theme/styleHandler'
6import { cn } from '../../lib/utils/cn'
7import { IconContext } from './IconContext'
8
9// @ts-ignore
10// import IconStyles from './Icon.module.css'
11
12interface Props {
13 className?: string
14 size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'xxxlarge' | number
15 type?: string
16 color?: string
17 strokeWidth?: number
18 fill?: string
19 stroke?: string
20 background?: 'brand' | 'gray' | 'red' | 'yellow' | 'green' | 'blue' | 'indigo' | 'purple' | 'pink'
21 src?: React.ReactNode
22 icon?: any
23 viewBox?: string
24}
25
26interface StringMap {
27 [key: string]: number
28}
29
30function IconBase({
31 className,
32 size,
33 type = 'Mail',
34 color,
35 strokeWidth,
36 fill = undefined,
37 stroke = undefined,
38 background,
39 src,
40 icon,
41 ...props
42}: Props) {
43 const __styles = styleHandler('icon')
44
45 return (
46 <IconContext.Consumer>
47 {({ contextSize, className: contextClassName }) => {
48 const defaultSizes: StringMap = {
49 tiny: 14,
50 small: 18,
51 medium: 20,
52 large: 20,
53 xlarge: 24,
54 xxlarge: 30,
55 xxxlarge: 42,
56 }
57
58 const defaultSize = defaultSizes['large']
59 // @ts-ignore
60
61 const FeatherIcon = icon
62
63 // const iconSize = typeof size === 'string' ? defaultSizes[contextSize] : 21
64 let iconSize: any = 21
65
66 // use contextSize of parent (via context hook) if one exists
67 if (contextSize) {
68 iconSize = contextSize
69 ? typeof contextSize === 'string'
70 ? defaultSizes[contextSize]
71 : contextSize
72 : defaultSize
73 }
74
75 // use size prop of this component if one exists
76 if (size) {
77 iconSize = size ? (typeof size === 'string' ? defaultSizes[size] : size) : defaultSize
78 }
79
80 // confitional used for Icons with no color settings
81 // default these icons to use 'currentColor' ie, the text color
82 const noColor = !color && !fill && !stroke
83
84 let classes = ['sbui-icon', className]
85 if (contextClassName) {
86 classes.push(contextClassName)
87 }
88
89 const IconComponent = () => (
90 <FeatherIcon
91 color={!noColor ? color : 'currentColor'}
92 stroke={!noColor ? stroke : 'currentColor'}
93 className={cn(classes)}
94 strokeWidth={strokeWidth}
95 size={iconSize}
96 fill={!noColor ? (fill ? fill : 'none') : 'none'}
97 {...props}
98 />
99 )
100
101 const Icon = src ? (
102 // custom SVG file
103 <div className="relative" style={{ width: iconSize + 'px', height: iconSize + 'px' }}>
104 <svg
105 xmlns="http://www.w3.org/2000/svg"
106 viewBox="0 0 16 16"
107 color={!noColor ? color : 'currentColor'}
108 fill={!noColor ? (fill ? fill : 'none') : 'none'}
109 stroke={!noColor ? stroke : 'currentColor'}
110 className={cn(classes)}
111 width="100%"
112 height="100%"
113 strokeWidth={strokeWidth ?? undefined}
114 {...props}
115 >
116 {/* Import custom icon path from svg with 16x16px viewport */}
117 {src}
118 </svg>
119 </div>
120 ) : (
121 // feather icon
122 IconComponent()
123 )
124
125 return background ? <div className={__styles.container}>{Icon}</div> : Icon
126 }}
127 </IconContext.Consumer>
128 )
129}
130
131export default IconBase