UNPKG

native-base

Version:

Essential cross-platform UI components for React Native

340 lines (270 loc) 13.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.usePropsResolution = usePropsResolution; exports.usePropsResolutionWithComponentTheme = void 0; var _lodash = _interopRequireDefault(require("lodash.get")); var _lodash2 = _interopRequireDefault(require("lodash.merge")); var _lodash3 = _interopRequireDefault(require("lodash.isempty")); var _reactNative = require("react-native"); var _useNativeBase = require("../useNativeBase"); var _colorMode = require("../../core/color-mode"); var _tools = require("../../theme/tools"); var _useBreakpointResolvedProps = require("../useBreakpointResolvedProps"); var _propsFlattener = require("./propsFlattener"); var _useResponsiveSSRProps = require("../useResponsiveSSRProps"); var _react = _interopRequireDefault(require("react")); var _ResponsiveQueryProvider = require("../../utils/useResponsiveQuery/ResponsiveQueryProvider"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const SPREAD_PROP_SPECIFICITY_ORDER = ['p', 'padding', 'px', 'py', 'pt', 'pb', 'pl', 'pr', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', 'm', 'margin', 'mx', 'my', 'mt', 'mb', 'ml', 'mr', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight']; const FINAL_SPREAD_PROPS = ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight']; const MARGIN_MAP = { mx: ['marginRight', 'marginLeft'], my: ['marginTop', 'marginBottom'], mt: ['marginTop'], mb: ['marginBottom'], mr: ['marginRight'], ml: ['marginLeft'] }; MARGIN_MAP.margin = [...MARGIN_MAP.mx, ...MARGIN_MAP.my]; MARGIN_MAP.m = MARGIN_MAP.margin; MARGIN_MAP.marginTop = MARGIN_MAP.mt; MARGIN_MAP.marginBottom = MARGIN_MAP.mb; MARGIN_MAP.marginLeft = MARGIN_MAP.ml; MARGIN_MAP.marginRight = MARGIN_MAP.mr; const PADDING_MAP = { px: ['paddingRight', 'paddingLeft'], py: ['paddingTop', 'paddingBottom'], pt: ['paddingTop'], pb: ['paddingBottom'], pr: ['paddingRight'], pl: ['paddingLeft'] }; PADDING_MAP.padding = [...PADDING_MAP.px, ...PADDING_MAP.py]; PADDING_MAP.p = PADDING_MAP.padding; PADDING_MAP.paddingTop = PADDING_MAP.pt; PADDING_MAP.paddingBottom = PADDING_MAP.pb; PADDING_MAP.paddingLeft = PADDING_MAP.pl; PADDING_MAP.paddingRight = PADDING_MAP.pr; const SPREAD_PROP_SPECIFICITY_MAP = { ...PADDING_MAP, ...MARGIN_MAP }; function propsSpreader(incomingProps, incomingSpecifity) { const flattenedDefaultProps = { ...incomingProps }; const specificity = {}; SPREAD_PROP_SPECIFICITY_ORDER.forEach(prop => { if (prop in flattenedDefaultProps) { const val = incomingProps[prop] || flattenedDefaultProps[prop]; if (!FINAL_SPREAD_PROPS.includes(prop)) { delete flattenedDefaultProps[prop]; specificity[prop] = incomingSpecifity[prop]; } SPREAD_PROP_SPECIFICITY_MAP[prop].forEach(newProp => { if ((0, _propsFlattener.compareSpecificity)(specificity[newProp], specificity[prop])) { specificity[newProp] = incomingSpecifity[prop]; flattenedDefaultProps[newProp] = val; } }); } }); return (0, _lodash2.default)({}, flattenedDefaultProps); } /** * @summary Combines provided porps with component's theme props and resloves them. * @arg {string} component - Name of the component. * @arg {object} incomingProps - Props passed by the user. * @arg {object} state - dependent states. * @arg {object} config - configuration for resolution. Accepts key like ignoreProps, resolveResponsively. * @returns {object} Resolved and flattened props. */ function usePropsResolution(component, incomingProps, state, config) { var _config$componentThem; const { theme } = (0, _useNativeBase.useNativeBase)(); const componentTheme = (_config$componentThem = config === null || config === void 0 ? void 0 : config.componentTheme) !== null && _config$componentThem !== void 0 ? _config$componentThem : (0, _lodash.default)(theme, "components.".concat(component), {}); if (process.env.NODE_ENV === 'development' && incomingProps.debug) { /* eslint-disable-next-line */ console.log("%c".concat(component), 'background: #d97706; color: #111; font-weight: 700; padding: 2px 8px;'); /* eslint-disable-next-line */ console.log("%cusePropsResolution", 'background: #4b5563; color: #d97706; font-weight: 700; padding: 2px 8px;'); /* eslint-disable-next-line */ console.log('%c incomingProps: ', 'color: #4ade80; font-weight: 700;', incomingProps); /* eslint-disable-next-line */ console.log('%c state: ', 'color: #4ade80; font-weight: 700;', state); /* eslint-disable-next-line */ console.log('%c componentTheme: ', 'color: #4ade80; font-weight: 700;', componentTheme); } const resolvedProps = usePropsResolutionWithComponentTheme(componentTheme, incomingProps, state, config); // Not Resolve theme props and pseudo props if (incomingProps !== null && incomingProps !== void 0 && incomingProps.INTERNAL_notResolveThemeAndPseudoProps) { delete incomingProps.INTERNAL_notResolveThemeAndPseudoProps; return incomingProps; } if (process.env.NODE_ENV === 'development' && incomingProps.debug) { /* eslint-disable-next-line */ console.log('%c resolvedProps: ', 'color: #22d3ee; font-weight: 700;', resolvedProps); } return resolvedProps; } const usePropsResolutionWithComponentTheme = (componentTheme, incomingProps, state, config) => { const modifiedPropsForSSR = (0, _useResponsiveSSRProps.useResponsiveSSRProps)(incomingProps); const [ignoredProps, cleanIncomingProps] = (0, _tools.extractInObject)(modifiedPropsForSSR, ['children', 'onPress', 'icon', 'onOpen', 'onClose'].concat((config === null || config === void 0 ? void 0 : config.ignoreProps) || [])); const responsiveQueryContext = _react.default.useContext(_ResponsiveQueryProvider.ResponsiveQueryContext); const disableCSSMediaQueries = responsiveQueryContext.disableCSSMediaQueries; const resolveResponsively = ['colorScheme', 'size', 'variant', ...((config === null || config === void 0 ? void 0 : config.resolveResponsively) || [])]; const { theme } = (0, _useNativeBase.useNativeBase)(); const colorModeProps = (0, _colorMode.useColorMode)(); const extendedTheme = []; if (config !== null && config !== void 0 && config.extendTheme) { config === null || config === void 0 ? void 0 : config.extendTheme.map(componentName => { extendedTheme.push((0, _lodash.default)(theme, "components.".concat(componentName), {})); }); } if (!(0, _lodash3.default)(componentTheme)) extendedTheme.push(componentTheme); const resolveComponentTheme = (themeType, providedTheme) => { try { if (themeType[1]) { return typeof providedTheme[themeType[0]][themeType[1]] !== 'function' ? providedTheme[themeType[0]][themeType[1]] : providedTheme[themeType[0]][themeType[1]]({ theme, ...incomingWithDefaultProps, ...colorModeProps }); } else { return typeof providedTheme[themeType[0]] !== 'function' ? providedTheme[themeType[0]] : providedTheme[themeType[0]]({ theme, ...incomingWithDefaultProps, ...colorModeProps }); } } catch { return {}; } }; const callPropsFlattener = (targetProps = {}, latestSpecifictyMap = {}, specificity = 1) => { return (0, _propsFlattener.propsFlattener)({ props: process.env.NODE_ENV === 'development' && cleanIncomingProps.debug ? { ...targetProps, debug: true } : targetProps, platform: _reactNative.Platform.OS, colormode: colorModeProps.colorMode, state: state || {}, currentSpecificityMap: latestSpecifictyMap, previouslyFlattenProps: flattenProps || {}, cascadePseudoProps: config === null || config === void 0 ? void 0 : config.cascadePseudoProps }, specificity); }; // STEP 1: combine default props and incoming props const incomingWithDefaultProps = (0, _lodash2.default)({}, componentTheme.defaultProps || {}, cleanIncomingProps); // STEP 1.5: resolving component theme let combinedBaseStyle = {}; let combinedVariantStyle = {}; let combinedSizeStyle = {}; extendedTheme.map(extededComponentTheme => { if (extededComponentTheme.baseStyle) { combinedBaseStyle = { ...combinedBaseStyle, ...resolveComponentTheme(['baseStyle'], extededComponentTheme) }; } if (incomingWithDefaultProps.variant) { if (extededComponentTheme.variants) { combinedVariantStyle = { ...combinedVariantStyle, ...resolveComponentTheme(['variants', incomingWithDefaultProps.variant], extededComponentTheme) }; } } if (incomingWithDefaultProps.size && extededComponentTheme !== null && extededComponentTheme !== void 0 && extededComponentTheme.sizes && extededComponentTheme !== null && extededComponentTheme !== void 0 && extededComponentTheme.sizes[incomingWithDefaultProps.size]) { if (typeof extededComponentTheme.sizes[incomingWithDefaultProps.size] === 'string' || typeof extededComponentTheme.sizes[incomingWithDefaultProps.size] === 'number') { incomingWithDefaultProps.size = extededComponentTheme.sizes[incomingWithDefaultProps.size]; } else { combinedSizeStyle = { ...combinedSizeStyle, ...resolveComponentTheme(['sizes', incomingWithDefaultProps.size], extededComponentTheme) }; incomingWithDefaultProps.size = undefined; } } }); // STEP 2: flatten them if (process.env.NODE_ENV === 'development' && cleanIncomingProps.debug) { /* eslint-disable-next-line */ console.log("%cFlattening incoming and Default", 'background: #4b5563; color: #FFF; font-weight: 700; padding: 2px 8px;'); } //TODO: hack let flattenProps, specificityMap; [flattenProps, specificityMap] = callPropsFlattener(incomingWithDefaultProps, {}, 2); const responsiveProps = {}; if (disableCSSMediaQueries) { // STEP 2.5: resolving responsive props resolveResponsively.map(propsName => { if (flattenProps[propsName]) { // @ts-ignore responsiveProps[propsName] = flattenProps[propsName]; } }); } if (resolveResponsively.includes('direction')) { const propName = 'direction'; if (flattenProps[propName]) { // @ts-ignore responsiveProps[propName] = flattenProps[propName]; } } const responsivelyResolvedProps = (0, _useBreakpointResolvedProps.useBreakpointResolvedProps)(responsiveProps); flattenProps = { ...flattenProps, ...responsivelyResolvedProps }; // STEP 3: Pass it to baseStyle, then variant and then size and resolve them. // NOTE: Resoloving baseStyle let flattenBaseStyle, baseSpecificityMap; if (combinedBaseStyle) { if (process.env.NODE_ENV === 'development' && cleanIncomingProps.debug) { /* eslint-disable-next-line */ console.log("%cFlattening baseStyle", 'background: #4b5563; color: #eee; font-weight: 700; padding: 2px 8px;'); } [flattenBaseStyle, baseSpecificityMap] = callPropsFlattener(combinedBaseStyle, specificityMap); } // NOTE: Resolving variants let flattenVariantStyle, variantSpecificityMap; // Extracting props from variant if (combinedVariantStyle) { if (process.env.NODE_ENV === 'development' && cleanIncomingProps.debug) { /* eslint-disable-next-line */ console.log("%cFlattening variantStyle", 'background: #4b5563; color: #FFF; font-weight: 700; padding: 2px 8px;'); } [flattenVariantStyle, variantSpecificityMap] = callPropsFlattener(combinedVariantStyle, baseSpecificityMap || specificityMap); // We remove variant from original props if we found it in the componentTheme //@ts-ignore flattenProps.variant = undefined; } // NOTE: Resolving size let flattenSizeStyle, sizeSpecificityMap; // Extracting props from size if (combinedSizeStyle) { if (process.env.NODE_ENV === 'development' && cleanIncomingProps.debug) { /* eslint-disable-next-line */ console.log("%cFlattening sizeStyle", 'background: #4b5563; color: #FFF; font-weight: 700; padding: 2px 8px;'); } [flattenSizeStyle, sizeSpecificityMap] = callPropsFlattener(combinedSizeStyle, variantSpecificityMap || baseSpecificityMap || specificityMap); } // STEP 4: merge const defaultStyles = (0, _lodash2.default)({}, flattenBaseStyle, flattenVariantStyle, flattenSizeStyle); /*Resolve all the internal used Pseudo Props*/ const resolvePseudoProps = (flatPseudoProp, baseStylePseudoProp) => /** Props coming from Pseudo inside defaultStyles(baseStyle) */ { for (const prop in flatPseudoProp) { baseStylePseudoProp[prop] = flatPseudoProp[prop]; /* Replace all the similar prop from from internal props */ } return baseStylePseudoProp; }; for (const prop in defaultStyles) { if (prop.startsWith('_') && flattenProps.hasOwnProperty(prop)) { /*Resolve all the internal used Pseudo Props*/ defaultStyles[prop] = resolvePseudoProps(flattenProps[prop], defaultStyles[prop]); } delete flattenProps[prop]; } const defaultSpecificity = (0, _lodash2.default)({}, specificityMap, baseSpecificityMap, variantSpecificityMap, sizeSpecificityMap); flattenProps = propsSpreader({ ...defaultStyles, ...flattenProps }, defaultSpecificity); const resolvedProps = (0, _tools.omitUndefined)({ ...flattenProps, ...ignoredProps }); // STEP 5: Return return resolvedProps; }; exports.usePropsResolutionWithComponentTheme = usePropsResolutionWithComponentTheme; //# sourceMappingURL=usePropsResolution.js.map