diff --git a/dist/src/StyleProvider.js b/dist/src/StyleProvider.js index 261fa37..99a2629 100644 --- a/dist/src/StyleProvider.js +++ b/dist/src/StyleProvider.js @@ -31,7 +31,7 @@ theme:_this.createTheme(props)};return _this; return{ theme:this.state.theme}; -}},{key:'UNSAFE_componentWillReceiveProps',value:function UNSAFE_componentWillReceiveProps( +}},{key:'componentDidUpdate',value:function componentDidUpdate( nextProps){ if(nextProps.style!==this.props.style){ diff --git a/dist/src/StyleProvider.js.map b/dist/src/StyleProvider.js.map index ede7bc9..4342de8 100644 --- a/dist/src/StyleProvider.js.map +++ b/dist/src/StyleProvider.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/StyleProvider.js"],"names":["StyleProvider","props","context","state","theme","createTheme","nextProps","style","setState","Theme","children","Children","only","React","Component","propTypes","PropTypes","element","isRequired","object","defaultProps","childContextTypes","ThemeShape"],"mappings":"ujBAAA,4B;AACA,qC;AACA,8B;AACA,gE;;;;;AAKqBA,a;;;;;;;;;;;;;;AAcnB,uBAAYC,KAAZ,CAAmBC,OAAnB,CAA4B;AACpBD,KADoB,CACbC,OADa;AAE1B,MAAKC,KAAL,CAAa;AACXC,MAAO,MAAKC,WAAL,CAAiBJ,KAAjB,CADI,CAAb,CAF0B;;AAK3B,C;;AAEiB;AAChB,MAAO;AACLG,MAAO,KAAKD,KAAL,CAAWC,KADb,CAAP;;AAGD,C;;AAEgCE,S,CAAW;AAC1C,GAAIA,UAAUC,KAAV,GAAoB,KAAKN,KAAL,CAAWM,KAAnC,CAA0C;AACxC,KAAKC,QAAL,CAAc;AACZJ,MAAO,KAAKC,WAAL,CAAiBC,SAAjB,CADK,CAAd;;AAGD;AACF,C;;AAEWL,K,CAAO;AACjB,MAAO,IAAIQ,gBAAJ,CAAUR,MAAMM,KAAhB,CAAP;AACD,C;;AAEQ;AACCG,QADD,CACc,KAAKT,KADnB,CACCS,QADD;;AAGP,MAAOC,iBAASC,IAAT,CAAcF,QAAd,CAAP;AACD,C,2BA3CwCG,gBAAMC,S,EAA5Bd,a,CACZe,S,CAAY,CACjBL,SAAUM,oBAAUC,OAAV,CAAkBC,UADX,CAEjBX,MAAOS,oBAAUG,MAFA,C,CADAnB,a,CAMZoB,Y,CAAe,CACpBb,MAAO,EADa,C,CANHP,a,CAUZqB,iB,CAAoB,CACzBjB,MAAOkB,kBAAWJ,UADO,C,iBAVRlB,a","file":"StyleProvider.js","sourcesContent":["import React, { Children } from 'react';\nimport PropTypes from 'prop-types';\nimport Theme, { ThemeShape } from './Theme';\nimport normalizeStyle from './StyleNormalizer/normalizeStyle';\n\n/**\n * Provides a theme to child components trough context.\n */\nexport default class StyleProvider extends React.Component {\n static propTypes = {\n children: PropTypes.element.isRequired,\n style: PropTypes.object,\n };\n\n static defaultProps = {\n style: {},\n };\n\n static childContextTypes = {\n theme: ThemeShape.isRequired,\n };\n\n constructor(props, context) {\n super(props, context);\n this.state = {\n theme: this.createTheme(props),\n };\n }\n\n getChildContext() {\n return {\n theme: this.state.theme,\n };\n }\n\n UNSAFE_componentWillReceiveProps(nextProps) {\n if (nextProps.style !== this.props.style) {\n this.setState({\n theme: this.createTheme(nextProps),\n });\n }\n }\n\n createTheme(props) {\n return new Theme(props.style);\n }\n\n render() {\n const { children } = this.props;\n\n return Children.only(children);\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/StyleProvider.js"],"names":["StyleProvider","props","context","state","theme","createTheme","nextProps","style","setState","Theme","children","Children","only","React","Component","propTypes","PropTypes","element","isRequired","object","defaultProps","childContextTypes","ThemeShape"],"mappings":"ujBAAA,4B;AACA,qC;AACA,8B;AACA,gE;;;;;AAKqBA,a;;;;;;;;;;;;;;AAcnB,uBAAYC,KAAZ,CAAmBC,OAAnB,CAA4B;AACpBD,KADoB,CACbC,OADa;AAE1B,MAAKC,KAAL,CAAa;AACXC,MAAO,MAAKC,WAAL,CAAiBJ,KAAjB,CADI,CAAb,CAF0B;;AAK3B,C;;AAEiB;AAChB,MAAO;AACLG,MAAO,KAAKD,KAAL,CAAWC,KADb,CAAP;;AAGD,C;;AAEkBE,S,CAAW;AAC5B,GAAIA,UAAUC,KAAV,GAAoB,KAAKN,KAAL,CAAWM,KAAnC,CAA0C;AACxC,KAAKC,QAAL,CAAc;AACZJ,MAAO,KAAKC,WAAL,CAAiBC,SAAjB,CADK,CAAd;;AAGD;AACF,C;;AAEWL,K,CAAO;AACjB,MAAO,IAAIQ,gBAAJ,CAAUR,MAAMM,KAAhB,CAAP;AACD,C;;AAEQ;AACCG,QADD,CACc,KAAKT,KADnB,CACCS,QADD;;AAGP,MAAOC,iBAASC,IAAT,CAAcF,QAAd,CAAP;AACD,C,2BA3CwCG,gBAAMC,S,EAA5Bd,a,CACZe,S,CAAY,CACjBL,SAAUM,oBAAUC,OAAV,CAAkBC,UADX,CAEjBX,MAAOS,oBAAUG,MAFA,C,CADAnB,a,CAMZoB,Y,CAAe,CACpBb,MAAO,EADa,C,CANHP,a,CAUZqB,iB,CAAoB,CACzBjB,MAAOkB,kBAAWJ,UADO,C,iBAVRlB,a","file":"StyleProvider.js","sourcesContent":["import React, { Children } from 'react';\nimport PropTypes from 'prop-types';\nimport Theme, { ThemeShape } from './Theme';\nimport normalizeStyle from './StyleNormalizer/normalizeStyle';\n\n/**\n * Provides a theme to child components trough context.\n */\nexport default class StyleProvider extends React.Component {\n static propTypes = {\n children: PropTypes.element.isRequired,\n style: PropTypes.object,\n };\n\n static defaultProps = {\n style: {},\n };\n\n static childContextTypes = {\n theme: ThemeShape.isRequired,\n };\n\n constructor(props, context) {\n super(props, context);\n this.state = {\n theme: this.createTheme(props),\n };\n }\n\n getChildContext() {\n return {\n theme: this.state.theme,\n };\n }\n\n componentDidUpdate(nextProps) {\n if (nextProps.style !== this.props.style) {\n this.setState({\n theme: this.createTheme(nextProps),\n });\n }\n }\n\n createTheme(props) {\n return new Theme(props.style);\n }\n\n render() {\n const { children } = this.props;\n\n return Children.only(children);\n }\n}\n"]} \ No newline at end of file diff --git a/dist/src/connectStyle.js b/dist/src/connectStyle.js index a438322..89cc6db 100644 --- a/dist/src/connectStyle.js +++ b/dist/src/connectStyle.js @@ -14,7 +14,9 @@ Object.defineProperty(exports,"__esModule",{value:true});var _extends=Object.ass -clearThemeCache=clearThemeCache;var _react=require('react');var _react2=_interopRequireDefault(_react);var _propTypes=require('prop-types');var _propTypes2=_interopRequireDefault(_propTypes);var _hoistNonReactStatics=require('hoist-non-react-statics');var _hoistNonReactStatics2=_interopRequireDefault(_hoistNonReactStatics);var _lodash=require('lodash');var _=_interopRequireWildcard(_lodash);var _normalizeStyle=require('./StyleNormalizer/normalizeStyle');var _normalizeStyle2=_interopRequireDefault(_normalizeStyle);var _reactNative=require('react-native');var _Theme=require('./Theme');var _Theme2=_interopRequireDefault(_Theme);var _resolveComponentStyle=require('./resolveComponentStyle');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i {\n return !isStyleVariant(key) && !isChildStyle(key);\n });\n}\n\n/**\n * Resolves the final component style by using the theme style, if available and\n * merging it with the style provided directly through the style prop, and style\n * variants applied through the styleName prop.\n *\n * @param componentStyleName The component name that will be used\n * to target this component in style rules.\n * @param componentStyle The default component style.\n * @param mapPropsToStyleNames Pure function to customize styleNames depending on props.\n * @param options The additional connectStyle options\n * @param options.virtual The default value of the virtual prop\n * @param options.withRef Create component ref with addedProps; if true, ref name is wrappedInstance\n * @returns {StyledComponent} The new component that will handle\n * the styling of the wrapped component.\n */\nexport default (\n componentStyleName,\n componentStyle = {},\n mapPropsToStyleNames,\n options = {}\n) => {\n function getComponentDisplayName(WrappedComponent) {\n return WrappedComponent.displayName || WrappedComponent.name || \"Component\";\n }\n\n return function wrapWithStyledComponent(WrappedComponent) {\n const componentDisplayName = getComponentDisplayName(WrappedComponent);\n\n if (!_.isPlainObject(componentStyle)) {\n throwConnectStyleError(\n \"Component style must be plain object\",\n componentDisplayName\n );\n }\n\n if (!_.isString(componentStyleName)) {\n throwConnectStyleError(\n \"Component Style Name must be string\",\n componentDisplayName\n );\n }\n\n class StyledComponent extends React.Component {\n static contextTypes = {\n theme: ThemeShape,\n // The style inherited from the parent\n // parentStyle: PropTypes.object,\n parentPath: PropTypes.array\n };\n\n static childContextTypes = {\n // Provide the parent style to child components\n // parentStyle: PropTypes.object,\n // resolveStyle: PropTypes.func,\n parentPath: PropTypes.array\n };\n\n static propTypes = {\n // Element style that overrides any other style of the component\n style: PropTypes.oneOfType([\n PropTypes.object,\n PropTypes.number,\n PropTypes.array\n ]),\n // The style variant names to apply to this component,\n // multiple variants may be separated with a space character\n styleName: PropTypes.string,\n // Virtual elements will propagate the parent\n // style to their children, i.e., the children\n // will behave as they are placed directly below\n // the parent of a virtual element.\n virtual: PropTypes.bool\n };\n\n static defaultProps = {\n virtual: options.virtual\n };\n\n static displayName = `Styled(${componentDisplayName})`;\n static WrappedComponent = WrappedComponent;\n\n constructor(props, context) {\n super(props, context);\n // console.log(context.parentPath);\n const styleNames = this.getStyleNames(props);\n const style = props.style;\n\n const finalStyle = this.getFinalStyle(\n props,\n context,\n style,\n styleNames\n );\n\n this.setWrappedInstance = this.setWrappedInstance.bind(this);\n this.resolveConnectedComponentStyle = this.resolveConnectedComponentStyle.bind(\n this\n );\n this.state = {\n style: finalStyle,\n // AddedProps are additional WrappedComponent props\n // Usually they are set trough alternative ways,\n // such as theme style, or trough options\n addedProps: this.resolveAddedProps(),\n styleNames\n };\n }\n\n getFinalStyle(props, context, style, styleNames) {\n let resolvedStyle = {};\n if (context.parentPath) {\n resolvedStyle = this.getOrSetStylesInCache(\n context,\n props,\n styleNames,\n [...context.parentPath, componentStyleName, ...styleNames]\n );\n } else {\n resolvedStyle = this.resolveStyle(context, props, styleNames);\n themeCache[componentStyleName] = resolvedStyle;\n }\n\n const concreteStyle = getConcreteStyle(_.merge({}, resolvedStyle));\n\n if (_.isArray(style)) {\n return [concreteStyle, ...style];\n }\n\n if (typeof style == \"number\" || typeof style == \"object\") {\n return [concreteStyle, style];\n }\n\n return concreteStyle;\n }\n\n getStyleNames(props) {\n const styleNamesArr = _.map(props, (value, key) => {\n if (typeof value !== \"object\" && value === true) {\n return \".\" + key;\n } else {\n return false;\n }\n });\n _.remove(styleNamesArr, (value, index) => {\n return value === false;\n });\n\n return styleNamesArr;\n }\n\n getParentPath() {\n if (!this.context.parentPath) {\n return [componentStyleName];\n } else {\n return [\n ...this.context.parentPath,\n componentStyleName,\n ...this.getStyleNames(this.props)\n ];\n }\n }\n\n getChildContext() {\n return {\n // parentStyle: this.props.virtual ?\n // this.context.parentStyle :\n // this.state.childrenStyle,\n // resolveStyle: this.resolveConnectedComponentStyle,\n parentPath: this.getParentPath()\n };\n }\n\n UNSAFE_componentWillReceiveProps(nextProps, nextContext) {\n const styleNames = this.getStyleNames(nextProps);\n const style = nextProps.style;\n if (this.shouldRebuildStyle(nextProps, nextContext, styleNames)) {\n const finalStyle = this.getFinalStyle(\n nextProps,\n nextContext,\n style,\n styleNames\n );\n\n this.setState({\n style: finalStyle,\n // childrenStyle: resolvedStyle.childrenStyle,\n styleNames\n });\n }\n }\n\n setNativeProps(nativeProps) {\n if (this.wrappedInstance.setNativeProps) {\n this.wrappedInstance.setNativeProps(nativeProps);\n }\n }\n\n setWrappedInstance(component) {\n if (component && component._root) {\n this._root = component._root;\n } else {\n this._root = component;\n }\n this.wrappedInstance = this._root;\n }\n\n hasStyleNameChanged(nextProps, styleNames) {\n return (\n mapPropsToStyleNames &&\n this.props !== nextProps &&\n // Even though props did change here,\n // it doesn't necessary means changed props are those which affect styleName\n !_.isEqual(this.state.styleNames, styleNames)\n );\n }\n\n shouldRebuildStyle(nextProps, nextContext, styleNames) {\n return (\n nextProps.style !== this.props.style ||\n nextProps.styleName !== this.props.styleName ||\n nextContext.theme !== this.context.theme ||\n !_.isEqual(nextContext.parentPath, this.context.parentPath) ||\n this.hasStyleNameChanged(nextProps, styleNames)\n );\n }\n\n resolveStyleNames(props) {\n const { styleName } = props;\n const styleNames = styleName ? styleName.split(/\\s/g) : [];\n\n if (!mapPropsToStyleNames) {\n return styleNames;\n }\n\n // We only want to keep the unique style names\n return _.uniq(mapPropsToStyleNames(styleNames, props));\n }\n\n resolveAddedProps() {\n const addedProps = {};\n if (options.withRef) {\n addedProps.ref = \"wrappedInstance\";\n }\n return addedProps;\n }\n\n getOrSetStylesInCache(context, props, styleNames, path) {\n if (themeCache && themeCache[path.join(\">\")]) {\n // console.log('**************');\n\n return themeCache[path.join(\">\")];\n } else {\n const resolvedStyle = this.resolveStyle(context, props, styleNames);\n if (Object.keys(themeCache).length < 10000) {\n themeCache[path.join(\">\")] = resolvedStyle;\n }\n return resolvedStyle;\n }\n }\n\n resolveStyle(context, props, styleNames) {\n let parentStyle = {};\n\n const theme = getTheme(context);\n const themeStyle = theme.createComponentStyle(\n componentStyleName,\n componentStyle\n );\n\n if (context.parentPath) {\n parentStyle = themeCache[context.parentPath.join(\">\")];\n } else {\n parentStyle = resolveComponentStyle(\n componentStyleName,\n styleNames,\n themeStyle,\n parentStyle\n );\n }\n\n return resolveComponentStyle(\n componentStyleName,\n styleNames,\n themeStyle,\n parentStyle\n );\n }\n\n /**\n * A helper function provided to child components that enables\n * them to resolve their style for any set of prop values.\n *\n * @param props The component props to use to resolve the style values.\n * @returns {*} The resolved component style.\n */\n resolveConnectedComponentStyle(props) {\n const styleNames = this.resolveStyleNames(props);\n return this.resolveStyle(this.context, props, styleNames)\n .componentStyle;\n }\n\n render() {\n // console.log('themeCache', themeCache);\n\n // if(componentStyleName == 'NativeBase.Text') {\n // console.log(this.state.style);\n // console.log(themeCache);\n // }\n\n const { addedProps, style } = this.state;\n return (\n \n );\n }\n }\n\n return hoistStatics(StyledComponent, WrappedComponent);\n };\n};\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/connectStyle.js"],"names":["clearThemeCache","_","themeCache","throwConnectStyleError","errorMessage","componentDisplayName","Error","getTheme","context","theme","Theme","getDefaultTheme","isStyleVariant","propertyName","test","isChildStyle","getConcreteStyle","style","pickBy","value","key","componentStyleName","componentStyle","mapPropsToStyleNames","options","getComponentDisplayName","WrappedComponent","displayName","name","wrapWithStyledComponent","isPlainObject","isString","StyledComponent","props","setWrappedInstance","bind","resolveConnectedComponentStyle","state","addedProps","resolveAddedProps","styleNamesArr","map","remove","index","parentPath","getStyleNames","getParentPath","nativeProps","wrappedInstance","setNativeProps","component","_root","styleName","styleNames","split","uniq","withRef","ref","path","join","resolvedStyle","resolveStyle","Object","keys","length","parentStyle","themeStyle","createComponentStyle","resolveStyleNames","getFinalStyle","React","Component","contextTypes","ThemeShape","PropTypes","array","childContextTypes","propTypes","oneOfType","object","number","string","virtual","bool","defaultProps","getOrSetStylesInCache","concreteStyle","merge","isArray"],"mappings":"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","file":"connectStyle.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport hoistStatics from 'hoist-non-react-statics';\nimport * as _ from 'lodash';\nimport memoize from 'memoize-one';\n\nimport normalizeStyle from './StyleNormalizer/normalizeStyle';\nimport { StyleSheet } from \"react-native\";\n\nimport Theme, { ThemeShape } from \"./Theme\";\nimport { resolveComponentStyle } from \"./resolveComponentStyle\";\n\nlet themeCache = {};\n\n/**\n * clear theme cache\n * @export\n */\nexport function clearThemeCache() {\n themeCache = {};\n}\n\n/**\n * Formats and throws an error when connecting component style with the theme.\n *\n * @param errorMessage The error message.\n * @param componentDisplayName The name of the component that is being connected.\n */\nfunction throwConnectStyleError(errorMessage, componentDisplayName) {\n throw Error(\n `${errorMessage} - when connecting ${componentDisplayName} component to style.`\n );\n}\n\n/**\n * Returns the theme object from the provided context,\n * or an empty theme if the context doesn't contain a theme.\n *\n * @param context The React component context.\n * @returns {Theme} The Theme object.\n */\nfunction getTheme(context) {\n // Fallback to a default theme if the component isn't\n // rendered in a StyleProvider.\n return context.theme || Theme.getDefaultTheme();\n}\n\n/**\n * Matches any style properties that represent component style variants.\n * Those styles can be applied to the component by using the styleName\n * prop. All style variant property names must start with a single '.'\n * character, e.g., '.variant'.\n *\n * @param propertyName The style property name.\n * @returns {boolean} True if the style property represents a component variant, false otherwise.\n */\nfunction isStyleVariant(propertyName) {\n return /^\\./.test(propertyName);\n}\n\n/**\n * Matches any style properties that represent style rules that target the\n * component children. Those styles can have two formats, they can either\n * target the components by component name ('shoutem.ui.Text'), or by component\n * name and variant ('shoutem.ui.Text.line-through'). Beside specifying the\n * component name, those styles can also target any component by using the\n * '*' wildcard ('*', or '*.line-through'). The rule to identify those styles is\n * that they have to contain a '.' character in their name or be a '*'.\n *\n * @param propertyName The style property name.\n * @returns {boolean} True if the style property represents a child style, false otherwise.\n */\nfunction isChildStyle(propertyName) {\n return /(^[^\\.].*\\.)|^\\*$/.test(propertyName);\n}\n\nfunction getConcreteStyle(style) {\n return _.pickBy(style, (value, key) => {\n return !isStyleVariant(key) && !isChildStyle(key);\n });\n}\n\n/**\n * Resolves the final component style by using the theme style, if available and\n * merging it with the style provided directly through the style prop, and style\n * variants applied through the styleName prop.\n *\n * @param componentStyleName The component name that will be used\n * to target this component in style rules.\n * @param componentStyle The default component style.\n * @param mapPropsToStyleNames Pure function to customize styleNames depending on props.\n * @param options The additional connectStyle options\n * @param options.virtual The default value of the virtual prop\n * @param options.withRef Create component ref with addedProps; if true, ref name is wrappedInstance\n * @returns {StyledComponent} The new component that will handle\n * the styling of the wrapped component.\n */\nexport default (\n componentStyleName,\n componentStyle = {},\n mapPropsToStyleNames,\n options = {}\n) => {\n function getComponentDisplayName(WrappedComponent) {\n return WrappedComponent.displayName || WrappedComponent.name || \"Component\";\n }\n\n return function wrapWithStyledComponent(WrappedComponent) {\n const componentDisplayName = getComponentDisplayName(WrappedComponent);\n\n if (!_.isPlainObject(componentStyle)) {\n throwConnectStyleError(\n \"Component style must be plain object\",\n componentDisplayName\n );\n }\n\n if (!_.isString(componentStyleName)) {\n throwConnectStyleError(\n \"Component Style Name must be string\",\n componentDisplayName\n );\n }\n\n class StyledComponent extends React.Component {\n static contextTypes = {\n theme: ThemeShape,\n // The style inherited from the parent\n // parentStyle: PropTypes.object,\n parentPath: PropTypes.array\n };\n\n static childContextTypes = {\n // Provide the parent style to child components\n // parentStyle: PropTypes.object,\n // resolveStyle: PropTypes.func,\n parentPath: PropTypes.array\n };\n\n static propTypes = {\n // Element style that overrides any other style of the component\n style: PropTypes.oneOfType([\n PropTypes.object,\n PropTypes.number,\n PropTypes.array\n ]),\n // The style variant names to apply to this component,\n // multiple variants may be separated with a space character\n styleName: PropTypes.string,\n // Virtual elements will propagate the parent\n // style to their children, i.e., the children\n // will behave as they are placed directly below\n // the parent of a virtual element.\n virtual: PropTypes.bool\n };\n\n static defaultProps = {\n virtual: options.virtual\n };\n\n static displayName = `Styled(${componentDisplayName})`;\n static WrappedComponent = WrappedComponent;\n\n constructor(props, context) {\n super(props, context);\n // console.log(context.parentPath);\n this.setWrappedInstance = this.setWrappedInstance.bind(this);\n this.resolveConnectedComponentStyle = this.resolveConnectedComponentStyle.bind(\n this\n );\n this.state = {\n // AddedProps are additional WrappedComponent props\n // Usually they are set trough alternative ways,\n // such as theme style, or trough options\n addedProps: this.resolveAddedProps(),\n };\n }\n\n getFinalStyle = memoize((props, context, style, styleNames) => {\n let resolvedStyle = {};\n if (context.parentPath) {\n resolvedStyle = this.getOrSetStylesInCache(\n context,\n props,\n styleNames,\n [...context.parentPath, componentStyleName, ...styleNames]\n );\n } else {\n resolvedStyle = this.resolveStyle(context, props, styleNames);\n themeCache[componentStyleName] = resolvedStyle;\n }\n\n const concreteStyle = getConcreteStyle(_.merge({}, resolvedStyle));\n\n if (_.isArray(style)) {\n return [concreteStyle, ...style];\n }\n\n if (typeof style == \"number\" || typeof style == \"object\") {\n return [concreteStyle, style];\n }\n\n return concreteStyle;\n })\n\n getStyleNames(props) {\n const styleNamesArr = _.map(props, (value, key) => {\n if (typeof value !== \"object\" && value === true) {\n return \".\" + key;\n } else {\n return false;\n }\n });\n _.remove(styleNamesArr, (value, index) => {\n return value === false;\n });\n\n return styleNamesArr;\n }\n\n getParentPath() {\n if (!this.context.parentPath) {\n return [componentStyleName];\n } else {\n return [\n ...this.context.parentPath,\n componentStyleName,\n ...this.getStyleNames(this.props)\n ];\n }\n }\n\n getChildContext() {\n return {\n // parentStyle: this.props.virtual ?\n // this.context.parentStyle :\n // this.state.childrenStyle,\n // resolveStyle: this.resolveConnectedComponentStyle,\n parentPath: this.getParentPath()\n };\n }\n\n setNativeProps(nativeProps) {\n if (this.wrappedInstance.setNativeProps) {\n this.wrappedInstance.setNativeProps(nativeProps);\n }\n }\n\n setWrappedInstance(component) {\n if (component && component._root) {\n this._root = component._root;\n } else {\n this._root = component;\n }\n this.wrappedInstance = this._root;\n }\n\n resolveStyleNames(props) {\n const { styleName } = props;\n const styleNames = styleName ? styleName.split(/\\s/g) : [];\n\n if (!mapPropsToStyleNames) {\n return styleNames;\n }\n\n // We only want to keep the unique style names\n return _.uniq(mapPropsToStyleNames(styleNames, props));\n }\n\n resolveAddedProps() {\n const addedProps = {};\n if (options.withRef) {\n addedProps.ref = \"wrappedInstance\";\n }\n return addedProps;\n }\n\n getOrSetStylesInCache(context, props, styleNames, path) {\n if (themeCache && themeCache[path.join(\">\")]) {\n // console.log('**************');\n\n return themeCache[path.join(\">\")];\n } else {\n const resolvedStyle = this.resolveStyle(context, props, styleNames);\n if (Object.keys(themeCache).length < 10000) {\n themeCache[path.join(\">\")] = resolvedStyle;\n }\n return resolvedStyle;\n }\n }\n\n resolveStyle(context, props, styleNames) {\n let parentStyle = {};\n\n const theme = getTheme(context);\n const themeStyle = theme.createComponentStyle(\n componentStyleName,\n componentStyle\n );\n\n if (context.parentPath) {\n parentStyle = themeCache[context.parentPath.join(\">\")];\n } else {\n parentStyle = resolveComponentStyle(\n componentStyleName,\n styleNames,\n themeStyle,\n parentStyle\n );\n }\n\n return resolveComponentStyle(\n componentStyleName,\n styleNames,\n themeStyle,\n parentStyle\n );\n }\n\n /**\n * A helper function provided to child components that enables\n * them to resolve their style for any set of prop values.\n *\n * @param props The component props to use to resolve the style values.\n * @returns {*} The resolved component style.\n */\n resolveConnectedComponentStyle(props) {\n const styleNames = this.resolveStyleNames(props);\n return this.resolveStyle(this.context, props, styleNames)\n .componentStyle;\n }\n\n render() {\n // console.log('themeCache', themeCache);\n\n // if(componentStyleName == 'NativeBase.Text') {\n // console.log(this.state.style);\n // console.log(themeCache);\n // }\n\n const style = this.getFinalStyle(\n this.props,\n this.context,\n this.props.style,\n this.getStyleNames(this.props)\n );\n\n const { addedProps } = this.state;\n return (\n \n );\n }\n }\n\n return hoistStatics(StyledComponent, WrappedComponent);\n };\n};\n"]} \ No newline at end of file diff --git a/package.json b/package.json index e7f7d7f..4757716 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "dependencies": { "hoist-non-react-statics": "^1.0.5", "lodash": "4.17.11", + "memoize-one": "^5.0.5", "prop-types": "^15.5.10" }, "peerDependencies": { diff --git a/src/StyleProvider.js b/src/StyleProvider.js index 318b052..a7b5305 100644 --- a/src/StyleProvider.js +++ b/src/StyleProvider.js @@ -33,10 +33,10 @@ export default class StyleProvider extends React.Component { }; } - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.style !== this.props.style) { + componentDidUpdate(prevProps) { + if (prevProps.style !== this.props.style) { this.setState({ - theme: this.createTheme(nextProps), + theme: this.createTheme(this.props), }); } } diff --git a/src/connectStyle.js b/src/connectStyle.js index 63be75f..0e31e34 100644 --- a/src/connectStyle.js +++ b/src/connectStyle.js @@ -2,6 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import hoistStatics from 'hoist-non-react-statics'; import * as _ from 'lodash'; +import memoize from 'memoize-one'; + import normalizeStyle from './StyleNormalizer/normalizeStyle'; import { StyleSheet } from "react-native"; @@ -162,31 +164,19 @@ export default ( constructor(props, context) { super(props, context); // console.log(context.parentPath); - const styleNames = this.getStyleNames(props); - const style = props.style; - - const finalStyle = this.getFinalStyle( - props, - context, - style, - styleNames - ); - this.setWrappedInstance = this.setWrappedInstance.bind(this); this.resolveConnectedComponentStyle = this.resolveConnectedComponentStyle.bind( this ); this.state = { - style: finalStyle, // AddedProps are additional WrappedComponent props // Usually they are set trough alternative ways, // such as theme style, or trough options addedProps: this.resolveAddedProps(), - styleNames }; } - getFinalStyle(props, context, style, styleNames) { + getFinalStyle = memoize((props, context, style, styleNames) => { let resolvedStyle = {}; if (context.parentPath) { resolvedStyle = this.getOrSetStylesInCache( @@ -211,7 +201,7 @@ export default ( } return concreteStyle; - } + }) getStyleNames(props) { const styleNamesArr = _.map(props, (value, key) => { @@ -250,25 +240,6 @@ export default ( }; } - UNSAFE_componentWillReceiveProps(nextProps, nextContext) { - const styleNames = this.getStyleNames(nextProps); - const style = nextProps.style; - if (this.shouldRebuildStyle(nextProps, nextContext, styleNames)) { - const finalStyle = this.getFinalStyle( - nextProps, - nextContext, - style, - styleNames - ); - - this.setState({ - style: finalStyle, - // childrenStyle: resolvedStyle.childrenStyle, - styleNames - }); - } - } - setNativeProps(nativeProps) { if (this.wrappedInstance.setNativeProps) { this.wrappedInstance.setNativeProps(nativeProps); @@ -284,26 +255,6 @@ export default ( this.wrappedInstance = this._root; } - hasStyleNameChanged(nextProps, styleNames) { - return ( - mapPropsToStyleNames && - this.props !== nextProps && - // Even though props did change here, - // it doesn't necessary means changed props are those which affect styleName - !_.isEqual(this.state.styleNames, styleNames) - ); - } - - shouldRebuildStyle(nextProps, nextContext, styleNames) { - return ( - nextProps.style !== this.props.style || - nextProps.styleName !== this.props.styleName || - nextContext.theme !== this.context.theme || - !_.isEqual(nextContext.parentPath, this.context.parentPath) || - this.hasStyleNameChanged(nextProps, styleNames) - ); - } - resolveStyleNames(props) { const { styleName } = props; const styleNames = styleName ? styleName.split(/\s/g) : []; @@ -387,7 +338,14 @@ export default ( // console.log(themeCache); // } - const { addedProps, style } = this.state; + const style = this.getFinalStyle( + this.props, + this.context, + this.props.style, + this.getStyleNames(this.props) + ); + + const { addedProps } = this.state; return (