{"version":3,"file":"styled-components.cjs.js","sources":["../src/models/StyleTags.js","../src/models/StyleSheet.js","../src/models/StyleSheetManager.js","../src/models/ThemeProvider.js","../src/models/StyledComponent.js","../src/models/ComponentStyle.js","../src/constructors/styled.js","../src/constructors/keyframes.js"],"sourcesContent":["// @flow\n/* eslint-disable flowtype/object-type-delimiter */\n/* eslint-disable react/prop-types */\n\nimport React from 'react'\nimport { IS_BROWSER, DISABLE_SPEEDY, SC_ATTR } from '../constants'\nimport { type ExtractedComp } from '../utils/extractCompsFromCSS'\nimport { splitByRules } from '../utils/stringifyRules'\nimport getNonce from '../utils/nonce'\n\nexport interface Tag {\n // $FlowFixMe: Doesn't seem to accept any combination w/ HTMLStyleElement for some reason\n styleTag: HTMLStyleElement | null;\n names: string[];\n getIds(): string[];\n insertMarker(id: string): T;\n insertRules(id: string, cssRules: string[]): void;\n css(): string;\n toHTML(): string;\n toElement(): React.Element<*>;\n clone(): Tag;\n}\n\n/* this error is used for makeStyleTag */\nconst parentNodeUnmountedErr =\n process.env.NODE_ENV !== 'production'\n ? `\nTrying to insert a new style tag, but the given Node is unmounted!\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`.trim()\n : ''\n\n/* this error is used for tags */\nconst throwCloneTagErr = () => {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `\nThe clone method cannot be used on the client!\n- Are you running in a client-like environment on the server?\n- Are you trying to run SSR on the client?\n`.trim()\n : ''\n )\n}\n\n/* this marker separates component styles and is important for rehydration */\nconst makeTextMarker = id => `\\n/* sc-component-id: ${id} */\\n`\n\n/* retrieve a sheet for a given style tag */\nconst sheetForTag = (tag: HTMLStyleElement): CSSStyleSheet => {\n // $FlowFixMe\n if (tag.sheet) return tag.sheet\n\n /* Firefox quirk requires us to step through all stylesheets to find one owned by the given tag */\n const size = document.styleSheets.length\n for (let i = 0; i < size; i += 1) {\n const sheet = document.styleSheets[i]\n // $FlowFixMe\n if (sheet.ownerNode === tag) return sheet\n }\n\n /* we should always be able to find a tag */\n throw new Error()\n}\n\n/* insert a rule safely and return whether it was actually injected */\nconst safeInsertRule = (\n sheet: CSSStyleSheet,\n cssRule: string,\n index: number\n): boolean => {\n /* abort early if cssRule string is falsy */\n if (!cssRule) return false\n\n const maxIndex = sheet.cssRules.length\n\n try {\n /* use insertRule and cap passed index with maxIndex (no of cssRules) */\n sheet.insertRule(cssRule, index <= maxIndex ? index : maxIndex)\n } catch (err) {\n /* any error indicates an invalid rule */\n return false\n }\n\n return true\n}\n\n/* insert multiple rules using safeInsertRule */\nconst safeInsertRules = (\n sheet: CSSStyleSheet,\n cssRules: string[],\n insertIndex: number\n): number => {\n /* inject each rule and count up the number of actually injected ones */\n let injectedRules = 0\n const cssRulesSize = cssRules.length\n for (let i = 0; i < cssRulesSize; i += 1) {\n const cssRule = cssRules[i]\n if (safeInsertRule(sheet, cssRule, insertIndex + injectedRules)) {\n injectedRules += 1\n }\n }\n\n /* return number of injected rules */\n return injectedRules\n}\n\n/* add up all numbers in array up until and including the index */\nconst addUpUntilIndex = (sizes: number[], index: number): number => {\n let totalUpToIndex = 0\n for (let i = 0; i <= index; i += 1) {\n totalUpToIndex += sizes[i]\n }\n\n return totalUpToIndex\n}\n\n/* create a new style tag after lastEl */\nconst makeStyleTag = (target: ?HTMLElement, lastTag: ?Node) => {\n const el = document.createElement('style')\n el.type = 'text/css'\n el.setAttribute(SC_ATTR, '')\n\n const nonce = getNonce()\n if (nonce) {\n el.setAttribute('nonce', nonce)\n }\n\n /* Work around insertRule quirk in EdgeHTML */\n el.appendChild(document.createTextNode(''))\n\n if (target && !lastTag) {\n /* Append to target when no previous element was passed */\n target.appendChild(el)\n } else {\n if (!lastTag || !target || !lastTag.parentNode) {\n throw new Error(parentNodeUnmountedErr)\n }\n\n /* Insert new style tag after the previous one */\n lastTag.parentNode.insertBefore(el, lastTag.nextSibling)\n }\n\n return el\n}\n\n/* takes a css factory function and outputs an html styled tag factory */\nconst wrapAsHtmlTag = (css: () => string, names: string[]) => (): string => {\n const nonce = getNonce()\n const nonceProp = nonce ? `nonce=\"${nonce}\" ` : ''\n const attr = `${SC_ATTR}=\"${names.join(' ')}\"`\n return ``\n}\n\n/* takes a css factory function and outputs an element factory */\nconst wrapAsElement = (css: () => string, names: string[]) => () => {\n const props = {\n type: 'text/css',\n [SC_ATTR]: names.join(' '),\n }\n\n const nonce = getNonce()\n if (nonce) {\n // $FlowFixMe\n props.nonce = nonce\n }\n\n return \n}\n\nconst getIdsFromMarkersFactory = (markers: Object) => (): string[] =>\n Object.keys(markers)\n\n/* speedy tags utilise insertRule */\nconst makeSpeedyTag = (el: HTMLStyleElement): Tag => {\n const markers = Object.create(null)\n const sizes = []\n const names = []\n\n const insertMarker = id => {\n const prev = markers[id]\n if (prev !== undefined) {\n return prev\n }\n\n const marker = (markers[id] = sizes.length)\n sizes.push(0)\n return marker\n }\n\n const insertRules = (id, cssRules) => {\n const marker = insertMarker(id)\n const sheet = sheetForTag(el)\n const insertIndex = addUpUntilIndex(sizes, marker)\n sizes[marker] += safeInsertRules(sheet, cssRules, insertIndex)\n }\n\n const css = () => {\n const { cssRules } = sheetForTag(el)\n let str = ''\n let i = 0\n\n // eslint-disable-next-line guard-for-in\n for (const id in markers) {\n str += makeTextMarker(id)\n const end = markers[id] + i\n for (; i < end; i += 1) {\n str += cssRules[i].cssText\n }\n }\n\n return str\n }\n\n return {\n styleTag: el,\n getIds: getIdsFromMarkersFactory(markers),\n names,\n insertMarker,\n insertRules,\n css,\n toHTML: wrapAsHtmlTag(css, names),\n toElement: wrapAsElement(css, names),\n clone: throwCloneTagErr,\n }\n}\n\nconst makeBrowserTag = (el: HTMLStyleElement): Tag => {\n const markers = Object.create(null)\n const names = []\n\n const insertMarker = id => {\n const prev = markers[id]\n if (prev !== undefined) {\n return prev\n }\n\n const marker = (markers[id] = document.createTextNode(makeTextMarker(id)))\n el.appendChild(marker)\n return marker\n }\n\n const insertRules = (id, cssRules) => {\n insertMarker(id).appendData(cssRules.join(' '))\n }\n\n const css = () => {\n let str = ''\n // eslint-disable-next-line guard-for-in\n for (const id in markers) {\n str += markers[id].data\n }\n return str\n }\n\n return {\n styleTag: el,\n getIds: getIdsFromMarkersFactory(markers),\n names,\n insertMarker,\n insertRules,\n css,\n toHTML: wrapAsHtmlTag(css, names),\n toElement: wrapAsElement(css, names),\n clone: throwCloneTagErr,\n }\n}\n\nconst makeServerTag = (): Tag<[string]> => {\n const markers = Object.create(null)\n const names = []\n\n const insertMarker = id => {\n const prev = markers[id]\n if (prev !== undefined) {\n return prev\n }\n\n return (markers[id] = [makeTextMarker(id)])\n }\n\n const insertRules = (id, cssRules) => {\n const marker = insertMarker(id)\n marker[0] += cssRules.join(' ')\n }\n\n const css = () => {\n let str = ''\n // eslint-disable-next-line guard-for-in\n for (const id in markers) {\n str += markers[id][0]\n }\n return str\n }\n\n const tag = {\n styleTag: null,\n getIds: getIdsFromMarkersFactory(markers),\n names,\n insertMarker,\n insertRules,\n css,\n toHTML: wrapAsHtmlTag(css, names),\n toElement: wrapAsElement(css, names),\n clone() {\n return {\n ...tag,\n names: [...names],\n markers: { ...markers },\n }\n },\n }\n\n return tag\n}\n\nexport const makeTag = (\n target: ?HTMLElement,\n lastEl: ?HTMLStyleElement,\n forceServer?: boolean\n): Tag => {\n if (IS_BROWSER && !forceServer) {\n const el = makeStyleTag(target, lastEl)\n if (DISABLE_SPEEDY) {\n return makeBrowserTag(el)\n } else {\n return makeSpeedyTag(el)\n }\n }\n\n return makeServerTag()\n}\n\n/* TODO: Turn into fully functional composition (tag.names) */\nexport const makeRehydrationTag = (\n tag: Tag,\n els: HTMLStyleElement[],\n extracted: ExtractedComp[],\n names: string[]\n): Tag => {\n let isReady = false\n\n /* rehydration function that adds all rules to the new tag */\n const rehydrate = () => {\n /* only rehydrate once */\n if (isReady) {\n return\n } else {\n isReady = true\n }\n\n /* add all extracted components to the new tag */\n for (let i = 0; i < extracted.length; i += 1) {\n const { componentId, cssFromDOM } = extracted[i]\n const cssRules = splitByRules(cssFromDOM)\n tag.insertRules(componentId, cssRules)\n }\n\n /* remove old HTMLStyleElements, since they have been rehydrated */\n for (let i = 0; i < els.length; i += 1) {\n const el = els[i]\n if (el.parentNode) {\n el.parentNode.removeChild(el)\n }\n }\n }\n\n /* add rehydrated names to the new tag */\n for (let i = 0; i < names.length; i += 1) {\n tag.names.push(names[i])\n }\n\n return {\n ...tag,\n /* add rehydration hook to insertion methods */\n insertMarker: id => {\n rehydrate()\n return tag.insertMarker(id)\n },\n insertRules: (id, cssRules) => {\n rehydrate()\n return tag.insertRules(id, cssRules)\n },\n }\n}\n","// @flow\n\nimport { cloneElement } from 'react'\nimport { IS_BROWSER, DISABLE_SPEEDY, SC_ATTR } from '../constants'\nimport { makeTag, makeRehydrationTag, type Tag } from './StyleTags'\nimport extractComps from '../utils/extractCompsFromCSS'\n\n/* determine the maximum number of components before tags are sharded */\nlet MAX_SIZE\nif (IS_BROWSER) {\n /* in speedy mode we can keep a lot more rules in a sheet before a slowdown can be expected */\n MAX_SIZE = DISABLE_SPEEDY ? 40 : 1000\n} else {\n /* for servers we do not need to shard at all */\n MAX_SIZE = -1\n}\n\nlet sheetRunningId = 0\nlet global\n\nclass StyleSheet {\n id: number\n sealed: boolean\n forceServer: boolean\n target: ?HTMLElement\n tagMap: { [string]: Tag }\n hashes: { [string]: string }\n deferred: { [string]: string[] }\n rehydratedNames: { [string]: boolean }\n tags: Tag[]\n capacity: number\n clones: StyleSheet[]\n\n constructor(\n target: ?HTMLElement = IS_BROWSER ? document.head : null,\n forceServer?: boolean = false\n ) {\n this.id = sheetRunningId += 1\n this.sealed = false\n this.forceServer = forceServer\n this.target = forceServer ? null : target\n this.tagMap = {}\n this.hashes = {}\n this.deferred = {}\n this.rehydratedNames = {}\n this.tags = []\n this.capacity = 1\n this.clones = []\n }\n\n /* rehydrate all SSR'd style tags */\n rehydrate() {\n if (!IS_BROWSER || this.forceServer) {\n return this\n }\n\n const els = []\n const names = []\n let extracted = []\n\n /* retrieve all of our SSR style elements from the DOM */\n const nodes = document.querySelectorAll(`style[${SC_ATTR}]`)\n const nodesSize = nodes.length\n\n for (let i = 0; i < nodesSize; i += 1) {\n // $FlowFixMe: We can trust that all elements in this query are style elements\n const el = (nodes[i]: HTMLStyleElement)\n\n /* retrieve all component names */\n const elNames = (el.getAttribute(SC_ATTR) || '').trim().split(/\\s+/)\n const elNamesSize = elNames.length\n for (let j = 0; j < elNamesSize; j += 1) {\n const name = elNames[j]\n /* add rehydrated name to sheet to avoid readding styles */\n this.rehydratedNames[name] = true\n names.push(name)\n }\n\n /* extract all components and their CSS */\n extracted = extracted.concat(extractComps(el.textContent))\n /* store original HTMLStyleElement */\n els.push(el)\n }\n\n /* use initial sheet tag for rehydration */\n const tag = makeTag(this.target, null, this.forceServer)\n const rehydrationTag = makeRehydrationTag(tag, els, extracted, names)\n\n this.tags = [rehydrationTag]\n this.capacity = MAX_SIZE\n\n /* retrieve all component ids */\n const extractedSize = extracted.length\n for (let j = 0; j < extractedSize; j += 1) {\n this.tagMap[extracted[j].componentId] = rehydrationTag\n }\n\n return this\n }\n\n /* retrieve a \"global\" instance of StyleSheet which is typically used when no other is available */\n static get global(): StyleSheet {\n return global || (global = new StyleSheet().rehydrate())\n }\n\n /* NOTE: This is just for backwards-compatibility with jest-styled-components */\n static get instance(): StyleSheet {\n return StyleSheet.global\n }\n\n /* reset the internal \"global\" instance */\n static reset(forceServer?: boolean = false) {\n global = new StyleSheet(undefined, forceServer).rehydrate()\n }\n\n /* adds \"children\" to the StyleSheet that inherit all of the parents' rules\n * while their own rules do not affect the parent */\n clone() {\n const sheet = new StyleSheet(this.target, this.forceServer)\n /* add to clone array */\n this.clones.push(sheet)\n\n /* clone all tags */\n sheet.tags = this.tags.map(tag => {\n const ids = tag.getIds()\n const newTag = tag.clone()\n\n /* reconstruct tagMap */\n for (let i = 0; i < ids.length; i += 1) {\n sheet.tagMap[ids[i]] = newTag\n }\n\n return newTag\n })\n\n /* clone other maps */\n sheet.rehydratedNames = { ...this.rehydratedNames }\n sheet.deferred = { ...this.deferred }\n sheet.hashes = { ...this.hashes }\n\n return sheet\n }\n\n /* force StyleSheet to create a new tag on the next injection */\n sealAllTags() {\n this.capacity = 1\n this.sealed = true\n }\n\n /* get a tag for a given componentId, assign the componentId to one, or shard */\n getTagForId(id: string): Tag {\n /* simply return a tag, when the componentId was already assigned one */\n const prev = this.tagMap[id]\n if (prev !== undefined && !this.sealed) {\n return prev\n }\n\n let tag = this.tags[this.tags.length - 1]\n\n /* shard (create a new tag) if the tag is exhausted (See MAX_SIZE) */\n this.capacity -= 1\n if (this.capacity === 0) {\n this.capacity = MAX_SIZE\n this.sealed = false\n tag = makeTag(this.target, tag ? tag.styleTag : null, this.forceServer)\n this.tags.push(tag)\n }\n\n return (this.tagMap[id] = tag)\n }\n\n /* optimal caching: hash is known and name can be returned */\n getNameForHash(hash: string) {\n return this.hashes[hash]\n }\n\n /* rehydration check: name is known, hash is unknown, but styles are present */\n alreadyInjected(hash: any, name: string) {\n if (!this.rehydratedNames[name]) return false\n\n this.hashes[hash] = name\n return true\n }\n\n /* checks whether component is already registered */\n hasInjectedComponent(id: string): boolean {\n return !!this.tagMap[id]\n }\n\n /* registers a componentId and registers it on its tag */\n deferredInject(id: string, cssRules: string[]) {\n const { clones } = this\n for (let i = 0; i < clones.length; i += 1) {\n clones[i].deferredInject(id, cssRules)\n }\n\n this.getTagForId(id).insertMarker(id)\n this.deferred[id] = cssRules\n }\n\n inject(id: string, cssRules: string[], hash?: string, name?: string) {\n const { clones } = this\n for (let i = 0; i < clones.length; i += 1) {\n clones[i].inject(id, cssRules, hash, name)\n }\n\n /* add deferred rules for component */\n let injectRules = cssRules\n const deferredRules = this.deferred[id]\n if (deferredRules !== undefined) {\n injectRules = deferredRules.concat(injectRules)\n delete this.deferred[id]\n }\n\n const tag = this.getTagForId(id)\n tag.insertRules(id, injectRules)\n\n if (hash && name) {\n tag.names.push(name)\n this.hashes[hash] = name\n }\n }\n\n toHTML() {\n return this.tags.map(tag => tag.toHTML()).join('')\n }\n\n toReactElements() {\n const { id } = this\n\n return this.tags.map((tag, i) => {\n const key = `sc-${id}-${i}`\n return cloneElement(tag.toElement(), { key })\n })\n }\n}\n\nexport default StyleSheet\n","// @flow\nimport React, { Component } from 'react'\nimport PropTypes from 'prop-types'\nimport StyleSheet from './StyleSheet'\nimport ServerStyleSheet from './ServerStyleSheet'\nimport { CONTEXT_KEY } from '../constants'\n\n/* this error is used for makeStyleTag */\nconst targetPropErr =\n process.env.NODE_ENV !== 'production'\n ? `\nThe StyleSheetManager expects a valid target or sheet prop!\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`.trim()\n : ''\n\nclass StyleSheetManager extends Component {\n sheetInstance: StyleSheet\n props: {\n sheet?: StyleSheet | null,\n target?: HTMLElement | null,\n }\n\n getChildContext() {\n return { [CONTEXT_KEY]: this.sheetInstance }\n }\n\n componentWillMount() {\n if (this.props.sheet) {\n this.sheetInstance = this.props.sheet\n } else if (this.props.target) {\n this.sheetInstance = new StyleSheet(this.props.target)\n } else {\n throw new Error(targetPropErr)\n }\n }\n\n render() {\n /* eslint-disable react/prop-types */\n // Flow v0.43.1 will report an error accessing the `children` property,\n // but v0.47.0 will not. It is necessary to use a type cast instead of\n // a \"fixme\" comment to satisfy both Flow versions.\n return React.Children.only((this.props: any).children)\n }\n}\n\nStyleSheetManager.childContextTypes = {\n [CONTEXT_KEY]: PropTypes.oneOfType([\n PropTypes.instanceOf(StyleSheet),\n PropTypes.instanceOf(ServerStyleSheet),\n ]).isRequired,\n}\n\nStyleSheetManager.propTypes = {\n sheet: PropTypes.oneOfType([\n PropTypes.instanceOf(StyleSheet),\n PropTypes.instanceOf(ServerStyleSheet),\n ]),\n target: PropTypes.shape({\n appendChild: PropTypes.func.isRequired,\n }),\n}\n\nexport default StyleSheetManager\n","// @flow\n/* globals React$Element */\nimport React, { Component } from 'react'\nimport PropTypes from 'prop-types'\nimport isPlainObject from 'is-plain-object'\nimport createBroadcast from '../utils/create-broadcast'\nimport type { Broadcast } from '../utils/create-broadcast'\nimport once from '../utils/once'\n\n// NOTE: DO NOT CHANGE, changing this is a semver major change!\nexport const CHANNEL = '__styled-components__'\nexport const CHANNEL_NEXT = `${CHANNEL}next__`\n\nexport const CONTEXT_CHANNEL_SHAPE = PropTypes.shape({\n getTheme: PropTypes.func,\n subscribe: PropTypes.func,\n unsubscribe: PropTypes.func,\n})\n\nexport type Theme = { [key: string]: mixed }\ntype ThemeProviderProps = {|\n children?: React$Element,\n theme: Theme | ((outerTheme: Theme) => void),\n|}\n\nlet warnChannelDeprecated\nif (process.env.NODE_ENV !== 'production') {\n warnChannelDeprecated = once(() => {\n // eslint-disable-next-line no-console\n console.error(\n `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.`\n )\n })\n}\n\nconst isFunction = test => typeof test === 'function'\n\n/**\n * Provide a theme to an entire react component tree via context and event listeners (have to do\n * both context and event emitter as pure components block context updates)\n */\nclass ThemeProvider extends Component {\n getTheme: (theme?: Theme | ((outerTheme: Theme) => void)) => Theme\n outerTheme: Theme\n unsubscribeToOuterId: string\n props: ThemeProviderProps\n broadcast: Broadcast\n unsubscribeToOuterId: number = -1\n\n constructor() {\n super()\n this.getTheme = this.getTheme.bind(this)\n }\n\n componentWillMount() {\n // If there is a ThemeProvider wrapper anywhere around this theme provider, merge this theme\n // with the outer theme\n const outerContext = this.context[CHANNEL_NEXT]\n if (outerContext !== undefined) {\n this.unsubscribeToOuterId = outerContext.subscribe(theme => {\n this.outerTheme = theme\n\n if (this.broadcast !== undefined) {\n this.publish(this.props.theme)\n }\n })\n }\n\n this.broadcast = createBroadcast(this.getTheme())\n }\n\n getChildContext() {\n return {\n ...this.context,\n [CHANNEL_NEXT]: {\n getTheme: this.getTheme,\n subscribe: this.broadcast.subscribe,\n unsubscribe: this.broadcast.unsubscribe,\n },\n [CHANNEL]: subscriber => {\n if (process.env.NODE_ENV !== 'production') {\n warnChannelDeprecated()\n }\n\n // Patch the old `subscribe` provide via `CHANNEL` for older clients.\n const unsubscribeId = this.broadcast.subscribe(subscriber)\n return () => this.broadcast.unsubscribe(unsubscribeId)\n },\n }\n }\n\n componentWillReceiveProps(nextProps: ThemeProviderProps) {\n if (this.props.theme !== nextProps.theme) {\n this.publish(nextProps.theme)\n }\n }\n\n componentWillUnmount() {\n if (this.unsubscribeToOuterId !== -1) {\n this.context[CHANNEL_NEXT].unsubscribe(this.unsubscribeToOuterId)\n }\n }\n\n // Get the theme from the props, supporting both (outerTheme) => {} as well as object notation\n getTheme(passedTheme: (outerTheme: Theme) => void | Theme) {\n const theme = passedTheme || this.props.theme\n if (isFunction(theme)) {\n const mergedTheme = theme(this.outerTheme)\n if (\n process.env.NODE_ENV !== 'production' &&\n !isPlainObject(mergedTheme)\n ) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? '[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!'\n : ''\n )\n }\n return mergedTheme\n }\n if (!isPlainObject(theme)) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? '[ThemeProvider] Please make your theme prop a plain object'\n : ''\n )\n }\n return { ...this.outerTheme, ...(theme: Object) }\n }\n\n publish(theme: Theme | ((outerTheme: Theme) => void)) {\n this.broadcast.publish(this.getTheme(theme))\n }\n\n render() {\n if (!this.props.children) {\n return null\n }\n return React.Children.only(this.props.children)\n }\n}\n\nThemeProvider.childContextTypes = {\n [CHANNEL]: PropTypes.func, // legacy\n [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE,\n}\nThemeProvider.contextTypes = {\n [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE,\n}\n\nexport default ThemeProvider\n","// @flow\n\nimport { Component, createElement } from 'react'\nimport PropTypes from 'prop-types'\n\nimport type { Theme } from './ThemeProvider'\nimport createWarnTooManyClasses from '../utils/createWarnTooManyClasses'\n\nimport validAttr from '../utils/validAttr'\nimport isTag from '../utils/isTag'\nimport isStyledComponent from '../utils/isStyledComponent'\nimport getComponentName from '../utils/getComponentName'\nimport determineTheme from '../utils/determineTheme'\nimport escape from '../utils/escape'\nimport type { RuleSet, Target } from '../types'\nimport { CONTEXT_KEY } from '../constants'\n\nimport { CHANNEL, CHANNEL_NEXT, CONTEXT_CHANNEL_SHAPE } from './ThemeProvider'\nimport StyleSheet from './StyleSheet'\nimport ServerStyleSheet from './ServerStyleSheet'\n\n// HACK for generating all static styles without needing to allocate\n// an empty execution context every single time...\nconst STATIC_EXECUTION_CONTEXT = {}\n\nexport default (ComponentStyle: Function, constructWithOptions: Function) => {\n const identifiers = {}\n\n /* We depend on components having unique IDs */\n const generateId = (_displayName: string, parentComponentId: string) => {\n const displayName =\n typeof _displayName !== 'string' ? 'sc' : escape(_displayName)\n\n let componentId\n\n /**\n * only fall back to hashing the component injection order if\n * a proper displayName isn't provided by the babel plugin\n */\n if (!_displayName) {\n const nr = (identifiers[displayName] || 0) + 1\n identifiers[displayName] = nr\n\n componentId = `${displayName}-${ComponentStyle.generateName(\n displayName + nr\n )}`\n } else {\n componentId = `${displayName}-${ComponentStyle.generateName(displayName)}`\n }\n\n return parentComponentId !== undefined\n ? `${parentComponentId}-${componentId}`\n : componentId\n }\n\n class BaseStyledComponent extends Component {\n static target: Target\n static styledComponentId: string\n static attrs: Object\n static componentStyle: Object\n static warnTooManyClasses: Function\n\n attrs = {}\n state = {\n theme: null,\n generatedClassName: '',\n }\n unsubscribeId: number = -1\n\n unsubscribeFromContext() {\n if (this.unsubscribeId !== -1) {\n this.context[CHANNEL_NEXT].unsubscribe(this.unsubscribeId)\n }\n }\n\n buildExecutionContext(theme: any, props: any) {\n const { attrs } = this.constructor\n const context = { ...props, theme }\n if (attrs === undefined) {\n return context\n }\n\n this.attrs = Object.keys(attrs).reduce((acc, key) => {\n const attr = attrs[key]\n // eslint-disable-next-line no-param-reassign\n acc[key] = typeof attr === 'function' ? attr(context) : attr\n return acc\n }, {})\n\n return { ...context, ...this.attrs }\n }\n\n generateAndInjectStyles(theme: any, props: any) {\n const { attrs, componentStyle, warnTooManyClasses } = this.constructor\n const styleSheet = this.context[CONTEXT_KEY] || StyleSheet.global\n\n // staticaly styled-components don't need to build an execution context object,\n // and shouldn't be increasing the number of class names\n if (componentStyle.isStatic && attrs === undefined) {\n return componentStyle.generateAndInjectStyles(\n STATIC_EXECUTION_CONTEXT,\n styleSheet\n )\n } else {\n const executionContext = this.buildExecutionContext(theme, props)\n const className = componentStyle.generateAndInjectStyles(\n executionContext,\n styleSheet\n )\n\n if (\n process.env.NODE_ENV !== 'production' &&\n warnTooManyClasses !== undefined\n ) {\n warnTooManyClasses(className)\n }\n\n return className\n }\n }\n\n componentWillMount() {\n const { componentStyle } = this.constructor\n const styledContext = this.context[CHANNEL_NEXT]\n\n // If this is a staticaly-styled component, we don't need to the theme\n // to generate or build styles.\n if (componentStyle.isStatic) {\n const generatedClassName = this.generateAndInjectStyles(\n STATIC_EXECUTION_CONTEXT,\n this.props\n )\n this.setState({ generatedClassName })\n // If there is a theme in the context, subscribe to the event emitter. This\n // is necessary due to pure components blocking context updates, this circumvents\n // that by updating when an event is emitted\n } else if (styledContext !== undefined) {\n const { subscribe } = styledContext\n this.unsubscribeId = subscribe(nextTheme => {\n // This will be called once immediately\n const theme = determineTheme(\n this.props,\n nextTheme,\n this.constructor.defaultProps\n )\n const generatedClassName = this.generateAndInjectStyles(\n theme,\n this.props\n )\n\n this.setState({ theme, generatedClassName })\n })\n } else {\n // eslint-disable-next-line react/prop-types\n const theme = this.props.theme || {}\n const generatedClassName = this.generateAndInjectStyles(\n theme,\n this.props\n )\n this.setState({ theme, generatedClassName })\n }\n }\n\n componentWillReceiveProps(nextProps: {\n theme?: Theme,\n [key: string]: any,\n }) {\n // If this is a staticaly-styled component, we don't need to listen to\n // props changes to update styles\n const { componentStyle } = this.constructor\n if (componentStyle.isStatic) {\n return\n }\n\n this.setState(oldState => {\n const theme = determineTheme(\n nextProps,\n oldState.theme,\n this.constructor.defaultProps\n )\n const generatedClassName = this.generateAndInjectStyles(\n theme,\n nextProps\n )\n\n return { theme, generatedClassName }\n })\n }\n\n componentWillUnmount() {\n this.unsubscribeFromContext()\n }\n\n render() {\n // eslint-disable-next-line react/prop-types\n const { innerRef } = this.props\n const { generatedClassName } = this.state\n const { styledComponentId, target } = this.constructor\n\n const isTargetTag = isTag(target)\n\n const className = [\n // eslint-disable-next-line react/prop-types\n this.props.className,\n styledComponentId,\n this.attrs.className,\n generatedClassName,\n ]\n .filter(Boolean)\n .join(' ')\n\n const baseProps = {\n ...this.attrs,\n className,\n }\n\n if (isStyledComponent(target)) {\n baseProps.innerRef = innerRef\n } else {\n baseProps.ref = innerRef\n }\n\n const propsForElement = Object.keys(this.props).reduce(\n (acc, propName) => {\n // Don't pass through non HTML tags through to HTML elements\n // always omit innerRef\n if (\n propName !== 'innerRef' &&\n propName !== 'className' &&\n (!isTargetTag || validAttr(propName))\n ) {\n // eslint-disable-next-line no-param-reassign\n acc[propName] = this.props[propName]\n }\n\n return acc\n },\n baseProps\n )\n\n return createElement(target, propsForElement)\n }\n }\n\n const createStyledComponent = (\n target: Target,\n options: Object,\n rules: RuleSet\n ) => {\n const {\n displayName = isTag(target)\n ? `styled.${target}`\n : `Styled(${getComponentName(target)})`,\n componentId = generateId(options.displayName, options.parentComponentId),\n ParentComponent = BaseStyledComponent,\n rules: extendingRules,\n attrs,\n } = options\n\n const styledComponentId =\n options.displayName && options.componentId\n ? `${escape(options.displayName)}-${options.componentId}`\n : componentId\n\n const componentStyle = new ComponentStyle(\n extendingRules === undefined ? rules : extendingRules.concat(rules),\n attrs,\n styledComponentId\n )\n\n class StyledComponent extends ParentComponent {\n static contextTypes = {\n [CHANNEL]: PropTypes.func,\n [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE,\n [CONTEXT_KEY]: PropTypes.oneOfType([\n PropTypes.instanceOf(StyleSheet),\n PropTypes.instanceOf(ServerStyleSheet),\n ]),\n }\n\n static displayName = displayName\n static styledComponentId = styledComponentId\n static attrs = attrs\n static componentStyle = componentStyle\n static target = target\n\n static withComponent(tag) {\n const { componentId: previousComponentId, ...optionsToCopy } = options\n\n const newComponentId =\n previousComponentId &&\n `${previousComponentId}-${\n isTag(tag) ? tag : escape(getComponentName(tag))\n }`\n\n const newOptions = {\n ...optionsToCopy,\n componentId: newComponentId,\n ParentComponent: StyledComponent,\n }\n\n return createStyledComponent(tag, newOptions, rules)\n }\n\n static get extend() {\n const {\n rules: rulesFromOptions,\n componentId: parentComponentId,\n ...optionsToCopy\n } = options\n\n const newRules =\n rulesFromOptions === undefined\n ? rules\n : rulesFromOptions.concat(rules)\n\n const newOptions = {\n ...optionsToCopy,\n rules: newRules,\n parentComponentId,\n ParentComponent: StyledComponent,\n }\n\n return constructWithOptions(createStyledComponent, target, newOptions)\n }\n }\n\n if (process.env.NODE_ENV !== 'production') {\n StyledComponent.warnTooManyClasses = createWarnTooManyClasses(displayName)\n }\n\n return StyledComponent\n }\n\n return createStyledComponent\n}\n","// @flow\nimport hashStr from '../vendor/glamor/hash'\n\nimport type { RuleSet, NameGenerator, Flattener, Stringifier } from '../types'\nimport StyleSheet from './StyleSheet'\nimport { IS_BROWSER } from '../constants'\nimport isStyledComponent from '../utils/isStyledComponent'\n\nconst areStylesCacheable = IS_BROWSER\n\nconst isStaticRules = (rules: RuleSet, attrs?: Object): boolean => {\n for (let i = 0; i < rules.length; i += 1) {\n const rule = rules[i]\n\n // recursive case\n if (Array.isArray(rule) && !isStaticRules(rule)) {\n return false\n } else if (typeof rule === 'function' && !isStyledComponent(rule)) {\n // functions are allowed to be static if they're just being\n // used to get the classname of a nested styled copmonent\n return false\n }\n }\n\n if (attrs !== undefined) {\n // eslint-disable-next-line guard-for-in, no-restricted-syntax\n for (const key in attrs) {\n const value = attrs[key]\n if (typeof value === 'function') {\n return false\n }\n }\n }\n\n return true\n}\n\nconst isHRMEnabled =\n typeof module !== 'undefined' &&\n module.hot &&\n process.env.NODE_ENV !== 'production'\n\n/*\n ComponentStyle is all the CSS-specific stuff, not\n the React-specific stuff.\n */\nexport default (\n nameGenerator: NameGenerator,\n flatten: Flattener,\n stringifyRules: Stringifier\n) => {\n class ComponentStyle {\n rules: RuleSet\n componentId: string\n isStatic: boolean\n lastClassName: ?string\n\n constructor(rules: RuleSet, attrs?: Object, componentId: string) {\n this.rules = rules\n this.isStatic = !isHRMEnabled && isStaticRules(rules, attrs)\n this.componentId = componentId\n\n if (!StyleSheet.global.hasInjectedComponent(componentId)) {\n const placeholder =\n process.env.NODE_ENV !== 'production' ? [`.${componentId} {}`] : []\n StyleSheet.global.deferredInject(componentId, placeholder)\n }\n }\n\n /*\n * Flattens a rule set into valid CSS\n * Hashes it, wraps the whole chunk in a .hash1234 {}\n * Returns the hash to be injected on render()\n * */\n generateAndInjectStyles(executionContext: Object, styleSheet: StyleSheet) {\n const { isStatic, lastClassName } = this\n if (isStatic && lastClassName !== undefined) {\n return lastClassName\n }\n\n const flatCSS = flatten(this.rules, executionContext)\n const hash = hashStr(this.componentId + flatCSS.join(''))\n const existingName = styleSheet.getNameForHash(hash)\n\n if (existingName !== undefined) {\n if (areStylesCacheable) {\n this.lastClassName = existingName\n }\n\n return existingName\n }\n\n const name = nameGenerator(hash)\n if (areStylesCacheable) {\n this.lastClassName = existingName\n }\n\n if (styleSheet.alreadyInjected(hash, name)) {\n return name\n }\n\n const css = stringifyRules(flatCSS, `.${name}`)\n // NOTE: this can only be set when we inject the class-name.\n // For some reason, presumably due to how css is stringifyRules behaves in\n // differently between client and server, styles break.\n styleSheet.inject(this.componentId, css, hash, name)\n return name\n }\n\n static generateName(str: string) {\n return nameGenerator(hashStr(str))\n }\n }\n\n return ComponentStyle\n}\n","// @flow\nimport type { Target } from '../types'\nimport domElements from '../utils/domElements'\n\nexport default (styledComponent: Function, constructWithOptions: Function) => {\n const styled = (tag: Target) => constructWithOptions(styledComponent, tag)\n\n // Shorthands for all valid HTML Elements\n domElements.forEach(domElement => {\n styled[domElement] = styled(domElement)\n })\n\n return styled\n}\n","// @flow\nimport hashStr from '../vendor/glamor/hash'\nimport type { Interpolation, NameGenerator, Stringifier } from '../types'\nimport StyleSheet from '../models/StyleSheet'\n\nconst replaceWhitespace = (str: string): string => str.replace(/\\s|\\\\n/g, '')\n\nexport default (\n nameGenerator: NameGenerator,\n stringifyRules: Stringifier,\n css: Function\n) => (\n strings: Array,\n ...interpolations: Array\n): string => {\n const rules = css(strings, ...interpolations)\n const hash = hashStr(replaceWhitespace(JSON.stringify(rules)))\n\n const existingName = StyleSheet.global.getNameForHash(hash)\n if (existingName !== undefined) {\n return existingName\n }\n\n const name = nameGenerator(hash)\n if (StyleSheet.global.alreadyInjected(hash, name)) return name\n\n StyleSheet.global.inject(\n `sc-keyframes-${name}`,\n stringifyRules(rules, name, '@keyframes'),\n hash,\n name\n )\n\n return name\n}\n"],"names":["create","insertMarker","id","getChildContext","componentWillMount","state","unsubscribeId","attrs","reduce","length","i"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAgLyBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBCSAC;;;;;;;;;;;;;;;;2BAeoBC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BCrL3CC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAF,kCAAA;AACA,yCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA0BEC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+JCUEC;;;eAIAC;;;;;;;;;;;;;;;;;+BAe2BC,OAAYC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BCjEfC,QAA0BC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCA0ClD,OAAA,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnDJ;;;;;;;;;;;;;;;;;;;SCSK,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}