UNPKG

@gitlab/ui

Version:
98 lines (88 loc) 4.14 kB
import { PROP_TYPE_ANY } from '../constants/props'; import { cloneDeep } from './clone-deep'; import { getComponentConfig } from './config'; import { identity } from './identity'; import { isUndefined, isObject, isArray, isFunction } from './inspect'; import { hasOwnProperty, clone, keys } from './object'; import { upperFirst } from './string'; // Suffix can be a falsey value so nothing is appended to string // (helps when looping over props & some shouldn't change) // Use data last parameters to allow for currying const suffixPropName = (suffix, value) => value + (suffix ? upperFirst(suffix) : ''); // Generates a prop object const makeProp = function () { let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : PROP_TYPE_ANY; let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; let requiredOrValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; let validator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; const required = requiredOrValidator === true; validator = required ? validator : requiredOrValidator; return { ...(type ? { type } : {}), ...(required ? { required } : isUndefined(value) ? {} : { default: isObject(value) ? () => value : value }), ...(isUndefined(validator) ? {} : { validator }) }; }; // Copies props from one array/object to a new array/object // Prop values are also cloned as new references to prevent possible // mutation of original prop object values // Optionally accepts a function to transform the prop name const copyProps = function (props) { let transformFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : identity; if (isArray(props)) { return props.map(transformFn); } const copied = {}; for (const prop in props) { /* istanbul ignore else */ if (hasOwnProperty(props, prop)) { // If the prop value is an object, do a shallow clone // to prevent potential mutations to the original object copied[transformFn(prop)] = isObject(props[prop]) ? clone(props[prop]) : props[prop]; } } return copied; }; // Given an array of properties or an object of property keys, // plucks all the values off the target object, returning a new object // that has props that reference the original prop values const pluckProps = function (keysToPluck, objToPluck) { let transformFn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : identity; return (isArray(keysToPluck) ? keysToPluck.slice() : keys(keysToPluck)).reduce((memo, prop) => { memo[transformFn(prop)] = objToPluck[prop]; return memo; }, {}); }; // Make a prop object configurable by global configuration // Replaces the current `default` key of each prop with a `getComponentConfig()` // call that falls back to the current default value of the prop const makePropConfigurable = (prop, key, componentKey) => ({ ...cloneDeep(prop), default: function bvConfigurablePropDefault() { const value = getComponentConfig(componentKey, key, prop.default); return isFunction(value) ? value() : value; } }); // Make a props object configurable by global configuration // Replaces the current `default` key of each prop with a `getComponentConfig()` // call that falls back to the current default value of the prop const makePropsConfigurable = (props, componentKey) => keys(props).reduce((result, key) => ({ ...result, [key]: makePropConfigurable(props[key], key, componentKey) }), {}); // Get function name we use in `makePropConfigurable()` // for the prop default value override to compare // against in `hasPropFunction()` const configurablePropDefaultFnName = makePropConfigurable({}, '', '').default.name; // Detect wether the given value is currently a function // and isn't the props default function const hasPropFunction = fn => isFunction(fn) && fn.name && fn.name !== configurablePropDefaultFnName; export { copyProps, hasPropFunction, makeProp, makePropConfigurable, makePropsConfigurable, pluckProps, suffixPropName };