UNPKG

baseui

Version:

A React Component library implementing the Base design language

191 lines (173 loc) 7.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getOverride = getOverride; exports.getOverrideProps = getOverrideProps; exports.getOverrides = getOverrides; exports.mergeConfigurationOverrides = mergeConfigurationOverrides; exports.mergeOverride = mergeOverride; exports.mergeOverrides = mergeOverrides; exports.toObjectOverride = toObjectOverride; exports.useOverrides = useOverrides; var React = _interopRequireWildcard(require("react")); var _reactIs = require("react-is"); var _deepMerge = _interopRequireDefault(require("../utils/deep-merge")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } /* Copyright (c) Uber Technologies, Inc. This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. */ // Object -> any // eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-explicit-any /** * Given an override argument, returns the component implementation override if it exists */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function getOverride(_override) { if ((0, _reactIs.isValidElementType)(_override)) { return _override; } // Check if override is OverrideObjectT if (_override && typeof _override === 'object') { // Remove this 'any' once this flow issue is fixed: // https://github.com/facebook/flow/issues/6666 // eslint-disable-next-line @typescript-eslint/no-explicit-any return _override.component; } // null/undefined return _override; } /** * Given an override argument, returns the override props that should be passed * to the component when rendering it. */ function getOverrideProps(_override) { if (_override && typeof _override === 'object') { if (typeof _override.props === 'object') { //@ts-expect-error return { ..._override.props, $style: _override.style }; } else { //@ts-expect-error return { $style: _override.style }; } } //@ts-expect-error return {}; } /** * Coerces an override argument into an override object * (sometimes it is just an override component) */ function toObjectOverride(_override) { if ((0, _reactIs.isValidElementType)(_override)) { return { // eslint-disable-next-line @typescript-eslint/no-explicit-any component: _override }; } // Flow can't figure out that typeof 'function' above will // catch React.StatelessFunctionalComponent // (probably related to https://github.com/facebook/flow/issues/6666) // eslint-disable-next-line @typescript-eslint/no-explicit-any return _override || {}; } /** * Get a convenient override array that will always have [component, props] */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function getOverrides( // eslint-disable-next-line @typescript-eslint/no-explicit-any _override, // eslint-disable-next-line @typescript-eslint/no-explicit-any defaultComponent) { const Component = getOverride(_override) || defaultComponent; if (_override && typeof _override === 'object' && typeof _override.props === 'function') { // TODO(v11) if (process.env.NODE_ENV !== "production") { console.warn('baseui:Overrides Props as a function will be removed in the next major version. Override the whole component instead. ' + 'See https://baseweb.design/guides/understanding-overrides/#override-the-entire-subcomponent'); } const DynamicOverride = /*#__PURE__*/React.forwardRef((props, ref) => { const mappedProps = _override.props(props); const nextProps = getOverrideProps({ ..._override, props: mappedProps }); return /*#__PURE__*/React.createElement(Component, _extends({ ref: ref }, nextProps)); }); DynamicOverride.displayName = Component.displayName; // @ts-expect-error return [DynamicOverride, {}]; } const props = getOverrideProps(_override); return [Component, props]; } /** * Merges two overrides objects – this is useful if you want to inject your own * overrides into a child component, but also accept further overrides from * from upstream. See `mergeOverride` below. */ function mergeOverrides(target = {}, source = {}) { const merged = Object.assign({}, target, source); const allIdentifiers = Object.keys(merged); // const allIdentifiers = Object.keys({...target, ...source}); return allIdentifiers.reduce((acc, name) => { // @ts-ignore acc[name] = mergeOverride(toObjectOverride(target[name]), toObjectOverride(source[name])); return acc; }, {}); } /** * Merges two override objects using the following behavior: * - Component implementation from the source (parent) replaces target * - Props and styles are both deep merged */ function mergeOverride(target, source) { // Shallow merge should handle `component` const merged = { ...target, ...source }; if (target.props && source.props) { merged.props = mergeConfigurationOverrides(target.props, source.props); } if (target.style && source.style) { merged.style = mergeConfigurationOverrides(target.style, source.style); } return merged; } /** * Since style or props overrides can be an object *or* a function, we need to handle * the case that one of them is a function. We do this by returning a new * function that deep merges the result of each style override */ function mergeConfigurationOverrides(target, source) { // Simple case of both objects if (typeof target === 'object' && typeof source === 'object') { return (0, _deepMerge.default)({}, target, source); } // At least one is a function, return a new composite function return (...args) => { return (0, _deepMerge.default)({}, typeof target === 'function' ? target(...args) : target, typeof source === 'function' ? source(...args) : source); }; } // Lil' hook for memoized unpacking of overrides function useOverrides(defaults, overrides = {}) { return React.useMemo(() => Object.keys(defaults).reduce((obj, key) => { obj[key] = getOverrides(overrides[key], defaults[key]); return obj; }, {}), [overrides]); }