UNPKG

75.9 kBJavaScriptView Raw
1import Stylis from 'stylis/stylis.min';
2import _insertRulePlugin from 'stylis-rule-sheet';
3import React, { cloneElement, createContext, Component, createElement } from 'react';
4import { isElement, isValidElementType, ForwardRef } from 'react-is';
5import memoize from 'memoize-one';
6import stream from 'stream';
7import PropTypes from 'prop-types';
8import ReactDOM from 'react-dom';
9import validAttr from '@emotion/is-prop-valid';
10
11//
12
13var interleave = (function (strings, interpolations) {
14 var result = [strings[0]];
15
16 for (var i = 0, len = interpolations.length; i < len; i += 1) {
17 result.push(interpolations[i], strings[i + 1]);
18 }
19
20 return result;
21});
22
23var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
24 return typeof obj;
25} : function (obj) {
26 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
27};
28
29var classCallCheck = function (instance, Constructor) {
30 if (!(instance instanceof Constructor)) {
31 throw new TypeError("Cannot call a class as a function");
32 }
33};
34
35var createClass = function () {
36 function defineProperties(target, props) {
37 for (var i = 0; i < props.length; i++) {
38 var descriptor = props[i];
39 descriptor.enumerable = descriptor.enumerable || false;
40 descriptor.configurable = true;
41 if ("value" in descriptor) descriptor.writable = true;
42 Object.defineProperty(target, descriptor.key, descriptor);
43 }
44 }
45
46 return function (Constructor, protoProps, staticProps) {
47 if (protoProps) defineProperties(Constructor.prototype, protoProps);
48 if (staticProps) defineProperties(Constructor, staticProps);
49 return Constructor;
50 };
51}();
52
53var _extends = Object.assign || function (target) {
54 for (var i = 1; i < arguments.length; i++) {
55 var source = arguments[i];
56
57 for (var key in source) {
58 if (Object.prototype.hasOwnProperty.call(source, key)) {
59 target[key] = source[key];
60 }
61 }
62 }
63
64 return target;
65};
66
67var inherits = function (subClass, superClass) {
68 if (typeof superClass !== "function" && superClass !== null) {
69 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
70 }
71
72 subClass.prototype = Object.create(superClass && superClass.prototype, {
73 constructor: {
74 value: subClass,
75 enumerable: false,
76 writable: true,
77 configurable: true
78 }
79 });
80 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
81};
82
83var objectWithoutProperties = function (obj, keys) {
84 var target = {};
85
86 for (var i in obj) {
87 if (keys.indexOf(i) >= 0) continue;
88 if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
89 target[i] = obj[i];
90 }
91
92 return target;
93};
94
95var possibleConstructorReturn = function (self, call) {
96 if (!self) {
97 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
98 }
99
100 return call && (typeof call === "object" || typeof call === "function") ? call : self;
101};
102
103//
104var isPlainObject = (function (x) {
105 return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x.constructor === Object;
106});
107
108//
109var EMPTY_ARRAY = Object.freeze([]);
110var EMPTY_OBJECT = Object.freeze({});
111
112//
113function isFunction(test) {
114 return typeof test === 'function';
115}
116
117//
118
119function getComponentName(target) {
120 return target.displayName || target.name || 'Component';
121}
122
123//
124function isStyledComponent(target) {
125 return target && typeof target.styledComponentId === 'string';
126}
127
128//
129
130
131var SC_ATTR = typeof process !== 'undefined' && process.env.SC_ATTR || 'data-styled';
132
133var SC_VERSION_ATTR = 'data-styled-version';
134
135var SC_STREAM_ATTR = 'data-styled-streamed';
136
137var IS_BROWSER = typeof window !== 'undefined' && 'HTMLElement' in window;
138
139var DISABLE_SPEEDY = process.env.NODE_ENV !== 'production';
140
141// Shared empty execution context when generating static styles
142var STATIC_EXECUTION_CONTEXT = {};
143
144//
145
146
147/**
148 * Parse errors.md and turn it into a simple hash of code: message
149 */
150var ERRORS = process.env.NODE_ENV !== 'production' ? {
151 "1": "Cannot create styled-component for component: %s.\n\n",
152 "2": "Can't collect styles once you've consumed a `ServerStyleSheet`'s styles! `ServerStyleSheet` is a one off instance for each server-side render cycle.\n\n- Are you trying to reuse it across renders?\n- Are you accidentally calling collectStyles twice?\n\n",
153 "3": "Streaming SSR is only supported in a Node.js environment; Please do not try to call this method in the browser.\n\n",
154 "4": "The `StyleSheetManager` expects a valid target or sheet prop!\n\n- Does this error occur on the client and is your target falsy?\n- Does this error occur on the server and is the sheet falsy?\n\n",
155 "5": "The clone method cannot be used on the client!\n\n- Are you running in a client-like environment on the server?\n- Are you trying to run SSR on the client?\n\n",
156 "6": "Trying to insert a new style tag, but the given Node is unmounted!\n\n- Are you using a custom target that isn't mounted?\n- Does your document not have a valid head element?\n- Have you accidentally removed a style tag manually?\n\n",
157 "7": "ThemeProvider: Please return an object from your \"theme\" prop function, e.g.\n\n```js\ntheme={() => ({})}\n```\n\n",
158 "8": "ThemeProvider: Please make your \"theme\" prop an object.\n\n",
159 "9": "Missing document `<head>`\n\n",
160 "10": "Cannot find a StyleSheet instance. Usually this happens if there are multiple copies of styled-components loaded at once. Check out this issue for how to troubleshoot and fix the common cases where this situation can happen: https://github.com/styled-components/styled-components/issues/1941#issuecomment-417862021\n\n",
161 "11": "_This error was replaced with a dev-time warning, it will be deleted for v4 final._ [createGlobalStyle] received children which will not be rendered. Please use the component without passing children elements.\n\n",
162 "12": "It seems you are interpolating a keyframe declaration (%s) into an untagged string. This was supported in styled-components v3, but is not longer supported in v4 as keyframes are now injected on-demand. Please wrap your string in the css\\`\\` helper (see https://www.styled-components.com/docs/api#css), which ensures the styles are injected correctly.\n"
163} : {};
164
165/**
166 * super basic version of sprintf
167 */
168function format() {
169 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
170 args[_key] = arguments[_key];
171 }
172
173 var a = args[0];
174 var b = [];
175 var c = void 0;
176
177 for (c = 1; c < args.length; c += 1) {
178 b.push(args[c]);
179 }
180
181 b.forEach(function (d) {
182 a = a.replace(/%[a-z]/, d);
183 });
184
185 return a;
186}
187
188/**
189 * Create an error file out of errors.md for development and a simple web link to the full errors
190 * in production mode.
191 */
192
193var StyledComponentsError = function (_Error) {
194 inherits(StyledComponentsError, _Error);
195
196 function StyledComponentsError(code) {
197 classCallCheck(this, StyledComponentsError);
198
199 for (var _len2 = arguments.length, interpolations = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
200 interpolations[_key2 - 1] = arguments[_key2];
201 }
202
203 if (process.env.NODE_ENV === 'production') {
204 var _this = possibleConstructorReturn(this, _Error.call(this, 'An error occurred. See https://github.com/styled-components/styled-components/blob/master/src/utils/errors.md#' + code + ' for more information. ' + (interpolations ? 'Additional arguments: ' + interpolations.join(', ') : '')));
205 } else {
206 var _this = possibleConstructorReturn(this, _Error.call(this, format.apply(undefined, [ERRORS[code]].concat(interpolations)).trim()));
207 }
208 return possibleConstructorReturn(_this);
209 }
210
211 return StyledComponentsError;
212}(Error);
213
214//
215var SC_COMPONENT_ID = /^[^\S\n]*?\/\* sc-component-id:\s*(\S+)\s+\*\//gm;
216
217var extractComps = (function (maybeCSS) {
218 var css = '' + (maybeCSS || ''); // Definitely a string, and a clone
219 var existingComponents = [];
220 css.replace(SC_COMPONENT_ID, function (match, componentId, matchIndex) {
221 existingComponents.push({ componentId: componentId, matchIndex: matchIndex });
222 return match;
223 });
224 return existingComponents.map(function (_ref, i) {
225 var componentId = _ref.componentId,
226 matchIndex = _ref.matchIndex;
227
228 var nextComp = existingComponents[i + 1];
229 var cssFromDOM = nextComp ? css.slice(matchIndex, nextComp.matchIndex) : css.slice(matchIndex);
230 return { componentId: componentId, cssFromDOM: cssFromDOM };
231 });
232});
233
234//
235
236var COMMENT_REGEX = /^\s*\/\/.*$/gm;
237
238// NOTE: This stylis instance is only used to split rules from SSR'd style tags
239var stylisSplitter = new Stylis({
240 global: false,
241 cascade: true,
242 keyframe: false,
243 prefix: false,
244 compress: false,
245 semicolon: true
246});
247
248var stylis = new Stylis({
249 global: false,
250 cascade: true,
251 keyframe: false,
252 prefix: true,
253 compress: false,
254 semicolon: false // NOTE: This means "autocomplete missing semicolons"
255});
256
257// Wrap `insertRulePlugin to build a list of rules,
258// and then make our own plugin to return the rules. This
259// makes it easier to hook into the existing SSR architecture
260
261var parsingRules = [];
262
263// eslint-disable-next-line consistent-return
264var returnRulesPlugin = function returnRulesPlugin(context) {
265 if (context === -2) {
266 var parsedRules = parsingRules;
267 parsingRules = [];
268 return parsedRules;
269 }
270};
271
272var parseRulesPlugin = _insertRulePlugin(function (rule) {
273 parsingRules.push(rule);
274});
275
276var _componentId = void 0;
277var _selector = void 0;
278var _selectorRegexp = void 0;
279
280var selfReferenceReplacer = function selfReferenceReplacer(match, offset, string) {
281 if (
282 // the first self-ref is always untouched
283 offset > 0 &&
284 // there should be at least two self-refs to do a replacement (.b > .b)
285 string.slice(0, offset).indexOf(_selector) !== -1 &&
286 // no consecutive self refs (.b.b); that is a precedence boost and treated differently
287 string.slice(offset - _selector.length, offset) !== _selector) {
288 return '.' + _componentId;
289 }
290
291 return match;
292};
293
294/**
295 * When writing a style like
296 *
297 * & + & {
298 * color: red;
299 * }
300 *
301 * The second ampersand should be a reference to the static component class. stylis
302 * has no knowledge of static class so we have to intelligently replace the base selector.
303 */
304var selfReferenceReplacementPlugin = function selfReferenceReplacementPlugin(context, _, selectors) {
305 if (context === 2 && selectors.length && selectors[0].lastIndexOf(_selector) > 0) {
306 // eslint-disable-next-line no-param-reassign
307 selectors[0] = selectors[0].replace(_selectorRegexp, selfReferenceReplacer);
308 }
309};
310
311stylis.use([selfReferenceReplacementPlugin, parseRulesPlugin, returnRulesPlugin]);
312stylisSplitter.use([parseRulesPlugin, returnRulesPlugin]);
313
314var splitByRules = function splitByRules(css) {
315 return stylisSplitter('', css);
316};
317
318function stringifyRules(rules, selector, prefix) {
319 var componentId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '&';
320
321 var flatCSS = rules.join('').replace(COMMENT_REGEX, ''); // replace JS comments
322
323 var cssStr = selector && prefix ? prefix + ' ' + selector + ' { ' + flatCSS + ' }' : flatCSS;
324
325 // stylis has no concept of state to be passed to plugins
326 // but since JS is single=threaded, we can rely on that to ensure
327 // these properties stay in sync with the current stylis run
328 _componentId = componentId;
329 _selector = selector;
330 _selectorRegexp = new RegExp('\\' + _selector + '\\b', 'g');
331
332 return stylis(prefix || !selector ? '' : selector, cssStr);
333}
334
335//
336/* eslint-disable camelcase, no-undef */
337
338var getNonce = (function () {
339 return typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;
340});
341
342//
343// Helper to call a given function, only once
344var once = (function (cb) {
345 var called = false;
346
347 return function () {
348 if (!called) {
349 called = true;
350 cb();
351 }
352 };
353});
354
355//
356/* These are helpers for the StyleTags to keep track of the injected
357 * rule names for each (component) ID that they're keeping track of.
358 * They're crucial for detecting whether a name has already been
359 * injected.
360 * (This excludes rehydrated names) */
361
362/* adds a new ID:name pairing to a names dictionary */
363var addNameForId = function addNameForId(names, id, name) {
364 if (name) {
365 // eslint-disable-next-line no-param-reassign
366 var namesForId = names[id] || (names[id] = Object.create(null));
367 namesForId[name] = true;
368 }
369};
370
371/* resets an ID entirely by overwriting it in the dictionary */
372var resetIdNames = function resetIdNames(names, id) {
373 // eslint-disable-next-line no-param-reassign
374 names[id] = Object.create(null);
375};
376
377/* factory for a names dictionary checking the existance of an ID:name pairing */
378var hasNameForId = function hasNameForId(names) {
379 return function (id, name) {
380 return names[id] !== undefined && names[id][name];
381 };
382};
383
384/* stringifies names for the html/element output */
385var stringifyNames = function stringifyNames(names) {
386 var str = '';
387 // eslint-disable-next-line guard-for-in
388 for (var id in names) {
389 str += Object.keys(names[id]).join(' ') + ' ';
390 }
391 return str.trim();
392};
393
394/* clones the nested names dictionary */
395var cloneNames = function cloneNames(names) {
396 var clone = Object.create(null);
397 // eslint-disable-next-line guard-for-in
398 for (var id in names) {
399 clone[id] = _extends({}, names[id]);
400 }
401 return clone;
402};
403
404//
405
406/* These are helpers that deal with the insertRule (aka speedy) API
407 * They are used in the StyleTags and specifically the speedy tag
408 */
409
410/* retrieve a sheet for a given style tag */
411var sheetForTag = function sheetForTag(tag) {
412 // $FlowFixMe
413 if (tag.sheet) return tag.sheet;
414
415 /* Firefox quirk requires us to step through all stylesheets to find one owned by the given tag */
416 var size = document.styleSheets.length;
417 for (var i = 0; i < size; i += 1) {
418 var sheet = document.styleSheets[i];
419 // $FlowFixMe
420 if (sheet.ownerNode === tag) return sheet;
421 }
422
423 /* we should always be able to find a tag */
424 throw new StyledComponentsError(10);
425};
426
427/* insert a rule safely and return whether it was actually injected */
428var safeInsertRule = function safeInsertRule(sheet, cssRule, index) {
429 /* abort early if cssRule string is falsy */
430 if (!cssRule) return false;
431
432 var maxIndex = sheet.cssRules.length;
433
434 try {
435 /* use insertRule and cap passed index with maxIndex (no of cssRules) */
436 sheet.insertRule(cssRule, index <= maxIndex ? index : maxIndex);
437 } catch (err) {
438 /* any error indicates an invalid rule */
439 return false;
440 }
441
442 return true;
443};
444
445/* deletes `size` rules starting from `removalIndex` */
446var deleteRules = function deleteRules(sheet, removalIndex, size) {
447 var lowerBound = removalIndex - size;
448 for (var i = removalIndex; i > lowerBound; i -= 1) {
449 sheet.deleteRule(i);
450 }
451};
452
453//
454
455/* this marker separates component styles and is important for rehydration */
456var makeTextMarker = function makeTextMarker(id) {
457 return '\n/* sc-component-id: ' + id + ' */\n';
458};
459
460/* add up all numbers in array up until and including the index */
461var addUpUntilIndex = function addUpUntilIndex(sizes, index) {
462 var totalUpToIndex = 0;
463 for (var i = 0; i <= index; i += 1) {
464 totalUpToIndex += sizes[i];
465 }
466
467 return totalUpToIndex;
468};
469
470/* create a new style tag after lastEl */
471var makeStyleTag = function makeStyleTag(target, tagEl, insertBefore) {
472 var el = document.createElement('style');
473 el.setAttribute(SC_ATTR, '');
474 el.setAttribute(SC_VERSION_ATTR, "4.0.2");
475
476 var nonce = getNonce();
477 if (nonce) {
478 el.setAttribute('nonce', nonce);
479 }
480
481 /* Work around insertRule quirk in EdgeHTML */
482 el.appendChild(document.createTextNode(''));
483
484 if (target && !tagEl) {
485 /* Append to target when no previous element was passed */
486 target.appendChild(el);
487 } else {
488 if (!tagEl || !target || !tagEl.parentNode) {
489 throw new StyledComponentsError(6);
490 }
491
492 /* Insert new style tag after the previous one */
493 tagEl.parentNode.insertBefore(el, insertBefore ? tagEl : tagEl.nextSibling);
494 }
495
496 return el;
497};
498
499/* takes a css factory function and outputs an html styled tag factory */
500var wrapAsHtmlTag = function wrapAsHtmlTag(css, names) {
501 return function (additionalAttrs) {
502 var nonce = getNonce();
503 var attrs = [nonce && 'nonce="' + nonce + '"', SC_ATTR + '="' + stringifyNames(names) + '"', SC_VERSION_ATTR + '="' + "4.0.2" + '"', additionalAttrs];
504
505 var htmlAttr = attrs.filter(Boolean).join(' ');
506 return '<style ' + htmlAttr + '>' + css() + '</style>';
507 };
508};
509
510/* takes a css factory function and outputs an element factory */
511var wrapAsElement = function wrapAsElement(css, names) {
512 return function () {
513 var _props;
514
515 var props = (_props = {}, _props[SC_ATTR] = stringifyNames(names), _props[SC_VERSION_ATTR] = "4.0.2", _props);
516
517 var nonce = getNonce();
518 if (nonce) {
519 // $FlowFixMe
520 props.nonce = nonce;
521 }
522
523 // eslint-disable-next-line react/no-danger
524 return React.createElement('style', _extends({}, props, { dangerouslySetInnerHTML: { __html: css() } }));
525 };
526};
527
528var getIdsFromMarkersFactory = function getIdsFromMarkersFactory(markers) {
529 return function () {
530 return Object.keys(markers);
531 };
532};
533
534/* speedy tags utilise insertRule */
535var makeSpeedyTag = function makeSpeedyTag(el, getImportRuleTag) {
536 var names = Object.create(null);
537 var markers = Object.create(null);
538 var sizes = [];
539
540 var extractImport = getImportRuleTag !== undefined;
541 /* indicates whther getImportRuleTag was called */
542 var usedImportRuleTag = false;
543
544 var insertMarker = function insertMarker(id) {
545 var prev = markers[id];
546 if (prev !== undefined) {
547 return prev;
548 }
549
550 markers[id] = sizes.length;
551 sizes.push(0);
552 resetIdNames(names, id);
553
554 return markers[id];
555 };
556
557 var insertRules = function insertRules(id, cssRules, name) {
558 var marker = insertMarker(id);
559 var sheet = sheetForTag(el);
560 var insertIndex = addUpUntilIndex(sizes, marker);
561
562 var injectedRules = 0;
563 var importRules = [];
564 var cssRulesSize = cssRules.length;
565
566 for (var i = 0; i < cssRulesSize; i += 1) {
567 var cssRule = cssRules[i];
568 var mayHaveImport = extractImport; /* @import rules are reordered to appear first */
569 if (mayHaveImport && cssRule.indexOf('@import') !== -1) {
570 importRules.push(cssRule);
571 } else if (safeInsertRule(sheet, cssRule, insertIndex + injectedRules)) {
572 mayHaveImport = false;
573 injectedRules += 1;
574 }
575 }
576
577 if (extractImport && importRules.length > 0) {
578 usedImportRuleTag = true;
579 // $FlowFixMe
580 getImportRuleTag().insertRules(id + '-import', importRules);
581 }
582
583 sizes[marker] += injectedRules; /* add up no of injected rules */
584 addNameForId(names, id, name);
585 };
586
587 var removeRules = function removeRules(id) {
588 var marker = markers[id];
589 if (marker === undefined) return;
590
591 var size = sizes[marker];
592 var sheet = sheetForTag(el);
593 var removalIndex = addUpUntilIndex(sizes, marker) - 1;
594 deleteRules(sheet, removalIndex, size);
595 sizes[marker] = 0;
596 resetIdNames(names, id);
597
598 if (extractImport && usedImportRuleTag) {
599 // $FlowFixMe
600 getImportRuleTag().removeRules(id + '-import');
601 }
602 };
603
604 var css = function css() {
605 var _sheetForTag = sheetForTag(el),
606 cssRules = _sheetForTag.cssRules;
607
608 var str = '';
609
610 // eslint-disable-next-line guard-for-in
611 for (var id in markers) {
612 str += makeTextMarker(id);
613 var marker = markers[id];
614 var end = addUpUntilIndex(sizes, marker);
615 var size = sizes[marker];
616 for (var i = end - size; i < end; i += 1) {
617 var rule = cssRules[i];
618 if (rule !== undefined) {
619 str += rule.cssText;
620 }
621 }
622 }
623
624 return str;
625 };
626
627 return {
628 clone: function clone() {
629 throw new StyledComponentsError(5);
630 },
631
632 css: css,
633 getIds: getIdsFromMarkersFactory(markers),
634 hasNameForId: hasNameForId(names),
635 insertMarker: insertMarker,
636 insertRules: insertRules,
637 removeRules: removeRules,
638 sealed: false,
639 styleTag: el,
640 toElement: wrapAsElement(css, names),
641 toHTML: wrapAsHtmlTag(css, names)
642 };
643};
644
645var makeTextNode = function makeTextNode(id) {
646 return document.createTextNode(makeTextMarker(id));
647};
648
649var makeBrowserTag = function makeBrowserTag(el, getImportRuleTag) {
650 var names = Object.create(null);
651 var markers = Object.create(null);
652
653 var extractImport = getImportRuleTag !== undefined;
654
655 /* indicates whther getImportRuleTag was called */
656 var usedImportRuleTag = false;
657
658 var insertMarker = function insertMarker(id) {
659 var prev = markers[id];
660 if (prev !== undefined) {
661 return prev;
662 }
663
664 markers[id] = makeTextNode(id);
665 el.appendChild(markers[id]);
666 names[id] = Object.create(null);
667
668 return markers[id];
669 };
670
671 var insertRules = function insertRules(id, cssRules, name) {
672 var marker = insertMarker(id);
673 var importRules = [];
674 var cssRulesSize = cssRules.length;
675
676 for (var i = 0; i < cssRulesSize; i += 1) {
677 var rule = cssRules[i];
678 var mayHaveImport = extractImport;
679 if (mayHaveImport && rule.indexOf('@import') !== -1) {
680 importRules.push(rule);
681 } else {
682 mayHaveImport = false;
683 var separator = i === cssRulesSize - 1 ? '' : ' ';
684 marker.appendData('' + rule + separator);
685 }
686 }
687
688 addNameForId(names, id, name);
689
690 if (extractImport && importRules.length > 0) {
691 usedImportRuleTag = true;
692 // $FlowFixMe
693 getImportRuleTag().insertRules(id + '-import', importRules);
694 }
695 };
696
697 var removeRules = function removeRules(id) {
698 var marker = markers[id];
699 if (marker === undefined) return;
700
701 /* create new empty text node and replace the current one */
702 var newMarker = makeTextNode(id);
703 el.replaceChild(newMarker, marker);
704 markers[id] = newMarker;
705 resetIdNames(names, id);
706
707 if (extractImport && usedImportRuleTag) {
708 // $FlowFixMe
709 getImportRuleTag().removeRules(id + '-import');
710 }
711 };
712
713 var css = function css() {
714 var str = '';
715
716 // eslint-disable-next-line guard-for-in
717 for (var id in markers) {
718 str += markers[id].data;
719 }
720
721 return str;
722 };
723
724 return {
725 clone: function clone() {
726 throw new StyledComponentsError(5);
727 },
728
729 css: css,
730 getIds: getIdsFromMarkersFactory(markers),
731 hasNameForId: hasNameForId(names),
732 insertMarker: insertMarker,
733 insertRules: insertRules,
734 removeRules: removeRules,
735 sealed: false,
736 styleTag: el,
737 toElement: wrapAsElement(css, names),
738 toHTML: wrapAsHtmlTag(css, names)
739 };
740};
741
742var makeServerTag = function makeServerTag(namesArg, markersArg) {
743 var names = namesArg === undefined ? Object.create(null) : namesArg;
744 var markers = markersArg === undefined ? Object.create(null) : markersArg;
745
746 var insertMarker = function insertMarker(id) {
747 var prev = markers[id];
748 if (prev !== undefined) {
749 return prev;
750 }
751
752 return markers[id] = [''];
753 };
754
755 var insertRules = function insertRules(id, cssRules, name) {
756 var marker = insertMarker(id);
757 marker[0] += cssRules.join(' ');
758 addNameForId(names, id, name);
759 };
760
761 var removeRules = function removeRules(id) {
762 var marker = markers[id];
763 if (marker === undefined) return;
764 marker[0] = '';
765 resetIdNames(names, id);
766 };
767
768 var css = function css() {
769 var str = '';
770 // eslint-disable-next-line guard-for-in
771 for (var id in markers) {
772 var cssForId = markers[id][0];
773 if (cssForId) {
774 str += makeTextMarker(id) + cssForId;
775 }
776 }
777 return str;
778 };
779
780 var clone = function clone() {
781 var namesClone = cloneNames(names);
782 var markersClone = Object.create(null);
783
784 // eslint-disable-next-line guard-for-in
785 for (var id in markers) {
786 markersClone[id] = [markers[id][0]];
787 }
788
789 return makeServerTag(namesClone, markersClone);
790 };
791
792 var tag = {
793 clone: clone,
794 css: css,
795 getIds: getIdsFromMarkersFactory(markers),
796 hasNameForId: hasNameForId(names),
797 insertMarker: insertMarker,
798 insertRules: insertRules,
799 removeRules: removeRules,
800 sealed: false,
801 styleTag: null,
802 toElement: wrapAsElement(css, names),
803 toHTML: wrapAsHtmlTag(css, names)
804 };
805
806 return tag;
807};
808
809var makeTag = function makeTag(target, tagEl, forceServer, insertBefore, getImportRuleTag) {
810 if (IS_BROWSER && !forceServer) {
811 var el = makeStyleTag(target, tagEl, insertBefore);
812
813 if (DISABLE_SPEEDY) {
814 return makeBrowserTag(el, getImportRuleTag);
815 } else {
816 return makeSpeedyTag(el, getImportRuleTag);
817 }
818 }
819
820 return makeServerTag();
821};
822
823/* wraps a given tag so that rehydration is performed once when necessary */
824var makeRehydrationTag = function makeRehydrationTag(tag, els, extracted, immediateRehydration) {
825 /* rehydration function that adds all rules to the new tag */
826 var rehydrate = once(function () {
827 /* add all extracted components to the new tag */
828 for (var i = 0, len = extracted.length; i < len; i += 1) {
829 var _extracted$i = extracted[i],
830 componentId = _extracted$i.componentId,
831 cssFromDOM = _extracted$i.cssFromDOM;
832
833 var cssRules = splitByRules(cssFromDOM);
834 tag.insertRules(componentId, cssRules);
835 }
836
837 /* remove old HTMLStyleElements, since they have been rehydrated */
838 for (var _i = 0, _len = els.length; _i < _len; _i += 1) {
839 var el = els[_i];
840 if (el.parentNode) {
841 el.parentNode.removeChild(el);
842 }
843 }
844 });
845
846 if (immediateRehydration) rehydrate();
847
848 return _extends({}, tag, {
849
850 /* add rehydration hook to methods */
851 insertMarker: function insertMarker(id) {
852 rehydrate();
853 return tag.insertMarker(id);
854 },
855
856 insertRules: function insertRules(id, cssRules, name) {
857 rehydrate();
858 return tag.insertRules(id, cssRules, name);
859 },
860
861 removeRules: function removeRules(id) {
862 rehydrate();
863 return tag.removeRules(id);
864 }
865 });
866};
867
868//
869
870var SPLIT_REGEX = /\s+/;
871
872/* determine the maximum number of components before tags are sharded */
873var MAX_SIZE = void 0;
874if (IS_BROWSER) {
875 /* in speedy mode we can keep a lot more rules in a sheet before a slowdown can be expected */
876 MAX_SIZE = DISABLE_SPEEDY ? 40 : 1000;
877} else {
878 /* for servers we do not need to shard at all */
879 MAX_SIZE = -1;
880}
881
882var sheetRunningId = 0;
883var master = void 0;
884
885var StyleSheet = function () {
886
887 /* a map from ids to tags */
888
889 /* deferred rules for a given id */
890
891 /* this is used for not reinjecting rules via hasNameForId() */
892
893 /* when rules for an id are removed using remove() we have to ignore rehydratedNames for it */
894
895 /* a list of tags belonging to this StyleSheet */
896
897 /* a tag for import rules */
898
899 /* current capacity until a new tag must be created */
900
901 /* children (aka clones) of this StyleSheet inheriting all and future injections */
902
903 function StyleSheet() {
904 var _this = this;
905
906 var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : IS_BROWSER ? document.head : null;
907 var forceServer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
908 classCallCheck(this, StyleSheet);
909
910 this.getImportRuleTag = function () {
911 var importRuleTag = _this.importRuleTag;
912
913 if (importRuleTag !== undefined) {
914 return importRuleTag;
915 }
916
917 var firstTag = _this.tags[0];
918 var insertBefore = true;
919
920 return _this.importRuleTag = makeTag(_this.target, firstTag ? firstTag.styleTag : null, _this.forceServer, insertBefore);
921 };
922
923 sheetRunningId += 1;
924 this.id = sheetRunningId;
925 this.forceServer = forceServer;
926 this.target = forceServer ? null : target;
927 this.tagMap = {};
928 this.deferred = {};
929 this.rehydratedNames = {};
930 this.ignoreRehydratedNames = {};
931 this.tags = [];
932 this.capacity = 1;
933 this.clones = [];
934 }
935
936 /* rehydrate all SSR'd style tags */
937
938
939 StyleSheet.prototype.rehydrate = function rehydrate() {
940 if (!IS_BROWSER || this.forceServer) {
941 return this;
942 }
943 var els = [];
944 var extracted = [];
945 var isStreamed = false;
946
947 /* retrieve all of our SSR style elements from the DOM */
948 var nodes = document.querySelectorAll('style[' + SC_ATTR + '][' + SC_VERSION_ATTR + '="' + "4.0.2" + '"]');
949 var nodesSize = nodes.length;
950
951 /* abort rehydration if no previous style tags were found */
952 if (nodesSize === 0) {
953 return this;
954 }
955
956 for (var i = 0; i < nodesSize; i += 1) {
957 // $FlowFixMe: We can trust that all elements in this query are style elements
958 var el = nodes[i];
959
960 /* check if style tag is a streamed tag */
961 if (!isStreamed) isStreamed = !!el.getAttribute(SC_STREAM_ATTR);
962
963 /* retrieve all component names */
964 var elNames = (el.getAttribute(SC_ATTR) || '').trim().split(SPLIT_REGEX);
965 var elNamesSize = elNames.length;
966 for (var j = 0; j < elNamesSize; j += 1) {
967 var name = elNames[j];
968 /* add rehydrated name to sheet to avoid readding styles */
969 this.rehydratedNames[name] = true;
970 }
971
972 /* extract all components and their CSS */
973 extracted.push.apply(extracted, extractComps(el.textContent));
974
975 /* store original HTMLStyleElement */
976 els.push(el);
977 }
978
979 /* abort rehydration if nothing was extracted */
980 var extractedSize = extracted.length;
981 if (extractedSize === 0) {
982 return this;
983 }
984
985 /* create a tag to be used for rehydration */
986 var tag = this.makeTag(null);
987 var rehydrationTag = makeRehydrationTag(tag, els, extracted, isStreamed);
988
989 /* reset capacity and adjust MAX_SIZE by the initial size of the rehydration */
990 this.capacity = Math.max(1, MAX_SIZE - extractedSize);
991 this.tags.push(rehydrationTag);
992
993 /* retrieve all component ids */
994 for (var _j = 0; _j < extractedSize; _j += 1) {
995 this.tagMap[extracted[_j].componentId] = rehydrationTag;
996 }
997
998 return this;
999 };
1000
1001 /* retrieve a "master" instance of StyleSheet which is typically used when no other is available
1002 * The master StyleSheet is targeted by createGlobalStyle, keyframes, and components outside of any
1003 * StyleSheetManager's context */
1004
1005
1006 /* reset the internal "master" instance */
1007 StyleSheet.reset = function reset() {
1008 var forceServer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1009
1010 master = new StyleSheet(undefined, forceServer).rehydrate();
1011 };
1012
1013 /* adds "children" to the StyleSheet that inherit all of the parents' rules
1014 * while their own rules do not affect the parent */
1015
1016
1017 StyleSheet.prototype.clone = function clone() {
1018 var sheet = new StyleSheet(this.target, this.forceServer);
1019
1020 /* add to clone array */
1021 this.clones.push(sheet);
1022
1023 /* clone all tags */
1024 sheet.tags = this.tags.map(function (tag) {
1025 var ids = tag.getIds();
1026 var newTag = tag.clone();
1027
1028 /* reconstruct tagMap */
1029 for (var i = 0; i < ids.length; i += 1) {
1030 sheet.tagMap[ids[i]] = newTag;
1031 }
1032
1033 return newTag;
1034 });
1035
1036 /* clone other maps */
1037 sheet.rehydratedNames = _extends({}, this.rehydratedNames);
1038 sheet.deferred = _extends({}, this.deferred);
1039
1040 return sheet;
1041 };
1042
1043 /* force StyleSheet to create a new tag on the next injection */
1044
1045
1046 StyleSheet.prototype.sealAllTags = function sealAllTags() {
1047 this.capacity = 1;
1048
1049 this.tags.forEach(function (tag) {
1050 // eslint-disable-next-line no-param-reassign
1051 tag.sealed = true;
1052 });
1053 };
1054
1055 StyleSheet.prototype.makeTag = function makeTag$$1(tag) {
1056 var lastEl = tag ? tag.styleTag : null;
1057 var insertBefore = false;
1058
1059 return makeTag(this.target, lastEl, this.forceServer, insertBefore, this.getImportRuleTag);
1060 };
1061
1062 /* get a tag for a given componentId, assign the componentId to one, or shard */
1063 StyleSheet.prototype.getTagForId = function getTagForId(id) {
1064 /* simply return a tag, when the componentId was already assigned one */
1065 var prev = this.tagMap[id];
1066 if (prev !== undefined && !prev.sealed) {
1067 return prev;
1068 }
1069
1070 var tag = this.tags[this.tags.length - 1];
1071
1072 /* shard (create a new tag) if the tag is exhausted (See MAX_SIZE) */
1073 this.capacity -= 1;
1074
1075 if (this.capacity === 0) {
1076 this.capacity = MAX_SIZE;
1077 tag = this.makeTag(tag);
1078 this.tags.push(tag);
1079 }
1080
1081 return this.tagMap[id] = tag;
1082 };
1083
1084 /* mainly for createGlobalStyle to check for its id */
1085
1086
1087 StyleSheet.prototype.hasId = function hasId(id) {
1088 return this.tagMap[id] !== undefined;
1089 };
1090
1091 /* caching layer checking id+name to already have a corresponding tag and injected rules */
1092
1093
1094 StyleSheet.prototype.hasNameForId = function hasNameForId(id, name) {
1095 /* exception for rehydrated names which are checked separately */
1096 if (this.ignoreRehydratedNames[id] === undefined && this.rehydratedNames[name]) {
1097 return true;
1098 }
1099
1100 var tag = this.tagMap[id];
1101 return tag !== undefined && tag.hasNameForId(id, name);
1102 };
1103
1104 /* registers a componentId and registers it on its tag */
1105
1106
1107 StyleSheet.prototype.deferredInject = function deferredInject(id, cssRules) {
1108 /* don't inject when the id is already registered */
1109 if (this.tagMap[id] !== undefined) return;
1110
1111 var clones = this.clones;
1112
1113 for (var i = 0; i < clones.length; i += 1) {
1114 clones[i].deferredInject(id, cssRules);
1115 }
1116
1117 this.getTagForId(id).insertMarker(id);
1118 this.deferred[id] = cssRules;
1119 };
1120
1121 /* injects rules for a given id with a name that will need to be cached */
1122
1123
1124 StyleSheet.prototype.inject = function inject(id, cssRules, name) {
1125 var clones = this.clones;
1126
1127
1128 for (var i = 0; i < clones.length; i += 1) {
1129 clones[i].inject(id, cssRules, name);
1130 }
1131
1132 var tag = this.getTagForId(id);
1133
1134 /* add deferred rules for component */
1135 if (this.deferred[id] !== undefined) {
1136 // Combine passed cssRules with previously deferred CSS rules
1137 // NOTE: We cannot mutate the deferred array itself as all clones
1138 // do the same (see clones[i].inject)
1139 var rules = this.deferred[id].concat(cssRules);
1140 tag.insertRules(id, rules, name);
1141
1142 this.deferred[id] = undefined;
1143 } else {
1144 tag.insertRules(id, cssRules, name);
1145 }
1146 };
1147
1148 /* removes all rules for a given id, which doesn't remove its marker but resets it */
1149
1150
1151 StyleSheet.prototype.remove = function remove(id) {
1152 var tag = this.tagMap[id];
1153 if (tag === undefined) return;
1154
1155 var clones = this.clones;
1156
1157 for (var i = 0; i < clones.length; i += 1) {
1158 clones[i].remove(id);
1159 }
1160
1161 /* remove all rules from the tag */
1162 tag.removeRules(id);
1163
1164 /* ignore possible rehydrated names */
1165 this.ignoreRehydratedNames[id] = true;
1166
1167 /* delete possible deferred rules */
1168 this.deferred[id] = undefined;
1169 };
1170
1171 StyleSheet.prototype.toHTML = function toHTML() {
1172 return this.tags.map(function (tag) {
1173 return tag.toHTML();
1174 }).join('');
1175 };
1176
1177 StyleSheet.prototype.toReactElements = function toReactElements() {
1178 var id = this.id;
1179
1180
1181 return this.tags.map(function (tag, i) {
1182 var key = 'sc-' + id + '-' + i;
1183 return cloneElement(tag.toElement(), { key: key });
1184 });
1185 };
1186
1187 createClass(StyleSheet, null, [{
1188 key: 'master',
1189 get: function get$$1() {
1190 return master || (master = new StyleSheet().rehydrate());
1191 }
1192
1193 /* NOTE: This is just for backwards-compatibility with jest-styled-components */
1194
1195 }, {
1196 key: 'instance',
1197 get: function get$$1() {
1198 return StyleSheet.master;
1199 }
1200 }]);
1201 return StyleSheet;
1202}();
1203
1204//
1205
1206var Keyframes = function () {
1207 function Keyframes(name, rules) {
1208 var _this = this;
1209
1210 classCallCheck(this, Keyframes);
1211
1212 this.inject = function (styleSheet) {
1213 if (!styleSheet.hasNameForId(_this.id, _this.name)) {
1214 styleSheet.inject(_this.id, _this.rules, _this.name);
1215 }
1216 };
1217
1218 this.toString = function () {
1219 throw new StyledComponentsError(12, String(_this.name));
1220 };
1221
1222 this.name = name;
1223 this.rules = rules;
1224
1225 this.id = 'sc-keyframes-' + name;
1226 }
1227
1228 Keyframes.prototype.getName = function getName() {
1229 return this.name;
1230 };
1231
1232 return Keyframes;
1233}();
1234
1235//
1236
1237/**
1238 * inlined version of
1239 * https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/hyphenateStyleName.js
1240 */
1241
1242var uppercasePattern = /([A-Z])/g;
1243var msPattern = /^ms-/;
1244
1245/**
1246 * Hyphenates a camelcased CSS property name, for example:
1247 *
1248 * > hyphenateStyleName('backgroundColor')
1249 * < "background-color"
1250 * > hyphenateStyleName('MozTransition')
1251 * < "-moz-transition"
1252 * > hyphenateStyleName('msTransition')
1253 * < "-ms-transition"
1254 *
1255 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
1256 * is converted to `-ms-`.
1257 *
1258 * @param {string} string
1259 * @return {string}
1260 */
1261function hyphenateStyleName(string) {
1262 return string.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-');
1263}
1264
1265//
1266
1267var objToCss = function objToCss(obj, prevKey) {
1268 var css = Object.keys(obj).filter(function (key) {
1269 var chunk = obj[key];
1270 return chunk !== undefined && chunk !== null && chunk !== false && chunk !== '';
1271 }).map(function (key) {
1272 if (isPlainObject(obj[key])) return objToCss(obj[key], key);
1273 return hyphenateStyleName(key) + ': ' + obj[key] + ';';
1274 }).join(' ');
1275 return prevKey ? prevKey + ' {\n ' + css + '\n}' : css;
1276};
1277
1278/**
1279 * It's falsish not falsy because 0 is allowed.
1280 */
1281var isFalsish = function isFalsish(chunk) {
1282 return chunk === undefined || chunk === null || chunk === false || chunk === '';
1283};
1284
1285function flatten(chunk, executionContext, styleSheet) {
1286 if (Array.isArray(chunk)) {
1287 var ruleSet = [];
1288
1289 for (var i = 0, len = chunk.length, result; i < len; i += 1) {
1290 result = flatten(chunk[i], executionContext, styleSheet);
1291
1292 if (result === null) continue;else if (Array.isArray(result)) ruleSet.push.apply(ruleSet, result);else ruleSet.push(result);
1293 }
1294
1295 return ruleSet;
1296 }
1297
1298 if (isFalsish(chunk)) {
1299 return null;
1300 }
1301
1302 /* Handle other components */
1303 if (isStyledComponent(chunk)) {
1304 return '.' + chunk.styledComponentId;
1305 }
1306
1307 /* Either execute or defer the function */
1308 if (isFunction(chunk)) {
1309 if (executionContext) {
1310 if (process.env.NODE_ENV !== 'production') {
1311 /* Warn if not referring styled component */
1312 try {
1313 // eslint-disable-next-line new-cap
1314 if (isElement(new chunk(executionContext))) {
1315 console.warn(getComponentName(chunk) + ' is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.');
1316 }
1317 // eslint-disable-next-line no-empty
1318 } catch (e) {}
1319 }
1320
1321 return flatten(chunk(executionContext), executionContext, styleSheet);
1322 } else return chunk;
1323 }
1324
1325 if (chunk instanceof Keyframes) {
1326 if (styleSheet) {
1327 chunk.inject(styleSheet);
1328 return chunk.getName();
1329 } else return chunk;
1330 }
1331
1332 /* Handle objects */
1333 return isPlainObject(chunk) ? objToCss(chunk) : chunk.toString();
1334}
1335
1336//
1337
1338function css(styles) {
1339 for (var _len = arguments.length, interpolations = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1340 interpolations[_key - 1] = arguments[_key];
1341 }
1342
1343 if (isFunction(styles) || isPlainObject(styles)) {
1344 // $FlowFixMe
1345 return flatten(interleave(EMPTY_ARRAY, [styles].concat(interpolations)));
1346 }
1347
1348 // $FlowFixMe
1349 return flatten(interleave(styles, interpolations));
1350}
1351
1352//
1353
1354function constructWithOptions(componentConstructor, tag) {
1355 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EMPTY_OBJECT;
1356
1357 if (!isValidElementType(tag)) {
1358 throw new StyledComponentsError(1, String(tag));
1359 }
1360
1361 /* This is callable directly as a template function */
1362 // $FlowFixMe: Not typed to avoid destructuring arguments
1363 var templateFunction = function templateFunction() {
1364 return componentConstructor(tag, options, css.apply(undefined, arguments));
1365 };
1366
1367 /* If config methods are called, wrap up a new template function and merge options */
1368 templateFunction.withConfig = function (config) {
1369 return constructWithOptions(componentConstructor, tag, _extends({}, options, config));
1370 };
1371 templateFunction.attrs = function (attrs) {
1372 return constructWithOptions(componentConstructor, tag, _extends({}, options, {
1373 attrs: _extends({}, options.attrs || EMPTY_OBJECT, attrs)
1374 }));
1375 };
1376
1377 return templateFunction;
1378}
1379
1380//
1381// Source: https://github.com/garycourt/murmurhash-js/blob/master/murmurhash2_gc.js
1382function murmurhash(c) {
1383 for (var e = c.length | 0, a = e | 0, d = 0, b; e >= 4;) {
1384 b = c.charCodeAt(d) & 255 | (c.charCodeAt(++d) & 255) << 8 | (c.charCodeAt(++d) & 255) << 16 | (c.charCodeAt(++d) & 255) << 24, b = 1540483477 * (b & 65535) + ((1540483477 * (b >>> 16) & 65535) << 16), b ^= b >>> 24, b = 1540483477 * (b & 65535) + ((1540483477 * (b >>> 16) & 65535) << 16), a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16) ^ b, e -= 4, ++d;
1385 }
1386 switch (e) {
1387 case 3:
1388 a ^= (c.charCodeAt(d + 2) & 255) << 16;
1389 case 2:
1390 a ^= (c.charCodeAt(d + 1) & 255) << 8;
1391 case 1:
1392 a ^= c.charCodeAt(d) & 255, a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16);
1393 }
1394 a ^= a >>> 13;
1395 a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16);
1396 return (a ^ a >>> 15) >>> 0;
1397}
1398
1399//
1400/* eslint-disable no-bitwise */
1401
1402/* This is the "capacity" of our alphabet i.e. 2x26 for all letters plus their capitalised
1403 * counterparts */
1404var charsLength = 52;
1405
1406/* start at 75 for 'a' until 'z' (25) and then start at 65 for capitalised letters */
1407var getAlphabeticChar = function getAlphabeticChar(code) {
1408 return String.fromCharCode(code + (code > 25 ? 39 : 97));
1409};
1410
1411/* input a number, usually a hash and convert it to base-52 */
1412function generateAlphabeticName(code) {
1413 var name = '';
1414 var x = void 0;
1415
1416 /* get a char and divide by alphabet-length */
1417 for (x = code; x > charsLength; x = Math.floor(x / charsLength)) {
1418 name = getAlphabeticChar(x % charsLength) + name;
1419 }
1420
1421 return getAlphabeticChar(x % charsLength) + name;
1422}
1423
1424//
1425
1426function isStaticRules(rules, attrs) {
1427 for (var i = 0; i < rules.length; i += 1) {
1428 var rule = rules[i];
1429
1430 // recursive case
1431 if (Array.isArray(rule) && !isStaticRules(rule)) {
1432 return false;
1433 } else if (isFunction(rule) && !isStyledComponent(rule)) {
1434 // functions are allowed to be static if they're just being
1435 // used to get the classname of a nested styled component
1436 return false;
1437 }
1438 }
1439
1440 if (attrs !== undefined) {
1441 // eslint-disable-next-line guard-for-in, no-restricted-syntax
1442 for (var key in attrs) {
1443 var value = attrs[key];
1444 if (isFunction(value)) {
1445 return false;
1446 }
1447 }
1448 }
1449
1450 return true;
1451}
1452
1453//
1454
1455//
1456
1457var isHMREnabled = process.env.NODE_ENV !== 'production' && typeof module !== 'undefined' && module.hot;
1458
1459/* combines hashStr (murmurhash) and nameGenerator for convenience */
1460var hasher = function hasher(str) {
1461 return generateAlphabeticName(murmurhash(str));
1462};
1463
1464/*
1465 ComponentStyle is all the CSS-specific stuff, not
1466 the React-specific stuff.
1467 */
1468
1469var ComponentStyle = function () {
1470 function ComponentStyle(rules, attrs, componentId) {
1471 classCallCheck(this, ComponentStyle);
1472
1473 this.rules = rules;
1474 this.isStatic = !isHMREnabled && isStaticRules(rules, attrs);
1475 this.componentId = componentId;
1476
1477 if (!StyleSheet.master.hasId(componentId)) {
1478 var placeholder = process.env.NODE_ENV !== 'production' ? ['.' + componentId + ' {}'] : [];
1479
1480 StyleSheet.master.deferredInject(componentId, placeholder);
1481 }
1482 }
1483
1484 /*
1485 * Flattens a rule set into valid CSS
1486 * Hashes it, wraps the whole chunk in a .hash1234 {}
1487 * Returns the hash to be injected on render()
1488 * */
1489
1490
1491 ComponentStyle.prototype.generateAndInjectStyles = function generateAndInjectStyles(executionContext, styleSheet) {
1492 var isStatic = this.isStatic,
1493 componentId = this.componentId,
1494 lastClassName = this.lastClassName;
1495
1496 if (IS_BROWSER && isStatic && lastClassName !== undefined && styleSheet.hasNameForId(componentId, lastClassName)) {
1497 return lastClassName;
1498 }
1499
1500 var flatCSS = flatten(this.rules, executionContext, styleSheet);
1501 var name = hasher(this.componentId + flatCSS.join(''));
1502 if (!styleSheet.hasNameForId(componentId, name)) {
1503 styleSheet.inject(this.componentId, stringifyRules(flatCSS, '.' + name, undefined, componentId), name);
1504 }
1505
1506 this.lastClassName = name;
1507 return name;
1508 };
1509
1510 ComponentStyle.generateName = function generateName(str) {
1511 return hasher(str);
1512 };
1513
1514 return ComponentStyle;
1515}();
1516
1517//
1518
1519var LIMIT = 200;
1520
1521var createWarnTooManyClasses = (function (displayName) {
1522 var generatedClasses = {};
1523 var warningSeen = false;
1524
1525 return function (className) {
1526 if (!warningSeen) {
1527 generatedClasses[className] = true;
1528 if (Object.keys(generatedClasses).length >= LIMIT) {
1529 // Unable to find latestRule in test environment.
1530 /* eslint-disable no-console, prefer-template */
1531 console.warn('Over ' + LIMIT + ' classes were generated for component ' + displayName + '. \n' + 'Consider using the attrs method, together with a style object for frequently changed styles.\n' + 'Example:\n' + ' const Component = styled.div.attrs({\n' + ' style: ({ background }) => ({\n' + ' background,\n' + ' }),\n' + ' })`width: 100%;`\n\n' + ' <Component />');
1532 warningSeen = true;
1533 generatedClasses = {};
1534 }
1535 }
1536 };
1537});
1538
1539//
1540
1541var determineTheme = (function (props, fallbackTheme) {
1542 var defaultProps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EMPTY_OBJECT;
1543
1544 // Props should take precedence over ThemeProvider, which should take precedence over
1545 // defaultProps, but React automatically puts defaultProps on props.
1546
1547 /* eslint-disable react/prop-types, flowtype-errors/show-errors */
1548 var isDefaultTheme = defaultProps ? props.theme === defaultProps.theme : false;
1549 var theme = props.theme && !isDefaultTheme ? props.theme : fallbackTheme || defaultProps.theme;
1550 /* eslint-enable */
1551
1552 return theme;
1553});
1554
1555//
1556var escapeRegex = /[[\].#*$><+~=|^:(),"'`-]+/g;
1557var dashesAtEnds = /(^-|-$)/g;
1558
1559/**
1560 * TODO: Explore using CSS.escape when it becomes more available
1561 * in evergreen browsers.
1562 */
1563function escape(str) {
1564 return str
1565 // Replace all possible CSS selectors
1566 .replace(escapeRegex, '-')
1567
1568 // Remove extraneous hyphens at the start and end
1569 .replace(dashesAtEnds, '');
1570}
1571
1572//
1573
1574function isTag(target) /* : %checks */{
1575 return typeof target === 'string';
1576}
1577
1578//
1579
1580function generateDisplayName(target) {
1581 return isTag(target) ? 'styled.' + target : 'Styled(' + getComponentName(target) + ')';
1582}
1583
1584var _TYPE_STATICS;
1585
1586var REACT_STATICS = {
1587 childContextTypes: true,
1588 contextTypes: true,
1589 defaultProps: true,
1590 displayName: true,
1591 getDerivedStateFromProps: true,
1592 propTypes: true,
1593 type: true
1594};
1595
1596var KNOWN_STATICS = {
1597 name: true,
1598 length: true,
1599 prototype: true,
1600 caller: true,
1601 callee: true,
1602 arguments: true,
1603 arity: true
1604};
1605
1606var TYPE_STATICS = (_TYPE_STATICS = {}, _TYPE_STATICS[ForwardRef] = {
1607 $$typeof: true,
1608 render: true
1609}, _TYPE_STATICS);
1610
1611var defineProperty$1 = Object.defineProperty,
1612 getOwnPropertyNames = Object.getOwnPropertyNames,
1613 _Object$getOwnPropert = Object.getOwnPropertySymbols,
1614 getOwnPropertySymbols = _Object$getOwnPropert === undefined ? function () {
1615 return [];
1616} : _Object$getOwnPropert,
1617 getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
1618 getPrototypeOf = Object.getPrototypeOf,
1619 objectPrototype = Object.prototype;
1620var arrayPrototype = Array.prototype;
1621
1622
1623function hoistNonReactStatics(targetComponent, sourceComponent, blacklist) {
1624 if (typeof sourceComponent !== 'string') {
1625 // don't hoist over string (html) components
1626
1627 var inheritedComponent = getPrototypeOf(sourceComponent);
1628
1629 if (inheritedComponent && inheritedComponent !== objectPrototype) {
1630 hoistNonReactStatics(targetComponent, inheritedComponent, blacklist);
1631 }
1632
1633 var keys = arrayPrototype.concat(getOwnPropertyNames(sourceComponent),
1634 // $FlowFixMe
1635 getOwnPropertySymbols(sourceComponent));
1636
1637 var targetStatics = TYPE_STATICS[targetComponent.$$typeof] || REACT_STATICS;
1638
1639 var sourceStatics = TYPE_STATICS[sourceComponent.$$typeof] || REACT_STATICS;
1640
1641 var i = keys.length;
1642 var descriptor = void 0;
1643 var key = void 0;
1644
1645 // eslint-disable-next-line no-plusplus
1646 while (i--) {
1647 key = keys[i];
1648
1649 if (
1650 // $FlowFixMe
1651 !KNOWN_STATICS[key] && !(blacklist && blacklist[key]) && !(sourceStatics && sourceStatics[key]) &&
1652 // $FlowFixMe
1653 !(targetStatics && targetStatics[key])) {
1654 descriptor = getOwnPropertyDescriptor(sourceComponent, key);
1655
1656 if (descriptor) {
1657 try {
1658 // Avoid failures from read-only properties
1659 defineProperty$1(targetComponent, key, descriptor);
1660 } catch (e) {
1661 /* fail silently */
1662 }
1663 }
1664 }
1665 }
1666
1667 return targetComponent;
1668 }
1669
1670 return targetComponent;
1671}
1672
1673//
1674function isDerivedReactComponent(fn) {
1675 return !!(fn && fn.prototype && fn.prototype.isReactComponent);
1676}
1677
1678//
1679
1680var ThemeContext = createContext();
1681
1682var ThemeConsumer = ThemeContext.Consumer;
1683
1684/**
1685 * Provide a theme to an entire react component tree via context
1686 */
1687
1688var ThemeProvider = function (_Component) {
1689 inherits(ThemeProvider, _Component);
1690
1691 function ThemeProvider(props) {
1692 classCallCheck(this, ThemeProvider);
1693
1694 var _this = possibleConstructorReturn(this, _Component.call(this, props));
1695
1696 _this.getContext = memoize(_this.getContext.bind(_this));
1697 _this.renderInner = _this.renderInner.bind(_this);
1698 return _this;
1699 }
1700
1701 ThemeProvider.prototype.render = function render() {
1702 if (!this.props.children) return null;
1703
1704 return React.createElement(
1705 ThemeContext.Consumer,
1706 null,
1707 this.renderInner
1708 );
1709 };
1710
1711 ThemeProvider.prototype.renderInner = function renderInner(outerTheme) {
1712 var context = this.getContext(this.props.theme, outerTheme);
1713
1714 return React.createElement(
1715 ThemeContext.Provider,
1716 { value: context },
1717 React.Children.only(this.props.children)
1718 );
1719 };
1720
1721 /**
1722 * Get the theme from the props, supporting both (outerTheme) => {}
1723 * as well as object notation
1724 */
1725
1726
1727 ThemeProvider.prototype.getTheme = function getTheme(theme, outerTheme) {
1728 if (isFunction(theme)) {
1729 var mergedTheme = theme(outerTheme);
1730
1731 if (process.env.NODE_ENV !== 'production' && (mergedTheme === null || Array.isArray(mergedTheme) || (typeof mergedTheme === 'undefined' ? 'undefined' : _typeof(mergedTheme)) !== 'object')) {
1732 throw new StyledComponentsError(7);
1733 }
1734
1735 return mergedTheme;
1736 }
1737
1738 if (theme === null || Array.isArray(theme) || (typeof theme === 'undefined' ? 'undefined' : _typeof(theme)) !== 'object') {
1739 throw new StyledComponentsError(8);
1740 }
1741
1742 return _extends({}, outerTheme, theme);
1743 };
1744
1745 ThemeProvider.prototype.getContext = function getContext(theme, outerTheme) {
1746 return this.getTheme(theme, outerTheme);
1747 };
1748
1749 return ThemeProvider;
1750}(Component);
1751
1752//
1753
1754var ServerStyleSheet = function () {
1755 function ServerStyleSheet() {
1756 classCallCheck(this, ServerStyleSheet);
1757
1758 /* The master sheet might be reset, so keep a reference here */
1759 this.masterSheet = StyleSheet.master;
1760 this.instance = this.masterSheet.clone();
1761 this.sealed = false;
1762 }
1763
1764 /**
1765 * Mark the ServerStyleSheet as being fully emitted and manually GC it from the
1766 * StyleSheet singleton.
1767 */
1768
1769
1770 ServerStyleSheet.prototype.seal = function seal() {
1771 if (!this.sealed) {
1772 /* Remove sealed StyleSheets from the master sheet */
1773 var index = this.masterSheet.clones.indexOf(this.instance);
1774 this.masterSheet.clones.splice(index, 1);
1775 this.sealed = true;
1776 }
1777 };
1778
1779 ServerStyleSheet.prototype.collectStyles = function collectStyles(children) {
1780 if (this.sealed) {
1781 throw new StyledComponentsError(2);
1782 }
1783
1784 return React.createElement(
1785 StyleSheetManager,
1786 { sheet: this.instance },
1787 children
1788 );
1789 };
1790
1791 ServerStyleSheet.prototype.getStyleTags = function getStyleTags() {
1792 this.seal();
1793 return this.instance.toHTML();
1794 };
1795
1796 ServerStyleSheet.prototype.getStyleElement = function getStyleElement() {
1797 this.seal();
1798 return this.instance.toReactElements();
1799 };
1800
1801 ServerStyleSheet.prototype.interleaveWithNodeStream = function interleaveWithNodeStream(readableStream) {
1802 var _this = this;
1803
1804 if (IS_BROWSER) {
1805 throw new StyledComponentsError(3);
1806 }
1807
1808 /* the tag index keeps track of which tags have already been emitted */
1809 var instance = this.instance;
1810
1811 var instanceTagIndex = 0;
1812
1813 var streamAttr = SC_STREAM_ATTR + '="true"';
1814
1815 var transformer = new stream.Transform({
1816 transform: function appendStyleChunks(chunk, /* encoding */_, callback) {
1817 var tags = instance.tags;
1818
1819 var html = '';
1820
1821 /* retrieve html for each new style tag */
1822 for (; instanceTagIndex < tags.length; instanceTagIndex += 1) {
1823 var tag = tags[instanceTagIndex];
1824 html += tag.toHTML(streamAttr);
1825 }
1826
1827 /* force our StyleSheets to emit entirely new tags */
1828 instance.sealAllTags();
1829
1830 /* prepend style html to chunk */
1831 this.push(html + chunk);
1832 callback();
1833 }
1834 });
1835
1836 readableStream.on('end', function () {
1837 return _this.seal();
1838 });
1839 readableStream.on('error', function (err) {
1840 _this.seal();
1841
1842 // forward the error to the transform stream
1843 transformer.emit('error', err);
1844 });
1845
1846 return readableStream.pipe(transformer);
1847 };
1848
1849 return ServerStyleSheet;
1850}();
1851
1852//
1853
1854var StyleSheetContext = createContext();
1855
1856var StyleSheetConsumer = StyleSheetContext.Consumer;
1857
1858var StyleSheetManager = function (_Component) {
1859 inherits(StyleSheetManager, _Component);
1860
1861 function StyleSheetManager(props) {
1862 classCallCheck(this, StyleSheetManager);
1863
1864 var _this = possibleConstructorReturn(this, _Component.call(this, props));
1865
1866 _this.getContext = memoize(_this.getContext);
1867 return _this;
1868 }
1869
1870 StyleSheetManager.prototype.getContext = function getContext(sheet, target) {
1871 if (sheet) {
1872 return sheet;
1873 } else if (target) {
1874 return new StyleSheet(target);
1875 } else {
1876 throw new StyledComponentsError(4);
1877 }
1878 };
1879
1880 StyleSheetManager.prototype.render = function render() {
1881 var _props = this.props,
1882 children = _props.children,
1883 sheet = _props.sheet,
1884 target = _props.target;
1885
1886 var context = this.getContext(sheet, target);
1887 return React.createElement(
1888 StyleSheetContext.Provider,
1889 { value: context },
1890 React.Children.only(children)
1891 );
1892 };
1893
1894 return StyleSheetManager;
1895}(Component);
1896process.env.NODE_ENV !== "production" ? StyleSheetManager.propTypes = {
1897 sheet: PropTypes.oneOfType([PropTypes.instanceOf(StyleSheet), PropTypes.instanceOf(ServerStyleSheet)]),
1898
1899 target: PropTypes.shape({
1900 appendChild: PropTypes.func.isRequired
1901 })
1902} : void 0;
1903
1904//
1905
1906var classNameUseCheckInjector = (function (target) {
1907 var elementClassName = '';
1908
1909 var targetCDM = target.componentDidMount;
1910
1911 // eslint-disable-next-line no-param-reassign
1912 target.componentDidMount = function componentDidMount() {
1913 if (typeof targetCDM === 'function') {
1914 targetCDM.call(this);
1915 }
1916
1917 var classNames = elementClassName.replace(/ +/g, ' ').trim().split(' ');
1918 // eslint-disable-next-line react/no-find-dom-node
1919 var node = ReactDOM.findDOMNode(this);
1920 var selector = classNames.map(function (s) {
1921 return '.' + s;
1922 }).join('');
1923
1924 if (node && node.nodeType === 1 && !classNames.every(function (className) {
1925 return node.classList && node.classList.contains(className);
1926 }) && !node.querySelector(selector)) {
1927 console.warn('It looks like you\'ve wrapped styled() around your React component (' + getComponentName(this.props.forwardedClass.target) + '), but the className prop is not being passed down to a child. No styles will be rendered unless className is composed within your React component.');
1928 }
1929 };
1930
1931 var prevRenderInner = target.renderInner;
1932
1933 // eslint-disable-next-line no-param-reassign
1934 target.renderInner = function renderInner() {
1935 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
1936 args[_key] = arguments[_key];
1937 }
1938
1939 var element = prevRenderInner.apply(this, args);
1940
1941 elementClassName = element.props.className;
1942
1943 return element;
1944 };
1945});
1946
1947//
1948
1949var identifiers = {};
1950
1951/* We depend on components having unique IDs */
1952function generateId(_ComponentStyle, _displayName, parentComponentId) {
1953 var displayName = typeof _displayName !== 'string' ? 'sc' : escape(_displayName);
1954
1955 /**
1956 * This ensures uniqueness if two components happen to share
1957 * the same displayName.
1958 */
1959 var nr = (identifiers[displayName] || 0) + 1;
1960 identifiers[displayName] = nr;
1961
1962 var componentId = displayName + '-' + _ComponentStyle.generateName(displayName + nr);
1963
1964 return parentComponentId ? parentComponentId + '-' + componentId : componentId;
1965}
1966
1967var warnInnerRef = once(function () {
1968 return (
1969 // eslint-disable-next-line no-console
1970 console.warn('The "innerRef" API has been removed in styled-components v4 in favor of React 16 ref forwarding, use "ref" instead like a typical component.')
1971 );
1972});
1973
1974// $FlowFixMe
1975
1976var StyledComponent = function (_Component) {
1977 inherits(StyledComponent, _Component);
1978
1979 function StyledComponent() {
1980 classCallCheck(this, StyledComponent);
1981
1982 var _this = possibleConstructorReturn(this, _Component.call(this));
1983
1984 _this.attrs = {};
1985
1986 _this.renderOuter = _this.renderOuter.bind(_this);
1987 _this.renderInner = _this.renderInner.bind(_this);
1988
1989 if (process.env.NODE_ENV !== 'production' && IS_BROWSER) {
1990 classNameUseCheckInjector(_this);
1991 }
1992 return _this;
1993 }
1994
1995 StyledComponent.prototype.render = function render() {
1996 return React.createElement(
1997 StyleSheetConsumer,
1998 null,
1999 this.renderOuter
2000 );
2001 };
2002
2003 StyledComponent.prototype.renderOuter = function renderOuter(styleSheet) {
2004 this.styleSheet = styleSheet;
2005
2006 return React.createElement(
2007 ThemeConsumer,
2008 null,
2009 this.renderInner
2010 );
2011 };
2012
2013 StyledComponent.prototype.renderInner = function renderInner(theme) {
2014 var _props$forwardedClass = this.props.forwardedClass,
2015 componentStyle = _props$forwardedClass.componentStyle,
2016 defaultProps = _props$forwardedClass.defaultProps,
2017 styledComponentId = _props$forwardedClass.styledComponentId,
2018 target = _props$forwardedClass.target;
2019
2020
2021 var generatedClassName = void 0;
2022 if (componentStyle.isStatic) {
2023 generatedClassName = this.generateAndInjectStyles(EMPTY_OBJECT, this.props, this.styleSheet);
2024 } else if (theme !== undefined) {
2025 generatedClassName = this.generateAndInjectStyles(determineTheme(this.props, theme, defaultProps), this.props, this.styleSheet);
2026 } else {
2027 generatedClassName = this.generateAndInjectStyles(this.props.theme || EMPTY_OBJECT, this.props, this.styleSheet);
2028 }
2029 var elementToBeCreated = this.props.as || this.attrs.as || target;
2030 var isTargetTag = isTag(elementToBeCreated);
2031
2032 var propsForElement = _extends({}, this.attrs);
2033
2034 var key = void 0;
2035 // eslint-disable-next-line guard-for-in
2036 for (key in this.props) {
2037 if (process.env.NODE_ENV !== 'production' && key === 'innerRef') {
2038 warnInnerRef();
2039 }
2040
2041 if (key === 'forwardedClass' || key === 'as') continue;else if (key === 'forwardedRef') propsForElement.ref = this.props[key];else if (!isTargetTag || validAttr(key)) {
2042 // Don't pass through non HTML tags through to HTML elements
2043 propsForElement[key] = key === 'style' && key in this.attrs ? _extends({}, this.attrs[key], this.props[key]) : this.props[key];
2044 }
2045 }
2046
2047 propsForElement.className = [this.props.className, styledComponentId, this.attrs.className, generatedClassName].filter(Boolean).join(' ');
2048
2049 return createElement(elementToBeCreated, propsForElement);
2050 };
2051
2052 StyledComponent.prototype.buildExecutionContext = function buildExecutionContext(theme, props, attrs) {
2053 var context = _extends({}, props, { theme: theme });
2054
2055 if (attrs === undefined) return context;
2056
2057 this.attrs = {};
2058
2059 var attr = void 0;
2060 var key = void 0;
2061
2062 /* eslint-disable guard-for-in */
2063 for (key in attrs) {
2064 attr = attrs[key];
2065
2066 this.attrs[key] = isFunction(attr) && !isDerivedReactComponent(attr) && !isStyledComponent(attr) ? attr(context) : attr;
2067 }
2068 /* eslint-enable */
2069
2070 return _extends({}, context, this.attrs);
2071 };
2072
2073 StyledComponent.prototype.generateAndInjectStyles = function generateAndInjectStyles(theme, props) {
2074 var styleSheet = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : StyleSheet.master;
2075 var _props$forwardedClass2 = props.forwardedClass,
2076 attrs = _props$forwardedClass2.attrs,
2077 componentStyle = _props$forwardedClass2.componentStyle,
2078 warnTooManyClasses = _props$forwardedClass2.warnTooManyClasses;
2079
2080 // statically styled-components don't need to build an execution context object,
2081 // and shouldn't be increasing the number of class names
2082
2083 if (componentStyle.isStatic && attrs === undefined) {
2084 return componentStyle.generateAndInjectStyles(EMPTY_OBJECT, styleSheet);
2085 }
2086
2087 var className = componentStyle.generateAndInjectStyles(this.buildExecutionContext(theme, props, props.forwardedClass.attrs), styleSheet);
2088
2089 if (warnTooManyClasses) {
2090 warnTooManyClasses(className);
2091 }
2092
2093 return className;
2094 };
2095
2096 return StyledComponent;
2097}(Component);
2098
2099function createStyledComponent(target, options, rules) {
2100 var isTargetStyledComp = isStyledComponent(target);
2101 var isClass = !isTag(target);
2102
2103 var _options$displayName = options.displayName,
2104 displayName = _options$displayName === undefined ? generateDisplayName(target) : _options$displayName,
2105 _options$componentId = options.componentId,
2106 componentId = _options$componentId === undefined ? generateId(ComponentStyle, options.displayName, options.parentComponentId) : _options$componentId,
2107 _options$ParentCompon = options.ParentComponent,
2108 ParentComponent = _options$ParentCompon === undefined ? StyledComponent : _options$ParentCompon,
2109 attrs = options.attrs;
2110
2111
2112 var styledComponentId = options.displayName && options.componentId ? escape(options.displayName) + '-' + options.componentId : options.componentId || componentId;
2113
2114 // fold the underlying StyledComponent attrs up (implicit extend)
2115 var finalAttrs =
2116 // $FlowFixMe
2117 isTargetStyledComp && target.attrs ? _extends({}, target.attrs, attrs) : attrs;
2118
2119 var componentStyle = new ComponentStyle(isTargetStyledComp ? // fold the underlying StyledComponent rules up (implicit extend)
2120 // $FlowFixMe
2121 target.componentStyle.rules.concat(rules) : rules, finalAttrs, styledComponentId);
2122
2123 /**
2124 * forwardRef creates a new interim component, which we'll take advantage of
2125 * instead of extending ParentComponent to create _another_ interim class
2126 */
2127 var WrappedStyledComponent = React.forwardRef(function (props, ref) {
2128 return React.createElement(ParentComponent, _extends({}, props, { forwardedClass: WrappedStyledComponent, forwardedRef: ref }));
2129 });
2130
2131 // $FlowFixMe
2132 WrappedStyledComponent.attrs = finalAttrs;
2133 // $FlowFixMe
2134 WrappedStyledComponent.componentStyle = componentStyle;
2135 WrappedStyledComponent.displayName = displayName;
2136 // $FlowFixMe
2137 WrappedStyledComponent.styledComponentId = styledComponentId;
2138
2139 // fold the underlying StyledComponent target up since we folded the styles
2140 // $FlowFixMe
2141 WrappedStyledComponent.target = isTargetStyledComp ? target.target : target;
2142
2143 // $FlowFixMe
2144 WrappedStyledComponent.withComponent = function withComponent(tag) {
2145 var previousComponentId = options.componentId,
2146 optionsToCopy = objectWithoutProperties(options, ['componentId']);
2147
2148
2149 var newComponentId = previousComponentId && previousComponentId + '-' + (isTag(tag) ? tag : escape(getComponentName(tag)));
2150
2151 var newOptions = _extends({}, optionsToCopy, {
2152 attrs: finalAttrs,
2153 componentId: newComponentId,
2154 ParentComponent: ParentComponent
2155 });
2156
2157 return createStyledComponent(tag, newOptions, rules);
2158 };
2159
2160 if (process.env.NODE_ENV !== 'production') {
2161 // $FlowFixMe
2162 WrappedStyledComponent.warnTooManyClasses = createWarnTooManyClasses(displayName);
2163 }
2164
2165 if (isClass) {
2166 hoistNonReactStatics(WrappedStyledComponent, target, {
2167 // all SC-specific things should not be hoisted
2168 attrs: true,
2169 componentStyle: true,
2170 displayName: true,
2171 styledComponentId: true,
2172 target: true,
2173 warnTooManyClasses: true,
2174 withComponent: true
2175 });
2176 }
2177
2178 return WrappedStyledComponent;
2179}
2180
2181//
2182// Thanks to ReactDOMFactories for this handy list!
2183
2184var domElements = ['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',
2185
2186// SVG
2187'circle', 'clipPath', 'defs', 'ellipse', 'foreignObject', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'svg', 'text', 'tspan'];
2188
2189//
2190
2191var styled = function styled(tag) {
2192 return constructWithOptions(createStyledComponent, tag);
2193};
2194
2195// Shorthands for all valid HTML Elements
2196domElements.forEach(function (domElement) {
2197 styled[domElement] = styled(domElement);
2198});
2199
2200//
2201
2202var GlobalStyle = function () {
2203 function GlobalStyle(rules, componentId) {
2204 classCallCheck(this, GlobalStyle);
2205
2206 this.rules = rules;
2207 this.componentId = componentId;
2208 this.isStatic = isStaticRules(rules);
2209
2210 if (!StyleSheet.master.hasId(componentId)) {
2211 StyleSheet.master.deferredInject(componentId, []);
2212 }
2213 }
2214
2215 GlobalStyle.prototype.createStyles = function createStyles(executionContext, styleSheet) {
2216 var flatCSS = flatten(this.rules, executionContext, styleSheet);
2217 var css = stringifyRules(flatCSS, '');
2218
2219 styleSheet.inject(this.componentId, css);
2220 };
2221
2222 GlobalStyle.prototype.removeStyles = function removeStyles(styleSheet) {
2223 var componentId = this.componentId;
2224
2225 if (styleSheet.hasId(componentId)) {
2226 styleSheet.remove(componentId);
2227 }
2228 };
2229
2230 // TODO: overwrite in-place instead of remove+create?
2231
2232
2233 GlobalStyle.prototype.renderStyles = function renderStyles(executionContext, styleSheet) {
2234 this.removeStyles(styleSheet);
2235 this.createStyles(executionContext, styleSheet);
2236 };
2237
2238 return GlobalStyle;
2239}();
2240
2241//
2242
2243// place our cache into shared context so it'll persist between HMRs
2244if (IS_BROWSER) {
2245 window.scCGSHMRCache = {};
2246}
2247
2248function createGlobalStyle(strings) {
2249 for (var _len = arguments.length, interpolations = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
2250 interpolations[_key - 1] = arguments[_key];
2251 }
2252
2253 var rules = css.apply(undefined, [strings].concat(interpolations));
2254 var id = 'sc-global-' + murmurhash(JSON.stringify(rules));
2255 var style = new GlobalStyle(rules, id);
2256
2257 var GlobalStyleComponent = function (_React$Component) {
2258 inherits(GlobalStyleComponent, _React$Component);
2259
2260 function GlobalStyleComponent() {
2261 classCallCheck(this, GlobalStyleComponent);
2262
2263 var _this = possibleConstructorReturn(this, _React$Component.call(this));
2264
2265 var _this$constructor = _this.constructor,
2266 globalStyle = _this$constructor.globalStyle,
2267 styledComponentId = _this$constructor.styledComponentId;
2268
2269
2270 if (IS_BROWSER) {
2271 window.scCGSHMRCache[styledComponentId] = (window.scCGSHMRCache[styledComponentId] || 0) + 1;
2272 }
2273
2274 /**
2275 * This fixes HMR compatiblility. Don't ask me why, but this combination of
2276 * caching the closure variables via statics and then persisting the statics in
2277 * state works across HMR where no other combination did. ¯\_(ツ)_/¯
2278 */
2279 _this.state = {
2280 globalStyle: globalStyle,
2281 styledComponentId: styledComponentId
2282 };
2283 return _this;
2284 }
2285
2286 GlobalStyleComponent.prototype.componentDidMount = function componentDidMount() {
2287 if (process.env.NODE_ENV !== 'production' && IS_BROWSER && window.scCGSHMRCache[this.state.styledComponentId] > 1 && !this.props.suppressMultiMountWarning) {
2288 console.warn('The global style component ' + this.state.styledComponentId + ' was composed and rendered multiple times in your React component tree. Only the last-rendered copy will have its styles remain in <head> (or your StyleSheetManager target.)');
2289 }
2290 };
2291
2292 GlobalStyleComponent.prototype.componentWillUnmount = function componentWillUnmount() {
2293 if (window.scCGSHMRCache[this.state.styledComponentId]) {
2294 window.scCGSHMRCache[this.state.styledComponentId] -= 1;
2295 }
2296 /**
2297 * Depending on the order "render" is called this can cause the styles to be lost
2298 * until the next render pass of the remaining instance, which may
2299 * not be immediate.
2300 */
2301 if (window.scCGSHMRCache[this.state.styledComponentId] === 0) {
2302 this.state.globalStyle.removeStyles(this.styleSheet);
2303 }
2304 };
2305
2306 GlobalStyleComponent.prototype.render = function render() {
2307 var _this2 = this;
2308
2309 if (process.env.NODE_ENV !== 'production' && React.Children.count(this.props.children)) {
2310 console.warn('The global style component ' + this.state.styledComponentId + ' was given child JSX. createGlobalStyle does not render children.');
2311 }
2312
2313 return React.createElement(
2314 StyleSheetConsumer,
2315 null,
2316 function (styleSheet) {
2317 _this2.styleSheet = styleSheet || StyleSheet.master;
2318
2319 var globalStyle = _this2.state.globalStyle;
2320
2321
2322 if (globalStyle.isStatic) {
2323 globalStyle.renderStyles(STATIC_EXECUTION_CONTEXT, _this2.styleSheet);
2324
2325 return null;
2326 } else {
2327 return React.createElement(
2328 ThemeConsumer,
2329 null,
2330 function (theme) {
2331 var defaultProps = _this2.constructor.defaultProps;
2332
2333
2334 var context = _extends({}, _this2.props);
2335
2336 if (typeof theme !== 'undefined') {
2337 context.theme = determineTheme(_this2.props, theme, defaultProps);
2338 }
2339
2340 globalStyle.renderStyles(context, _this2.styleSheet);
2341
2342 return null;
2343 }
2344 );
2345 }
2346 }
2347 );
2348 };
2349
2350 return GlobalStyleComponent;
2351 }(React.Component);
2352
2353 GlobalStyleComponent.defaultProps = {
2354 suppressMultiMountWarning: false
2355 };
2356 GlobalStyleComponent.globalStyle = style;
2357 GlobalStyleComponent.styledComponentId = id;
2358 process.env.NODE_ENV !== "production" ? GlobalStyleComponent.propTypes = {
2359 suppressMultiMountWarning: PropTypes.bool
2360 } : void 0;
2361
2362
2363 return GlobalStyleComponent;
2364}
2365
2366//
2367
2368var replaceWhitespace = function replaceWhitespace(str) {
2369 return str.replace(/\s|\\n/g, '');
2370};
2371
2372function keyframes(strings) {
2373 /* Warning if you've used keyframes on React Native */
2374 if (process.env.NODE_ENV !== 'production' && typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
2375 console.warn('`keyframes` cannot be used on ReactNative, only on the web. To do animation in ReactNative please use Animated.');
2376 }
2377
2378 for (var _len = arguments.length, interpolations = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
2379 interpolations[_key - 1] = arguments[_key];
2380 }
2381
2382 var rules = css.apply(undefined, [strings].concat(interpolations));
2383
2384 var name = generateAlphabeticName(murmurhash(replaceWhitespace(JSON.stringify(rules))));
2385
2386 return new Keyframes(name, stringifyRules(rules, name, '@keyframes'));
2387}
2388
2389//
2390
2391var withTheme = (function (Component$$1) {
2392 var WithTheme = React.forwardRef(function (props, ref) {
2393 return React.createElement(
2394 ThemeConsumer,
2395 null,
2396 function (theme) {
2397 // $FlowFixMe
2398 var defaultProps = Component$$1.defaultProps;
2399
2400 var themeProp = determineTheme(props, theme, defaultProps);
2401
2402 if (process.env.NODE_ENV !== 'production' && themeProp === undefined) {
2403 // eslint-disable-next-line no-console
2404 console.warn('[withTheme] You are not using a ThemeProvider nor passing a theme prop or a theme in defaultProps in component class ' + getComponentName(Component$$1));
2405 }
2406
2407 return React.createElement(Component$$1, _extends({}, props, { theme: themeProp, ref: ref }));
2408 }
2409 );
2410 });
2411
2412 hoistNonReactStatics(WithTheme, Component$$1);
2413
2414 WithTheme.displayName = 'WithTheme(' + getComponentName(Component$$1) + ')';
2415
2416 return WithTheme;
2417});
2418
2419//
2420
2421/* eslint-disable */
2422var __DO_NOT_USE_OR_YOU_WILL_BE_HAUNTED_BY_SPOOKY_GHOSTS = {
2423 StyleSheet: StyleSheet
2424};
2425
2426//
2427
2428/* Warning if you've imported this file on React Native */
2429if (process.env.NODE_ENV !== 'production' && typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
2430 // eslint-disable-next-line no-console
2431 console.warn("It looks like you've imported 'styled-components' on React Native.\n" + "Perhaps you're looking to import 'styled-components/native'?\n" + 'Read more about this at https://www.styled-components.com/docs/basics#react-native');
2432}
2433
2434/* Warning if there are several instances of styled-components */
2435if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test' && typeof window !== 'undefined' && typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Node.js') === -1 && navigator.userAgent.indexOf('jsdom') === -1) {
2436 window['__styled-components-init__'] = window['__styled-components-init__'] || 0;
2437
2438 if (window['__styled-components-init__'] === 1) {
2439 // eslint-disable-next-line no-console
2440 console.warn("It looks like there are several instances of 'styled-components' initialized in this application. " + 'This may cause dynamic styles not rendering properly, errors happening during rehydration process ' + 'and makes your application bigger without a good reason.\n\n' + 'See https://s-c.sh/2BAXzed for more info.');
2441 }
2442
2443 window['__styled-components-init__'] += 1;
2444}
2445
2446//
2447
2448export default styled;
2449export { css, keyframes, createGlobalStyle, isStyledComponent, ThemeConsumer, ThemeProvider, withTheme, ServerStyleSheet, StyleSheetManager, __DO_NOT_USE_OR_YOU_WILL_BE_HAUNTED_BY_SPOOKY_GHOSTS };
2450//# sourceMappingURL=styled-components.esm.js.map