UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

190 lines (163 loc) 9.39 kB
import _keys from "lodash/keys"; import _omit from "lodash/omit"; import _first from "lodash/first"; import _reject from "lodash/reject"; import _pick from "lodash/pick"; import _values from "lodash/values"; import _flatten from "lodash/flatten"; import _isNil from "lodash/isNil"; import _reduce from "lodash/reduce"; import _castArray from "lodash/castArray"; import _includes from "lodash/includes"; import _filter from "lodash/filter"; import _isUndefined from "lodash/isUndefined"; import _mapValues from "lodash/mapValues"; 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; } function _defineProperty(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; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } import React from 'react'; import createReactClass from 'create-react-class'; import PropTypes from 'react-peek/prop-types'; import { isPlainObjectOrEsModule, omitFunctionPropsDeep } from './state-management'; // creates a React component export function createClass(spec) { var _spec$_isPrivate = spec._isPrivate, _isPrivate = _spec$_isPrivate === void 0 ? false : _spec$_isPrivate, getDefaultProps = spec.getDefaultProps, _spec$statics = spec.statics, statics = _spec$statics === void 0 ? {} : _spec$statics, _spec$components = spec.components, components = _spec$components === void 0 ? {} : _spec$components, _spec$reducers = spec.reducers, reducers = _spec$reducers === void 0 ? {} : _spec$reducers, _spec$selectors = spec.selectors, selectors = _spec$selectors === void 0 ? {} : _spec$selectors, _spec$initialState = spec.initialState, initialState = _spec$initialState === void 0 ? getDefaultProps && omitFunctionPropsDeep(getDefaultProps.apply(spec)) : _spec$initialState, _spec$propName = spec.propName, propName = _spec$propName === void 0 ? null : _spec$propName, _spec$propTypes = spec.propTypes, propTypes = _spec$propTypes === void 0 ? {} : _spec$propTypes, _spec$render = spec.render, render = _spec$render === void 0 ? function () { return null; } : _spec$render, restDefinition = _objectWithoutProperties(spec, ["_isPrivate", "getDefaultProps", "statics", "components", "reducers", "selectors", "initialState", "propName", "propTypes", "render"]); var propTypeValidators = _objectSpread(_objectSpread({}, propTypes), _mapValues(spec.components, function (componentValue, componentKey) { return PropTypes.any; })); // Intentionally keep this object type inferred so it can be passed to // `createReactClass` var newDefinition = _objectSpread(_objectSpread({ getDefaultProps: getDefaultProps }, restDefinition), {}, { statics: _objectSpread(_objectSpread(_objectSpread({}, statics), components), {}, { _isPrivate: _isPrivate, reducers: reducers, selectors: selectors, initialState: initialState, propName: propName }), propTypes: propTypeValidators, render: render }); if (!_isUndefined(newDefinition.statics)) { newDefinition.statics.definition = newDefinition; } var newClass = createReactClass(newDefinition); // This conditional (and breaking change) was introduced to help us move from // legacy React classes to functional components & es6 classes which lack // `getDefaultProps`. if (newClass.getDefaultProps) { newClass.defaultProps = newClass.getDefaultProps(); delete newClass.getDefaultProps; } return newClass; } // return all elements matching the specified types export function filterTypes(children, types) { if (types === undefined) return []; return _filter(React.Children.toArray(children), function (element) { return /*#__PURE__*/React.isValidElement(element) && _includes(_castArray(types), element.type); }); } // return all elements found in props and children of the specified types export function findTypes(props, types) { if (types === undefined) { return []; } // get elements from props (using types.propName) var elementsFromProps = _reduce(_castArray(types), function (acc, type) { return _isNil(type.propName) ? [] : createElements(type, _flatten(_values(_pick(props, type.propName)))); }, []); if (props.children === undefined) { return elementsFromProps; } // return elements from props and elements from children return elementsFromProps.concat(filterTypes(props.children, types)); } // return all elements found in props and children of the specified types // export function findTypes<P2>( // props: { children?: React.ReactNode }, // types?: TypesType<P2> // ): React.ReactNode[] { // if (types === undefined) { // return []; // } // // get elements from props (using types.propName) // const elementsFromProps: React.ReactNode[] = _.reduce( // _.castArray<any>(types), // (acc: React.ReactNode[], type): React.ReactNode[] => { // return _.isNil(type.propName) // ? [] // : createElements( // type, // _.flatten(_.values(_.pick(props, type.propName))) // ); // }, // [] // ); // if (props.children === undefined) { // return elementsFromProps; // } // // return elements from props and elements from children // return elementsFromProps.concat(filterTypes<P2>(props.children, types)); // } // return all elements not matching the specified types export function rejectTypes(children, types) { types = [].concat(types); // coerce to Array return _reject(React.Children.toArray(children), function (element) { return /*#__PURE__*/React.isValidElement(element) && _includes(types, element.type); }); } // return an array of elements (of the given type) for each of the values export function createElements(type) { var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; return _reduce(values, function (elements, typeValue) { if ( /*#__PURE__*/React.isValidElement(typeValue) && typeValue.type === type) { return elements.concat(typeValue); } else if (isPlainObjectOrEsModule(typeValue) && ! /*#__PURE__*/React.isValidElement(typeValue)) { return elements.concat( /*#__PURE__*/React.createElement(type, typeValue)); } else if (_isUndefined(typeValue)) { return elements; } else { return elements.concat( /*#__PURE__*/React.createElement(type, null, typeValue)); } }, []); } // return the first element found in props and children of the specificed type(s) export function getFirst(props, types, defaultValue) { return _first(findTypes(props, types)) || defaultValue; } // Omit props defined in propTypes of the given type and any extra keys given // in third argument // // We also have a "magic" prop that's always excluded called `callbackId`. That // prop can be used to identify a component in a list without having to create // extra closures. // // Note: The Partial<P> type is referring to the props passed into the omitProps, // not the props defined on the component. export function omitProps(props, component) { var keys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var targetIsDOMElement = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; // We only want to exclude the `callbackId` key when we're omitting props // destined for a dom element var additionalOmittedKeys = targetIsDOMElement ? ['initialState', 'callbackId'] : ['initialState']; // this is to support non-createClass components that we've converted to TypeScript if (component === undefined) { return _omit(props, keys.concat(additionalOmittedKeys)); } return _omit(props, _keys(component.propTypes).concat(keys).concat(additionalOmittedKeys)); }