From bd8d6ba271588618692d4356d385f20f03630efd Mon Sep 17 00:00:00 2001 From: Neil Gabbadon Date: Sun, 31 Jan 2016 21:19:27 -0500 Subject: [PATCH] Implements prepareStyles as composition of functions in muiTheme Signed-off-by: Neil Gabbadon --- package.json | 1 + src/mixins/style-propable.js | 11 ++-- src/styles/getMuiTheme.js | 4 ++ src/styles/transformers/autoprefixer.js | 7 +++ src/styles/transformers/callOnce.js | 15 +++++ src/styles/transformers/index.js | 9 +++ src/styles/transformers/rtl.js | 81 +++++++++++++++++++++++++ 7 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 src/styles/transformers/autoprefixer.js create mode 100644 src/styles/transformers/callOnce.js create mode 100644 src/styles/transformers/index.js create mode 100644 src/styles/transformers/rtl.js diff --git a/package.json b/package.json index e5de51ae8246b2..2f33307191ba43 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "homepage": "http://material-ui.com/", "dependencies": { "inline-style-prefixer": "^0.6.6", + "lodash.flowright": "^3.2.1", "lodash.merge": "^3.3.2", "lodash.throttle": "~3.0.4", "react-addons-create-fragment": "^0.14.0", diff --git a/src/mixins/style-propable.js b/src/mixins/style-propable.js index e64ba9ed83cf2d..3bcdcf71279c8a 100644 --- a/src/mixins/style-propable.js +++ b/src/mixins/style-propable.js @@ -1,5 +1,5 @@ import React from 'react'; -import {mergeStyles, mergeAndPrefix, prepareStyles as prepare} from '../utils/styles'; +import {mergeStyles, mergeAndPrefix} from '../utils/styles'; /** * This mixin isn't necessary and will be removed soon. DO NOT USE! @@ -22,8 +22,11 @@ export default { mergeAndPrefix, prepareStyles(...args) { - return prepare((this.state && this.state.muiTheme) || - this.context.muiTheme || - (this.props && this.props.muiTheme), ...args); + const { + prepareStyles = (style) => (style), + } = (this.state && this.state.muiTheme) || (this.context && this.context.muiTheme) || + (this.props && this.props.muiTheme) || {}; + + return prepareStyles(mergeStyles({}, ...args)); }, }; diff --git a/src/styles/getMuiTheme.js b/src/styles/getMuiTheme.js index e32af09288e7ce..6d854d1b94f0f6 100644 --- a/src/styles/getMuiTheme.js +++ b/src/styles/getMuiTheme.js @@ -4,6 +4,8 @@ import ColorManipulator from '../utils/color-manipulator'; import autoPrefix from './auto-prefix'; import lightBaseTheme from './baseThemes/lightBaseTheme'; import zIndex from './zIndex'; +import {autoprefixer, callOnce, rtl} from './transformers'; +import compose from 'lodash.flowright'; /** * Get the MUI theme corresponding to a base theme. @@ -240,7 +242,9 @@ export default function getMuiTheme(baseTheme, muiTheme) { }, }, muiTheme); + const transformers = [autoprefixer, rtl, callOnce].map(t => t(muiTheme)).filter(t => t); muiTheme.prefix = autoPrefix.getTransform(muiTheme.userAgent); + muiTheme.prepareStyles = compose(...transformers); return muiTheme; } diff --git a/src/styles/transformers/autoprefixer.js b/src/styles/transformers/autoprefixer.js new file mode 100644 index 00000000000000..273d049ecf1290 --- /dev/null +++ b/src/styles/transformers/autoprefixer.js @@ -0,0 +1,7 @@ +export default function(muiTheme) { + if (muiTheme.userAgent === false) return; + + return (style) => { + return muiTheme.prefix(style); + }; +} diff --git a/src/styles/transformers/callOnce.js b/src/styles/transformers/callOnce.js new file mode 100644 index 00000000000000..02ea8686a186d7 --- /dev/null +++ b/src/styles/transformers/callOnce.js @@ -0,0 +1,15 @@ +import warning from 'warning'; + +const CALLED_ONCE = 'muiPrepared'; + +export default function callOnce() { + if (process.env.NODE_ENV === 'production') return; + + return (style) => { + if (style[CALLED_ONCE]) { + warning(false, 'You cannot call prepareStyles() on the same style object more than once.'); + } + style[CALLED_ONCE] = true; + return style; + }; +} diff --git a/src/styles/transformers/index.js b/src/styles/transformers/index.js new file mode 100644 index 00000000000000..2cd9a61bec1eec --- /dev/null +++ b/src/styles/transformers/index.js @@ -0,0 +1,9 @@ +import autoprefixer from './autoprefixer'; +import callOnce from './callOnce'; +import rtl from './rtl'; + +export { + autoprefixer, + callOnce, + rtl, +}; diff --git a/src/styles/transformers/rtl.js b/src/styles/transformers/rtl.js new file mode 100644 index 00000000000000..91fe80b1f4b1da --- /dev/null +++ b/src/styles/transformers/rtl.js @@ -0,0 +1,81 @@ +const reTranslate = /((^|\s)translate(3d|X)?\()(\-?[\d]+)/; +const reSkew = /((^|\s)skew(x|y)?\()\s*(\-?[\d]+)(deg|rad|grad)(,\s*(\-?[\d]+)(deg|rad|grad))?/; + +/** + * This function ensures that `style` supports both ltr and rtl directions by + * checking `styleConstants` in `muiTheme` and replacing attribute keys if + * necessary. + */ +export default function rtl(muiTheme) { + if (!muiTheme.isRtl) return; + + return (style) => { + const flippedAttributes = { + // Keys and their replacements. + right: 'left', + left: 'right', + marginRight: 'marginLeft', + marginLeft: 'marginRight', + paddingRight: 'paddingLeft', + paddingLeft: 'paddingRight', + borderRight: 'borderLeft', + borderLeft: 'borderRight', + }; + + let newStyle = {}; + + Object.keys(style).forEach(function(attribute) { + let value = style[attribute]; + let key = attribute; + + if (flippedAttributes.hasOwnProperty(attribute)) { + key = flippedAttributes[attribute]; + } + + switch (attribute) { + case 'float': + case 'textAlign': + if (value === 'right') { + value = 'left'; + } else if (value === 'left') { + value = 'right'; + } + break; + + case 'direction': + if (value === 'ltr') { + value = 'rtl'; + } else if (value === 'rtl') { + value = 'ltr'; + } + break; + + case 'transform': + let matches; + if ((matches = value.match(reTranslate))) { + value = value.replace(matches[0], matches[1] + (-parseFloat(matches[4])) ); + } + if ((matches = value.match(reSkew))) { + value = value.replace(matches[0], matches[1] + (-parseFloat(matches[4])) + matches[5] + + matches[6] ? ',' + (-parseFloat(matches[7])) + matches[8] : '' + ); + } + break; + + case 'transformOrigin': + if (value.indexOf('right') > -1) { + value = value.replace('right', 'left'); + } else if (value.indexOf('left') > -1) { + value = value.replace('left', 'right'); + } + break; + } + + newStyle[key] = value; + }); + + return newStyle; + }; +} + +