-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathIcon.js
118 lines (108 loc) · 2.59 KB
/
Icon.js
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
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {
pickBy,
get,
mapKeys
} from 'lodash';
import css from './Icon.css';
import icons from './icons';
const propTypes = {
ariaLabel: PropTypes.string,
children: PropTypes.node,
icon: PropTypes.oneOfType([
PropTypes.oneOf(Object.keys(icons)),
PropTypes.func,
]),
iconClassName: PropTypes.string,
iconPosition: PropTypes.oneOf([
'start',
'end',
]),
iconRootClass: PropTypes.string,
iconStyle: PropTypes.oneOf([
'action',
]),
id: PropTypes.string,
size: PropTypes.oneOf([
'small',
'medium',
'large',
]),
status: PropTypes.oneOf([
'error',
'warn',
'success',
]),
tabIndex: PropTypes.string,
};
const Icon = React.forwardRef(({
children,
icon = 'default',
iconClassName,
iconPosition = 'start',
iconRootClass,
iconStyle,
id,
size = 'medium',
status,
tabIndex,
...rest
}, ref) => {
const getRootClass = classNames(
css.icon,
iconRootClass,
// If icon position is defined
{ [css[`icon-position-${iconPosition}`]]: children && iconPosition },
// If a status is defined
{ [css[`status-${status}`]]: status },
// Icons that contains "left" or "right should flip on dir="rtl"
{ [css.flippable]: typeof icon === 'string' && icon.match(/(right|left)/) },
// Apply icon style
{ [css[iconStyle]]: iconStyle },
);
const getSVGClass = classNames(
'stripes__icon',
iconClassName,
`icon-${icon}`,
css[size],
);
// Defaults to the default-icon
let IconElement = icons.default;
// Custom icon
if (typeof icon === 'function') {
IconElement = icon;
// Find icon in icons list
} else if (typeof icon === 'string' && typeof icons[icon] === 'function') {
IconElement = get(icons, icon, icons.default);
}
const ariaAttributes = pickBy(rest, (_, key) => key.startsWith('aria'));
const formattedAriaAttributes = mapKeys(ariaAttributes, (_, key) => {
if (key.startsWith('aria')) {
return key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
return key;
});
return (
<span
className={getRootClass}
id={id}
ref={ref}
role="presentation"
tabIndex={tabIndex}
{...formattedAriaAttributes}
>
<IconElement
data-test-icon-element
className={getSVGClass}
viewBox="0 0 32 32"
focusable="false"
/>
{ children ? <span className={css.label}>{children}</span> : null }
</span>
);
});
Icon.displayName = 'Icon';
Icon.propTypes = propTypes;
export default Icon;