New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

emotion-theming

Package Overview
Dependencies
Maintainers
2
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

emotion-theming - npm Package Compare versions

Comparing version 9.2.9 to 10.0.0-beta.0

dist/index.browser.cjs.js

2

dist/emotion.umd.min.js

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["exports","prop-types","react"],t):t(e.emotionTheming={},null,e.React)}(this,function(e,t,n){"use strict";function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e}).apply(this,arguments)}function s(e,t){e.prototype=Object.create(t.prototype),(e.prototype.constructor=e).__proto__=t}t=t&&t.hasOwnProperty("default")?t.default:t;var r,o=function(e){var o={},r=0,n=e;return{publish:function(e){for(var t in n=e,o){var r=o[t];void 0!==r&&r(n)}},subscribe:function(e){var t=r;return o[t]=e,r+=1,e(n),t},unsubscribe:function(e){o[e]=void 0}}},u="__EMOTION_THEMING__",c=((r={})[u]=t.object,r),p=function(e){return"[object Object]"===Object.prototype.toString.call(e)};function a(e,t){if("function"==typeof e){var r=e(t);if(!p(r))throw new Error("[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!");return r}if(!p(e))throw new Error("[ThemeProvider] Please make your theme prop a plain object");return void 0===t?e:i({},t,e)}var h=function(e){function t(){return e.apply(this,arguments)||this}s(t,e);var r=t.prototype;return r.componentWillMount=function(){var t=this;void 0!==this.context[u]&&(this.unsubscribeToOuterId=this.context[u].subscribe(function(e){t.outerTheme=e,void 0!==t.broadcast&&t.publish(t.props.theme)})),this.broadcast=o(a(this.props.theme,this.outerTheme))},r.getChildContext=function(){var e;return(e={})[u]={subscribe:this.broadcast.subscribe,unsubscribe:this.broadcast.unsubscribe},e},r.componentWillReceiveProps=function(e){this.props.theme!==e.theme&&this.publish(e.theme)},r.componentWillUnmount=function(){var e=this.context[u];void 0!==e&&e.unsubscribe(this.unsubscribeToOuterId)},r.publish=function(e){this.broadcast.publish(a(e,this.outerTheme))},r.render=function(){return this.props.children?n.Children.only(this.props.children):null},t.childContextTypes=c,t.contextTypes=c,t}(n.Component);"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var f,l=(function(e,t){var p,a,h,f,l,b,d,m;e.exports=(p={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},h=Object.defineProperty,f=Object.getOwnPropertyNames,l=Object.getOwnPropertySymbols,b=Object.getOwnPropertyDescriptor,d=Object.getPrototypeOf,m=d&&d(Object),function e(t,r,o){if("string"!=typeof r){if(m){var n=d(r);n&&n!==m&&e(t,n,o)}var i=f(r);l&&(i=i.concat(l(r)));for(var s=0;s<i.length;++s){var u=i[s];if(!(p[u]||a[u]||o&&o[u])){var c=b(r,u);try{h(t,u,c)}catch(e){}}}return t}return t})}(f={exports:{}},f.exports),f.exports);e.ThemeProvider=h,e.withTheme=function(o){var e=o.displayName||o.name||"Component",t=function(t){function e(e){return t.call(this,e)||this}s(e,t);var r=e.prototype;return r.componentWillMount=function(){var t=this,e=this.context[u];void 0!==e?this.unsubscribeId=e.subscribe(function(e){t.setState({theme:e})}):console.error("[withTheme] Please use ThemeProvider to be able to use withTheme")},r.componentWillUnmount=function(){-1!==this.unsubscribeId&&this.context[u].unsubscribe(this.unsubscribeId)},r.render=function(){return n.createElement(o,i({theme:this.state.theme},this.props))},e}(n.Component);return t.displayName="WithTheme("+e+")",t.contextTypes=c,l(t,o)},e.channel=u,e.contextTypes=c,e.createBroadcast=o,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("@emotion/core")):"function"==typeof define&&define.amd?define(["exports","react","@emotion/core"],t):t(e.emotionTheming={},e.React,e.emotionCore)}(this,function(e,o,i){"use strict";function a(){return(a=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}var t=function(r){var n=new WeakMap;return function(e){if(n.has(e))return n.get(e);var t=r(e);return n.set(e,t),t}},r=t(function(n){return t(function(e){return t=n,"function"==typeof(r=e)?r(t):a({},t,r);var t,r})});"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var n,f=(function(e,t){var c,p,l,s,m,d,y,h;e.exports=(c={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},p={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},l=Object.defineProperty,s=Object.getOwnPropertyNames,m=Object.getOwnPropertySymbols,d=Object.getOwnPropertyDescriptor,y=Object.getPrototypeOf,h=y&&y(Object),function e(t,r,n){if("string"!=typeof r){if(h){var o=y(r);o&&o!==h&&e(t,o,n)}var i=s(r);m&&(i=i.concat(m(r)));for(var a=0;a<i.length;++a){var f=i[a];if(!(c[f]||p[f]||n&&n[f])){var u=d(r,f);try{l(t,f,u)}catch(e){}}}return t}return t})}(n={exports:{}},n.exports),n.exports);e.ThemeProvider=function(t){return o.createElement(i.ThemeContext.Consumer,null,function(e){return t.theme!==e&&(e=r(e)(t.theme)),o.createElement(i.ThemeContext.Provider,{value:e},t.children)})},e.withTheme=function(n){var e=n.displayName||n.name||"Component",t=o.forwardRef(function(t,r){return o.createElement(i.ThemeContext.Consumer,null,function(e){return o.createElement(n,a({theme:e,ref:r},t))})});return t.displayName="WithTheme("+e+")",f(t,n)},Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=emotion.umd.min.js.map
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var PropTypes = _interopDefault(require('prop-types'));
var React = require('react');
var hoistNonReactStatics = _interopDefault(require('hoist-non-react-statics'));
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
if (process.env.NODE_ENV === 'production') {
module.exports = require('./index.cjs.prod.js');
} else {
module.exports = require('./index.cjs.dev.js');
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
// https://github.com/styled-components/styled-components/blob/e05b3fe247e9d956bcde786cec376e32afb85bca/src/utils/create-broadcast.js
var createBroadcast = function createBroadcast(initialState) {
var listeners = {};
var id = 0;
var state = initialState;
function publish(nextState) {
state = nextState;
for (var key in listeners) {
// $FlowFixMe
var listener = listeners[key];
if (listener === undefined) {
continue;
}
listener(state);
}
}
function subscribe(listener) {
var currentId = id;
listeners[currentId] = listener;
id += 1;
listener(state);
return currentId;
}
function unsubscribe(unsubID) {
listeners[unsubID] = undefined;
}
return {
publish: publish,
subscribe: subscribe,
unsubscribe: unsubscribe
};
};
var channel = '__EMOTION_THEMING__';
var _contextTypes;
var contextTypes = (_contextTypes = {}, _contextTypes[channel] = PropTypes.object, _contextTypes);
var isPlainObject = function isPlainObject(test) {
return Object.prototype.toString.call(test) === '[object Object]';
};
// Get the theme from the props, supporting both (outerTheme) => {} as well as object notation
function getTheme(theme, outerTheme) {
if (typeof theme === 'function') {
var mergedTheme = theme(outerTheme);
if (!isPlainObject(mergedTheme)) {
throw new Error('[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!');
}
return mergedTheme;
}
if (!isPlainObject(theme)) {
throw new Error('[ThemeProvider] Please make your theme prop a plain object');
}
if (outerTheme === undefined) {
return theme;
}
return _extends({}, outerTheme, theme);
}
var ThemeProvider =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(ThemeProvider, _Component);
function ThemeProvider() {
return _Component.apply(this, arguments) || this;
}
var _proto = ThemeProvider.prototype;
_proto.componentWillMount = function componentWillMount() {
var _this = this;
// If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme
// with the outer theme
if (this.context[channel] !== undefined) {
this.unsubscribeToOuterId = this.context[channel].subscribe(function (theme) {
_this.outerTheme = theme;
if (_this.broadcast !== undefined) {
_this.publish(_this.props.theme);
}
});
}
this.broadcast = createBroadcast(getTheme(this.props.theme, this.outerTheme));
};
_proto.getChildContext = function getChildContext() {
var _ref;
return _ref = {}, _ref[channel] = {
subscribe: this.broadcast.subscribe,
unsubscribe: this.broadcast.unsubscribe
}, _ref;
};
_proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
this.publish(nextProps.theme);
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
var themeContext = this.context[channel];
if (themeContext !== undefined) {
themeContext.unsubscribe(this.unsubscribeToOuterId);
}
};
_proto.publish = function publish(theme) {
this.broadcast.publish(getTheme(theme, this.outerTheme));
};
_proto.render = function render() {
if (!this.props.children) {
return null;
}
return React.Children.only(this.props.children);
};
ThemeProvider.childContextTypes = contextTypes;
ThemeProvider.contextTypes = contextTypes;
return ThemeProvider;
}(React.Component);
var withTheme = function withTheme(Component) {
var componentName = Component.displayName || Component.name || 'Component';
var WithTheme =
/*#__PURE__*/
function (_React$Component) {
_inheritsLoose(WithTheme, _React$Component);
function WithTheme(props) {
return _React$Component.call(this, props) || this;
}
var _proto = WithTheme.prototype;
_proto.componentWillMount = function componentWillMount() {
var _this = this;
var themeContext = this.context[channel];
if (themeContext === undefined) {
// eslint-disable-next-line no-console
console.error('[withTheme] Please use ThemeProvider to be able to use withTheme');
return;
}
this.unsubscribeId = themeContext.subscribe(function (theme) {
_this.setState({
theme: theme
});
});
};
_proto.componentWillUnmount = function componentWillUnmount() {
if (this.unsubscribeId !== -1) {
this.context[channel].unsubscribe(this.unsubscribeId);
}
};
_proto.render = function render() {
return React.createElement(Component, _extends({
theme: this.state.theme
}, this.props));
};
return WithTheme;
}(React.Component);
WithTheme.displayName = "WithTheme(" + componentName + ")";
WithTheme.contextTypes = contextTypes;
return hoistNonReactStatics(WithTheme, Component);
};
exports.ThemeProvider = ThemeProvider;
exports.withTheme = withTheme;
exports.channel = channel;
exports.contextTypes = contextTypes;
exports.createBroadcast = createBroadcast;

