apjames93/mui-storyblok

View on GitHub
src/lib/components/PageGrid/atoms/Icon/Icon.js

Summary

Maintainability
A
0 mins
Test Coverage
A
96%
import React, { lazy, Suspense } from 'react';
import PropTypes from 'prop-types';
import customIcons from 'lib/utils/customIcons';
import Storyblok from 'lib/utils/Storyblok';
import { muiStringProp } from 'lib/utils/customProps';

// import styles for icons in styleguide
import 'lib/styles/styles.scss';

/* istanbul ignore next */
const MuiIcon = lazy(() => import('@material-ui/core/Icon'));
/* istanbul ignore next */
const BBBSvg = lazy(() => import('./components/BBBSvg/BBBSvg'));
/* istanbul ignore next */
const FacebookSvg = lazy(() => import('./components/FacebookSvg/FacebookSvg'));
/* istanbul ignore next */
const GoogleSvg = lazy(() => import('./components/GoogleSvg/GoogleSvg'));
/* istanbul ignore next */
const LinkedinSvg = lazy(() => import('./components/LinkedinSvg/LinkedinSvg'));
/* istanbul ignore next */
const YouTubeSvg = lazy(() => import('./components/YouTubeSvg/YouTubeSvg'));
/* istanbul ignore next */
const InstagramSvg = lazy(() => import('./components/InstagramSvg/InstagramSvg'));
/* istanbul ignore next */
const TwitterSvg = lazy(() => import('./components/TwitterSvg/TwitterSvg'));
/* istanbul ignore next */
const YelpSvg = lazy(() => import('./components/YelpSvg/YelpSvg'));
/* istanbul ignore next */
const GithubSvg = lazy(() => import('./components/GithubSvg/GithubSvg'));


// import icons to use for custom icons passed down to app;

export const Icon = ({
  color,
  fontSize,
  iconName,
  rootClass,
  storyblokClass,
  dataBlokC,
  dataBlokUid,
  style,
}) => {
  const Sus = props => (
    <Suspense fallback={<></>}>
      <props.Comp
        {...props}
        data-blok-c={dataBlokC}
        data-blok-uid={dataBlokUid}
      />
    </Suspense>
  );
  const styles = Storyblok.arrayToMuiStyles(rootClass, { ...style });

  const customIcon = customIcons.find(icon => icon.iconName === iconName);
  if (customIcon) {
    const Custom = customIcon.Component;
    return (
      <Custom
        className={`${styles.root} ${storyblokClass}`}
        color={color}
        fontSize={fontSize}
        data-blok-c={dataBlokC}
        data-blok-uid={dataBlokUid}
        {...customIcon.props}
      />
    );
  }

  switch (iconName) {
    case 'facebook':
      return <Sus Comp={FacebookSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'bbb':
      return <Sus Comp={BBBSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'linkedin':
      return <Sus Comp={LinkedinSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'google':
      return <Sus Comp={GoogleSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'youtube':
      return <Sus Comp={YouTubeSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'instagram':
      return <Sus Comp={InstagramSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'twitter':
      return <Sus Comp={TwitterSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'yelp':
      return <Sus Comp={YelpSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    case 'github':
      return <Sus Comp={GithubSvg} color={color} fontSize={fontSize} className={`${styles.root} ${storyblokClass}`} />;
    default:
      return (
        <Suspense fallback={<></>}>
          <MuiIcon
            color={color}
            fontSize={fontSize}
            className={`${styles.root} ${storyblokClass}`}
            data-blok-c={dataBlokC}
            data-blok-uid={dataBlokUid}
          >
            {iconName}
          </MuiIcon>
        </Suspense>
      );
  }
};

export default Icon;

Icon.propTypes = {
  /** any icon from https://material.io/resources/icons/?style=baseline */
  iconName: PropTypes.string.isRequired,
  /**
   * mui prop: 'inherit', 'primary', 'secondary', 'action', 'error', 'disabled'
   * The color of the component. It supports those theme colors that make sense for this component.
   * */
  color(props, propName, componentName) {
    const validProp = ['inherit', 'primary', 'secondary', 'action', 'error', 'disabled'];
    return muiStringProp(props, propName, componentName, validProp);
  },
  /**
   * mui prop: 'default', 'small', 'inherit', 'large'
   * The fontSize applied to the icon. Defaults to 24px, but can be configure to inherit font size.
   * */
  fontSize(props, propName, componentName) {
    const validProp = ['default', 'small', 'inherit', 'large'];
    return muiStringProp(props, propName, componentName, validProp);
  },
  /**
   * storyblok multiselect of css classes
   * Override or extend the styles applied to the component
   * */
  rootClass: PropTypes.arrayOf(PropTypes.string),

  /** storyblok prop for when in editor to allow click bridge */
  dataBlokC: PropTypes.string,
  /** storyblok prop for when in editor to allow click bridge */
  dataBlokUid: PropTypes.string,
  /** storyblok prop for when in editor to allow click bridge */
  storyblokClass: PropTypes.string,
};

Icon.defaultProps = {
  rootClass: [],
  color: 'secondary',
  fontSize: 'default',
  dataBlokC: '',
  dataBlokUid: '',
  storyblokClass: '',
};