From 10f88670ed940a7193cfe0f01c182c2988ab0d92 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Sat, 23 Jul 2016 19:16:48 -0700 Subject: [PATCH] [add] support for `textShadow*` and `transition` style props Close #170 --- .../__tests__/processTextShadow-test.js | 24 +++++++++++++++++++ .../__tests__/processTransform-test.js | 5 +++- .../__tests__/processVendorPrefixes-test.js | 17 +++++++++++++ src/apis/StyleSheet/createReactStyleObject.js | 24 ++++++++----------- src/apis/StyleSheet/processTextShadow.js | 19 +++++++++++++++ src/apis/StyleSheet/processTransform.js | 2 +- src/apis/StyleSheet/processVendorPrefixes.js | 16 +++++++++++++ src/components/Text/TextStylePropTypes.js | 7 +++--- src/components/View/ViewStylePropTypes.js | 1 + 9 files changed, 96 insertions(+), 19 deletions(-) create mode 100644 src/apis/StyleSheet/__tests__/processTextShadow-test.js create mode 100644 src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js create mode 100644 src/apis/StyleSheet/processTextShadow.js create mode 100644 src/apis/StyleSheet/processVendorPrefixes.js diff --git a/src/apis/StyleSheet/__tests__/processTextShadow-test.js b/src/apis/StyleSheet/__tests__/processTextShadow-test.js new file mode 100644 index 00000000..3ffcb6c2 --- /dev/null +++ b/src/apis/StyleSheet/__tests__/processTextShadow-test.js @@ -0,0 +1,24 @@ +/* eslint-env mocha */ + +import assert from 'assert' +import processTextShadow from '../processTextShadow' + +suite('apis/StyleSheet/processTextShadow', () => { + test('textShadowOffset', () => { + const style = { + textShadowColor: 'red', + textShadowOffset: { width: 2, height: 2 }, + textShadowRadius: 5 + } + + assert.deepEqual( + processTextShadow(style), + { + textShadow: '2px 2px 5px red', + textShadowColor: null, + textShadowOffset: null, + textShadowRadius: null + } + ) + }) +}) diff --git a/src/apis/StyleSheet/__tests__/processTransform-test.js b/src/apis/StyleSheet/__tests__/processTransform-test.js index 3b797914..46e1ff49 100644 --- a/src/apis/StyleSheet/__tests__/processTransform-test.js +++ b/src/apis/StyleSheet/__tests__/processTransform-test.js @@ -26,7 +26,10 @@ suite('apis/StyleSheet/processTransform', () => { assert.deepEqual( processTransform(style), - { transform: 'matrix3d(1,2,3,4,5,6)' } + { + transform: 'matrix3d(1,2,3,4,5,6)', + transformMatrix: null + } ) }) }) diff --git a/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js b/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js new file mode 100644 index 00000000..c6c2ac9b --- /dev/null +++ b/src/apis/StyleSheet/__tests__/processVendorPrefixes-test.js @@ -0,0 +1,17 @@ +/* eslint-env mocha */ + +import assert from 'assert' +import processVendorPrefixes from '../processVendorPrefixes' + +suite('apis/StyleSheet/processVendorPrefixes', () => { + test('handles array values', () => { + const style = { + display: [ '-webkit-flex', 'flex' ] + } + + assert.deepEqual( + processVendorPrefixes(style), + { display: 'flex' } + ) + }) +}) diff --git a/src/apis/StyleSheet/createReactStyleObject.js b/src/apis/StyleSheet/createReactStyleObject.js index 26a52dd5..0c3647f8 100644 --- a/src/apis/StyleSheet/createReactStyleObject.js +++ b/src/apis/StyleSheet/createReactStyleObject.js @@ -1,22 +1,18 @@ import expandStyle from './expandStyle' import flattenStyle from '../../modules/flattenStyle' import prefixAll from 'inline-style-prefixer/static' +import processTextShadow from './processTextShadow' import processTransform from './processTransform' +import processVendorPrefixes from './processVendorPrefixes' -const addVendorPrefixes = (style) => { - let prefixedStyles = prefixAll(style) - // React@15 removed undocumented support for fallback values in - // inline-styles. Revert array values to the standard CSS value - for (const prop in prefixedStyles) { - const value = prefixedStyles[prop] - if (Array.isArray(value)) { - prefixedStyles[prop] = value[value.length - 1] - } - } - return prefixedStyles -} +const plugins = [ + processTextShadow, + processTransform, + processVendorPrefixes +] -const _createReactDOMStyleObject = (reactNativeStyle) => processTransform(expandStyle(flattenStyle(reactNativeStyle))) -const createReactDOMStyleObject = (reactNativeStyle) => addVendorPrefixes(_createReactDOMStyleObject(reactNativeStyle)) +const applyPlugins = (style) => plugins.reduce((style, plugin) => plugin(style), style) + +const createReactDOMStyleObject = (reactNativeStyle) => applyPlugins(expandStyle(flattenStyle(reactNativeStyle))) module.exports = createReactDOMStyleObject diff --git a/src/apis/StyleSheet/processTextShadow.js b/src/apis/StyleSheet/processTextShadow.js new file mode 100644 index 00000000..0826bbd3 --- /dev/null +++ b/src/apis/StyleSheet/processTextShadow.js @@ -0,0 +1,19 @@ +import normalizeValue from './normalizeValue' + +const processTextShadow = (style) => { + if (style && style.textShadowOffset) { + const { height, width } = style.textShadowOffset + const offsetX = normalizeValue(null, height || 0) + const offsetY = normalizeValue(null, width || 0) + const blurRadius = normalizeValue(null, style.textShadowRadius || 0) + const color = style.textShadowColor || 'currentcolor' + + style.textShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}` + style.textShadowColor = null + style.textShadowOffset = null + style.textShadowRadius = null + } + return style +} + +module.exports = processTextShadow diff --git a/src/apis/StyleSheet/processTransform.js b/src/apis/StyleSheet/processTransform.js index c8767960..caa72322 100644 --- a/src/apis/StyleSheet/processTransform.js +++ b/src/apis/StyleSheet/processTransform.js @@ -20,7 +20,7 @@ const processTransform = (style) => { style.transform = style.transform.map(mapTransform).join(' ') } else if (style.transformMatrix) { style.transform = convertTransformMatrix(style.transformMatrix) - delete style.transformMatrix + style.transformMatrix = null } } return style diff --git a/src/apis/StyleSheet/processVendorPrefixes.js b/src/apis/StyleSheet/processVendorPrefixes.js new file mode 100644 index 00000000..4a46405b --- /dev/null +++ b/src/apis/StyleSheet/processVendorPrefixes.js @@ -0,0 +1,16 @@ +import prefixAll from 'inline-style-prefixer/static' + +const processVendorPrefixes = (style) => { + let prefixedStyles = prefixAll(style) + // React@15 removed undocumented support for fallback values in + // inline-styles. Revert array values to the standard CSS value + for (const prop in prefixedStyles) { + const value = prefixedStyles[prop] + if (Array.isArray(value)) { + prefixedStyles[prop] = value[value.length - 1] + } + } + return prefixedStyles +} + +module.exports = processVendorPrefixes diff --git a/src/components/Text/TextStylePropTypes.js b/src/components/Text/TextStylePropTypes.js index 811250f1..b6c0c2f2 100644 --- a/src/components/Text/TextStylePropTypes.js +++ b/src/components/Text/TextStylePropTypes.js @@ -2,7 +2,7 @@ import { PropTypes } from 'react' import ColorPropType from '../../propTypes/ColorPropType' import ViewStylePropTypes from '../View/ViewStylePropTypes' -const { number, oneOf, oneOfType, string } = PropTypes +const { number, oneOf, oneOfType, shape, string } = PropTypes const numberOrString = oneOfType([ number, string ]) module.exports = { @@ -19,8 +19,9 @@ module.exports = { textDecorationLine: string, /* @platform web */ textOverflow: string, - /* @platform web */ - textShadow: string, + textShadowColor: ColorPropType, + textShadowOffset: shape({ width: number, height: number }), + textShadowRadius: number, /* @platform web */ textTransform: oneOf([ 'capitalize', 'lowercase', 'none', 'uppercase' ]), /* @platform web */ diff --git a/src/components/View/ViewStylePropTypes.js b/src/components/View/ViewStylePropTypes.js index 72f71a03..b0c17408 100644 --- a/src/components/View/ViewStylePropTypes.js +++ b/src/components/View/ViewStylePropTypes.js @@ -31,6 +31,7 @@ module.exports = { outline: string, overflowX: autoOrHiddenOrVisible, overflowY: autoOrHiddenOrVisible, + transition: string, userSelect: string, visibility: hiddenOrVisible, zIndex: number