All files / src/Box Box.tsx

100% Statements 18/18
100% Branches 9/9
100% Functions 2/2
100% Lines 18/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100                                                                        75x   7650x 7650x   7650x 257x 257x                 7650x     7650x                 7650x                 7650x   7650x   204x     7650x   1040x   7650x         75x   1306x 1306x              
import * as React from 'react';
import { Box as ReakitBox, BoxProps as ReakitBoxProps } from 'reakit';
import _get from 'lodash/get';
import classNames from 'classnames';
 
import { ThemeConfig, CSSProperties } from '../types';
import {
  useStyle,
  useClassName,
  omitCSSProps,
  pickHTMLProps,
  mergeRefs,
  createComponent,
  createElement,
  createHook
} from '../utils';
 
import * as styles from './styles';
 
type ComponentType<R> = React.ComponentType<R> & { useProps: any };
 
export type LocalBoxProps = {
  use?: string | ComponentType<any>;
  className?: string;
  children?: React.ReactNode | ((props: BoxProps) => React.ReactNode);
  altitude?: string;
  variant?: string;
  showBreakpoint?: string;
  hiddenBreakpoint?: string;
  /* Component-level theme overrides [Read more](TODO) */
  overrides?: ThemeConfig;
  elementRef?: React.Ref<any>;
  themeKey?: string;
};
export type BoxProps = ReakitBoxProps & CSSProperties & LocalBoxProps;
 
const useProps = createHook<BoxProps>(
  (_props, { themeKey, themeKeyOverride }) => {
    let props = _props;
    const { use } = props;
 
    if (use && typeof use !== 'string' && use.useProps) {
      const newProps = use.useProps({ ...props, use: undefined });
      props = { ...props, ...newProps };
    }
 
    // Convert CSS props to an object.
    // Example input:
    // props = { color: 'red', backgroundColor: 'blue', isEnabled: true }
    //
    // Example output:
    // style = { color: 'red', backgroundColor: 'blue' }
    const style = useStyle(props);
 
    // Append the styles from above as a className on the DOM element (with precedence).
    let className = useClassName({
      style: styles.style,
      styleProps: { ...props, style },
      themeKey,
      themeKeyOverride,
      prevClassName: props.className
    });
 
    // Append the Box styles as a className on the DOM element.
    className = useClassName({
      style: styles.Box,
      styleProps: props,
      prevClassName: className,
      themeKey,
      themeKeyOverride
    });
 
    // Pick out and invalid HTML props & omit the CSS props.
    const htmlProps = omitCSSProps(pickHTMLProps({ ...props, className }));
 
    if (props.elementRef) {
      // @ts-ignore
      htmlProps.ref = mergeRefs(props.elementRef, props.ref);
    }
 
    if (props.wrapElement) {
      // @ts-ignore
      htmlProps.wrapElement = props.wrapElement;
    }
    return { ...htmlProps };
  },
  { themeKey: 'Box' }
);
 
export const Box = createComponent<BoxProps>(
  props => {
    const boxProps = useProps(props);
    return createElement({ children: props.children, component: ReakitBox, use: props.use, htmlProps: boxProps });
  },
  {
    attach: { useProps },
    themeKey: 'Box'
  }
);