1 | import React, { PureComponent } from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 |
|
4 | import createIconSet, {
|
5 | DEFAULT_ICON_COLOR,
|
6 | DEFAULT_ICON_SIZE,
|
7 | } from './create-icon-set';
|
8 |
|
9 | export default function createMultiStyleIconSet(styles, optionsInput = {}) {
|
10 | const styleNames = Object.keys(styles);
|
11 |
|
12 | if (styleNames.length === 0) {
|
13 | throw new Error('You need to add at least one style');
|
14 | }
|
15 |
|
16 | const options = {
|
17 | defaultStyle: styleNames[0],
|
18 | fallbackFamily: () => styleNames[0],
|
19 | glyphValidator: () => true,
|
20 | ...optionsInput,
|
21 | };
|
22 |
|
23 | const iconSets = styleNames.reduce((acc, name) => {
|
24 | const style = styles[name];
|
25 |
|
26 | acc[name] = createIconSet(
|
27 | style.glyphMap || {},
|
28 | style.fontFamily || '',
|
29 | style.fontFile || '',
|
30 | style.fontStyle || {}
|
31 | );
|
32 |
|
33 | return acc;
|
34 | }, {});
|
35 |
|
36 | function styleFromProps(props) {
|
37 | return Object.keys(props).reduce(
|
38 | (result, propName) =>
|
39 | styleNames.indexOf(propName) !== -1 && props[propName] === true
|
40 | ? propName
|
41 | : result,
|
42 | options.defaultStyle
|
43 | );
|
44 | }
|
45 |
|
46 | function getIconSetForProps(props) {
|
47 | const { name } = props;
|
48 | const style = styleFromProps(props);
|
49 |
|
50 | if (options.glyphValidator(name, style)) return iconSets[style];
|
51 |
|
52 | const family = options.fallbackFamily(name);
|
53 |
|
54 | if (styleNames.indexOf(family) === -1) {
|
55 | return options.defaultStyle;
|
56 | }
|
57 |
|
58 | return iconSets[family];
|
59 | }
|
60 |
|
61 | function selectIconClass(iconSet, iconClass) {
|
62 | return iconClass.length > 0 ? iconSet[iconClass] : iconSet;
|
63 | }
|
64 |
|
65 | function reduceProps(props) {
|
66 | return Object.keys(props).reduce((acc, prop) => {
|
67 | if (styleNames.indexOf(prop) === -1) {
|
68 | acc[prop] = props[prop];
|
69 | }
|
70 |
|
71 | return acc;
|
72 | }, {});
|
73 | }
|
74 |
|
75 | function getStyledIconSet(style, name = '') {
|
76 | if (styleNames.indexOf(style) === -1) {
|
77 | return iconSets[options.defaultStyle];
|
78 | }
|
79 |
|
80 | return !name
|
81 | ? iconSets[styleFromProps({ [style]: true })]
|
82 | : getIconSetForProps({ name, [style]: true });
|
83 | }
|
84 |
|
85 | function getImageSource(
|
86 | name,
|
87 | size = DEFAULT_ICON_SIZE,
|
88 | color = DEFAULT_ICON_COLOR,
|
89 | style = options.defaultStyle
|
90 | ) {
|
91 | return getStyledIconSet(style, name).getImageSource(name, size, color);
|
92 | }
|
93 |
|
94 | function getFontFamily(style = options.defaultStyle) {
|
95 | return getStyledIconSet(style).getFontFamily();
|
96 | }
|
97 |
|
98 | function getRawGlyphMap(style = options.defaultStyle) {
|
99 | return getStyledIconSet(style).getRawGlyphMap();
|
100 | }
|
101 |
|
102 | function hasIcon(name, style = options.defaultStyle) {
|
103 | return options.glyphValidator(name, style);
|
104 | }
|
105 |
|
106 | function createStyledIconClass(selectClass = '') {
|
107 | class IconClass extends PureComponent {
|
108 | static propTypes = styleNames.reduce((acc, name) => {
|
109 | acc[name] = PropTypes.bool;
|
110 | return acc;
|
111 | }, {});
|
112 |
|
113 | static defaultProps = styleNames.reduce((acc, name) => {
|
114 | acc[name] = false;
|
115 | return acc;
|
116 | }, {});
|
117 |
|
118 | render() {
|
119 | const selectedIconSet = getIconSetForProps(this.props);
|
120 | const SelectedIconClass = selectIconClass(selectedIconSet, selectClass);
|
121 | const props = reduceProps(this.props);
|
122 |
|
123 | return <SelectedIconClass {...props} />;
|
124 | }
|
125 | }
|
126 |
|
127 | return IconClass;
|
128 | }
|
129 |
|
130 | const Icon = createStyledIconClass();
|
131 | Icon.Button = createStyledIconClass('Button');
|
132 | Icon.TabBarItem = createStyledIconClass('TabBarItem');
|
133 | Icon.TabBarItemIOS = createStyledIconClass('TabBarItemIOS');
|
134 | Icon.getStyledIconSet = getStyledIconSet;
|
135 | Icon.getImageSource = getImageSource;
|
136 | Icon.getFontFamily = getFontFamily;
|
137 | Icon.getRawGlyphMap = getRawGlyphMap;
|
138 | Icon.hasIcon = hasIcon;
|
139 |
|
140 | return Icon;
|
141 | }
|
142 |
|
\ | No newline at end of file |