UNPKG

@hakuna-matata-ui/system

Version:
348 lines (286 loc) 12.2 kB
import { useColorMode } from '@hakuna-matata-ui/color-mode'; export * from '@hakuna-matata-ui/color-mode'; import { toCSSVar, css, propNames, isStyleProp } from '@hakuna-matata-ui/styled-system'; export * from '@hakuna-matata-ui/styled-system'; import { ThemeProvider as ThemeProvider$1, Global, ThemeContext } from '@emotion/react'; export { keyframes } from '@emotion/react'; import { memoizedGet, runIfFn, omit, filterUndefined, mergeWith, objectFilter } from '@hakuna-matata-ui/utils'; import * as React from 'react'; import { useRef, useMemo } from 'react'; import isEqual from 'react-fast-compare'; import { createContext } from '@hakuna-matata-ui/react-utils'; import _styled from '@emotion/styled'; function _extends() { _extends = Object.assign || 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); } var ThemeProvider = function ThemeProvider(props) { var _props$cssVarsRoot = props.cssVarsRoot, cssVarsRoot = _props$cssVarsRoot === void 0 ? ":host, :root" : _props$cssVarsRoot, theme = props.theme, children = props.children; var computedTheme = React.useMemo(function () { return toCSSVar(theme); }, [theme]); return /*#__PURE__*/React.createElement(ThemeProvider$1, { theme: computedTheme }, /*#__PURE__*/React.createElement(Global, { styles: function styles(theme) { var _ref; return _ref = {}, _ref[cssVarsRoot] = theme.__cssVars, _ref; } }), children); }; function useTheme() { var theme = React.useContext(ThemeContext); if (!theme) { throw Error("useTheme: `theme` is undefined. Seems you forgot to wrap your app in `<ChakraProvider />` or `<ThemeProvider />`"); } return theme; } var _createContext = createContext({ name: "StylesContext", errorMessage: "useStyles: `styles` is undefined. Seems you forgot to wrap the components in `<StylesProvider />` " }), StylesProvider = _createContext[0], useStyles = _createContext[1]; /** * Applies styles defined in `theme.styles.global` globally * using emotion's `Global` component */ var GlobalStyle = function GlobalStyle() { var _useColorMode = useColorMode(), colorMode = _useColorMode.colorMode; return /*#__PURE__*/React.createElement(Global, { styles: function styles(theme) { var styleObjectOrFn = memoizedGet(theme, "styles.global"); var globalStyles = runIfFn(styleObjectOrFn, { theme: theme, colorMode: colorMode }); if (!globalStyles) return undefined; var styles = css(globalStyles)(theme); return styles; } }); }; /** * Carefully selected html elements for chakra components. * This is mostly for `chakra.<element>` syntax. */ var domElements = ["a", "b", "article", "aside", "blockquote", "button", "caption", "cite", "circle", "code", "dd", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hr", "img", "input", "kbd", "label", "li", "main", "mark", "nav", "ol", "p", "path", "pre", "q", "rect", "s", "svg", "section", "select", "strong", "small", "span", "sub", "sup", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "tr", "ul"]; function omitThemingProps(props) { return omit(props, ["styleConfig", "size", "variant", "colorScheme"]); } function useChakra() { var colorModeResult = useColorMode(); var theme = useTheme(); return _extends({}, colorModeResult, { theme: theme }); } // inspired from ./css.ts : resolveTokenValue var resolveTokenValue = function resolveTokenValue(theme, tokenValue, fallbackValue) { var _ref, _getValue; if (tokenValue == null) return tokenValue; var getValue = function getValue(val) { var _theme$__cssMap, _theme$__cssMap$val; return (_theme$__cssMap = theme.__cssMap) == null ? void 0 : (_theme$__cssMap$val = _theme$__cssMap[val]) == null ? void 0 : _theme$__cssMap$val.value; }; return (_ref = (_getValue = getValue(tokenValue)) != null ? _getValue : getValue(fallbackValue)) != null ? _ref : fallbackValue; }; function useToken(scale, token, fallback) { var theme = useTheme(); if (Array.isArray(token)) { var fallbackArr = []; if (fallback) { fallbackArr = Array.isArray(fallback) ? fallback : [fallback]; } return token.map(function (token, index) { var _fallbackArr$index; var path = scale + "." + token; return resolveTokenValue(theme, path, (_fallbackArr$index = fallbackArr[index]) != null ? _fallbackArr$index : token); }); } var path = scale + "." + token; return resolveTokenValue(theme, path, fallback); } function useProps(themeKey, props) { var _theme$components, _styleConfig$defaultP; var _useChakra = useChakra(), theme = _useChakra.theme, colorMode = _useChakra.colorMode; var styleConfig = props.styleConfig || ((_theme$components = theme.components) == null ? void 0 : _theme$components[themeKey]); var defaultProps = (_styleConfig$defaultP = styleConfig == null ? void 0 : styleConfig.defaultProps) != null ? _styleConfig$defaultP : {}; var propsWithDefault = _extends({}, defaultProps, filterUndefined(props)); var stylesRef = useRef({}); var mergedProps = mergeWith({}, propsWithDefault, { theme: theme, colorMode: colorMode }); var memoizedStyles = useMemo(function () { if (styleConfig) { var _styleConfig$baseStyl, _styleConfig$variants, _styleConfig$variants2, _styleConfig$sizes, _styleConfig$sizes2; var baseStyles = runIfFn((_styleConfig$baseStyl = styleConfig.baseStyle) != null ? _styleConfig$baseStyl : {}, mergedProps); var variants = runIfFn((_styleConfig$variants = (_styleConfig$variants2 = styleConfig.variants) == null ? void 0 : _styleConfig$variants2[mergedProps.variant]) != null ? _styleConfig$variants : {}, mergedProps); var sizes = runIfFn((_styleConfig$sizes = (_styleConfig$sizes2 = styleConfig.sizes) == null ? void 0 : _styleConfig$sizes2[mergedProps.size]) != null ? _styleConfig$sizes : {}, mergedProps); var styles = mergeWith(baseStyles, sizes, variants); if (styleConfig.parts) { styleConfig.parts.forEach(function (part) { var _styles$part; styles[part] = (_styles$part = styles[part]) != null ? _styles$part : {}; }); } var isStyleEqual = isEqual(stylesRef.current, styles); if (!isStyleEqual) { stylesRef.current = styles; } } return stylesRef.current; }, [styleConfig, mergedProps]); return { styles: memoizedStyles, props: omitThemingProps(propsWithDefault) }; } 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; } /** * List of props for emotion to omit from DOM. * It mostly consists of Chakra props */ var allPropNames = new Set([].concat(propNames, ["textStyle", "layerStyle", "apply", "isTruncated", "noOfLines", "focusBorderColor", "errorBorderColor", "as", "__css", "css", "sx"])); /** * htmlWidth and htmlHeight is used in the <Image /> * component to support the native `width` and `height` attributes * * https://github.com/monacohq/hakuna-matata-ui/issues/149 */ var validHTMLProps = new Set(["htmlWidth", "htmlHeight", "htmlSize"]); var shouldForwardProp = function shouldForwardProp(prop) { return validHTMLProps.has(prop) || !allPropNames.has(prop); }; var _excluded$1 = ["theme", "css", "__css", "sx"], _excluded2 = ["baseStyle"]; /** * Style resolver function that manages how style props are merged * in combination with other possible ways of defining styles. * * For example, take a component defined this way: * ```jsx * <Box fontSize="24px" sx={{ fontSize: "40px" }}></Box> * ``` * * We want to manage the priority of the styles properly to prevent unwanted * behaviors. Right now, the `sx` prop has the highest priority so the resolved * fontSize will be `40px` */ var toCSSObject = function toCSSObject(_ref) { var baseStyle = _ref.baseStyle; return function (props) { props.theme; var cssProp = props.css, __css = props.__css, sx = props.sx, rest = _objectWithoutPropertiesLoose(props, _excluded$1); var styleProps = objectFilter(rest, function (_, prop) { return isStyleProp(prop); }); var finalBaseStyle = runIfFn(baseStyle, props); var finalStyles = Object.assign({}, __css, finalBaseStyle, filterUndefined(styleProps), sx); var computedCSS = css(finalStyles)(props.theme); return cssProp ? [computedCSS, cssProp] : computedCSS; }; }; function styled(component, options) { var _ref2 = options != null ? options : {}, baseStyle = _ref2.baseStyle, styledOptions = _objectWithoutPropertiesLoose(_ref2, _excluded2); if (!styledOptions.shouldForwardProp) { styledOptions.shouldForwardProp = shouldForwardProp; } var styleObject = toCSSObject({ baseStyle: baseStyle }); return _styled(component, styledOptions)(styleObject); } var chakra = styled; domElements.forEach(function (tag) { chakra[tag] = chakra(tag); }); /** * All credit goes to Chance (Reach UI), Haz (Reakit) and (fluentui) * for creating the base type definitions upon which we improved on */ function forwardRef(component) { return /*#__PURE__*/React.forwardRef(component); } var _excluded = ["styleConfig"]; function useStyleConfig(themeKey, props, opts) { var _styleConfig$defaultP; if (props === void 0) { props = {}; } if (opts === void 0) { opts = {}; } var _props = props, styleConfigProp = _props.styleConfig, rest = _objectWithoutPropertiesLoose(_props, _excluded); var _useChakra = useChakra(), theme = _useChakra.theme, colorMode = _useChakra.colorMode; var themeStyleConfig = memoizedGet(theme, "components." + themeKey); var styleConfig = styleConfigProp || themeStyleConfig; var mergedProps = mergeWith({ theme: theme, colorMode: colorMode }, (_styleConfig$defaultP = styleConfig == null ? void 0 : styleConfig.defaultProps) != null ? _styleConfig$defaultP : {}, filterUndefined(omit(rest, ["children"]))); /** * Store the computed styles in a `ref` to avoid unneeded re-computation */ var stylesRef = useRef({}); if (styleConfig) { var _styleConfig$baseStyl, _styleConfig$variants, _styleConfig$variants2, _styleConfig$sizes$me, _styleConfig$sizes, _opts; var baseStyles = runIfFn((_styleConfig$baseStyl = styleConfig.baseStyle) != null ? _styleConfig$baseStyl : {}, mergedProps); var variants = runIfFn((_styleConfig$variants = (_styleConfig$variants2 = styleConfig.variants) == null ? void 0 : _styleConfig$variants2[mergedProps.variant]) != null ? _styleConfig$variants : {}, mergedProps); var sizes = runIfFn((_styleConfig$sizes$me = (_styleConfig$sizes = styleConfig.sizes) == null ? void 0 : _styleConfig$sizes[mergedProps.size]) != null ? _styleConfig$sizes$me : {}, mergedProps); var styles = mergeWith({}, baseStyles, sizes, variants); if ((_opts = opts) != null && _opts.isMultiPart && styleConfig.parts) { styleConfig.parts.forEach(function (part) { var _styles$part; styles[part] = (_styles$part = styles[part]) != null ? _styles$part : {}; }); } var isStyleEqual = isEqual(stylesRef.current, styles); if (!isStyleEqual) { stylesRef.current = styles; } } return stylesRef.current; } function useMultiStyleConfig(themeKey, props) { return useStyleConfig(themeKey, props, { isMultiPart: true }); } export { GlobalStyle, StylesProvider, ThemeProvider, chakra, forwardRef, omitThemingProps, shouldForwardProp, styled, toCSSObject, useChakra, useMultiStyleConfig, useProps, useStyleConfig, useStyles, useTheme, useToken };