glamorous
Version:
React component styling solved
1,556 lines (1,357 loc) • 62.8 kB
JavaScript
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