Skip to content

Commit 276570a

Browse files
add lib to repo
1 parent 0c0b2de commit 276570a

File tree

5 files changed

+369
-1
lines changed

5 files changed

+369
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
build
2-
lib
32
node_modules
43
npm-debug.log

lib/components/ThemeProvider.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.default = undefined;
7+
8+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
9+
10+
var _class, _temp;
11+
12+
var _react = require('react');
13+
14+
var _themrShape = require('../utils/themr-shape');
15+
16+
var _themrShape2 = _interopRequireDefault(_themrShape);
17+
18+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19+
20+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
21+
22+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
23+
24+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
25+
26+
var ThemeProvider = (_temp = _class = function (_Component) {
27+
_inherits(ThemeProvider, _Component);
28+
29+
function ThemeProvider() {
30+
_classCallCheck(this, ThemeProvider);
31+
32+
return _possibleConstructorReturn(this, (ThemeProvider.__proto__ || Object.getPrototypeOf(ThemeProvider)).apply(this, arguments));
33+
}
34+
35+
_createClass(ThemeProvider, [{
36+
key: 'getChildContext',
37+
value: function getChildContext() {
38+
return {
39+
themr: {
40+
theme: this.props.theme
41+
}
42+
};
43+
}
44+
}, {
45+
key: 'render',
46+
value: function render() {
47+
return _react.Children.only(this.props.children);
48+
}
49+
}]);
50+
51+
return ThemeProvider;
52+
}(_react.Component), _class.propTypes = {
53+
children: _react.PropTypes.element.isRequired,
54+
theme: _react.PropTypes.object.isRequired
55+
}, _class.defaultProps = {
56+
theme: {}
57+
}, _class.childContextTypes = {
58+
themr: _themrShape2.default.isRequired
59+
}, _temp);
60+
exports.default = ThemeProvider;

