Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
view-container / dist / models / StyledComponent.js
Size: Mime:
"use strict";
// @flow
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
            t[p[i]] = s[p[i]];
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const hoist_non_react_statics_1 = __importDefault(require("hoist-non-react-statics"));
const prop_types_1 = __importDefault(require("prop-types"));
const react_1 = require("react");
const constants_1 = require("../constants");
const createWarnTooManyClasses_1 = __importDefault(require("../utils/createWarnTooManyClasses"));
const determineTheme_1 = __importDefault(require("../utils/determineTheme"));
const escape_1 = __importDefault(require("../utils/escape"));
const generateDisplayName_1 = __importDefault(require("../utils/generateDisplayName"));
const getComponentName_1 = __importDefault(require("../utils/getComponentName"));
const isStyledComponent_1 = __importDefault(require("../utils/isStyledComponent"));
const isTag_1 = __importDefault(require("../utils/isTag"));
const validAttr_1 = __importDefault(require("../utils/validAttr"));
const hasInInheritanceChain_1 = __importDefault(require("../utils/hasInInheritanceChain"));
const ServerStyleSheet_1 = __importDefault(require("./ServerStyleSheet"));
const StyleSheet_1 = __importDefault(require("./StyleSheet"));
const ThemeProvider_1 = require("./ThemeProvider");
// HACK for generating all static styles without needing to allocate
// an empty execution context every single time...
const STATIC_EXECUTION_CONTEXT = {};
const exporting = (ComponentStyle, constructWithOptions) => {
    const identifiers = {};
    /* We depend on components having unique IDs */
    const generateId = (_displayName, parentComponentId) => {
        const displayName = typeof _displayName !== 'string' ? 'sc' : escape_1.default(_displayName);
        /**
         * This ensures uniqueness if two components happen to share
         * the same displayName.
         */
        const nr = (identifiers[displayName] || 0) + 1;
        identifiers[displayName] = nr;
        const componentId = `${displayName}-${ComponentStyle.generateName(displayName + nr)}`;
        return parentComponentId !== undefined
            ? `${parentComponentId}-${componentId}`
            : componentId;
    };
    // $FlowFixMe
    class BaseStyledComponent extends react_1.Component {
        constructor() {
            super(...arguments);
            this.attrs = {};
            this.state = {
                theme: null,
                generatedClassName: '',
            };
            this.unsubscribeId = -1;
        }
        unsubscribeFromContext() {
            if (this.unsubscribeId !== -1) {
                this.context[ThemeProvider_1.CHANNEL_NEXT].unsubscribe(this.unsubscribeId);
            }
        }
        buildExecutionContext(theme, props) {
            const { attrs } = this.constructor;
            const context = Object.assign({}, props, { theme });
            if (attrs === undefined) {
                return context;
            }
            this.attrs = Object.keys(attrs).reduce((acc, key) => {
                const attr = attrs[key];
                // eslint-disable-next-line no-param-reassign
                acc[key] =
                    typeof attr === 'function' && !hasInInheritanceChain_1.default(attr, react_1.Component)
                        ? attr(context)
                        : attr;
                return acc;
            }, {});
            return Object.assign({}, context, this.attrs);
        }
        generateAndInjectStyles(theme, props) {
            const { attrs, componentStyle, warnTooManyClasses } = this.constructor;
            const styleSheet = this.context[constants_1.CONTEXT_KEY] || StyleSheet_1.default.master;
            // staticaly styled-components don't need to build an execution context object,
            // and shouldn't be increasing the number of class names
            if (componentStyle.isStatic && attrs === undefined) {
                return componentStyle.generateAndInjectStyles(STATIC_EXECUTION_CONTEXT, styleSheet);
            }
            else {
                const executionContext = this.buildExecutionContext(theme, props);
                const className = componentStyle.generateAndInjectStyles(executionContext, styleSheet);
                if (process.env.NODE_ENV !== 'production' &&
                    warnTooManyClasses !== undefined) {
                    warnTooManyClasses(className);
                }
                return className;
            }
        }
        componentWillMount() {
            const { componentStyle } = this.constructor;
            const styledContext = this.context[ThemeProvider_1.CHANNEL_NEXT];
            // If this is a staticaly-styled component, we don't need to the theme
            // to generate or build styles.
            if (componentStyle.isStatic) {
                const generatedClassName = this.generateAndInjectStyles(STATIC_EXECUTION_CONTEXT, this.props);
                this.setState({ generatedClassName });
                // 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
            }
            else if (styledContext !== undefined) {
                const { subscribe } = styledContext;
                this.unsubscribeId = subscribe(nextTheme => {
                    // This will be called once immediately
                    const theme = determineTheme_1.default(this.props, nextTheme, this.constructor.defaultProps);
                    const generatedClassName = this.generateAndInjectStyles(theme, this.props);
                    this.setState({ theme, generatedClassName });
                });
            }
            else {
                // eslint-disable-next-line react/prop-types
                const theme = this.props.theme || {};
                const generatedClassName = this.generateAndInjectStyles(theme, this.props);
                this.setState({ theme, generatedClassName });
            }
        }
        componentWillReceiveProps(nextProps) {
            // If this is a statically-styled component, we don't need to listen to
            // props changes to update styles
            const { componentStyle } = this.constructor;
            if (componentStyle.isStatic) {
                return;
            }
            this.setState(prevState => {
                const theme = determineTheme_1.default(nextProps, prevState.theme, this.constructor.defaultProps);
                const generatedClassName = this.generateAndInjectStyles(theme, nextProps);
                return { theme, generatedClassName };
            });
        }
        componentWillUnmount() {
            this.unsubscribeFromContext();
        }
        render() {
            // eslint-disable-next-line react/prop-types
            const { innerRef } = this.props;
            const { generatedClassName } = this.state;
            const { styledComponentId, target } = this.constructor;
            const isTargetTag = isTag_1.default(target);
            const className = [
                // eslint-disable-next-line react/prop-types
                this.props.className,
                styledComponentId,
                this.attrs.className,
                generatedClassName,
            ]
                .filter(Boolean)
                .join(' ');
            const baseProps = Object.assign({}, this.attrs, { className });
            if (isStyledComponent_1.default(target)) {
                baseProps.innerRef = innerRef;
            }
            else {
                baseProps.ref = innerRef;
            }
            const propsForElement = Object.keys(this.props).reduce((acc, propName) => {
                // Don't pass through non HTML tags through to HTML elements
                // always omit innerRef
                if (propName !== 'innerRef' &&
                    propName !== 'className' &&
                    (!isTargetTag || validAttr_1.default(propName))) {
                    // eslint-disable-next-line no-param-reassign
                    acc[propName] = this.props[propName];
                }
                return acc;
            }, baseProps);
            return react_1.createElement(target, propsForElement);
        }
    }
    const createStyledComponent = (target, options, rules) => {
        const { isClass = !isTag_1.default(target), displayName = generateDisplayName_1.default(target), componentId = generateId(options.displayName, options.parentComponentId), ParentComponent = BaseStyledComponent, rules: extendingRules, attrs, } = options;
        const styledComponentId = options.displayName && options.componentId
            ? `${escape_1.default(options.displayName)}-${options.componentId}`
            : options.componentId || componentId;
        const componentStyle = new ComponentStyle(extendingRules === undefined ? rules : extendingRules.concat(rules), attrs, styledComponentId);
        class StyledComponent extends ParentComponent {
            static withComponent(tag) {
                const { componentId: previousComponentId } = options, optionsToCopy = __rest(options, ["componentId"]);
                const newComponentId = previousComponentId &&
                    `${previousComponentId}-${isTag_1.default(tag) ? tag : escape_1.default(getComponentName_1.default(tag))}`;
                const newOptions = Object.assign({}, optionsToCopy, { componentId: newComponentId, ParentComponent: StyledComponent });
                return createStyledComponent(tag, newOptions, rules);
            }
            static get extend() {
                const { rules: rulesFromOptions, componentId: parentComponentId } = options, optionsToCopy = __rest(options, ["rules", "componentId"]);
                const newRules = rulesFromOptions === undefined
                    ? rules
                    : rulesFromOptions.concat(rules);
                const newOptions = Object.assign({}, optionsToCopy, { rules: newRules, parentComponentId, ParentComponent: StyledComponent });
                return constructWithOptions(createStyledComponent, target, newOptions);
            }
        }
        StyledComponent.attrs = attrs;
        StyledComponent.componentStyle = componentStyle;
        StyledComponent.displayName = displayName;
        StyledComponent.styledComponentId = styledComponentId;
        StyledComponent.target = target;
        StyledComponent.contextTypes = {
            [ThemeProvider_1.CHANNEL]: prop_types_1.default.func,
            [ThemeProvider_1.CHANNEL_NEXT]: ThemeProvider_1.CONTEXT_CHANNEL_SHAPE,
            [constants_1.CONTEXT_KEY]: prop_types_1.default.oneOfType([
                prop_types_1.default.instanceOf(StyleSheet_1.default),
                prop_types_1.default.instanceOf(ServerStyleSheet_1.default),
            ]),
        };
        if (process.env.NODE_ENV !== 'production') {
            StyledComponent.warnTooManyClasses = createWarnTooManyClasses_1.default(displayName);
        }
        if (isClass) {
            hoist_non_react_statics_1.default(StyledComponent, target, {
                // all SC-specific things should not be hoisted
                attrs: true,
                componentStyle: true,
                displayName: true,
                extend: true,
                styledComponentId: true,
                target: true,
                warnTooManyClasses: true,
                withComponent: true,
            });
        }
        return StyledComponent;
    };
    return createStyledComponent;
};
exports.default = exporting;
//# sourceMappingURL=StyledComponent.js.map