UNPKG

glamorous

Version:

React component styling solved

1,556 lines (1,357 loc) 62.8 kB
import React from 'react'; import { css } from 'glamor'; var htmlTagNames = [ "a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdi", "bdo", "bgsound", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "command", "content", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame", "frameset", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "image", "img", "input", "ins", "isindex", "kbd", "keygen", "label", "legend", "li", "link", "listing", "main", "map", "mark", "marquee", "math", "menu", "menuitem", "meta", "meter", "multicol", "nav", "nextid", "nobr", "noembed", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "plaintext", "pre", "progress", "q", "rb", "rbc", "rp", "rt", "rtc", "ruby", "s", "samp", "script", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "tt", "u", "ul", "var", "video", "wbr", "xmp" ] ; var svgTagNames = [ "a", "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "animation", "audio", "canvas", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "handler", "hatch", "hatchpath", "hkern", "iframe", "image", "line", "linearGradient", "listener", "marker", "mask", "mesh", "meshgradient", "meshpatch", "meshrow", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "prefetch", "radialGradient", "rect", "script", "set", "solidColor", "solidcolor", "stop", "style", "svg", "switch", "symbol", "tbreak", "text", "textArea", "textPath", "title", "tref", "tspan", "unknown", "use", "video", "view", "vkern" ] ; var domElements = htmlTagNames.concat(svgTagNames).filter(function (tag, index, array) { return array.indexOf(tag) === index; }); var CHANNEL = '__glamorous__'; /* istanbul ignore next */ var isPreact = false; var _PropTypes = void 0; /* istanbul ignore next */ if (isPreact) { if (!React.PropTypes) { _PropTypes = function PropTypes() { return _PropTypes; }; ['array', 'bool', 'func', 'number', 'object', 'string', 'symbol', 'any', 'arrayOf', 'element', 'instanceOf', 'node', 'objectOf', 'oneOf', 'oneOfType', 'shape', 'exact'].forEach(function (type) { _PropTypes[type] = _PropTypes; }); } // copied from preact-compat /* eslint-disable no-eq-null, eqeqeq, consistent-return */ if (!React.Children) { var Children = { map: function map(children, fn, ctx) { if (children == null) { return null; } children = Children.toArray(children); if (ctx && ctx !== children) { fn = fn.bind(ctx); } return children.map(fn); }, forEach: function forEach(children, fn, ctx) { if (children == null) { return null; } children = Children.toArray(children); if (ctx && ctx !== children) { fn = fn.bind(ctx); } children.forEach(fn); }, count: function count(children) { return children && children.length || 0; }, only: function only(children) { children = Children.toArray(children); if (children.length !== 1) { throw new Error('Children.only() expects only one child.'); } return children[0]; }, toArray: function toArray(children) { if (children == null) { return []; } return [].concat(children); } }; React.Children = Children; } /* eslint-enable no-eq-null, eqeqeq, consistent-return */ } else if (parseFloat(React.version.slice(0, 4)) >= 15.5) { /* istanbul ignore next */ try { _PropTypes = require('prop-types'); /* istanbul ignore next */ } catch (error) { // ignore } } /* istanbul ignore next */ _PropTypes = _PropTypes || React.PropTypes; /* eslint import/no-mutable-exports:0, import/prefer-default-export:0, react/no-deprecated:0 */ var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var objectWithoutProperties = function (obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; function generateWarningMessage(Comp) { var componentName = Comp.displayName || Comp.name || 'FunctionComponent'; // eslint-disable-next-line max-len return 'glamorous warning: Expected component called "' + componentName + '" which uses withTheme to be within a ThemeProvider but none was found.'; } function withTheme(ComponentToTheme) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$noWarn = _ref.noWarn, noWarn = _ref$noWarn === undefined ? false : _ref$noWarn, _ref$createElement = _ref.createElement, createElement = _ref$createElement === undefined ? true : _ref$createElement; var ThemedComponent = function (_React$Component) { inherits(ThemedComponent, _React$Component); function ThemedComponent() { var _ref2; var _temp, _this, _ret; classCallCheck(this, ThemedComponent); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref2 = ThemedComponent.__proto__ || Object.getPrototypeOf(ThemedComponent)).call.apply(_ref2, [this].concat(args))), _this), _this.warned = noWarn, _this.state = { theme: {} }, _this.setTheme = function (theme) { return _this.setState({ theme: theme }); }, _temp), possibleConstructorReturn(_this, _ret); } createClass(ThemedComponent, [{ key: 'componentWillMount', // eslint-disable-next-line complexity value: function componentWillMount() { if (!this.context[CHANNEL]) { if (process.env.NODE_ENV !== 'production' && !this.warned) { this.warned = true; // eslint-disable-next-line no-console console.warn(generateWarningMessage(ComponentToTheme)); } } var theme = this.props.theme; if (this.context[CHANNEL]) { // if a theme is provided via props, // it takes precedence over context this.setTheme(theme ? theme : this.context[CHANNEL].getState()); } else { this.setTheme(theme || {}); } } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { if (this.props.theme !== nextProps.theme) { this.setTheme(nextProps.theme); } } }, { key: 'componentDidMount', value: function componentDidMount() { if (this.context[CHANNEL] && !this.props.theme) { // subscribe to future theme changes this.subscriptionId = this.context[CHANNEL].subscribe(this.setTheme); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { // cleanup subscription this.subscriptionId && this.context[CHANNEL].unsubscribe(this.subscriptionId); } }, { key: 'render', value: function render() { if (createElement) { return React.createElement(ComponentToTheme, _extends({}, this.props, this.state)); } else { // this allows us to effectively use the GlamorousComponent // as our `render` method without going through lifecycle hooks. // Also allows us to forward the context in the scenario where // a user wants to add more context. // eslint-disable-next-line babel/new-cap return ComponentToTheme.call(this, _extends({}, this.props, this.state), this.context); } } }]); return ThemedComponent; }(React.Component); ThemedComponent.propTypes = { theme: _PropTypes.object }; var defaultContextTypes = defineProperty({}, CHANNEL, _PropTypes.object); var userDefinedContextTypes = null; // configure the contextTypes to be settable by the user, // however also retaining the glamorous channel. Object.defineProperty(ThemedComponent, 'contextTypes', { enumerable: true, configurable: true, set: function set$$1(value) { userDefinedContextTypes = value; }, get: function get$$1() { // if the user has provided a contextTypes definition, // merge the default context types with the provided ones. if (userDefinedContextTypes) { return _extends({}, defaultContextTypes, userDefinedContextTypes); } return defaultContextTypes; } }); return ThemedComponent; } var isFunction_1 = isFunction; var toString = Object.prototype.toString; function isFunction (fn) { var string = toString.call(fn); return string === '[object Function]' || (typeof fn === 'function' && string !== '[object RegExp]') || (typeof window !== 'undefined' && // IE8 and below (fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt)) } /*! * isobject <https://github.com/jonschlinkert/isobject> * * Copyright (c) 2014-2017, Jon Schlinkert. * Released under the MIT License. */ var isobject = function isObject(val) { return val != null && typeof val === 'object' && Array.isArray(val) === false; }; function isObjectObject(o) { return isobject(o) === true && Object.prototype.toString.call(o) === '[object Object]'; } var isPlainObject = function isPlainObject(o) { var ctor,prot; if (isObjectObject(o) === false) return false; // If has modified constructor ctor = o.constructor; if (typeof ctor !== 'function') return false; // If has modified prototype prot = ctor.prototype; if (isObjectObject(prot) === false) return false; // If constructor does not have an Object-specific method if (prot.hasOwnProperty('isPrototypeOf') === false) { return false; } // Most likely a plain Object return true; }; function createBroadcast (initialState) { var listeners = {}; var id = 1; var _state = initialState; function getState () { return _state } function setState (state) { _state = state; var keys = Object.keys(listeners); var i = 0; var len = keys.length; for (; i < len; i++) { // if a listener gets unsubscribed during setState we just skip it if (listeners[keys[i]]) { listeners[keys[i]](state); } } } // subscribe to changes and return the subscriptionId function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('listener must be a function.') } var currentId = id; listeners[currentId] = listener; id += 1; return currentId } // remove subscription by removing the listener function function unsubscribe (id) { listeners[id] = undefined; } return { getState: getState, setState: setState, subscribe: subscribe, unsubscribe: unsubscribe } } /** * This is a component which will provide a theme to the entire tree * via context and event listener * (because pure components block context updates) * inspired by the styled-components implementation * https://github.com/styled-components/styled-components * @param {Object} theme the theme object.. */ var ThemeProvider = function (_React$Component) { inherits(ThemeProvider, _React$Component); function ThemeProvider() { var _ref; var _temp, _this, _ret; classCallCheck(this, ThemeProvider); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = ThemeProvider.__proto__ || Object.getPrototypeOf(ThemeProvider)).call.apply(_ref, [this].concat(args))), _this), _this.broadcast = createBroadcast(_this.props.theme), _this.setOuterTheme = function (theme) { _this.outerTheme = theme; }, _temp), possibleConstructorReturn(_this, _ret); } createClass(ThemeProvider, [{ key: 'getTheme', // create theme, by merging with outer theme, if present value: function getTheme(passedTheme) { var theme = passedTheme || this.props.theme; if (isFunction_1(theme)) { var mergedTheme = theme(this.outerTheme); if (!isPlainObject(mergedTheme)) { throw new Error('[ThemeProvider] Please return an object from your theme function, ' + 'i.e. theme={() => ({})}!'); } return mergedTheme; } return _extends({}, this.outerTheme, theme); } }, { key: 'getChildContext', value: function getChildContext() { return defineProperty({}, CHANNEL, this.broadcast); } }, { key: 'componentDidMount', value: function componentDidMount() { // create a new subscription for keeping track of outer theme, if present if (this.context[CHANNEL]) { this.subscriptionId = this.context[CHANNEL].subscribe(this.setOuterTheme); } } }, { key: 'componentWillMount', value: function componentWillMount() { // set broadcast state by merging outer theme with own if (this.context[CHANNEL]) { this.setOuterTheme(this.context[CHANNEL].getState()); this.broadcast.setState(this.getTheme()); } } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { if (this.props.theme !== nextProps.theme) { this.broadcast.setState(this.getTheme(nextProps.theme)); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.subscriptionId && this.context[CHANNEL].unsubscribe(this.subscriptionId); } }, { key: 'render', value: function render() { return this.props.children ? React.Children.only(this.props.children) : null; } }]); return ThemeProvider; }(React.Component); ThemeProvider.childContextTypes = defineProperty({}, CHANNEL, _PropTypes.object.isRequired); ThemeProvider.contextTypes = defineProperty({}, CHANNEL, _PropTypes.object); ThemeProvider.propTypes = { theme: _PropTypes.oneOfType([_PropTypes.object, _PropTypes.func]).isRequired, children: _PropTypes.node }; /** * This function takes a className string and gets all the * associated glamor styles. It's used to merge glamor styles * from a className to make sure that specificity is not * a problem when passing a className to a component. * @param {String} [className=''] the className string * @return {Object} { glamorStyles, glamorlessClassName } * - glamorStyles is an array of all the glamor styles objects * - glamorlessClassName is the rest of the className string * without the glamor classNames */ function extractGlamorStyles(className) { var glamorlessClassName = []; var glamorStyles = []; className.toString().split(' ').forEach(function (name) { if (name.indexOf('css-') === 0) { var style = buildGlamorSrcFromClassName(name); glamorStyles.push(style); } else { glamorlessClassName.push(name); } }); return { glamorlessClassName: glamorlessClassName, glamorStyles: glamorStyles }; } /** Glamor's css function returns an object with the shape * * { * [`data-css-${hash}`]: '', * toString() { return `css-${hash}` } * } * * Whenever glamor's build function encounters an object with * this shape it just pulls the resulting styles from the cache. * * note: the toString method is not needed to qualify the shape **/ function buildGlamorSrcFromClassName(className) { return defineProperty({}, 'data-' + className, ''); } function getGlamorClassName$1(_ref2) { var styles = _ref2.styles, props = _ref2.props, cssOverrides = _ref2.cssOverrides, cssProp = _ref2.cssProp, context = _ref2.context, displayName = _ref2.displayName; var _handleStyles = handleStyles([].concat(toConsumableArray(styles), [props.className, cssOverrides, cssProp]), props, context), mappedArgs = _handleStyles.mappedArgs, nonGlamorClassNames = _handleStyles.nonGlamorClassNames; // eslint-disable-next-line max-len var isDev = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV; var devRules = isDev ? { label: displayName } : null; var glamorClassName = css.apply(undefined, [devRules].concat(toConsumableArray(mappedArgs))).toString(); var extras = nonGlamorClassNames.join(' ').trim(); return (glamorClassName + ' ' + extras).trim(); } // this next function is on a "hot" code-path // so it's pretty complex to make sure it's fast. // eslint-disable-next-line complexity function handleStyles(styles, props, context) { var current = void 0; var mappedArgs = []; var nonGlamorClassNames = []; for (var i = 0; i < styles.length; i++) { current = styles[i]; if (typeof current === 'function') { var result = current(props, context); if (typeof result === 'string') { var _extractGlamorStyles = extractGlamorStyles(result), glamorStyles = _extractGlamorStyles.glamorStyles, glamorlessClassName = _extractGlamorStyles.glamorlessClassName; mappedArgs.push.apply(mappedArgs, toConsumableArray(glamorStyles)); nonGlamorClassNames.push.apply(nonGlamorClassNames, toConsumableArray(glamorlessClassName)); } else { mappedArgs.push(result); } } else if (typeof current === 'string') { var _extractGlamorStyles2 = extractGlamorStyles(current), _glamorStyles = _extractGlamorStyles2.glamorStyles, _glamorlessClassName = _extractGlamorStyles2.glamorlessClassName; mappedArgs.push.apply(mappedArgs, toConsumableArray(_glamorStyles)); nonGlamorClassNames.push.apply(nonGlamorClassNames, toConsumableArray(_glamorlessClassName)); } else if (Array.isArray(current)) { var recursed = handleStyles(current, props, context); mappedArgs.push.apply(mappedArgs, toConsumableArray(recursed.mappedArgs)); nonGlamorClassNames.push.apply(nonGlamorClassNames, toConsumableArray(recursed.nonGlamorClassNames)); } else { mappedArgs.push(current); } } return { mappedArgs: mappedArgs, nonGlamorClassNames: nonGlamorClassNames }; } /* * This is a relatively small abstraction that's ripe for open sourcing. * Documentation is in the README.md */ function createGlamorous$1(splitProps) { return glamorous; /** * This is the main export and the function that people * interact with most directly. * * It accepts a component which can be a string or * a React Component and returns * a "glamorousComponentFactory" * @param {String|ReactComponent} comp the component to render * @param {Object} options helpful info for the GlamorousComponents * @return {Function} the glamorousComponentFactory */ function glamorous(comp) { var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var rootEl = config.rootEl, displayName = config.displayName, shouldClassNameUpdate = config.shouldClassNameUpdate, _config$filterProps = config.filterProps, filterProps = _config$filterProps === undefined ? [] : _config$filterProps, _config$forwardProps = config.forwardProps, forwardProps = _config$forwardProps === undefined ? [] : _config$forwardProps, _config$propsAreCssOv = config.propsAreCssOverrides, propsAreCssOverrides = _config$propsAreCssOv === undefined ? comp.propsAreCssOverrides : _config$propsAreCssOv, basePropsToApply = config.withProps; Object.assign(glamorousComponentFactory, { withConfig: withConfig }); return glamorousComponentFactory; function withConfig(newConfig) { return glamorous(comp, _extends({}, config, newConfig)); } /** * This returns a React Component that renders the comp (closure) * with a className based on the given glamor styles object(s) * @param {...Object|Function} styles the styles to create with glamor. * If any of these are functions, they are invoked with the component * props and the return value is used. * @return {ReactComponent} the ReactComponent function */ function glamorousComponentFactory() { for (var _len = arguments.length, styles = Array(_len), _key = 0; _key < _len; _key++) { styles[_key] = arguments[_key]; } /** * This is a component which will render the comp (closure) * with the glamorous styles (closure). Forwards any valid * props to the underlying component. */ var GlamorousComponent = withTheme(function (props, context) { props = getPropsToApply(GlamorousComponent.propsToApply, {}, props, context); var updateClassName = shouldUpdate(props, context, this.previous); if (shouldClassNameUpdate) { this.previous = { props: props, context: context }; } var _splitProps = splitProps(props, GlamorousComponent), toForward = _splitProps.toForward, cssOverrides = _splitProps.cssOverrides, cssProp = _splitProps.cssProp; // create className to apply this.className = updateClassName ? getGlamorClassName$1({ styles: GlamorousComponent.styles, props: props, cssOverrides: cssOverrides, cssProp: cssProp, context: context, displayName: GlamorousComponent.displayName }) : this.className; return React.createElement(GlamorousComponent.comp, _extends({ ref: props.innerRef }, toForward, { className: this.className })); }, { noWarn: true, createElement: false }); GlamorousComponent.propTypes = { // className accepts an object due to glamor's css function // returning an object with a toString method that gives the className className: _PropTypes.oneOfType([_PropTypes.string, _PropTypes.object]), cssOverrides: _PropTypes.object, innerRef: _PropTypes.func, glam: _PropTypes.object }; function shouldUpdate(props, context, previous) { // exiting early so components which do not use this // optimization are not penalized by hanging onto // references to previous props and context if (!shouldClassNameUpdate) { return true; } var update = true; if (previous) { if (!shouldClassNameUpdate(previous.props, props, previous.context, context)) { update = false; } } return update; } Object.assign(GlamorousComponent, getGlamorousComponentMetadata({ comp: comp, styles: styles, rootEl: rootEl, filterProps: filterProps, forwardProps: forwardProps, displayName: displayName, propsToApply: basePropsToApply }), { isGlamorousComponent: true, propsAreCssOverrides: propsAreCssOverrides, withComponent: function (newComp) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var fwp = GlamorousComponent.forwardProps, flp = GlamorousComponent.filterProps, componentProperties = objectWithoutProperties(GlamorousComponent, ['forwardProps', 'filterProps']); return glamorous(_extends({}, componentProperties, { comp: newComp }), _extends({ // allows the forwardProps and filterProps to be overridden forwardProps: fwp, filterProps: flp }, options))(); }, withProps: function () { for (var _len2 = arguments.length, propsToApply = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { propsToApply[_key2] = arguments[_key2]; } return glamorous(GlamorousComponent, { withProps: propsToApply })(); }, withConfig: withConfig }); return GlamorousComponent; } } function getGlamorousComponentMetadata(_ref) { var comp = _ref.comp, styles = _ref.styles, rootEl = _ref.rootEl, filterProps = _ref.filterProps, forwardProps = _ref.forwardProps, displayName = _ref.displayName, basePropsToApply = _ref.propsToApply; var componentsComp = comp.comp ? comp.comp : comp; var propsToApply = comp.propsToApply ? [].concat(toConsumableArray(comp.propsToApply), toConsumableArray(arrayify(basePropsToApply))) : arrayify(basePropsToApply); return { // join styles together (for anyone doing: glamorous(glamorous.a({}), {})) styles: when(comp.styles, styles), // keep track of the ultimate rootEl to render (we never // actually render anything but // the base component, even when people wrap a glamorous // component in glamorous comp: componentsComp, rootEl: rootEl || componentsComp, // join forwardProps and filterProps // (for anyone doing: glamorous(glamorous.a({}), {})) forwardProps: when(comp.forwardProps, forwardProps), filterProps: when(comp.filterProps, filterProps), // set the displayName to something that's slightly more // helpful than `GlamorousComponent` :) displayName: displayName || 'glamorous(' + getDisplayName(comp) + ')', // these are props that should be applied to the component at render time propsToApply: propsToApply }; } } /** * reduces the propsToApply given to a single props object * @param {Array} propsToApply an array of propsToApply objects: * - object * - array of propsToApply items * - function that accepts the accumulated props and the context * @param {Object} accumulator an object to apply props onto * @param {Object} props the props that should ultimately take precedence * @param {*} context the context object * @return {Object} the reduced props */ function getPropsToApply(propsToApply, accumulator, props, context) { // using forEach rather than reduce here because the reduce solution // effectively did the same thing because we manipulate the `accumulator` propsToApply.forEach(function (propsToApplyItem) { if (typeof propsToApplyItem === 'function') { return Object.assign(accumulator, propsToApplyItem(Object.assign({}, accumulator, props), context)); } else if (Array.isArray(propsToApplyItem)) { return Object.assign(accumulator, getPropsToApply(propsToApplyItem, accumulator, props, context)); } return Object.assign(accumulator, propsToApplyItem); }); // props wins return Object.assign(accumulator, props); } function arrayify() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return Array.isArray(x) ? x : [x]; } function when(comp, prop) { return comp ? comp.concat(prop) : prop; } function getDisplayName(comp) { return typeof comp === 'string' ? comp : comp.displayName || comp.name || 'unknown'; } // // Main // function memoize (fn, options) { var cache = options && options.cache ? options.cache : cacheDefault; var serializer = options && options.serializer ? options.serializer : serializerDefault; var strategy = options && options.strategy ? options.strategy : strategyDefault; return strategy(fn, { cache: cache, serializer: serializer }) } // // Strategy // function isPrimitive (value) { return value == null || (typeof value !== 'function' && typeof value !== 'object') } function monadic (fn, cache, serializer, arg) { var cacheKey = isPrimitive(arg) ? arg : serializer(arg); if (!cache.has(cacheKey)) { var computedValue = fn.call(this, arg); cache.set(cacheKey, computedValue); return computedValue } return cache.get(cacheKey) } function variadic (fn, cache, serializer) { var args = Array.prototype.slice.call(arguments, 3); var cacheKey = serializer(args); if (!cache.has(cacheKey)) { var computedValue = fn.apply(this, args); cache.set(cacheKey, computedValue); return computedValue } return cache.get(cacheKey) } function assemble (fn, context, strategy, cache, serialize) { return strategy.bind( context, fn, cache, serialize ) } function strategyDefault (fn, options) { var strategy = fn.length === 1 ? monadic : variadic; return assemble( fn, this, strategy, options.cache.create(), options.serializer ) } function strategyVariadic (fn, options) { var strategy = variadic; return assemble( fn, this, strategy, options.cache.create(), options.serializer ) } function strategyMonadic (fn, options) { var strategy = monadic; return assemble( fn, this, strategy, options.cache.create(), options.serializer ) } // // Serializer // function serializerDefault () { return JSON.stringify(arguments) } // // Cache // function ObjectWithoutPrototypeCache () { this.cache = Object.create(null); } ObjectWithoutPrototypeCache.prototype.has = function (key) { return (key in this.cache) }; ObjectWithoutPrototypeCache.prototype.get = function (key) { return this.cache[key] }; ObjectWithoutPrototypeCache.prototype.set = function (key, value) { this.cache[key] = value; }; var cacheDefault = { create: function create () { return new ObjectWithoutPrototypeCache() } }; // // API // var src$1 = memoize; var strategies = { variadic: strategyVariadic, monadic: strategyMonadic }; src$1.strategies = strategies; function unwrapExports (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var a = ["coords","download","href","name","rel","shape","target","type"]; var abbr = ["title"]; var applet = ["alt","height","name","width"]; var area = ["alt","coords","download","href","rel","shape","target","type"]; var audio = ["controls","loop","muted","preload","src"]; var base = ["href","target"]; var basefont = ["size"]; var bdo = ["dir"]; var blockquote = ["cite"]; var button = ["disabled","form","name","type","value"]; var canvas = ["height","width"]; var col = ["span","width"]; var colgroup = ["span","width"]; var data = ["value"]; var del = ["cite"]; var details = ["open"]; var dfn = ["title"]; var dialog = ["open"]; var embed = ["height","src","type","width"]; var fieldset = ["disabled","form","name"]; var font = ["size"]; var form = ["accept","action","method","name","target"]; var frame = ["name","scrolling","src"]; var frameset = ["cols","rows"]; var head = ["profile"]; var hr = ["size","width"]; var html = ["manifest"]; var iframe = ["height","name","sandbox","scrolling","src","width"]; var img = ["alt","height","name","sizes","src","width"]; var input = ["accept","alt","autoCapitalize","autoCorrect","autoSave","checked","defaultChecked","defaultValue","disabled","form","height","list","max","min","multiple","name","onChange","pattern","placeholder","required","results","size","src","step","title","type","value","width"]; var ins = ["cite"]; var keygen = ["challenge","disabled","form","name"]; var label = ["form"]; var li = ["type","value"]; var link = ["color","href","integrity","media","nonce","rel","scope","sizes","target","title","type"]; var map = ["name"]; var meta = ["content","name"]; var meter = ["high","low","max","min","optimum","value"]; var object = ["data","form","height","name","type","width"]; var ol = ["reversed","start","type"]; var optgroup = ["disabled","label"]; var option = ["disabled","label","selected","value"]; var output = ["form","name"]; var param = ["name","type","value"]; var pre = ["width"]; var progress = ["max","value"]; var q = ["cite"]; var script = ["async","defer","integrity","nonce","src","type"]; var select = ["defaultValue","disabled","form","multiple","name","onChange","required","size","value"]; var slot = ["name"]; var source = ["media","sizes","src","type"]; var style = ["media","nonce","title","type"]; var table = ["summary","width"]; var td = ["headers","height","scope","width"]; var textarea = ["autoCapitalize","autoCorrect","cols","defaultValue","disabled","form","name","onChange","placeholder","required","rows","value","wrap"]; var th = ["headers","height","scope","width"]; var track = ["default","kind","label","src"]; var ul = ["type"]; var video = ["controls","height","loop","muted","poster","preload","src","width"]; var svg = ["accentHeight","accumulate","additive","alignmentBaseline","allowReorder","alphabetic","amplitude","arabicForm","ascent","attributeName","attributeType","autoReverse","azimuth","baseFrequency","baseProfile","baselineShift","bbox","begin","bias","by","calcMode","capHeight","clip","clipPath","clipPathUnits","clipRule","color","colorInterpolation","colorInterpolationFilters","colorProfile","colorRendering","contentScriptType","contentStyleType","cursor","cx","cy","d","decelerate","descent","diffuseConstant","direction","display","divisor","dominantBaseline","dur","dx","dy","edgeMode","elevation","enableBackground","end","exponent","externalResourcesRequired","fill","fillOpacity","fillRule","filter","filterRes","filterUnits","floodColor","floodOpacity","focusable","fontFamily","fontSize","fontSizeAdjust","fontStretch","fontStyle","fontVariant","fontWeight","format","from","fx","fy","g1","g2","glyphName","glyphOrientationHorizontal","glyphOrientationVertical","glyphRef","gradientTransform","gradientUnits","hanging","height","horizAdvX","horizOriginX","ideographic","imageRendering","in","in2","intercept","k","k1","k2","k3","k4","kernelMatrix","kernelUnitLength","kerning","keyPoints","keySplines","keyTimes","lengthAdjust","letterSpacing","lightingColor","limitingConeAngle","local","markerEnd","markerHeight","markerMid","markerStart","markerUnits","markerWidth","mask","maskContentUnits","maskUnits","mathematical","mode","numOctaves","offset","opacity","operator","order","orient","orientation","origin","overflow","overlinePosition","overlineThickness","paintOrder","panose1","pathLength","patternContentUnits","patternTransform","patternUnits","pointerEvents","points","pointsAtX","pointsAtY","pointsAtZ","preserveAlpha","preserveAspectRatio","primitiveUnits","r","radius","refX","refY","renderingIntent","repeatCount","repeatDur","requiredExtensions","requiredFeatures","restart","result","rotate","rx","ry","scale","seed","shapeRendering","slope","spacing","specularConstant","specularExponent","speed","spreadMethod","startOffset","stdDeviation","stemh","stemv","stitchTiles","stopColor","stopOpacity","strikethroughPosition","strikethroughThickness","string","stroke","strokeDasharray","strokeDashoffset","strokeLinecap","strokeLinejoin","strokeMiterlimit","strokeOpacity","strokeWidth","surfaceScale","systemLanguage","tableValues","targetX","targetY","textAnchor","textDecoration","textLength","textRendering","to","transform","u1","u2","underlinePosition","underlineThickness","unicode","unicodeBidi","unicodeRange","unitsPerEm","vAlphabetic","vHanging","vIdeographic","vMathematical","values","vectorEffect","version","vertAdvY","vertOriginX","vertOriginY","viewBox","viewTarget","visibility","width","widths","wordSpacing","writingMode","x","x1","x2","xChannelSelector","xHeight","xlinkActuate","xlinkArcrole","xlinkHref","xlinkRole","xlinkShow","xlinkTitle","xlinkType","xmlBase","xmlLang","xmlSpace","xmlns","xmlnsXlink","y","y1","y2","yChannelSelector","z","zoomAndPan"]; var elements = {"html":["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","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","math","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"],"svg":["a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hkern","image","line","linearGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern"]}; var reactHtmlAttributes = { a: a, abbr: abbr, applet: applet, area: area, audio: audio, base: base, basefont: basefont, bdo: bdo, blockquote: blockquote, button: button, canvas: canvas, col: col, colgroup: colgroup, data: data, del: del, details: details, dfn: dfn, dialog: dialog, embed: embed, fieldset: fieldset, font: font, form: form, frame: frame, frameset: frameset, head: head, hr: hr, html: html, iframe: iframe, img: img, input: input, ins: ins, keygen: keygen, label: label, li: li, link: link, map: map, meta: meta, meter: meter, object: object, ol: ol, optgroup: optgroup, option: option, output: output, param: param, pre: pre, progress: progress, q: q, script: script, select: select, slot: slot, source: source, style: style, table: table, td: td, textarea: textarea, th: th, track: track, ul: ul, video: video, svg: svg, elements: elements, "*": ["about","acceptCharset","accessKey","allowFullScreen","allowTransparency","autoComplete","autoFocus","autoPlay","capture","cellPadding","cellSpacing","charSet","classID","className","colSpan","contentEditable","contextMenu","crossOrigin","dangerouslySetInnerHTML","datatype","dateTime","dir","draggable","encType","formAction","formEncType","formMethod","formNoValidate","formTarget","frameBorder","hidden","hrefLang","htmlFor","httpEquiv","icon","id","inlist","inputMode","is","itemID","itemProp","itemRef","itemScope","itemType","keyParams","keyType","lang","marginHeight","marginWidth","maxLength","mediaGroup","minLength","noValidate","prefix","property","radioGroup","readOnly","resource","role","rowSpan","scoped","seamless","security","spellCheck","srcDoc","srcLang","srcSet","style","suppressContentEditableWarning","tabIndex","title","typeof","unselectable","useMap","vocab","wmode"] }; var reactHtmlAttributes$1 = Object.freeze({ a: a, abbr: abbr, applet: applet, area: area, audio: audio, base: base, basefont: basefont, bdo: bdo, blockquote: blockquote, button: button, canvas: canvas, col: col, colgroup: colgroup, data: data, del: del, details: details, dfn: dfn, dialog: dialog, embed: embed, fieldset: fieldset, font: font, form: form, frame: frame, frameset: frameset, head: head, hr: hr, html: html, iframe: iframe, img: img, input: input, ins: ins, keygen: keygen, label: label, li: li, link: link, map: map, meta: meta, meter: meter, object: object, ol: ol, optgroup: optgroup, option: option, output: output, param: param, pre: pre, progress: progress, q: q, script: script, select: select, slot: slot, source: source, style: style, table: table, td: td, textarea: textarea, th: th, track: track, ul: ul, video: video, svg: svg, elements: elements, default: reactHtmlAttributes }); var reactHtmlAttributes$2 = ( reactHtmlAttributes$1 && reactHtmlAttributes ) || reactHtmlAttributes$1; var dist = createCommonjsModule(function (module, exports) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = reactHtmlAttributes$2; module.exports = reactHtmlAttributes$2; // for CommonJS compatibility }); var reactHTMLAttributes = unwrapExports(dist); /* * This is used to check if a property name is one of the React-specific * properties and determine if that property should be forwarded * to the React component */ /* Logic copied from ReactDOMUnknownPropertyHook */ var reactProps = ['children', 'dangerouslySetInnerHTML', 'key', 'ref', 'autoFocus', 'defaultValue', 'valueLink', 'defaultChecked', 'checkedLink', 'innerHTML', 'suppressContentEditableWarning', 'onFocusIn', 'onFocusOut', 'className', /* List copied from https://facebook.github.io/react/docs/events.html */ 'onCopy', 'onCut', 'onPaste', 'onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onFocus', 'onBlur', 'onChange', 'onInput', 'onInvalid', 'onSubmit', 'onClick', 'onContextMenu', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp', 'onSelect', 'onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'onScroll', 'onWheel', 'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded', 'onError', 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting', 'onLoad', 'onAnimationStart', 'onAnimationEnd', 'onAnimationIteration', 'onTransitionEnd', 'onCopyCapture', 'onCutCapture', 'onPasteCapture', 'onCompositionEndCapture', 'onCompositionStartCapture', 'onCompositionUpdateCapture', 'onKeyDownCapture', 'onKeyPressCapture', 'onKeyUpCapture', 'onFocusCapture', 'onBlurCapture', 'onChangeCapture', 'onInputCapture', 'onSubmitCapture', 'onClickCapture', 'onContextMenuCapture', 'onDoubleClickCapture', 'onDragCapture', 'onDragEndCapture', 'onDragEnterCapture', 'onDragExitCapture', 'onDragLeaveCapture', 'onDragOverCapture', 'onDragStartCapture', 'onDropCapture', 'onMouseDownCapture', 'onMouseEnterCapture', 'onMouseLeaveCapture', 'onMouseMoveCapture', 'onMouseOutCapture', 'onMouseOverCapture', 'onMouseUpCapture', 'onSelectCapture', 'onTouchCancelCapture', 'onTouchEndCapture', 'onTouchMoveCapture', 'onTouchStartCapture', 'onScrollCapture', 'onWheelCapture', 'onAbortCapture', 'onCanPlayCapture', 'onCanPlayThroughCapture', 'onDurationChangeCapture', 'onEmptiedCapture', 'onEncryptedCapture', 'onEndedCapture', 'onErrorCapture', 'onLoadedDataCapture', 'onLoadedMetadataCapture', 'onLoadStartCapture', 'onPauseCapture', 'onPlayCapture', 'onPlayingCapture', 'onProgressCapture', 'onRateChangeCapture', 'onSeekedCapture', 'onSeekingCapture', 'onStalledCapture', 'onSuspendCapture', 'onTimeUpdateCapture', 'onVolumeChangeCapture', 'onWaitingCapture', 'onLoadCapture', 'onAnimationStartCapture', 'onAnimationEndCapture', 'onAnimationIterationCapture', 'onTransitionEndCapture']; if (isPreact) { reactProps.push('autocomplete', 'autofocus', 'class', 'for', 'onDblClick', 'onSearch', 'slot', 'srcset'); } /* eslint max-lines:0, func-style:0 */ // copied from: // https://github.com/styled-components/styled-components/tree/ // 956e8210b6277860c89404f9cb08735f97eaa7e1/src/utils/validAttr.js /* Trying to avoid the unknown-prop errors on glamorous components by filtering by React's attribute whitelist. */ var globalReactHtmlProps = reactHTMLAttributes['*']; var supportedSVGTagNames = reactHTMLAttributes.elements.svg; var supportedHtmlTagNames = reactHTMLAttributes.elements.html; // these are valid attributes that have the // same name as CSS properties, and is used // for css overrides API var cssProps = ['color', 'height', 'width']; /* From DOMProperty */ var ATTRIBUTE_NAME_START_CHAR = // eslint-disable-next-line max-len ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; // eslint-disable-next-line max-len var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040'; var isCustomAttribute = RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$')); var isSvgTag = function (tagName) { return ( // in our context, we only say that SVG tags are SVG // if they are not also HTML. // See https://github.com/paypal/glamorous/issues/245 // the svg tag will always be treated as svg for // er... obvious reasons tagName === 'svg' || supportedHtmlTagNames.indexOf(tagName) === -1 && supportedSVGTagNames.indexOf(tagName) !== -1 ); }; var isHtmlProp = function (name, tagName) { var elementAttributes = void 0; if (isSvgTag(tagName)) { // all SVG attributes supported by React are grouped under 'svg' elementAttributes = reactHTMLAttributes.svg; } else { elementAttributes = reactHTMLAttributes[tagName] || []; } return globalReactHtmlProps.indexOf(name) !== -1 || elementAttributes.indexOf(name) !== -1; }; var isCssProp = function (name) { return cssProps.indexOf(name) !== -1; }; var isReactProp = function (name) { return reactProps.indexOf(name) !== -1; }; // eslint-disable-next-line complexity var shouldForwardProperty = function (tagName, name) { return typeof tagName !== 'string' || (isHtmlProp(name, tagName) || isReactProp(name) || isCustomAttribute(name.toLowerCase())) && (!isCssProp(name) || isSvgTag(tagName)); }; var shouldForwardProperty$1 = src$1(shouldForwardPropert