Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import React from 'react';
import PropTypes from 'prop-types';

import Button from '../../controls/Button/Button';
import Navigation, { NavigationTypes } from '../Navigation';
import ProductFooter, { ProductFooterTypes } from '../ProductFooter';
/** @todo (optimization) have a simpler validation that avoids importing the components */
import OneColumnLayout from './OneColumnLayout';
import TwoColumnLayout from './TwoColumnLayout';

export const LAYOUT_TYPES = {
  ONE_COLUMN: 'one-column',
  TWO_COLUMN: 'two-column',
  TWO_COLUMN_FLEXIBLE: 'two-column-flexible',
};

const PageLayout = ({ header, footer, children, actions, layoutType }) => (
  <div className={`PageLayout PageLayout--${layoutType}`}>
    <div className="PageLayout__header">
      <Navigation {...header} />
    </div>
    <div className="PageLayout__content">{children}</div>
    <div className="PageLayout__footer">
      <ProductFooter {...footer} />
    </div>
    {Array.isArray(actions) &&
      actions.length > 0 && (
        <div className="PageLayout__action-bar">
          <div className="PageLayout__actions-wrapper">
            <div className="PageLayout__actions">
              {actions.map((action, index) => (
                // We do not expect new action props after first render, so it's fine to use index
                // eslint-disable-next-line react/no-array-index-key
                <div key={index} className="PageLayout__action">
                  {action}
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
  </div>
);

function validateChildren(props, propName, componentName) {
  const children = React.Children.toArray(props[propName]);

  const invalidType = children.find(child => child.type !== OneColumnLayout && child.type !== TwoColumnLayout);

  return invalidType
    ? new TypeError(
        `\`${componentName}\` children should be of type \`OneColumnLayout\` or  \`TwoColumnLayout\`. Are you only setting the layoutType? Please note that the layoutType prop only affects the width of the header and the action bar.`
      )
    : '';
}

validateChildren.isRequired = (props, propName, componentName) => {
  const children = React.Children.toArray(props[propName]);
  if (children.length === 0) {
    return new TypeError(`\`${componentName}\` children prop is required.`);
  }

  return validateChildren(props, propName, componentName);
};

function validateActions(props, propName, componentName) {
  const prop = props[propName];

  if (!Array.isArray(prop)) return TypeError(`\`${componentName}\` actions should be an array of type \`Button\`.`);
  const children = React.Children.toArray(prop);
  const invalidType = children.find(child => child.type !== Button);

  return invalidType ? new TypeError(`\`${componentName}\` each action should be of type \`Button\`.`) : '';
}

PageLayout.propTypes = {
  /**
   * Props to be passed to the Navigation component
   * @todo bug with passed PropTypes, so have to ignore it for styleguide
   * https://github.com/reactjs/react-docgen/pull/352
   * @ignore
   * */
  header: PropTypes.shape(NavigationTypes).isRequired,
  /**
   * Props to be passed to the ProductFooter component
   * @todo bug with passed PropTypes, so have to ignore it for styleguide
   * https://github.com/reactjs/react-docgen/pull/352
   * @ignore
   */
  footer: PropTypes.shape(ProductFooterTypes),
  /** Content that is either a OneColumnLayout or TwoColumnLayout component */
  children: validateChildren.isRequired,
  /** An array of Buttons to be rendered in the action bar. If none are provided, action bar won't be rendered */
  actions: validateActions,
  /**
   * A control to make header and action bar, same width as the content, which depends on children passed
   *
   * Please note that the layoutType prop only affects the width of the header and the action bar.
   * Make sure you add OneColumnLayout or TwoColumnLayout components as children.
   */
  layoutType: PropTypes.oneOf(Object.values(LAYOUT_TYPES)).isRequired,
};

PageLayout.defaultProps = {
  actions: null,
  footer: null,
};

export default PageLayout;