UNPKG

styled-components

Version:

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

87 lines (71 loc) • 2.57 kB
// @flow import { Component, createElement, PropTypes } from 'react' import InlineStyle from './InlineStyle' import type { RuleSet, Target } from '../types' import { CHANNEL } from './ThemeProvider' /* eslint-disable react/prefer-stateless-function */ class AbstractStyledNativeComponent extends Component { static isPrototypeOf: Function state: any } const createStyledNativeComponent = (target: Target, rules: RuleSet, parent?: Target) => { /* Handle styled(OtherStyledNativeComponent) differently */ const isStyledNativeComponent = AbstractStyledNativeComponent.isPrototypeOf(target) if (isStyledNativeComponent) { return createStyledNativeComponent(target.target, target.rules.concat(rules), target) } const inlineStyle = new InlineStyle(rules) const ParentComponent = parent || AbstractStyledNativeComponent class StyledNativeComponent extends ParentComponent { static rules: RuleSet static target: Target unsubscribe: Function state: { theme: any } constructor() { super() this.state = { theme: null, } } componentWillMount() { // If there is a theme in the context, subscribe to the event emitter. This is necessary // due to pure components blocking context updates, this circumvents that by updating when an // event is emitted if (this.context[CHANNEL]) { const subscribe = this.context[CHANNEL] this.unsubscribe = subscribe(theme => { // This will be called once immediately this.setState({ theme }) }) } } componentWillUnmount() { if (this.unsubscribe) { this.unsubscribe() } } /* eslint-disable react/prop-types */ render() { const { style, children, innerRef } = this.props const theme = this.state.theme || this.props.theme || {} const generatedStyles = inlineStyle.generateStyleObject({ theme }) const propsForElement = Object.assign({}, this.props) propsForElement.style = [generatedStyles, style] if (innerRef) { propsForElement.ref = innerRef } return createElement(target, propsForElement, children) } } /* Used for inheritance */ StyledNativeComponent.rules = rules StyledNativeComponent.target = target StyledNativeComponent.displayName = target.displayName ? `Styled(${target.displayName})` : `styled.${target}` StyledNativeComponent.contextTypes = { [CHANNEL]: PropTypes.object, } return StyledNativeComponent } export default createStyledNativeComponent