UNPKG

substyle

Version:

Universal styling for reusable React components

90 lines (74 loc) 5.28 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } import invariant from 'invariant'; import coerceSelection from './coerceSelection'; import defaultPropsDecorator from './defaultPropsDecorator'; import { isElement, isModifier } from './filterKeys'; import memoize from './memoize'; import { hoistModifierStylesRecursive, pickNestedStyles } from './pickStyles'; import { compact, isPlainObject, keys, merge, values } from './utils'; var guessBaseClassName = function guessBaseClassName(classNames) { // all class names must start with the same prefix: the component's base class name // which will finally go to the container element var firstKey = classNames && keys(classNames)[0]; return firstKey && firstKey.split('__')[0].split('--')[0]; }; var deriveClassNames = function deriveClassNames(className, elementKeys, modifierKeys) { // do not derive class names, if the user did not specify any class name if (!className) { return undefined; } // derive class names based using the passed modifier/element keys var firstClassName = className.split(' ')[0]; var derivedClassNames = [].concat(_toConsumableArray(elementKeys.length === 0 ? modifierKeys.map(function (key) { return "".concat(firstClassName, "--").concat(key.substring(1)); }) : []), _toConsumableArray(elementKeys.map(function (key) { return "".concat(firstClassName, "__").concat(key); }))); // also use the provided `className` if there is no sub-element selection return elementKeys.length === 0 ? [className].concat(_toConsumableArray(derivedClassNames)) : derivedClassNames; }; function createSubstyle(_ref) { var style = _ref.style, className = _ref.className, classNames = _ref.classNames; var propsDecorator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultPropsDecorator; var baseClassName = className || guessBaseClassName(classNames) || (style === null || style === void 0 ? void 0 : style.className); var substyle = typeof style === 'function' ? style : memoize(function (select, defaultStyle) { var selectedKeys = coerceSelection(select); invariant(Array.isArray(selectedKeys), 'First parameter must be a string, an array of strings, ' + 'a plain object with boolean values, or a falsy value.'); invariant(!defaultStyle || isPlainObject(defaultStyle), 'Optional second parameter must be a plain object.'); var modifierKeys = selectedKeys.filter(isModifier); var elementKeys = selectedKeys.filter(isElement); var collectElementStyles = elementKeys.length > 0 ? function (fromStyle) { return values(pickNestedStyles(fromStyle, elementKeys)); } : function (fromStyle) { return [fromStyle]; }; var collectSelectedStyles = function collectSelectedStyles() { var fromStyle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return collectElementStyles(hoistModifierStylesRecursive(fromStyle, modifierKeys)); }; var derivedClassNames = deriveClassNames(baseClassName, elementKeys, modifierKeys); return createSubstyle(_objectSpread(_objectSpread(_objectSpread({}, (style || defaultStyle) && { style: merge.apply(void 0, [{}].concat(_toConsumableArray(collectSelectedStyles(defaultStyle)), _toConsumableArray(collectSelectedStyles(style)))) }), derivedClassNames && { className: derivedClassNames.join(' ') }), classNames && { classNames: classNames }), propsDecorator); }); var styleProps = _objectSpread({}, typeof style === 'function' ? style : { style: style }); var classNameSplit = _toConsumableArray(new Set([].concat(_toConsumableArray(styleProps.className ? styleProps.className.split(' ') : []), _toConsumableArray(baseClassName ? baseClassName.split(' ') : [])))); var mappedClassNames = classNames ? compact(classNameSplit.map(function (singleClassName) { return classNames[singleClassName]; })) : classNameSplit; var propsForSpread = propsDecorator(_objectSpread(_objectSpread({}, styleProps), mappedClassNames.length > 0 ? { className: mappedClassNames.join(' ') } : {})); // assign `style`, `className`, and/or any props added by the decorator to the return function object Object.assign(substyle, propsForSpread); return substyle; } export default createSubstyle;