styled-components 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/CODE_OF_CONDUCT.md +1 -1
  3. package/README.md +12 -67
  4. package/dist/styled-components.es.js +273 -110
  5. package/dist/styled-components.js +325 -119
  6. package/dist/styled-components.min.js +2 -2
  7. package/lib/hoc/withTheme.js +13 -7
  8. package/lib/models/BrowserStyleSheet.js +11 -0
  9. package/lib/models/ComponentStyle.js +45 -2
  10. package/lib/models/InlineStyle.js +1 -1
  11. package/lib/models/ServerStyleSheet.js +33 -17
  12. package/lib/models/StyleSheet.js +9 -0
  13. package/lib/models/StyledComponent.js +82 -38
  14. package/lib/models/StyledNativeComponent.js +31 -15
  15. package/lib/models/ThemeProvider.js +44 -12
  16. package/lib/native/index.js +1 -1
  17. package/lib/test/utils.js +5 -2
  18. package/lib/utils/create-broadcast.js +34 -24
  19. package/lib/utils/domElements.js +1 -1
  20. package/lib/utils/flatten.js +4 -1
  21. package/lib/utils/generateAlphabeticName.js +1 -1
  22. package/lib/utils/nonce.js +10 -0
  23. package/lib/utils/once.js +17 -0
  24. package/package.json +10 -10
  25. package/src/hoc/withTheme.js +14 -7
  26. package/src/models/BrowserStyleSheet.js +8 -0
  27. package/src/models/ComponentStyle.js +42 -2
  28. package/src/models/InlineStyle.js +1 -1
  29. package/src/models/ServerStyleSheet.js +27 -12
  30. package/src/models/StyleSheet.js +9 -0
  31. package/src/models/StyledComponent.js +81 -26
  32. package/src/models/StyledNativeComponent.js +30 -10
  33. package/src/models/ThemeProvider.js +38 -9
  34. package/src/models/test/ThemeProvider.test.js +7 -8
  35. package/src/native/index.js +1 -1
  36. package/src/native/test/native.test.js +14 -0
  37. package/src/test/__snapshots__/ssr.test.js.snap +147 -0
  38. package/src/test/expanded-api.test.js +24 -0
  39. package/src/test/props.test.js +14 -3
  40. package/src/test/ssr.test.js +90 -123
  41. package/src/test/styles.test.js +52 -0
  42. package/src/test/utils.js +5 -2
  43. package/src/utils/create-broadcast.js +31 -17
  44. package/src/utils/domElements.js +1 -0
  45. package/src/utils/flatten.js +16 -6
  46. package/src/utils/generateAlphabeticName.js +1 -1
  47. package/src/utils/nonce.js +6 -0
  48. package/src/utils/once.js +12 -0
  49. package/typings/styled-components.d.ts +15 -21
  50. package/typings/tests/issue1068.tsx +226 -0
  51. package/typings/tests/main-test.tsx +1 -1
  52. package/typings/tests/string-tags-test.tsx +62 -0
  53. package/typings/tests/themed-tests/issue1068.tsx +226 -0
  54. package/typings/tests/themed-tests/mytheme-styled-components.tsx +1 -1
  55. package/typings/tests/themed-tests/with-theme-test.tsx +2 -1
  56. package/typings/tests/with-theme-test.tsx +17 -0
  57. package/lib/constructors/test/injectGlobal.test.js +0 -63
  58. package/lib/constructors/test/keyframes.test.js +0 -48
  59. package/lib/constructors/test/styled.test.js +0 -19
  60. package/lib/models/AbstractStyledComponent.js +0 -43
  61. package/lib/models/test/ThemeProvider.test.js +0 -200
  62. package/lib/native/test/native.test.js +0 -290
  63. package/lib/no-parser/test/basic.test.js +0 -46
  64. package/lib/no-parser/test/flatten.test.js +0 -125
  65. package/lib/no-parser/test/keyframes.test.js +0 -45
  66. package/lib/primitives/test/primitives.test.js +0 -289
  67. package/lib/test/attrs.test.js +0 -158
  68. package/lib/test/basic.test.js +0 -267
  69. package/lib/test/css.test.js +0 -43
  70. package/lib/test/expanded-api.test.js +0 -90
  71. package/lib/test/extending.test.js +0 -198
  72. package/lib/test/overriding.test.js +0 -35
  73. package/lib/test/props.test.js +0 -38
  74. package/lib/test/rehydration.test.js +0 -306
  75. package/lib/test/ssr.test.js +0 -187
  76. package/lib/test/styles.test.js +0 -146
  77. package/lib/test/theme.test.js +0 -497
  78. package/lib/test/warnTooManyClasses.test.js +0 -71
  79. package/lib/utils/test/extractCompsFromCSS.test.js +0 -46
  80. package/lib/utils/test/flatten.test.js +0 -109
  81. package/lib/utils/test/generateAlphabeticName.test.js +0 -14
  82. package/lib/utils/test/interleave.test.js +0 -22
  83. package/lib/utils/test/validAttr.test.js +0 -560
  84. package/src/models/AbstractStyledComponent.js +0 -21
  85. package/typings/tags.d.ts +0 -137
