UNPKG

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