Comparing version 1.0.2 to 1.1.0
@@ -6,2 +6,6 @@ # Changelog | ||
### 1.1.0 (2017-07-12) | ||
Add `themeListener`—advanced helper to hook theming in any Component. | ||
### 1.0.2 (2017-07-12) | ||
@@ -8,0 +12,0 @@ |
@@ -17,6 +17,2 @@ 'use strict'; | ||
var _propTypes = require('prop-types'); | ||
var _propTypes2 = _interopRequireDefault(_propTypes); | ||
var _channel = require('./channel'); | ||
@@ -26,6 +22,8 @@ | ||
var _createThemeListener = require('./create-theme-listener'); | ||
var _createThemeListener2 = _interopRequireDefault(_createThemeListener); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -44,39 +42,25 @@ | ||
var themeListener = (0, _createThemeListener2.default)(CHANNEL); | ||
return function (Component) { | ||
var _class, _temp2; | ||
var _class, _temp; | ||
return _temp2 = _class = function (_React$Component) { | ||
return _temp = _class = function (_React$Component) { | ||
_inherits(WithTheme, _React$Component); | ||
function WithTheme() { | ||
var _ref; | ||
var _temp, _this, _ret; | ||
function WithTheme(props, context) { | ||
_classCallCheck(this, WithTheme); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var _this = _possibleConstructorReturn(this, (WithTheme.__proto__ || Object.getPrototypeOf(WithTheme)).call(this, props, context)); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = WithTheme.__proto__ || Object.getPrototypeOf(WithTheme)).call.apply(_ref, [this].concat(args))), _this), _this.state = { theme: {} }, _this.setTheme = function (theme) { | ||
_this.state = { theme: themeListener.initial(context) }; | ||
_this.setTheme = function (theme) { | ||
return _this.setState({ theme: theme }); | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
}; | ||
return _this; | ||
} | ||
_createClass(WithTheme, [{ | ||
key: 'componentWillMount', | ||
value: function componentWillMount() { | ||
if (!this.context[CHANNEL]) { | ||
throw new Error('[WithTheme(${getDisplayName(Component)})] Please use ThemeProvider to be able to use WithTheme'); | ||
} | ||
this.setState({ theme: this.context[CHANNEL].getState() }); | ||
} | ||
}, { | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
if (this.context[CHANNEL]) { | ||
this.unsubscribe = this.context[CHANNEL].subscribe(this.setTheme); | ||
} | ||
this.unsubscribe = themeListener.subscribe(this.context, this.setTheme); | ||
} | ||
@@ -101,4 +85,4 @@ }, { | ||
return WithTheme; | ||
}(_react2.default.Component), _class.displayName = 'WithTheme(' + getDisplayName(Component) + ')', _class.contextTypes = _defineProperty({}, CHANNEL, _propTypes2.default.object.isRequired), _temp2; | ||
}(_react2.default.Component), _class.displayName = 'WithTheme(' + getDisplayName(Component) + ')', _class.contextTypes = themeListener.contextTypes, _temp; | ||
}; | ||
} |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.ThemeProvider = exports.withTheme = exports.channel = undefined; | ||
exports.themeListener = exports.ThemeProvider = exports.withTheme = exports.channel = undefined; | ||
exports.createTheming = createTheming; | ||
@@ -18,2 +18,6 @@ | ||
var _createThemeListener = require('./create-theme-listener'); | ||
var _createThemeListener2 = _interopRequireDefault(_createThemeListener); | ||
var _channel = require('./channel'); | ||
@@ -28,2 +32,3 @@ | ||
var ThemeProvider = exports.ThemeProvider = (0, _createThemeProvider2.default)(); | ||
var themeListener = exports.themeListener = (0, _createThemeListener2.default)(); | ||
function createTheming() { | ||
@@ -35,3 +40,4 @@ var customChannel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _channel2.default; | ||
withTheme: (0, _createWithTheme2.default)(customChannel), | ||
ThemeProvider: (0, _createThemeProvider2.default)(customChannel) | ||
ThemeProvider: (0, _createThemeProvider2.default)(customChannel), | ||
themeListener: (0, _createThemeListener2.default)(customChannel) | ||
}; | ||
@@ -44,3 +50,4 @@ } | ||
ThemeProvider: ThemeProvider, | ||
themeListener: themeListener, | ||
createTheming: createTheming | ||
}; |
@@ -5,4 +5,2 @@ var _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; }; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -15,4 +13,4 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import channel from './channel'; | ||
import createThemeListener from './create-theme-listener'; | ||
@@ -26,39 +24,25 @@ var getDisplayName = function getDisplayName(Component) { | ||
var themeListener = createThemeListener(CHANNEL); | ||
return function (Component) { | ||
var _class, _temp2; | ||
var _class, _temp; | ||
return _temp2 = _class = function (_React$Component) { | ||
return _temp = _class = function (_React$Component) { | ||
_inherits(WithTheme, _React$Component); | ||
function WithTheme() { | ||
var _ref; | ||
var _temp, _this, _ret; | ||
function WithTheme(props, context) { | ||
_classCallCheck(this, WithTheme); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var _this = _possibleConstructorReturn(this, (WithTheme.__proto__ || Object.getPrototypeOf(WithTheme)).call(this, props, context)); | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = WithTheme.__proto__ || Object.getPrototypeOf(WithTheme)).call.apply(_ref, [this].concat(args))), _this), _this.state = { theme: {} }, _this.setTheme = function (theme) { | ||
_this.state = { theme: themeListener.initial(context) }; | ||
_this.setTheme = function (theme) { | ||
return _this.setState({ theme: theme }); | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
}; | ||
return _this; | ||
} | ||
_createClass(WithTheme, [{ | ||
key: 'componentWillMount', | ||
value: function componentWillMount() { | ||
if (!this.context[CHANNEL]) { | ||
throw new Error('[WithTheme(${getDisplayName(Component)})] Please use ThemeProvider to be able to use WithTheme'); | ||
} | ||
this.setState({ theme: this.context[CHANNEL].getState() }); | ||
} | ||
}, { | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
if (this.context[CHANNEL]) { | ||
this.unsubscribe = this.context[CHANNEL].subscribe(this.setTheme); | ||
} | ||
this.unsubscribe = themeListener.subscribe(this.context, this.setTheme); | ||
} | ||
@@ -83,4 +67,4 @@ }, { | ||
return WithTheme; | ||
}(React.Component), _class.displayName = 'WithTheme(' + getDisplayName(Component) + ')', _class.contextTypes = _defineProperty({}, CHANNEL, PropTypes.object.isRequired), _temp2; | ||
}(React.Component), _class.displayName = 'WithTheme(' + getDisplayName(Component) + ')', _class.contextTypes = themeListener.contextTypes, _temp; | ||
}; | ||
} |
import createThemeProvider from './create-theme-provider'; | ||
import createWithTheme from './create-with-theme'; | ||
import createThemeListener from './create-theme-listener'; | ||
import defaultChannel from './channel'; | ||
@@ -8,2 +9,3 @@ | ||
export var ThemeProvider = createThemeProvider(); | ||
export var themeListener = createThemeListener(); | ||
export function createTheming() { | ||
@@ -15,3 +17,4 @@ var customChannel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultChannel; | ||
withTheme: createWithTheme(customChannel), | ||
ThemeProvider: createThemeProvider(customChannel) | ||
ThemeProvider: createThemeProvider(customChannel), | ||
themeListener: createThemeListener(customChannel) | ||
}; | ||
@@ -24,3 +27,4 @@ } | ||
ThemeProvider: ThemeProvider, | ||
themeListener: themeListener, | ||
createTheming: createTheming | ||
}; |
{ | ||
"name": "theming", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Unified CSSinJS theming solution for React", | ||
@@ -5,0 +5,0 @@ "main": "dist/cjs", |
@@ -15,2 +15,3 @@ # theming | ||
* `createTheming` allows you to integrate `theming` into your CSSinJS library with custom `channel` (if you need custom one). | ||
* _Advanced usage:_ `themeListener` allows you to add theming support in your components. | ||
@@ -30,2 +31,3 @@ See [Motivation](#motivation) for details. | ||
* [withTheme](#withthemecomponent) | ||
* [themeListener](#themeListener) | ||
* [createTheming](#createthemingcustomchannel) | ||
@@ -234,2 +236,76 @@ * [Credits](#credits) | ||
### themeListener | ||
Advanced helper to hook theming in any Component. | ||
```js | ||
import { themeListener } from 'theming'; | ||
function CustomWithTheme(Component) { | ||
return class CustomWithTheme extends React.Component { | ||
static contextTypes = themeListener.contextTypes; | ||
constructor(props, context) { | ||
super(props, context); | ||
this.state = { theme: themeListener.initial(context) }; | ||
this.setTheme = theme => this.setState({ theme }); | ||
} | ||
componentDidMount() { | ||
this.unsubscribe = themeListener.subscribe(this.context, this.setTheme); | ||
} | ||
componentWillUnmount() { | ||
if (typeof this.unsubscribe === 'function') { | ||
this.unsubscribe(); | ||
} | ||
} | ||
render() { | ||
const { theme } = this.state; | ||
return <Component theme={theme} {...this.props} />; | ||
} | ||
} | ||
} | ||
``` | ||
themeListener is an `Object` with following fields: | ||
* `themeListener.contextTypes` | ||
* type: `Object` | ||
* meant to be added your component's contextTypes: | ||
```js | ||
static contextTypes = themeListener.contextTypes; | ||
// or | ||
static contextTypes = Object.assign({}, themeListener.contextTypes, { | ||
/* your Component's contextTypes */ | ||
}); | ||
``` | ||
* `themeListener.initial` | ||
* type: `Function` | ||
* takes a single context `Object`, where `context` is `context` of your component | ||
* meant to be used in `constructor` | ||
* throws an error if your component will be used outside ThemeProvider | ||
* example: | ||
```js | ||
constructor(props, context) { | ||
super(props, context); | ||
this.state = { theme: themeListener.initial(context) } | ||
} | ||
``` | ||
* `themeListener.subscribe` | ||
* type: `Function` | ||
* takes 2 arguments: | ||
* context `Object`, where `context` is `this.context` from your component | ||
* callback `Function`, which in turn will be invoked with theme update `Object`, every time theme is updated in `ThemeProvider` | ||
* meant to be used in `componentDidMount` | ||
* returns unsubscribe `Function`, which you should invoke in `componentWillUnmount` | ||
* example: | ||
```js | ||
componentDidMount() { | ||
this.unsubscribe = themeListener.subscribe(this.context, theme => this.setState({ theme })); | ||
} | ||
componentWillUnmount() { | ||
if (typeof this.unsubscribe === 'function') { | ||
this.unsubscribe(); | ||
} | ||
} | ||
``` | ||
### createTheming(customChannel) | ||
@@ -243,5 +319,5 @@ | ||
Default: `__THEMING__` | ||
Result: `Object { channel, withTheme, ThemeProvider }` | ||
Result: `Object { channel, withTheme, ThemeProvider. themeListener }` | ||
`withTheme` and `ThemeProvider` are the same as default ones, but with overwritten context channel. | ||
`withTheme`, `ThemeProvider` and `themeListener` are the same as default ones, but with overwritten context channel. | ||
@@ -248,0 +324,0 @@ `channel` is `customChannel` to track what is context channel. |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import channel from './channel'; | ||
import createThemeListener from './create-theme-listener'; | ||
@@ -9,28 +9,16 @@ const getDisplayName = Component => | ||
export default function createWithTheme(CHANNEL = channel) { | ||
const themeListener = createThemeListener(CHANNEL); | ||
return Component => | ||
class WithTheme extends React.Component { | ||
static displayName = `WithTheme(${getDisplayName(Component)})`; | ||
state = { theme: {} }; | ||
setTheme = theme => this.setState({ theme }); | ||
static contextTypes = themeListener.contextTypes; | ||
static contextTypes = { | ||
[CHANNEL]: PropTypes.object.isRequired, | ||
}; | ||
componentWillMount() { | ||
if (!this.context[CHANNEL]) { | ||
throw new Error( | ||
'[WithTheme(${getDisplayName(Component)})] Please use ThemeProvider to be able to use WithTheme', | ||
); | ||
} | ||
this.setState({ theme: this.context[CHANNEL].getState() }); | ||
constructor(props, context) { | ||
super(props, context); | ||
this.state = { theme: themeListener.initial(context) }; | ||
this.setTheme = theme => this.setState({ theme }); | ||
} | ||
componentDidMount() { | ||
if (this.context[CHANNEL]) { | ||
this.unsubscribe = this.context[CHANNEL].subscribe(this.setTheme); | ||
} | ||
this.unsubscribe = themeListener.subscribe(this.context, this.setTheme); | ||
} | ||
componentWillUnmount() { | ||
@@ -41,3 +29,2 @@ if (typeof this.unsubscribe === 'function') { | ||
} | ||
render() { | ||
@@ -44,0 +31,0 @@ const { theme } = this.state; |
@@ -105,6 +105,6 @@ import test from 'ava'; | ||
); | ||
wrapper.instance().unsubscribe = () => unsubscribed(true); | ||
t.false(unsubscribed()); | ||
wrapper.instance().unsubscribe = () => unsubscribed(true); | ||
wrapper.unmount(); | ||
@@ -124,3 +124,3 @@ | ||
Error, | ||
`withTheme(Comp) should throw if used with appropriate context`, | ||
`withTheme(Comp) should throw if used without appropriate context`, | ||
); | ||
@@ -127,0 +127,0 @@ }); |
import createThemeProvider from './create-theme-provider'; | ||
import createWithTheme from './create-with-theme'; | ||
import createThemeListener from './create-theme-listener'; | ||
import defaultChannel from './channel'; | ||
@@ -8,2 +9,3 @@ | ||
export const ThemeProvider = createThemeProvider(); | ||
export const themeListener = createThemeListener(); | ||
export function createTheming(customChannel = defaultChannel) { | ||
@@ -14,2 +16,3 @@ return { | ||
ThemeProvider: createThemeProvider(customChannel), | ||
themeListener: createThemeListener(customChannel), | ||
}; | ||
@@ -22,3 +25,4 @@ } | ||
ThemeProvider, | ||
themeListener, | ||
createTheming, | ||
}; |
@@ -24,3 +24,3 @@ import test from 'ava'; | ||
const actual = Object.keys(theming); | ||
const expected = ['channel', 'withTheme', 'ThemeProvider']; | ||
const expected = ['channel', 'withTheme', 'ThemeProvider', 'themeListener']; | ||
@@ -27,0 +27,0 @@ t.deepEqual( |
@@ -69,10 +69,12 @@ import React, { Component, PureComponent } from 'react'; | ||
}; | ||
componentWillMount() { | ||
if (this.context[channel]) { | ||
this.props.intercept(this.context[channel].getState()); | ||
constructor(props, context) { | ||
super(props, context) | ||
this.broadcast = this.context[channel]; | ||
if (this.broadcast) { | ||
this.props.intercept(this.broadcast.getState()); | ||
} | ||
} | ||
componentDidMount() { | ||
if (this.context[channel]) { | ||
this.unsubscribe = this.context[channel].subscribe(this.props.intercept); | ||
if (this.broadcast) { | ||
this.unsubscribe = this.broadcast.subscribe(this.props.intercept); | ||
} | ||
@@ -79,0 +81,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
70933
23
1444
373