lib/components/themr.js

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
8+
9+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
10+
11+
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; };
12+
13+
exports.themeable = themeable;
14+
15+
var _react = require('react');
16+
17+
var _react2 = _interopRequireDefault(_react);
18+
19+
var _invariant = require('invariant');
20+
21+
var _invariant2 = _interopRequireDefault(_invariant);
22+
23+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24+
25+
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
26+
27+
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; }
28+
29+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
30+
31+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
32+
33+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
34+
35+
/**
36+
* @typedef {Object.<string, TReactCSSThemrTheme>} TReactCSSThemrTheme
37+
*/
38+
39+
/**
40+
* @typedef {{}} TReactCSSThemrOptions
41+
* @property {String|Boolean} [composeTheme=COMPOSE_DEEPLY]
42+
* @property {Boolean} [withRef=false]
43+
*/
44+
45+
var COMPOSE_DEEPLY = 'deeply';
46+
var COMPOSE_SOFTLY = 'softly';
47+
var DONT_COMPOSE = false;
48+
49+
var DEFAULT_OPTIONS = {
50+
composeTheme: COMPOSE_DEEPLY,
51+
withRef: false
52+
};
53+
54+
var THEMR_CONFIG = typeof Symbol !== 'undefined' ? Symbol('THEMR_CONFIG') : '__REACT_CSS_THEMR_CONFIG__';
55+
56+
/**
57+
* Themr decorator
58+
* @param {String|Number|Symbol} componentName - Component name
59+
* @param {TReactCSSThemrTheme} [localTheme] - Base theme
60+
* @param {{}} [options] - Themr options
61+
* @returns {function(ThemedComponent:Function):Function} - ThemedComponent
62+
*/
63+
64+
exports.default = function (componentName, localTheme) {
65+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
66+
return function (ThemedComponent) {
67+
var _class, _temp;
68+
69+
var _DEFAULT_OPTIONS$opti = _extends({}, DEFAULT_OPTIONS, options),
70+
optionComposeTheme = _DEFAULT_OPTIONS$opti.composeTheme,
71+
optionWithRef = _DEFAULT_OPTIONS$opti.withRef;
72+
73+
validateComposeOption(optionComposeTheme);
74+
75+
var config = ThemedComponent[THEMR_CONFIG];
76+
if (config && config.componentName === componentName) {
77+
config.localTheme = themeable(config.localTheme, localTheme);
78+
return ThemedComponent;
79+
}
80+
81+
config = {
82+
componentName: componentName,
83+
localTheme: localTheme
84+
};
85+
86+
/**
87+
* @property {{wrappedInstance: *}} refs
88+
*/
89+
var Themed = (_temp = _class = function (_Component) {
90+
_inherits(Themed, _Component);
91+
92+
function Themed(props) {
93+
var _ref;
94+
95+
_classCallCheck(this, Themed);
96+
97+
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
98+
args[_key - 1] = arguments[_key];
99+
}
100+
101+
var _this = _possibleConstructorReturn(this, (_ref = Themed.__proto__ || Object.getPrototypeOf(Themed)).call.apply(_ref, [this, props].concat(args)));
102+
103+
_this.theme_ = _this.calcTheme(props);
104+
return _this;
105+
}
106+
107+
_createClass(Themed, [{
108+
key: 'getWrappedInstance',
109+
value: function getWrappedInstance() {
110+
(0, _invariant2.default)(optionWithRef, 'To access the wrapped instance, you need to specify ' + '{ withRef: true } as the third argument of the themr() call.');
111+
112+
return this.refs.wrappedInstance;
113+
}
114+
}, {
115+
key: 'getNamespacedTheme',
116+
value: function getNamespacedTheme(props) {
117+
var themeNamespace = props.themeNamespace,
118+
theme = props.theme;
119+
120+
if (!themeNamespace) return theme;
121+
if (themeNamespace && !theme) throw new Error('Invalid themeNamespace use in react-css-themr. ' + 'themeNamespace prop should be used only with theme prop.');
122+
123+
return Object.keys(theme).filter(function (key) {
124+
return key.startsWith(themeNamespace);
125+
}).reduce(function (result, key) {
126+
return _extends({}, result, _defineProperty({}, removeNamespace(key, themeNamespace), theme[key]));
127+
}, {});
128+
}
129+
}, {
130+
key: 'getThemeNotComposed',
131+
value: function getThemeNotComposed(props) {
132+
if (props.theme) return this.getNamespacedTheme(props);
133+
if (config.localTheme) return config.localTheme;
134+
return this.getContextTheme();
135+
}
136+
}, {
137+
key: 'getContextTheme',
138+
value: function getContextTheme() {
139+
return this.context.themr ? this.context.themr.theme[config.componentName] : {};
140+
}
141+
}, {
142+
key: 'getTheme',
143+
value: function getTheme(props) {
144+
return props.composeTheme === COMPOSE_SOFTLY ? _extends({}, this.getContextTheme(), config.localTheme, this.getNamespacedTheme(props)) : themeable(themeable(this.getContextTheme(), config.localTheme), this.getNamespacedTheme(props));
145+
}
146+
}, {
147+
key: 'calcTheme',
148+
value: function calcTheme(props) {
149+
var composeTheme = props.composeTheme;
150+
151+
return composeTheme ? this.getTheme(props) : this.getThemeNotComposed(props);
152+
}
153+
}, {
154+
key: 'componentWillReceiveProps',
155+
value: function componentWillReceiveProps(nextProps) {
156+
if (nextProps.composeTheme !== this.props.composeTheme || nextProps.theme !== this.props.theme || nextProps.themeNamespace !== this.props.themeNamespace) {
157+
this.theme_ = this.calcTheme(nextProps);
158+
}
159+
}
160+
}, {
161+
key: 'render',
162+
value: function render() {
163+
var renderedElement = void 0;
164+
//exclude themr-only props
165+
//noinspection JSUnusedLocalSymbols
166+
167+
var _props = this.props,
168+
composeTheme = _props.composeTheme,
169+
themeNamespace = _props.themeNamespace,
170+
props = _objectWithoutProperties(_props, ['composeTheme', 'themeNamespace']); //eslint-disable-line no-unused-vars
171+
172+
if (optionWithRef) {
173+
renderedElement = _react2.default.createElement(ThemedComponent, _extends({}, props, {
174+
ref: 'wrappedInstance',
175+
theme: this.theme_
176+
}));
177+
} else {
178+
renderedElement = _react2.default.createElement(ThemedComponent, _extends({}, props, {
179+
theme: this.theme_
180+
}));
181+
}
182+
183+
return renderedElement;
184+
}
185+
}]);
186+
187+
return Themed;
188+
}(_react.Component), _class.displayName = 'Themed' + ThemedComponent.name, _class.contextTypes = {
189+
themr: _react.PropTypes.object
190+
}, _class.propTypes = _extends({}, ThemedComponent.propTypes, {
191+
composeTheme: _react.PropTypes.oneOf([COMPOSE_DEEPLY, COMPOSE_SOFTLY, DONT_COMPOSE]),
192+
theme: _react.PropTypes.object,
193+
themeNamespace: _react.PropTypes.string
194+
}), _class.defaultProps = _extends({}, ThemedComponent.defaultProps, {
195+
composeTheme: optionComposeTheme
196+
}), _temp);
197+
198+
199+
Themed[THEMR_CONFIG] = config;
200+
201+
return Themed;
202+
};
203+
};
204+
205+
/**
206+
* Merges two themes by concatenating values with the same keys
207+
* @param {TReactCSSThemrTheme} [original] - Original theme object
208+
* @param {TReactCSSThemrTheme} [mixin] - Mixing theme object
209+
* @returns {TReactCSSThemrTheme} - Merged resulting theme
210+
*/
211+
212+
213+
function themeable() {
214+
var original = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
215+
var mixin = arguments[1];
216+
217+
//don't merge if no mixin is passed
218+
if (!mixin) return original;
219+
220+
//merge themes by concatenating values with the same keys
221+
return Object.keys(mixin).reduce(
222+
223+
//merging reducer
224+
function (result, key) {
225+
var originalValue = original[key];
226+
var mixinValue = mixin[key];
227+
228+
var newValue = void 0;
229+
230+
//check if values are nested objects
231+
if ((typeof originalValue === 'undefined' ? 'undefined' : _typeof(originalValue)) === 'object' && (typeof mixinValue === 'undefined' ? 'undefined' : _typeof(mixinValue)) === 'object') {
232+
//go recursive
233+
newValue = themeable(originalValue, mixinValue);
234+
} else {
235+
//either concat or take mixin value
236+
newValue = originalValue ? originalValue + ' ' + mixinValue : mixinValue;
237+
}
238+
239+
return _extends({}, result, _defineProperty({}, key, newValue));
240+
},
241+
242+
//use original theme as an acc
243+
original);
244+
}
245+
246+
/**
247+
* Validates compose option
248+
* @param {String|Boolean} composeTheme - Compose them option
249+
* @throws
250+
* @returns {undefined}
251+
*/
252+
function validateComposeOption(composeTheme) {
253+
if ([COMPOSE_DEEPLY, COMPOSE_SOFTLY, DONT_COMPOSE].indexOf(composeTheme) === -1) {
254+
throw new Error('Invalid composeTheme option for react-css-themr. Valid composition options are ' + COMPOSE_DEEPLY + ', ' + COMPOSE_SOFTLY + ' and ' + DONT_COMPOSE + '. The given option was ' + composeTheme);
255+
}
256+
}
257+
258+
/**
259+
* Removes namespace from key
260+
* @param {String} key - Key
261+
* @param {String} themeNamespace - Theme namespace
262+
* @returns {String} - Key
263+
*/
264+
function removeNamespace(key, themeNamespace) {
265+
var capitalized = key.substr(themeNamespace.length);
266+
return capitalized.slice(0, 1).toLowerCase() + capitalized.slice(1);
267+
}

lib/index.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _ThemeProvider = require('./components/ThemeProvider');
8+
9+
Object.defineProperty(exports, 'ThemeProvider', {
10+
enumerable: true,
11+
get: function get() {
12+
return _interopRequireDefault(_ThemeProvider).default;
13+
}
14+
});
15+
16+
var _themr = require('./components/themr');
17+
18+
Object.defineProperty(exports, 'themr', {
19+
enumerable: true,
20+
get: function get() {
21+
return _interopRequireDefault(_themr).default;
22+
}
23+
});
24+
Object.defineProperty(exports, 'themeable', {
25+
enumerable: true,
26+
get: function get() {
27+
return _themr.themeable;
28+
}
29+
});
30+
31+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

lib/utils/themr-shape.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _react = require('react');
8+
9+
exports.default = _react.PropTypes.shape({
10+
theme: _react.PropTypes.object.isRequired
11+
});

0 commit comments

Comments
 (0)