Repository URL to install this package:
Version:
1.2.13 ▾
|
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// @flow
const react_1 = __importStar(require("react"));
const prop_types_1 = __importDefault(require("prop-types"));
const create_broadcast_1 = __importDefault(require("../utils/create-broadcast"));
const once_1 = __importDefault(require("../utils/once"));
// NOTE: DO NOT CHANGE, changing this is a semver major change!
exports.CHANNEL = '__styled-components__';
exports.CHANNEL_NEXT = `${exports.CHANNEL}next__`;
exports.CONTEXT_CHANNEL_SHAPE = prop_types_1.default.shape({
getTheme: prop_types_1.default.func,
subscribe: prop_types_1.default.func,
unsubscribe: prop_types_1.default.func,
});
let warnChannelDeprecated;
if (process.env.NODE_ENV !== 'production') {
warnChannelDeprecated = once_1.default(() => {
// eslint-disable-next-line no-console
console.error(`Warning: Usage of \`context.${exports.CHANNEL}\` as a function is deprecated. It will be replaced with the object on \`.context.${exports.CHANNEL_NEXT}\` in a future version.`);
});
}
const isFunction = test => typeof test === 'function';
/**
* Provide a theme to an entire react component tree via context and event listeners (have to do
* both context and event emitter as pure components block context updates)
*/
class ThemeProvider extends react_1.Component {
constructor() {
super();
this.unsubscribeToOuterId = -1;
this.getTheme = this.getTheme.bind(this);
}
componentWillMount() {
// If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme
// with the outer theme
const outerContext = this.context[exports.CHANNEL_NEXT];
if (outerContext !== undefined) {
this.unsubscribeToOuterId = outerContext.subscribe(theme => {
this.outerTheme = theme;
if (this.broadcast !== undefined) {
this.publish(this.props.theme);
}
});
}
this.broadcast = create_broadcast_1.default(this.getTheme());
}
getChildContext() {
return Object.assign({}, this.context, { [exports.CHANNEL_NEXT]: {
getTheme: this.getTheme,
subscribe: this.broadcast.subscribe,
unsubscribe: this.broadcast.unsubscribe,
}, [exports.CHANNEL]: subscriber => {
if (process.env.NODE_ENV !== 'production') {
warnChannelDeprecated();
}
// Patch the old `subscribe` provide via `CHANNEL` for older clients.
const unsubscribeId = this.broadcast.subscribe(subscriber);
return () => this.broadcast.unsubscribe(unsubscribeId);
} });
}
componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
this.publish(nextProps.theme);
}
}
componentWillUnmount() {
if (this.unsubscribeToOuterId !== -1) {
this.context[exports.CHANNEL_NEXT].unsubscribe(this.unsubscribeToOuterId);
}
}
// Get the theme from the props, supporting both (outerTheme) => {} as well as object notation
getTheme(passedTheme) {
const theme = passedTheme || this.props.theme;
if (isFunction(theme)) {
const mergedTheme = theme(this.outerTheme);
if (process.env.NODE_ENV !== 'production' &&
(mergedTheme === null ||
Array.isArray(mergedTheme) ||
typeof mergedTheme !== 'object')) {
throw new Error(process.env.NODE_ENV !== 'production'
? '[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!'
: '');
}
return mergedTheme;
}
if (theme === null || Array.isArray(theme) || typeof theme !== 'object') {
throw new Error(process.env.NODE_ENV !== 'production'
? '[ThemeProvider] Please make your theme prop an object'
: '');
}
return Object.assign({}, this.outerTheme, theme);
}
publish(theme) {
this.broadcast.publish(this.getTheme(theme));
}
render() {
if (!this.props.children) {
return null;
}
return react_1.default.Children.only(this.props.children);
}
}
ThemeProvider.childContextTypes = {
[exports.CHANNEL]: prop_types_1.default.func,
[exports.CHANNEL_NEXT]: exports.CONTEXT_CHANNEL_SHAPE,
};
ThemeProvider.contextTypes = {
[exports.CHANNEL_NEXT]: exports.CONTEXT_CHANNEL_SHAPE,
};
exports.default = ThemeProvider;
//# sourceMappingURL=ThemeProvider.js.map