@@ -1,3 +0,4 @@

import PropTypes from 'prop-types';
import { Component, Children, createElement } from 'react';
import { createElement, forwardRef } from 'react';
import { ThemeContext } from '@emotion/core';
import weakMemoize from '@emotion/weak-memoize';
import hoistNonReactStatics from 'hoist-non-react-statics';

@@ -23,63 +24,7 @@

function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
// https://github.com/styled-components/styled-components/blob/e05b3fe247e9d956bcde786cec376e32afb85bca/src/utils/create-broadcast.js
var createBroadcast = function createBroadcast(initialState) {
var listeners = {};
var id = 0;
var state = initialState;
function publish(nextState) {
state = nextState;
for (var key in listeners) {
// $FlowFixMe
var listener = listeners[key];
if (listener === undefined) {
continue;
}
listener(state);
}
}
function subscribe(listener) {
var currentId = id;
listeners[currentId] = listener;
id += 1;
listener(state);
return currentId;
}
function unsubscribe(unsubID) {
listeners[unsubID] = undefined;
}
return {
publish: publish,
subscribe: subscribe,
unsubscribe: unsubscribe
};
};
var channel = '__EMOTION_THEMING__';
var _contextTypes;
var contextTypes = (_contextTypes = {}, _contextTypes[channel] = PropTypes.object, _contextTypes);
var isPlainObject = function isPlainObject(test) {
return Object.prototype.toString.call(test) === '[object Object]';
};
// Get the theme from the props, supporting both (outerTheme) => {} as well as object notation
function getTheme(theme, outerTheme) {
var getTheme = function getTheme(outerTheme, theme) {
if (typeof theme === 'function') {
var mergedTheme = theme(outerTheme);
if (!isPlainObject(mergedTheme)) {
if (process.env.NODE_ENV !== 'production' && (mergedTheme == null || typeof mergedTheme !== 'object' || Array.isArray(mergedTheme))) {
throw new Error('[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!');

@@ -91,134 +36,46 @@ }

if (!isPlainObject(theme)) {
if (process.env.NODE_ENV !== 'production' && (theme == null || typeof theme !== 'object' || Array.isArray(theme))) {
throw new Error('[ThemeProvider] Please make your theme prop a plain object');
}
if (outerTheme === undefined) {
return theme;
}
return _extends({}, outerTheme, theme);
}
};
var ThemeProvider =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(ThemeProvider, _Component);
var createCacheWithTheme = weakMemoize(function (outerTheme) {
return weakMemoize(function (theme) {
return getTheme(outerTheme, theme);
});
});
function ThemeProvider() {
return _Component.apply(this, arguments) || this;
}
var _proto = ThemeProvider.prototype;
_proto.componentWillMount = function componentWillMount() {
var _this = this;
// If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme
// with the outer theme
if (this.context[channel] !== undefined) {
this.unsubscribeToOuterId = this.context[channel].subscribe(function (theme) {
_this.outerTheme = theme;
if (_this.broadcast !== undefined) {
_this.publish(_this.props.theme);
}
});
var ThemeProvider = function ThemeProvider(props) {
return createElement(ThemeContext.Consumer, null, function (theme) {
if (props.theme !== theme) {
theme = createCacheWithTheme(theme)(props.theme);
}
this.broadcast = createBroadcast(getTheme(this.props.theme, this.outerTheme));
};
return createElement(ThemeContext.Provider, {
value: theme
}, props.children);
});
};
_proto.getChildContext = function getChildContext() {
var _ref;
// should we change this to be forwardRef/withCSSContext style so it doesn't merge with props?
var withTheme = function withTheme(Component) {
var componentName = Component.displayName || Component.name || 'Component';
return _ref = {}, _ref[channel] = {
subscribe: this.broadcast.subscribe,
unsubscribe: this.broadcast.unsubscribe
}, _ref;
};
var render = function render(props, ref) {
return createElement(ThemeContext.Consumer, null, function (theme) {
return createElement(Component, _extends({
theme: theme,
ref: ref
}, props));
});
}; // $FlowFixMe
_proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
if (this.props.theme !== nextProps.theme) {
this.publish(nextProps.theme);
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
var themeContext = this.context[channel];
if (themeContext !== undefined) {
themeContext.unsubscribe(this.unsubscribeToOuterId);
}
};
_proto.publish = function publish(theme) {
this.broadcast.publish(getTheme(theme, this.outerTheme));
};
_proto.render = function render() {
if (!this.props.children) {
return null;
}
return Children.only(this.props.children);
};
ThemeProvider.childContextTypes = contextTypes;
ThemeProvider.contextTypes = contextTypes;
return ThemeProvider;
}(Component);
var withTheme = function withTheme(Component$$1) {
var componentName = Component$$1.displayName || Component$$1.name || 'Component';
var WithTheme =
/*#__PURE__*/
function (_React$Component) {
_inheritsLoose(WithTheme, _React$Component);
function WithTheme(props) {
return _React$Component.call(this, props) || this;
}
var _proto = WithTheme.prototype;
_proto.componentWillMount = function componentWillMount() {
var _this = this;
var themeContext = this.context[channel];
if (themeContext === undefined) {
// eslint-disable-next-line no-console
console.error('[withTheme] Please use ThemeProvider to be able to use withTheme');
return;
}
this.unsubscribeId = themeContext.subscribe(function (theme) {
_this.setState({
theme: theme
});
});
};
_proto.componentWillUnmount = function componentWillUnmount() {
if (this.unsubscribeId !== -1) {
this.context[channel].unsubscribe(this.unsubscribeId);
}
};
_proto.render = function render() {
return createElement(Component$$1, _extends({
theme: this.state.theme
}, this.props));
};
return WithTheme;
}(Component);
var WithTheme = forwardRef(render);
WithTheme.displayName = "WithTheme(" + componentName + ")";
WithTheme.contextTypes = contextTypes;
return hoistNonReactStatics(WithTheme, Component$$1);
return hoistNonReactStatics(WithTheme, Component);
};
export { ThemeProvider, withTheme, channel, contextTypes, createBroadcast };
export { ThemeProvider, withTheme };
{
"name": "emotion-theming",
"version": "9.2.9",
"version": "10.0.0-beta.0",
"description": "A CSS-in-JS theming solution, inspired by styled-components",

@@ -35,14 +35,21 @@ "main": "dist/index.cjs.js",

"devDependencies": {
"@types/react": "16.0.16",
"dtslint": "^0.3.0",
"prop-types": "^15.6.1"
"@types/react": "16.3.18",
"dtslint": "^0.3.0"
},
"dependencies": {
"@emotion/weak-memoize": "^0.2.0",
"hoist-non-react-statics": "^2.3.1"
},
"peerDependencies": {
"prop-types": "15.x",
"@emotion/core": "0.x.x",
"react": "15.x || 16.x"
},
"umd:main": "./dist/emotion.umd.min.js"
"umd:main": "./dist/emotion.umd.min.js",
"publishConfig": {
"tag": "next"
},
"browser": {
"./dist/index.cjs.js": "./dist/index.browser.cjs.js",
"./dist/index.esm.js": "./dist/index.browser.esm.js"
}
}
# emotion-theming
> A CSS-in-JS theming solution for React(-like) views.
> A CSS-in-JS theming solution for React

@@ -9,10 +9,9 @@ _`emotion-theming` is a theming library inspired by [styled-components](https://github.com/styled-components/styled-components)_

* [Install](#install)
* [Usage](#usage)
* [API](#api)
* [ThemeProvider](#themeprovider)
* [withTheme](#withthemecomponent)
* [channel](#channel)
* [Credits](#credits)
* [License](#license)
- [Install](#install)
- [Usage](#usage)
- [API](#api)
- [ThemeProvider](#themeprovider)
- [withTheme](#withthemecomponent)
- [Credits](#credits)
- [License](#license)

@@ -31,5 +30,7 @@ ## Install

### TODO: Add example with the css prop
Theming is accomplished by placing the `ThemeProvider` component, at the top of the React component tree and wrapping descendants with the `withTheme` higher-order component (HOC). This HOC seamlessly acquires the current theme and injects it as a "prop" into your own component.
The theme prop is automatically injected into components created with `react-emotion`'s `styled`.
The theme prop is automatically injected into components created with `styled`.

@@ -40,4 +41,4 @@ Here is a complete example for a typical React + Emotion app (information about each piece of the theming API is listed afterward):

/** child.js */
import React from 'react';
import styled from 'react-emotion';
import React from 'react'
import styled from 'react-emotion'

@@ -54,11 +55,9 @@ const Container = styled.div`

export default Page extends React.Component {
export default class Page extends React.Component {
render() {
return (
<Container>
<Headline>
I'm red!
</Headline>
<Headline>I'm red!</Headline>
</Container>
);
)
}

@@ -68,11 +67,11 @@ }

/** parent.js */
import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from 'emotion-theming';
import React from 'react'
import ReactDOM from 'react-dom'
import { ThemeProvider } from 'emotion-theming'
import Page from './child.js';
import Page from './child.js'
const theme = {
color: 'red',
};
color: 'red'
}

@@ -85,3 +84,3 @@ class App extends React.Component {

</ThemeProvider>
);
)
}

@@ -91,3 +90,3 @@ }

// this assumes the HTML page template has a <main> element already inside <body>
ReactDOM.render(<App />, document.querySelector('main'));
ReactDOM.render(<App />, document.querySelector('main'))
```

@@ -99,10 +98,10 @@

### ThemeProvider: ReactComponent
### ThemeProvider: React.ComponentType
A React component that passes the theme object down the component tree via [context](https://facebook.github.io/react/docs/context.html). Additional `<ThemeProvider>` wrappers may be added deeper in the hierarchy to override the original theme. The theme object will be merged into its ancestor as if by [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). If a function is passed instead of an object it will be called with the ancestor theme and the result will be the new theme.
A React component that passes the theme object down the component tree via [context](https://reactjs.org/docs/context.html). Additional `<ThemeProvider>` wrappers may be added deeper in the hierarchy to override the original theme. The theme object will be merged into its ancestor as if by [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). If a function is passed instead of an object it will be called with the ancestor theme and the result will be the new theme.
_Accepts:_
* **`children`: ReactComponent** - A single React component.
* **`theme`: Object|Function** - An object or function that provides an object.
- **`children`: ReactComponent** - A single React component.
- **`theme`: Object|Function** - An object or function that provides an object.

@@ -144,3 +143,3 @@ ```jsx

### withTheme(component: ReactComponent): Function
### withTheme(component: React.ComponentType): React.ComponentType

@@ -169,47 +168,2 @@ A higher-order component that provides the current theme as a prop to the wrapped child and listens for changes. If the theme is updated, the child component will be re-rendered accordingly.

### channel: String
The emotion-theming package uses this string as the React context key by default.
If you wish to build your own components on top of this library, it is recommended to import the context key from this package instead of hardcoding its value.
```js
import { channel } from 'emotion-theming'
console.log(channel)
;('__EMOTION_THEMING__')
```
### createBroadcast: Function
Creates a broadcast that is used to listen to theme events via context. This is probably only useful for testing.
If you have styled components that depend on `theme` via `ThemeProvider`, one option is to wrap all your components being tested
in `ThemeProvider`. However if you're using `enzyme`, you'll lose the ability to call some methods that require it to be run on the root instance.
Instead you can `mount` a component a pass the channel and broadcast as part of `context`.
```js
import { channel, createBroadcast } from 'emotion-theming'
import { mount } from 'enzyme'
import PropTypes from 'prop-types'
import React from 'react'
describe('emotion-theming', function() {
it('can use theme from a ThemeProvider', function() {
const myTheme = { color: 'green' }
const broadcast = createBroadcast(myTheme)
const wrapper = mount(<MyComponent />, {
context: {
[channel]: broadcast
},
childContextTypes: {
[channel]: PropTypes.object
}
})
wrapper.setState({ foo: 'bar' })
expect(wrapper.state('foo')).toBe('bar')
})
})
```
## Credits

@@ -216,0 +170,0 @@

// @flow
export { default as ThemeProvider } from './theme-provider'
export { default as withTheme } from './with-theme'
export { channel, contextTypes, createBroadcast } from './utils'
// @flow
// adapted from styled-components' ThemeProvider
// https://github.com/styled-components/styled-components/blob/4503cab5b86aa9ef8314c5baa360a2fbb4812485/src/models/ThemeProvider.js
import * as React from 'react'
import { ThemeContext } from '@emotion/core'
import weakMemoize from '@emotion/weak-memoize'
import { Component, Children, type Node as ReactNode } from 'react'
import createBroadcast from './create-broadcast'
import { channel, contextTypes, type Theme } from './utils'
const isPlainObject = test =>
Object.prototype.toString.call(test) === '[object Object]'
type Props = {
theme: Theme,
children: ReactNode
}
// Get the theme from the props, supporting both (outerTheme) => {} as well as object notation
function getTheme(theme: Theme, outerTheme?: Object) {
let getTheme = (outerTheme: Object, theme: Object | (Object => Object)) => {
if (typeof theme === 'function') {
const mergedTheme = theme(outerTheme)
if (!isPlainObject(mergedTheme)) {
if (
process.env.NODE_ENV !== 'production' &&
(mergedTheme == null ||
typeof mergedTheme !== 'object' ||
Array.isArray(mergedTheme))
) {
throw new Error(

@@ -28,3 +21,6 @@ '[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!'

}
if (!isPlainObject(theme)) {
if (
process.env.NODE_ENV !== 'production' &&
(theme == null || typeof theme !== 'object' || Array.isArray(theme))
) {
throw new Error(

@@ -35,68 +31,33 @@ '[ThemeProvider] Please make your theme prop a plain object'

if (outerTheme === undefined) {
return theme
}
return { ...outerTheme, ...theme }
}
class ThemeProvider extends Component<Props> {
outerTheme: Object
broadcast: *
unsubscribeToOuterId: number
componentWillMount() {
// If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme
// with the outer theme
if (this.context[channel] !== undefined) {
this.unsubscribeToOuterId = this.context[channel].subscribe(theme => {
this.outerTheme = theme
let createCacheWithTheme = weakMemoize(outerTheme => {
return weakMemoize(theme => {
return getTheme(outerTheme, theme)
})
})
if (this.broadcast !== undefined) {
this.publish(this.props.theme)
type Props = {
theme: Object | (Object => Object),
children: React.Node
}
let ThemeProvider = (props: Props) => {
return (
<ThemeContext.Consumer>
{theme => {
if (props.theme !== theme) {
theme = createCacheWithTheme(theme)(props.theme)
}
})
}
this.broadcast = createBroadcast(
getTheme(this.props.theme, this.outerTheme)
)
}
getChildContext() {
return {
[channel]: {
subscribe: this.broadcast.subscribe,
unsubscribe: this.broadcast.unsubscribe
}
}
}
componentWillReceiveProps(nextProps: Props) {
if (this.props.theme !== nextProps.theme) {
this.publish(nextProps.theme)
}
}
componentWillUnmount() {
const themeContext = this.context[channel]
if (themeContext !== undefined) {
themeContext.unsubscribe(this.unsubscribeToOuterId)
}
}
publish(theme: Theme) {
this.broadcast.publish(getTheme(theme, this.outerTheme))
}
render() {
if (!this.props.children) {
return null
}
return Children.only(this.props.children)
}
return (
<ThemeContext.Provider value={theme}>
{props.children}
</ThemeContext.Provider>
)
}}
</ThemeContext.Consumer>
)
}
ThemeProvider.childContextTypes = contextTypes
ThemeProvider.contextTypes = contextTypes
export default ThemeProvider
// @flow
import * as React from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import { channel, contextTypes } from './utils'
import { ThemeContext } from '@emotion/core'
type Props = { theme: Object }
// should we change this to be forwardRef/withCSSContext style so it doesn't merge with props?
const withTheme = (Component: React.ComponentType<Props>) => {
const componentName = Component.displayName || Component.name || 'Component'
let render = (props, ref) => {
return (
<ThemeContext.Consumer>
{theme => {
return <Component theme={theme} ref={ref} {...props} />
}}
</ThemeContext.Consumer>
)
}
// $FlowFixMe
let WithTheme = React.forwardRef(render)
class WithTheme extends React.Component<{}, { theme: Object }> {
unsubscribeId: number
componentWillMount() {
const themeContext = this.context[channel]
if (themeContext === undefined) {
// eslint-disable-next-line no-console
console.error(
'[withTheme] Please use ThemeProvider to be able to use withTheme'
)
return
}
this.unsubscribeId = themeContext.subscribe(theme => {
this.setState({ theme })
})
}
componentWillUnmount() {
if (this.unsubscribeId !== -1) {
this.context[channel].unsubscribe(this.unsubscribeId)
}
}
render() {
return <Component theme={this.state.theme} {...this.props} />
}
}
WithTheme.displayName = `WithTheme(${componentName})`
WithTheme.contextTypes = contextTypes

@@ -40,0 +26,0 @@ return hoistNonReactStatics(WithTheme, Component)

@@ -1,34 +0,29 @@

// TypeScript Version: 2.3
import { ComponentClass, SFC } from "react";
// Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
// TypeScript Version: 2.8
export type OptionalThemeProps<Props, Theme> = Props & { theme?: Theme };
import * as React from 'react'
import { AddOptionalTo, PropsOf } from './helper'
export interface ThemeProviderProps<Theme> {
theme: Partial<Theme> | ((theme: Theme) => Theme);
theme: Partial<Theme> | ((outerTheme: Theme) => Theme)
}
export type ThemeProviderComponent<Theme> = ComponentClass<ThemeProviderProps<Theme>>;
export const ThemeProvider: ThemeProviderComponent<object>;
export function ThemeProvider<Theme>(
props: ThemeProviderProps<Theme>
): React.ReactElement<any>
/**
* Inject theme into component
* @todo Add more constraint to C so that
* this function only accepts components with theme props.
*/
// tslint:disable-next-line:no-unnecessary-generics
export function withTheme<Props, Theme = {}>(component: ComponentClass<Props> | SFC<Props>): ComponentClass<OptionalThemeProps<Props, Theme>>;
export function withTheme<C extends React.ComponentType<any>>(
component: C
): React.SFC<AddOptionalTo<PropsOf<C>, 'theme'>>
export interface EmotionThemingModule<Theme> {
ThemeProvider: ThemeProviderComponent<Theme>;
withTheme<Props>(component: ComponentClass<Props> | SFC<Props>): ComponentClass<OptionalThemeProps<Props, Theme>>;
export interface EmotionTheming<Theme> {
ThemeProvider(props: ThemeProviderProps<Theme>): React.ReactElement<any>
withTheme<C extends React.ComponentType<any>>(
component: C
): React.SFC<AddOptionalTo<PropsOf<C>, 'theme'>>
}
export const channel: "__EMOTION_THEMING__";
export type BroadcastListener<Theme = {}> = (state: Theme) => void;
export interface Broadcast<Theme = {}> {
publish(nextState: Theme): void;
subscribe(listener: BroadcastListener<Theme>): number;
unsubscribe(unsubID: number): void;
}
export function createBroadcast<Theme = {}>(initialState: Theme): Broadcast<Theme>;
{
"extends": "dtslint/dtslint.json",
"rules": {
"no-relative-import-in-test": false
"array-type": [true, "generic"],
"semicolon": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-module",
"check-rest-spread",
"check-type",
"check-typecast",
"check-type-operator",
"check-preblock"
],
"no-unnecessary-generics": false
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc