-
Notifications
You must be signed in to change notification settings - Fork 4k
Expand file tree
/
Copy pathIcon.js
More file actions
166 lines (134 loc) · 3.76 KB
/
Icon.js
File metadata and controls
166 lines (134 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
import * as React from 'react'
import {
createShorthandFactory,
customPropTypes,
getComponentType,
getUnhandledProps,
SUI,
useEventCallback,
useKeyOnly,
useKeyOrValueAndKey,
useValueAndKey,
} from '../../lib'
import IconGroup from './IconGroup'
function getAriaProps(props) {
const ariaOptions = {}
const { 'aria-label': ariaLabel, 'aria-hidden': ariaHidden } = props
if (_.isNil(ariaLabel)) {
ariaOptions['aria-hidden'] = 'true'
} else {
ariaOptions['aria-label'] = ariaLabel
}
if (!_.isNil(ariaHidden)) {
ariaOptions['aria-hidden'] = ariaHidden
}
return ariaOptions
}
/**
* An icon is a glyph used to represent something else.
* @see Image
*/
const Icon = React.forwardRef(function (props, ref) {
const {
bordered,
circular,
className,
color,
corner,
disabled,
fitted,
flipped,
inverted,
link,
loading,
name,
rotated,
size,
} = props
const classes = cx(
color,
name,
size,
useKeyOnly(bordered, 'bordered'),
useKeyOnly(circular, 'circular'),
useKeyOnly(disabled, 'disabled'),
useKeyOnly(fitted, 'fitted'),
useKeyOnly(inverted, 'inverted'),
useKeyOnly(link, 'link'),
useKeyOnly(loading, 'loading'),
useKeyOrValueAndKey(corner, 'corner'),
useValueAndKey(flipped, 'flipped'),
useValueAndKey(rotated, 'rotated'),
'icon',
className,
)
const rest = getUnhandledProps(Icon, props)
const ElementType = getComponentType(props, { defaultAs: 'i' })
const ariaProps = getAriaProps(props)
const handleClick = useEventCallback((e) => {
if (disabled) {
e.preventDefault()
return
}
props.onClick?.(e, props)
})
return (
<ElementType {...rest} {...ariaProps} className={classes} onClick={handleClick} ref={ref} />
)
})
Icon.displayName = 'Icon'
Icon.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
/** Formatted to appear bordered. */
bordered: PropTypes.bool,
/** Icon can formatted to appear circular. */
circular: PropTypes.bool,
/** Additional classes. */
className: PropTypes.string,
/** Color of the icon. */
color: PropTypes.oneOf(SUI.COLORS),
/** Icons can display a smaller corner icon. */
corner: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['top left', 'top right', 'bottom left', 'bottom right']),
]),
/** Show that the icon is inactive. */
disabled: PropTypes.bool,
/** Fitted, without space to left or right of Icon. */
fitted: PropTypes.bool,
/** Icon can be flipped. */
flipped: PropTypes.oneOf(['horizontally', 'vertically']),
/** Formatted to have its colors inverted for contrast. */
inverted: PropTypes.bool,
/** Icon can be formatted as a link. */
link: PropTypes.bool,
/** Icon can be used as a simple loader. */
loading: PropTypes.bool,
/** Name of the icon. */
name: customPropTypes.suggest(SUI.ALL_ICONS_IN_ALL_CONTEXTS),
/**
* Called on click.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onClick: PropTypes.func,
/** Icon can rotated. */
rotated: PropTypes.oneOf(['clockwise', 'counterclockwise']),
/** Size of the icon. */
size: PropTypes.oneOf(_.without(SUI.SIZES, 'medium')),
/** Icon can have an aria label. */
'aria-hidden': PropTypes.string,
/** Icon can have an aria label. */
'aria-label': PropTypes.string,
}
// Heads up!
// .create() factories should be defined on exported component to be visible as static properties
const MemoIcon = React.memo(Icon)
MemoIcon.Group = IconGroup
MemoIcon.create = createShorthandFactory(MemoIcon, (value) => ({ name: value }))
export default MemoIcon