@@ -32,10 +32,6 @@ var _getComponentName = require('../utils/getComponentName');
32
32
 
33
33
  var _getComponentName2 = _interopRequireDefault(_getComponentName);
34
34
 
35
- var _AbstractStyledComponent = require('./AbstractStyledComponent');
36
-
37
- var _AbstractStyledComponent2 = _interopRequireDefault(_AbstractStyledComponent);
38
-
39
35
  var _ThemeProvider = require('./ThemeProvider');
40
36
 
41
37
  var _StyleSheet = require('./StyleSheet');
@@ -61,10 +57,14 @@ var babelPluginFlowReactPropTypes_proptype_RuleSet = require('../types').babelPl
61
57
  var escapeRegex = /[[\].#*$><+~=|^:(),"'`]/g;
62
58
  var multiDashRegex = /--+/g;
63
59
 
60
+ // HACK for generating all static styles without needing to allocate
61
+ // an empty execution context every single time...
62
+ var STATIC_EXECUTION_CONTEXT = {};
63
+
64
64
  exports.default = function (ComponentStyle, constructWithOptions) {
65
65
  /* We depend on components having unique IDs */
66
66
  var identifiers = {};
67
- var generateId = function generateId(_displayName) {
67
+ var generateId = function generateId(_displayName, parentComponentId) {
68
68
  var displayName = typeof _displayName !== 'string' ? 'sc' : _displayName.replace(escapeRegex, '-') // Replace all possible CSS selectors
69
69
  .replace(multiDashRegex, '-'); // Replace multiple -- with single -
70
70
 
@@ -72,11 +72,12 @@ exports.default = function (ComponentStyle, constructWithOptions) {
72
72
  identifiers[displayName] = nr;
73
73
 
74
74
  var hash = ComponentStyle.generateName(displayName + nr);
75
- return displayName + '-' + hash;
75
+ var componentId = displayName + '-' + hash;
76
+ return parentComponentId !== undefined ? parentComponentId + '-' + componentId : componentId;
76
77
  };
77
78
 
78
- var BaseStyledComponent = function (_AbstractStyledCompon) {
79
- _inherits(BaseStyledComponent, _AbstractStyledCompon);
79
+ var BaseStyledComponent = function (_Component) {
80
+ _inherits(BaseStyledComponent, _Component);
80
81
 
81
82
  function BaseStyledComponent() {
82
83
  var _temp, _this, _ret;
@@ -87,12 +88,18 @@ exports.default = function (ComponentStyle, constructWithOptions) {
87
88
  args[_key] = arguments[_key];
88
89
  }
89
90
 
90
- return _ret = (_temp = (_this = _possibleConstructorReturn(this, _AbstractStyledCompon.call.apply(_AbstractStyledCompon, [this].concat(args))), _this), _this.attrs = {}, _this.state = {
91
+ return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.attrs = {}, _this.state = {
91
92
  theme: null,
92
93
  generatedClassName: ''
93
- }, _temp), _possibleConstructorReturn(_this, _ret);
94
+ }, _this.unsubscribeId = -1, _temp), _possibleConstructorReturn(_this, _ret);
94
95
  }
95
96
 
97
+ BaseStyledComponent.prototype.unsubscribeFromContext = function unsubscribeFromContext() {
98
+ if (this.unsubscribeId !== -1) {
99
+ this.context[_ThemeProvider.CHANNEL_NEXT].unsubscribe(this.unsubscribeId);
100
+ }
101
+ };
102
+
96
103
  BaseStyledComponent.prototype.buildExecutionContext = function buildExecutionContext(theme, props) {
97
104
  var attrs = this.constructor.attrs;
98
105
 
@@ -113,55 +120,86 @@ exports.default = function (ComponentStyle, constructWithOptions) {
113
120
 
114
121
  BaseStyledComponent.prototype.generateAndInjectStyles = function generateAndInjectStyles(theme, props) {
115
122
  var _constructor = this.constructor,
123
+ attrs = _constructor.attrs,
116
124
  componentStyle = _constructor.componentStyle,
117
125
  warnTooManyClasses = _constructor.warnTooManyClasses;
118
126
 
119
- var executionContext = this.buildExecutionContext(theme, props);
120
127
  var styleSheet = this.context[_StyleSheet.CONTEXT_KEY] || _StyleSheet2.default.instance;
121
- var className = componentStyle.generateAndInjectStyles(executionContext, styleSheet);
122
128
 
123
- if (warnTooManyClasses !== undefined) warnTooManyClasses(className);
129
+ // staticaly styled-components don't need to build an execution context object,
130
+ // and shouldn't be increasing the number of class names
131
+ if (componentStyle.isStatic && attrs === undefined) {
132
+ return componentStyle.generateAndInjectStyles(STATIC_EXECUTION_CONTEXT, styleSheet);
133
+ } else {
134
+ var executionContext = this.buildExecutionContext(theme, props);
135
+ var className = componentStyle.generateAndInjectStyles(executionContext, styleSheet);
136
+
137
+ if (warnTooManyClasses !== undefined) warnTooManyClasses(className);
124
138
 
125
- return className;
139
+ return className;
140
+ }
126
141
  };
127
142
 
128
143
  BaseStyledComponent.prototype.componentWillMount = function componentWillMount() {
129
144
  var _this2 = this;
130
145
 
131
- // If there is a theme in the context, subscribe to the event emitter. This
132
- // is necessary due to pure components blocking context updates, this circumvents
133
- // that by updating when an event is emitted
134
- if (this.context[_ThemeProvider.CHANNEL]) {
135
- var subscribe = this.context[_ThemeProvider.CHANNEL];
136
- this.unsubscribe = subscribe(function (nextTheme) {
146
+ var componentStyle = this.constructor.componentStyle;
147
+
148
+ var styledContext = this.context[_ThemeProvider.CHANNEL_NEXT];
149
+
150
+ // If this is a staticaly-styled component, we don't need to the theme
151
+ // to generate or build styles.
152
+ if (componentStyle.isStatic) {
153
+ var generatedClassName = this.generateAndInjectStyles(STATIC_EXECUTION_CONTEXT, this.props);
154
+ this.setState({ generatedClassName: generatedClassName });
155
+ // If there is a theme in the context, subscribe to the event emitter. This
156
+ // is necessary due to pure components blocking context updates, this circumvents
157
+ // that by updating when an event is emitted
158
+ } else if (styledContext !== undefined) {
159
+ var subscribe = styledContext.subscribe;
160
+
161
+ this.unsubscribeId = subscribe(function (nextTheme) {
137
162
  // This will be called once immediately
138
163
 
139
164
  // Props should take precedence over ThemeProvider, which should take precedence over
140
165
  // defaultProps, but React automatically puts defaultProps on props.
141
166
  var defaultProps = _this2.constructor.defaultProps;
167
+ /* eslint-disable react/prop-types */
142
168
 
143
169
  var isDefaultTheme = defaultProps && _this2.props.theme === defaultProps.theme;
144
170
  var theme = _this2.props.theme && !isDefaultTheme ? _this2.props.theme : nextTheme;
171
+ /* eslint-enable */
145
172
  var generatedClassName = _this2.generateAndInjectStyles(theme, _this2.props);
146
173
  _this2.setState({ theme: theme, generatedClassName: generatedClassName });
147
174
  });
148
175
  } else {
176
+ // eslint-disable-next-line react/prop-types
149
177
  var _theme = this.props.theme || {};
150
- var generatedClassName = this.generateAndInjectStyles(_theme, this.props);
151
- this.setState({ theme: _theme, generatedClassName: generatedClassName });
178
+ var _generatedClassName = this.generateAndInjectStyles(_theme, this.props);
179
+ this.setState({ theme: _theme, generatedClassName: _generatedClassName });
152
180
  }
153
181
  };
154
182
 
155
183
  BaseStyledComponent.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
156
184
  var _this3 = this;
157
185
 
186
+ // If this is a staticaly-styled component, we don't need to listen to
187
+ // props changes to update styles
188
+ var componentStyle = this.constructor.componentStyle;
189
+
190
+ if (componentStyle.isStatic) {
191
+ return;
192
+ }
193
+
158
194
  this.setState(function (oldState) {
159
195
  // Props should take precedence over ThemeProvider, which should take precedence over
160
196
  // defaultProps, but React automatically puts defaultProps on props.
161
197
  var defaultProps = _this3.constructor.defaultProps;
198
+ /* eslint-disable react/prop-types */
162
199
 
163
200
  var isDefaultTheme = defaultProps && nextProps.theme === defaultProps.theme;
164
201
  var theme = nextProps.theme && !isDefaultTheme ? nextProps.theme : oldState.theme;
202
+ /* eslint-enable */
165
203
  var generatedClassName = _this3.generateAndInjectStyles(theme, nextProps);
166
204
 
167
205
  return { theme: theme, generatedClassName: generatedClassName };
@@ -169,14 +207,13 @@ exports.default = function (ComponentStyle, constructWithOptions) {
169
207
  };
170
208
 
171
209
  BaseStyledComponent.prototype.componentWillUnmount = function componentWillUnmount() {
172
- if (this.unsubscribe) {
173
- this.unsubscribe();
174
- }
210
+ this.unsubscribeFromContext();
175
211
  };
176
212
 
177
213
  BaseStyledComponent.prototype.render = function render() {
178
214
  var _this4 = this;
179
215
 
216
+ // eslint-disable-next-line react/prop-types
180
217
  var innerRef = this.props.innerRef;
181
218
  var generatedClassName = this.state.generatedClassName;
182
219
  var _constructor2 = this.constructor,
@@ -186,7 +223,9 @@ exports.default = function (ComponentStyle, constructWithOptions) {
186
223
 
187
224
  var isTargetTag = (0, _isTag2.default)(target);
188
225
 
189
- var className = [this.props.className, styledComponentId, this.attrs.className, generatedClassName].filter(Boolean).join(' ');
226
+ var className = [
227
+ // eslint-disable-next-line react/prop-types
228
+ this.props.className, styledComponentId, this.attrs.className, generatedClassName].filter(Boolean).join(' ');
190
229
 
191
230
  var baseProps = _extends({}, this.attrs, {
192
231
  className: className
@@ -213,7 +252,7 @@ exports.default = function (ComponentStyle, constructWithOptions) {
213
252
  };
214
253
 
215
254
  return BaseStyledComponent;
216
- }(_AbstractStyledComponent2.default);
255
+ }(_react.Component);
217
256
 
218
257
  var createStyledComponent = function createStyledComponent(target, options, rules) {
219
258
  var _StyledComponent$cont;
@@ -221,7 +260,7 @@ exports.default = function (ComponentStyle, constructWithOptions) {
221
260
  var _options$displayName = options.displayName,
222
261
  displayName = _options$displayName === undefined ? (0, _isTag2.default)(target) ? 'styled.' + target : 'Styled(' + (0, _getComponentName2.default)(target) + ')' : _options$displayName,
223
262
  _options$componentId = options.componentId,
224
- componentId = _options$componentId === undefined ? generateId(options.displayName) : _options$componentId,
263
+ componentId = _options$componentId === undefined ? generateId(options.displayName, options.parentComponentId) : _options$componentId,
225
264
  _options$ParentCompon = options.ParentComponent,
226
265
  ParentComponent = _options$ParentCompon === undefined ? BaseStyledComponent : _options$ParentCompon,
227
266
  extendingRules = options.rules,
@@ -231,7 +270,7 @@ exports.default = function (ComponentStyle, constructWithOptions) {
231
270
  var styledComponentId = options.displayName && options.componentId ? options.displayName + '-' + options.componentId : componentId;
232
271
 
233
272
  var warnTooManyClasses = void 0;
234
- if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
273
+ if (process.env.NODE_ENV !== 'production') {
235
274
  warnTooManyClasses = (0, _createWarnTooManyClasses2.default)(displayName);
236
275
  }
237
276
 
@@ -247,26 +286,31 @@ exports.default = function (ComponentStyle, constructWithOptions) {
247
286
  }
248
287
 
249
288
  StyledComponent.withComponent = function withComponent(tag) {
250
- var _ = options.displayName,
251
- __ = options.componentId,
252
- optionsToCopy = _objectWithoutProperties(options, ['displayName', 'componentId']);
289
+ var previousComponentId = options.componentId,
290
+ optionsToCopy = _objectWithoutProperties(options, ['componentId']);
291
+
292
+ var newComponentId = previousComponentId && previousComponentId + '-' + ((0, _isTag2.default)(tag) ? tag : (0, _getComponentName2.default)(tag));
293
+
294
+ var newOptions = _extends({}, optionsToCopy, {
295
+ componentId: newComponentId,
296
+ ParentComponent: StyledComponent
297
+ });
253
298
 
254
- var newOptions = _extends({}, optionsToCopy, { ParentComponent: StyledComponent });
255
299
  return createStyledComponent(tag, newOptions, rules);
256
300
  };
257
301
 
258
302
  _createClass(StyledComponent, null, [{
259
303
  key: 'extend',
260
304
  get: function get() {
261
- var _ = options.displayName,
262
- __ = options.componentId,
263
- rulesFromOptions = options.rules,
264
- optionsToCopy = _objectWithoutProperties(options, ['displayName', 'componentId', 'rules']);
305
+ var rulesFromOptions = options.rules,
306
+ parentComponentId = options.componentId,
307
+ optionsToCopy = _objectWithoutProperties(options, ['rules', 'componentId']);
265
308
 
266
309
  var newRules = rulesFromOptions === undefined ? rules : rulesFromOptions.concat(rules);
267
310
 
268
311
  var newOptions = _extends({}, optionsToCopy, {
269
312
  rules: newRules,
313
+ parentComponentId: parentComponentId,
270
314
  ParentComponent: StyledComponent
271
315
  });
272
316
 
@@ -277,7 +321,7 @@ exports.default = function (ComponentStyle, constructWithOptions) {
277
321
  return StyledComponent;
278
322
  }(ParentComponent);
279
323
 
280
- StyledComponent.contextTypes = (_StyledComponent$cont = {}, _StyledComponent$cont[_ThemeProvider.CHANNEL] = _propTypes2.default.func, _StyledComponent$cont[_StyleSheet.CONTEXT_KEY] = _propTypes2.default.instanceOf(_StyleSheet2.default), _StyledComponent$cont);
324
+ StyledComponent.contextTypes = (_StyledComponent$cont = {}, _StyledComponent$cont[_ThemeProvider.CHANNEL] = _propTypes2.default.func, _StyledComponent$cont[_ThemeProvider.CHANNEL_NEXT] = _ThemeProvider.CONTEXT_CHANNEL_SHAPE, _StyledComponent$cont[_StyleSheet.CONTEXT_KEY] = _propTypes2.default.instanceOf(_StyleSheet2.default), _StyledComponent$cont);
281
325
  StyledComponent.displayName = displayName;
282
326
  StyledComponent.styledComponentId = styledComponentId;
283
327
  StyledComponent.attrs = attrs;
@@ -8,6 +8,10 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
8
8
 
9
9
  var _react = require('react');
10
10
 
11
+ var _propTypes = require('prop-types');
12
+
13
+ var _propTypes2 = _interopRequireDefault(_propTypes);
14
+
11
15
  var _isTag = require('../utils/isTag');
12
16
 
13
17
  var _isTag2 = _interopRequireDefault(_isTag);
@@ -22,10 +26,6 @@ var _getComponentName2 = _interopRequireDefault(_getComponentName);
22
26
 
23
27
  var _ThemeProvider = require('./ThemeProvider');
24
28
 
25
- var _AbstractStyledComponent = require('./AbstractStyledComponent');
26
-
27
- var _AbstractStyledComponent2 = _interopRequireDefault(_AbstractStyledComponent);
28
-
29
29
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30
30
 
31
31
  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; }
@@ -43,8 +43,8 @@ var babelPluginFlowReactPropTypes_proptype_Target = require('../types').babelPlu
43
43
  var babelPluginFlowReactPropTypes_proptype_RuleSet = require('../types').babelPluginFlowReactPropTypes_proptype_RuleSet || require('prop-types').any;
44
44
 
45
45
  exports.default = function (constructWithOptions, InlineStyle) {
46
- var BaseStyledNativeComponent = function (_AbstractStyledCompon) {
47
- _inherits(BaseStyledNativeComponent, _AbstractStyledCompon);
46
+ var BaseStyledNativeComponent = function (_Component) {
47
+ _inherits(BaseStyledNativeComponent, _Component);
48
48
 
49
49
  function BaseStyledNativeComponent() {
50
50
  var _temp, _this, _ret;
@@ -55,10 +55,11 @@ exports.default = function (constructWithOptions, InlineStyle) {
55
55
  args[_key] = arguments[_key];
56
56
  }
57
57
 
58
- return _ret = (_temp = (_this = _possibleConstructorReturn(this, _AbstractStyledCompon.call.apply(_AbstractStyledCompon, [this].concat(args))), _this), _this.attrs = {}, _this.state = {
58
+ return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.attrs = {}, _this.state = {
59
59
  theme: null,
60
60
  generatedStyles: undefined
61
- }, _this.onRef = function (node) {
61
+ }, _this.unsubscribeId = -1, _this.onRef = function (node) {
62
+ // eslint-disable-next-line react/prop-types
62
63
  var innerRef = _this.props.innerRef;
63
64
 
64
65
  _this.root = node;
@@ -69,6 +70,12 @@ exports.default = function (constructWithOptions, InlineStyle) {
69
70
  }, _temp), _possibleConstructorReturn(_this, _ret);
70
71
  }
71
72
 
73
+ BaseStyledNativeComponent.prototype.unsubscribeFromContext = function unsubscribeFromContext() {
74
+ if (this.unsubscribeId !== -1) {
75
+ this.context[_ThemeProvider.CHANNEL_NEXT].unsubscribe(this.unsubscribeId);
76
+ }
77
+ };
78
+
72
79
  BaseStyledNativeComponent.prototype.buildExecutionContext = function buildExecutionContext(theme, props) {
73
80
  var attrs = this.constructor.attrs;
74
81
 
@@ -101,21 +108,26 @@ exports.default = function (constructWithOptions, InlineStyle) {
101
108
  // If there is a theme in the context, subscribe to the event emitter. This
102
109
  // is necessary due to pure components blocking context updates, this circumvents
103
110
  // that by updating when an event is emitted
104
- if (this.context[_ThemeProvider.CHANNEL]) {
105
- var subscribe = this.context[_ThemeProvider.CHANNEL];
106
- this.unsubscribe = subscribe(function (nextTheme) {
111
+ var styledContext = this.context[_ThemeProvider.CHANNEL_NEXT];
112
+ if (styledContext !== undefined) {
113
+ var subscribe = styledContext.subscribe;
114
+
115
+ this.unsubscribeId = subscribe(function (nextTheme) {
107
116
  // This will be called once immediately
108
117
 
109
118
  // Props should take precedence over ThemeProvider, which should take precedence over
110
119
  // defaultProps, but React automatically puts defaultProps on props.
111
120
  var defaultProps = _this2.constructor.defaultProps;
121
+ /* eslint-disable react/prop-types */
112
122
 
113
123
  var isDefaultTheme = defaultProps && _this2.props.theme === defaultProps.theme;
114
124
  var theme = _this2.props.theme && !isDefaultTheme ? _this2.props.theme : nextTheme;
125
+ /* eslint-enable */
115
126
  var generatedStyles = _this2.generateAndInjectStyles(theme, _this2.props);
116
127
  _this2.setState({ theme: theme, generatedStyles: generatedStyles });
117
128
  });
118
129
  } else {
130
+ // eslint-disable-next-line react/prop-types
119
131
  var _theme = this.props.theme || {};
120
132
  var generatedStyles = this.generateAndInjectStyles(_theme, this.props);
121
133
  this.setState({ theme: _theme, generatedStyles: generatedStyles });
@@ -129,9 +141,11 @@ exports.default = function (constructWithOptions, InlineStyle) {
129
141
  // Props should take precedence over ThemeProvider, which should take precedence over
130
142
  // defaultProps, but React automatically puts defaultProps on props.
131
143
  var defaultProps = _this3.constructor.defaultProps;
144
+ /* eslint-disable react/prop-types */
132
145
 
133
146
  var isDefaultTheme = defaultProps && nextProps.theme === defaultProps.theme;
134
147
  var theme = nextProps.theme && !isDefaultTheme ? nextProps.theme : oldState.theme;
148
+ /* eslint-enable */
135
149
  var generatedStyles = _this3.generateAndInjectStyles(theme, nextProps);
136
150
 
137
151
  return { theme: theme, generatedStyles: generatedStyles };
@@ -139,9 +153,7 @@ exports.default = function (constructWithOptions, InlineStyle) {
139
153
  };
140
154
 
141
155
  BaseStyledNativeComponent.prototype.componentWillUnmount = function componentWillUnmount() {
142
- if (this.unsubscribe) {
143
- this.unsubscribe();
144
- }
156
+ this.unsubscribeFromContext();
145
157
  };
146
158
 
147
159
  BaseStyledNativeComponent.prototype.setNativeProps = function setNativeProps(nativeProps) {
@@ -158,6 +170,7 @@ exports.default = function (constructWithOptions, InlineStyle) {
158
170
  };
159
171
 
160
172
  BaseStyledNativeComponent.prototype.render = function render() {
173
+ // eslint-disable-next-line react/prop-types
161
174
  var _props = this.props,
162
175
  children = _props.children,
163
176
  style = _props.style;
@@ -182,9 +195,11 @@ exports.default = function (constructWithOptions, InlineStyle) {
182
195
  };
183
196
 
184
197
  return BaseStyledNativeComponent;
185
- }(_AbstractStyledComponent2.default);
198
+ }(_react.Component);
186
199
 
187
200
  var createStyledNativeComponent = function createStyledNativeComponent(target, options, rules) {
201
+ var _StyledNativeComponen;
202
+
188
203
  var _options$displayName = options.displayName,
189
204
  displayName = _options$displayName === undefined ? (0, _isTag2.default)(target) ? 'styled.' + target : 'Styled(' + (0, _getComponentName2.default)(target) + ')' : _options$displayName,
190
205
  _options$ParentCompon = options.ParentComponent,
@@ -242,6 +257,7 @@ exports.default = function (constructWithOptions, InlineStyle) {
242
257
  StyledNativeComponent.target = target;
243
258
  StyledNativeComponent.attrs = attrs;
244
259
  StyledNativeComponent.inlineStyle = inlineStyle;
260
+ StyledNativeComponent.contextTypes = (_StyledNativeComponen = {}, _StyledNativeComponen[_ThemeProvider.CHANNEL] = _propTypes2.default.func, _StyledNativeComponen[_ThemeProvider.CHANNEL_NEXT] = _ThemeProvider.CONTEXT_CHANNEL_SHAPE, _StyledNativeComponen);
245
261
  StyledNativeComponent.styledComponentId = 'StyledNativeComponent';
246
262
 
247
263
 
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  exports.__esModule = true;
4
- exports.CHANNEL = undefined;
4
+ exports.CONTEXT_CHANNEL_SHAPE = exports.CHANNEL_NEXT = exports.CHANNEL = undefined;
5
5
 
6
6
  var _ThemeProvider$childC, _ThemeProvider$contex;
7
7
 
@@ -27,6 +27,10 @@ var _createBroadcast = require('../utils/create-broadcast');
27
27
 
28
28
  var _createBroadcast2 = _interopRequireDefault(_createBroadcast);
29
29
 
30
+ var _once = require('../utils/once');
31
+
32
+ var _once2 = _interopRequireDefault(_once);
33
+
30
34
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
35
 
32
36
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -37,19 +41,32 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function"
37
41
  /* globals React$Element */
38
42
 
39
43
 
40
- // NOTE: DO NOT CHANGE, changing this is a semver major change!
41
44
  var babelPluginFlowReactPropTypes_proptype_Broadcast = require('../utils/create-broadcast').babelPluginFlowReactPropTypes_proptype_Broadcast || require('prop-types').any;
42
45
 
46
+ // NOTE: DO NOT CHANGE, changing this is a semver major change!
43
47
  var CHANNEL = exports.CHANNEL = '__styled-components__';
48
+ var CHANNEL_NEXT = exports.CHANNEL_NEXT = CHANNEL + 'next__';
49
+
50
+ var CONTEXT_CHANNEL_SHAPE = exports.CONTEXT_CHANNEL_SHAPE = _propTypes2.default.shape({
51
+ getTheme: _propTypes2.default.func,
52
+ subscribe: _propTypes2.default.func,
53
+ unsubscribe: _propTypes2.default.func
54
+ });
44
55
 
45
56
  if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_Theme', {
46
57
  value: require('prop-types').shape({})
47
58
  });
48
59
 
60
+
61
+ var warnChannelDeprecated = (0, _once2.default)(function () {
62
+ // eslint-disable-next-line no-console
63
+ console.error('Warning: Usage of `context.' + CHANNEL + '` as a function is deprecated. It will be replaced with the object on `.context.' + CHANNEL_NEXT + '` in a future version.');
64
+ });
49
65
  /**
50
66
  * Provide a theme to an entire react component tree via context and event listeners (have to do
51
67
  * both context and event emitter as pure components block context updates)
52
68
  */
69
+
53
70
  var ThemeProvider = function (_Component) {
54
71
  _inherits(ThemeProvider, _Component);
55
72
 
@@ -58,6 +75,8 @@ var ThemeProvider = function (_Component) {
58
75
 
59
76
  var _this = _possibleConstructorReturn(this, _Component.call(this));
60
77
 
78
+ _this.unsubscribeToOuterId = -1;
79
+
61
80
  _this.getTheme = _this.getTheme.bind(_this);
62
81
  return _this;
63
82
  }
@@ -67,9 +86,9 @@ var ThemeProvider = function (_Component) {
67
86
 
68
87
  // If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme
69
88
  // with the outer theme
70
- if (this.context[CHANNEL]) {
71
- var subscribe = this.context[CHANNEL];
72
- this.unsubscribeToOuter = subscribe(function (theme) {
89
+ var outerContext = this.context[CHANNEL_NEXT];
90
+ if (outerContext !== undefined) {
91
+ this.unsubscribeToOuterId = outerContext.subscribe(function (theme) {
73
92
  _this2.outerTheme = theme;
74
93
  });
75
94
  }
@@ -77,9 +96,22 @@ var ThemeProvider = function (_Component) {
77
96
  };
78
97
 
79
98
  ThemeProvider.prototype.getChildContext = function getChildContext() {
80
- var _extends2;
81
-
82
- return _extends({}, this.context, (_extends2 = {}, _extends2[CHANNEL] = this.broadcast.subscribe, _extends2));
99
+ var _this3 = this,
100
+ _extends2;
101
+
102
+ return _extends({}, this.context, (_extends2 = {}, _extends2[CHANNEL_NEXT] = {
103
+ getTheme: this.getTheme,
104
+ subscribe: this.broadcast.subscribe,
105
+ unsubscribe: this.broadcast.unsubscribe
106
+ }, _extends2[CHANNEL] = function (subscriber) {
107
+ warnChannelDeprecated();
108
+
109
+ // Patch the old `subscribe` provide via `CHANNEL` for older clients.
110
+ var unsubscribeId = _this3.broadcast.subscribe(subscriber);
111
+ return function () {
112
+ return _this3.broadcast.unsubscribe(unsubscribeId);
113
+ };
114
+ }, _extends2));
83
115
  };
84
116
 
85
117
  ThemeProvider.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
@@ -87,8 +119,8 @@ var ThemeProvider = function (_Component) {
87
119
  };
88
120
 
89
121
  ThemeProvider.prototype.componentWillUnmount = function componentWillUnmount() {
90
- if (this.context[CHANNEL]) {
91
- this.unsubscribeToOuter();
122
+ if (this.unsubscribeToOuterId !== -1) {
123
+ this.context[CHANNEL_NEXT].unsubscribe(this.unsubscribeToOuterId);
92
124
  }
93
125
  };
94
126
 
@@ -126,7 +158,7 @@ ThemeProvider.propTypes = {
126
158
  };
127
159
 
128
160
 
129
- ThemeProvider.childContextTypes = (_ThemeProvider$childC = {}, _ThemeProvider$childC[CHANNEL] = _propTypes2.default.func.isRequired, _ThemeProvider$childC);
130
- ThemeProvider.contextTypes = (_ThemeProvider$contex = {}, _ThemeProvider$contex[CHANNEL] = _propTypes2.default.func, _ThemeProvider$contex);
161
+ ThemeProvider.childContextTypes = (_ThemeProvider$childC = {}, _ThemeProvider$childC[CHANNEL] = _propTypes2.default.func, _ThemeProvider$childC[CHANNEL_NEXT] = CONTEXT_CHANNEL_SHAPE, _ThemeProvider$childC);
162
+ ThemeProvider.contextTypes = (_ThemeProvider$contex = {}, _ThemeProvider$contex[CHANNEL_NEXT] = CONTEXT_CHANNEL_SHAPE, _ThemeProvider$contex);
131
163
 
132
164
  exports.default = ThemeProvider;
@@ -47,7 +47,7 @@ var styled = function styled(tag) {
47
47
 
48
48
  /* React native lazy-requires each of these modules for some reason, so let's
49
49
  * assume it's for a good reason and not eagerly load them all */
50
- var aliases = 'ActivityIndicator ActivityIndicatorIOS ART Button DatePickerIOS DrawerLayoutAndroid\n Image ImageEditor ImageStore KeyboardAvoidingView ListView MapView Modal Navigator NavigatorIOS\n Picker PickerIOS ProgressBarAndroid ProgressViewIOS ScrollView SegmentedControlIOS Slider\n SliderIOS SnapshotViewIOS Switch RecyclerViewBackedScrollView RefreshControl StatusBar\n SwipeableListView SwitchAndroid SwitchIOS TabBarIOS Text TextInput ToastAndroid ToolbarAndroid\n Touchable TouchableHighlight TouchableNativeFeedback TouchableOpacity TouchableWithoutFeedback\n View ViewPagerAndroid WebView FlatList SectionList VirtualizedList';
50
+ var aliases = 'ActivityIndicator ActivityIndicatorIOS ART Button DatePickerIOS DrawerLayoutAndroid\n Image ImageBackground ImageEditor ImageStore KeyboardAvoidingView ListView MapView Modal Navigator NavigatorIOS\n Picker PickerIOS ProgressBarAndroid ProgressViewIOS ScrollView SegmentedControlIOS Slider\n SliderIOS SnapshotViewIOS Switch RecyclerViewBackedScrollView RefreshControl StatusBar\n SwipeableListView SwitchAndroid SwitchIOS TabBarIOS Text TextInput ToastAndroid ToolbarAndroid\n Touchable TouchableHighlight TouchableNativeFeedback TouchableOpacity TouchableWithoutFeedback\n View ViewPagerAndroid WebView FlatList SectionList VirtualizedList';
51
51
 
52
52
  /* Define a getter for each alias which simply gets the reactNative component
53
53
  * and passes it to styled */
package/lib/test/utils.js CHANGED
@@ -67,8 +67,11 @@ var seedNextClassnames = exports.seedNextClassnames = function seedNextClassname
67
67
  var resetStyled = exports.resetStyled = function resetStyled() {
68
68
  var isServer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
69
69
 
70
- if (!document.head) throw new Error("Missing document <head>");
71
- document.head.innerHTML = '';
70
+ if (!isServer) {
71
+ if (!document.head) throw new Error("Missing document <head>");
72
+ document.head.innerHTML = '';
73
+ }
74
+
72
75
  _StyleSheet2.default.reset(isServer);
73
76
  index = 0;
74
77
 
@@ -4,7 +4,8 @@ exports.__esModule = true;
4
4
  if (typeof exports !== "undefined") Object.defineProperty(exports, "babelPluginFlowReactPropTypes_proptype_Broadcast", {
5
5
  value: require("prop-types").shape({
6
6
  publish: require("prop-types").func.isRequired,
7
- subscribe: require("prop-types").func.isRequired
7
+ subscribe: require("prop-types").func.isRequired,
8
+ unsubscribe: require("prop-types").func.isRequired
8
9
  })
9
10
  });
10
11
  /**
@@ -13,30 +14,39 @@ if (typeof exports !== "undefined") Object.defineProperty(exports, "babelPluginF
13
14
  * @see https://github.com/ReactTraining/react-broadcast
14
15
  */
15
16
 
16
- var createBroadcast = function createBroadcast(initialValue) {
17
- var listeners = [];
18
- var currentValue = initialValue;
19
-
20
- return {
21
- publish: function publish(value) {
22
- currentValue = value;
23
- listeners.forEach(function (listener) {
24
- return listener(currentValue);
25
- });
26
- },
27
- subscribe: function subscribe(listener) {
28
- listeners.push(listener);
29
-
30
- // Publish to this subscriber once immediately.
31
- listener(currentValue);
32
-
33
- return function () {
34
- listeners = listeners.filter(function (item) {
35
- return item !== listener;
36
- });
37
- };
17
+ var createBroadcast = function createBroadcast(initialState) {
18
+ var listeners = {};
19
+ var id = 0;
20
+ var state = initialState;
21
+
22
+ function publish(nextState) {
23
+ state = nextState;
24
+
25
+ // eslint-disable-next-line guard-for-in, no-restricted-syntax
26
+ for (var key in listeners) {
27
+ var _listener = listeners[key];
28
+ if (_listener === undefined) {
29
+ // eslint-disable-next-line no-continue
30
+ continue;
31
+ }
32
+
33
+ _listener(state);
38
34
  }
39
- };
35
+ }
36
+
37
+ function subscribe(listener) {
38
+ var currentId = id;
39
+ listeners[currentId] = listener;
40
+ id += 1;
41
+ listener(state);
42
+ return currentId;
43
+ }
44
+
45
+ function unsubscribe(unsubID) {
46
+ listeners[unsubID] = undefined;
47
+ }
48
+
49
+ return { publish: publish, subscribe: subscribe, unsubscribe: unsubscribe };
40
50
  };
41
51
 
42
52
  exports.default = createBroadcast;
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
 
5
5
  // Thanks to ReactDOMFactories for this handy list!
6
6
 
7
- exports.default = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr',
7
+ exports.default = ['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr',
8
8
 
9
9
  // SVG
10
10
  'circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan'];
@@ -16,7 +16,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
16
16
  var babelPluginFlowReactPropTypes_proptype_Interpolation = require('../types').babelPluginFlowReactPropTypes_proptype_Interpolation || require('prop-types').any;
17
17
 
18
18
  var objToCss = exports.objToCss = function objToCss(obj, prevKey) {
19
- var css = Object.keys(obj).map(function (key) {
19
+ var css = Object.keys(obj).filter(function (key) {
20
+ var chunk = obj[key];
21
+ return chunk !== undefined && chunk !== null && chunk !== false && chunk !== '';
22
+ }).map(function (key) {
20
23
  if ((0, _isPlainObject2.default)(obj[key])) return objToCss(obj[key], key);
21
24
  return (0, _hyphenateStyleName2.default)(key) + ': ' + obj[key] + ';';
22
25
  }).join(' ');