Skip to content

Commit 5fd5ce0

Browse files
authored
Add style prop handling (#8)
1 parent 9f6ee14 commit 5fd5ce0

File tree

9 files changed

+199
-50
lines changed

9 files changed

+199
-50
lines changed

dist/components/FontAwesomeIcon.js

+13-25
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,11 @@ function normalizeIconArgs(icon) {
5959

6060
function FontAwesomeIcon(props) {
6161
var iconArgs = props.icon,
62-
maskArgs = props.mask,
63-
_props$height = props.height,
64-
height = _props$height === void 0 ? windowHeight * 0.1 : _props$height,
65-
_props$width = props.width,
66-
width = _props$width === void 0 ? windowWidth * 0.1 : _props$width;
62+
height = props.height,
63+
width = props.width,
64+
style = props.style;
6765
var iconLookup = normalizeIconArgs(iconArgs);
68-
var transform = objectWithKey('transform', typeof props.transform === 'string' ? _fontawesomeSvgCore.parse.transform(props.transform) : props.transform);
69-
var mask = objectWithKey('mask', normalizeIconArgs(maskArgs));
70-
var renderedIcon = (0, _fontawesomeSvgCore.icon)(iconLookup, _objectSpread({}, transform, mask));
66+
var renderedIcon = (0, _fontawesomeSvgCore.icon)(iconLookup);
7167

7268
if (!renderedIcon) {
7369
(0, _logger.default)("ERROR: icon not found for icon = ", iconArgs);
@@ -77,7 +73,8 @@ function FontAwesomeIcon(props) {
7773
var abstract = renderedIcon.abstract;
7874
var extraProps = {
7975
height: height,
80-
width: width
76+
width: width,
77+
style: style
8178
};
8279
Object.keys(props).forEach(function (key) {
8380
if (!FontAwesomeIcon.defaultProps.hasOwnProperty(key)) {
@@ -89,25 +86,16 @@ function FontAwesomeIcon(props) {
8986

9087
FontAwesomeIcon.displayName = 'FontAwesomeIcon';
9188
FontAwesomeIcon.propTypes = {
92-
mask: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.array, _propTypes.default.string]),
93-
icon: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.array, _propTypes.default.string]),
94-
listItem: _propTypes.default.bool,
95-
pull: _propTypes.default.oneOf(['right', 'left']),
96-
pulse: _propTypes.default.bool,
97-
rotation: _propTypes.default.oneOf([90, 180, 270]),
98-
spin: _propTypes.default.bool,
99-
transform: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object])
89+
height: _propTypes.default.number,
90+
width: _propTypes.default.number,
91+
style: _propTypes.default.shape(_objectSpread({}, _reactNative.ViewPropTypes.style)),
92+
icon: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.array, _propTypes.default.string])
10093
};
10194
FontAwesomeIcon.defaultProps = {
102-
mask: null,
103-
inverse: false,
10495
icon: null,
105-
listItem: false,
106-
pull: null,
107-
pulse: false,
108-
rotation: null,
109-
spin: false,
110-
transform: null
96+
style: null,
97+
height: windowHeight * 0.1,
98+
width: windowWidth * 0.1
11199
};
112100

113101
var convertCurry = _converter.default.bind(null, _react.default.createElement);

dist/converter.js

+40-5
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,55 @@ function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.
2323

2424
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
2525

26+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
27+
28+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
29+
2630
var svgObjectMap = {
2731
"svg": _reactNativeSvg.Svg,
28-
"path": _reactNativeSvg.Path
32+
"path": _reactNativeSvg.Path,
33+
"rect": _reactNativeSvg.Rect,
34+
"defs": _reactNativeSvg.Defs,
35+
"mask": _reactNativeSvg.Mask,
36+
"g": _reactNativeSvg.G,
37+
"clipPath": _reactNativeSvg.ClipPath
2938
};
3039

3140
function convert(createElement, element) {
3241
var extraProps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
3342

43+
// console.log(`DEBUG: in convert. element.tag = ${element.tag} and extraProps = `, extraProps)
44+
// console.log(`DEBUG: in convert. element.attributes = `, element.attributes)
3445
if (typeof element === 'string') {
3546
return element;
3647
}
3748

38-
var children = (element.children || []).map(convert.bind(null, createElement));
49+
var children = (element.children || []).map(function (child) {
50+
return convert(createElement, child, extraProps);
51+
});
3952
var mixins = Object.keys(element.attributes || {}).reduce(function (acc, key) {
4053
var val = element.attributes[key];
4154

4255
switch (key) {
4356
case 'class':
44-
case 'fill':
4557
case 'role':
46-
case 'style':
58+
case 'style': // TODO: when react-native-svg supports the style prop, there may be a better way to do this.
59+
// In the meantime, we're manually peeling off specific style properties, namely color, and passing them down
60+
// to children as a fill prop
61+
// See: https://github.com/react-native-community/react-native-svg/commit/e7d0eb6df676d4f63f9eba7c0cf5ddd6c4c85fbe
62+
4763
case 'xmlns':
4864
delete element.attributes[key];
4965
break;
5066

67+
case 'fill':
68+
// TODO: probably want to keep fill, but just translate 'currentColor' to 'black'
69+
// When react-native-svg supports currentColor, pass it through
70+
acc.attrs[key] = val === 'currentColor' ? 'black' : val;
71+
break;
72+
5173
default:
74+
// console.log(`DEBUG: for element tag <${element.tag}>, setting prop key=val to ${key}=`, val)
5275
if (key.indexOf('aria-') === 0 || key.indexOf('data-') === 0) {
5376
delete element.attributes[key];
5477
} else {
@@ -61,7 +84,19 @@ function convert(createElement, element) {
6184
}, {
6285
attrs: {}
6386
});
64-
return createElement.apply(void 0, [svgObjectMap[element.tag], _objectSpread({}, mixins.attrs, extraProps)].concat(_toConsumableArray(children)));
87+
88+
var style = // get rid of this key
89+
// store the result here
90+
extraProps.style,
91+
modifiedExtraProps = _objectWithoutProperties(extraProps, ["style"]); // If a color was passed in as a style sheet on the style prop, set the fill attribute to its value
92+
93+
94+
if (extraProps.style && extraProps.style.color) {
95+
modifiedExtraProps['fill'] = extraProps.style.color;
96+
} // console.log(`DEBUG: while creating element with tag=${element.tag}, we have extraProps: `, extraProps )
97+
98+
99+
return createElement.apply(void 0, [svgObjectMap[element.tag], _objectSpread({}, mixins.attrs, modifiedExtraProps)].concat(_toConsumableArray(children)));
65100
}
66101

67102
var _default = convert;

examples/Hello/App.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@ export default class App extends Component<Props> {
3232
<Text style={styles.instructions}>And now, for some icons:</Text>
3333

3434
<FontAwesomeIcon icon={ faCoffee } />
35-
<FontAwesomeIcon icon={ faBeer } />
35+
<FontAwesomeIcon icon={ faBeer } style={ styles.icon } />
36+
3637
</View>
3738
);
3839
}
3940
}
4041

4142
const styles = StyleSheet.create({
43+
icon: {
44+
color: 'green'
45+
},
4246
container: {
4347
flex: 1,
4448
justifyContent: 'center',

examples/Hello/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"dependencies": {
1515
"@fortawesome/fontawesome-svg-core": "^1.2.5",
1616
"@fortawesome/free-solid-svg-icons": "^5.4.0",
17-
"@fortawesome/react-native-fontawesome": "^0.0.1",
17+
"@fortawesome/react-native-fontawesome": "https://github.com/FortAwesome/react-native-fontawesome",
1818
"react": "16.5.0",
1919
"react-native": "0.57.2",
2020
"react-native-svg": "^7.0.3"

examples/Hello/yarn.lock

+2-3
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,9 @@
664664
dependencies:
665665
"@fortawesome/fontawesome-common-types" "^0.2.5"
666666

667-
"@fortawesome/react-native-fontawesome@^0.0.1":
667+
"@fortawesome/react-native-fontawesome@https://github.com/FortAwesome/react-native-fontawesome":
668668
version "0.0.1"
669-
resolved "https://registry.yarnpkg.com/@fortawesome/react-native-fontawesome/-/react-native-fontawesome-0.0.1.tgz#d960f949c43c0ac4b1122f4b67aaff0a2eda5486"
670-
integrity sha512-B4ga5xk+8wp3B2Ye5S2or177euOZyAVrh3TIX5sBOPzX7GnhpD9zFwqXLHLTkf91olgp4P6HQIQO218YKSrZBw==
669+
resolved "https://github.com/FortAwesome/react-native-fontawesome#9f6ee143563c402e5c5443ee6d8aaf365c3025d7"
671670
dependencies:
672671
humps "^2.0.1"
673672
prop-types "^15.6.2"

src/components/FontAwesomeIcon.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22
import convert from '../converter'
33
import PropTypes from 'prop-types'
4-
import { Dimensions, Text, View } from 'react-native'
4+
import { Dimensions, Text, View, ViewPropTypes } from 'react-native'
55
import { icon, parse } from '@fortawesome/fontawesome-svg-core'
66
import log from '../logger'
77

@@ -33,19 +33,19 @@ function normalizeIconArgs(icon) {
3333
}
3434

3535
export default function FontAwesomeIcon(props) {
36-
const { icon: iconArgs, height = windowHeight * 0.1, width = windowWidth * 0.1 } = props
36+
const { icon: iconArgs, height, width, style } = props
3737

3838
const iconLookup = normalizeIconArgs(iconArgs)
3939

40-
const renderedIcon = icon(iconLookup, {})
40+
const renderedIcon = icon(iconLookup)
4141

4242
if (!renderedIcon) {
4343
log("ERROR: icon not found for icon = ", iconArgs)
4444
return null
4545
}
4646

4747
const { abstract } = renderedIcon
48-
const extraProps = { height, width }
48+
const extraProps = { height, width, style }
4949

5050
Object.keys(props).forEach(key => {
5151
if (!FontAwesomeIcon.defaultProps.hasOwnProperty(key)) {
@@ -64,6 +64,8 @@ FontAwesomeIcon.propTypes = {
6464

6565
width: PropTypes.number,
6666

67+
style: PropTypes.shape({ ...ViewPropTypes.style }),
68+
6769
icon: PropTypes.oneOfType([
6870
PropTypes.object,
6971
PropTypes.array,
@@ -72,7 +74,10 @@ FontAwesomeIcon.propTypes = {
7274
}
7375

7476
FontAwesomeIcon.defaultProps = {
75-
icon: null
77+
icon: null,
78+
style: null,
79+
height: windowHeight * 0.1,
80+
width: windowWidth * 0.1
7681
}
7782

7883
const convertCurry = convert.bind(null, React.createElement)

src/components/__tests__/FontAwesomeIcon.test.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fontawesome from '@fortawesome/fontawesome-svg-core'
22
import FontAwesomeIcon from '../FontAwesomeIcon'
33
import React from 'react'
44
import renderer from 'react-test-renderer'
5+
import { StyleSheet } from 'react-native'
56

67
const faCoffee = {
78
prefix: 'fas',
@@ -31,16 +32,25 @@ fontawesome.library.add(faCoffee, faCircle)
3132

3233
test('renders correctly', () => {
3334
const tree = renderer.create(<FontAwesomeIcon height={10} width={10} icon={ ['fas', 'coffee'] } />).toJSON()
34-
expect(tree).toMatchSnapshot();
35+
expect(tree).toMatchSnapshot()
3536
})
3637

3738
test('renders correctly with default height and width', () => {
3839
const tree = renderer.create(<FontAwesomeIcon icon={ ['fas', 'coffee'] } />).toJSON()
39-
expect(tree).toMatchSnapshot();
40+
expect(tree).toMatchSnapshot()
4041
})
4142

4243
test('renders with icon object prop', () => {
4344
const tree = renderer.create(<FontAwesomeIcon icon={ faCoffee } />).toJSON()
44-
expect(tree).toMatchSnapshot();
45+
expect(tree).toMatchSnapshot()
4546
})
4647

48+
test('renders with style prop setting color', () => {
49+
const styles = StyleSheet.create({
50+
icon: {
51+
color: 'blue'
52+
}
53+
})
54+
const tree = renderer.create(<FontAwesomeIcon icon={ faCoffee } style={ styles.icon }/>).toJSON()
55+
expect(tree).toMatchSnapshot()
56+
})

src/components/__tests__/__snapshots__/FontAwesomeIcon.test.js.snap

+91-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ exports[`renders correctly 1`] = `
5151
opacity={1}
5252
originX={0}
5353
originY={0}
54-
propList={Array []}
54+
propList={
55+
Array [
56+
"fill",
57+
]
58+
}
5559
rotation={0}
5660
scaleX={1}
5761
scaleY={1}
@@ -122,7 +126,11 @@ exports[`renders correctly with default height and width 1`] = `
122126
opacity={1}
123127
originX={0}
124128
originY={0}
125-
propList={Array []}
129+
propList={
130+
Array [
131+
"fill",
132+
]
133+
}
126134
rotation={0}
127135
scaleX={1}
128136
scaleY={1}
@@ -193,7 +201,87 @@ exports[`renders with icon object prop 1`] = `
193201
opacity={1}
194202
originX={0}
195203
originY={0}
196-
propList={Array []}
204+
propList={
205+
Array [
206+
"fill",
207+
]
208+
}
209+
rotation={0}
210+
scaleX={1}
211+
scaleY={1}
212+
skewX={0}
213+
skewY={0}
214+
stroke={null}
215+
strokeDasharray={null}
216+
strokeDashoffset={null}
217+
strokeLinecap={0}
218+
strokeLinejoin={0}
219+
strokeMiterlimit={4}
220+
strokeOpacity={1}
221+
strokeWidth="1"
222+
x={0}
223+
y={0}
224+
/>
225+
</RNSVGSvgView>
226+
`;
227+
228+
exports[`renders with style prop setting color 1`] = `
229+
<RNSVGSvgView
230+
align="xMidYMid"
231+
bbHeight="133.4"
232+
bbWidth="75"
233+
fill="blue"
234+
meetOrSlice={0}
235+
minX={0}
236+
minY={0}
237+
style={
238+
Array [
239+
Object {
240+
"backgroundColor": "transparent",
241+
},
242+
undefined,
243+
false,
244+
Object {
245+
"flex": 0,
246+
"height": 133.4,
247+
"width": 75,
248+
},
249+
]
250+
}
251+
vbHeight={512}
252+
vbWidth={640}
253+
>
254+
<RNSVGPath
255+
d="M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z"
256+
fill={
257+
Array [
258+
0,
259+
0,
260+
0,
261+
1,
262+
1,
263+
]
264+
}
265+
fillOpacity={1}
266+
fillRule={1}
267+
matrix={
268+
Array [
269+
1,
270+
0,
271+
0,
272+
1,
273+
0,
274+
0,
275+
]
276+
}
277+
opacity={1}
278+
originX={0}
279+
originY={0}
280+
propList={
281+
Array [
282+
"fill",
283+
]
284+
}
197285
rotation={0}
198286
scaleX={1}
199287
scaleY={1}

0 commit comments

Comments
 (0)