{"size": 6996, "ext": "js", "max_stars_repo_path": "redbubble/node_modules/@redbubble/design-system/react/Sheets/index.js", "max_stars_repo_name": "vunamhung/codebases", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "redbubble/node_modules/@redbubble/design-system/react/Sheets/index.js", "max_issues_repo_name": "vunamhung/codebases", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "redbubble/node_modules/@redbubble/design-system/react/Sheets/index.js", "max_forks_repo_name": "vunamhung/codebases", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 25.6263736264, "max_line_length": 105, "alphanum_fraction": 0.5457404231}
import React from 'react';
import PropTypes from 'prop-types';
import cnames from 'classnames';
import { defineMessages, injectIntl } from 'react-intl';
import Button from '../Button';
import ChevronLeftIcon from '../Icons/ChevronLeftBig';
import * as constants from '../constants';
import { BackOff, SheetTransition, AnimatedTitle, AnimatedTitleBar } from './animations';
import styles from './styles.scss';

const messages = defineMessages({
  back: 'Back',
});

// A single sheet in the stack
class Sheet extends React.Component {
  constructor(props) {
    super(props);
    this.state = { activeChild: '', accessibleChild: '', selfAccessible: true };
    this.localRefs = {};
    this.openSheet = this.openSheet.bind(this);
    this.goBack = this.goBack.bind(this);
  }

  openSheet(sheet) {
    const { id, title, sheets } = this.props;

    if (!Object.keys(sheets).includes(sheet)) {
      // eslint-disable-next-line no-console
      console.warn(`
The Sheet "${sheet}" is not a child of the ${id || title} sheet.
You can only use openSheet to open sheets that are children of the current sheet.
      `);

      return;
    }

    this.setState({ activeChild: sheet, accessibleChild: sheet });
  }

  goBack() {
    this.setState({ activeChild: '', selfAccessible: true });
  }

  render() {
    const {
      children,
      sheets,
      title,
      parentSheet,
      goBack,
      hideTitleBar,
      setRef,
      rightAction,
      intl,
    } = this.props;

    const { activeChild, accessibleChild, selfAccessible } = this.state;

    const backOffProps = { initialPose: 'forward', pose: activeChild ? 'back' : 'forward' };

    return (
      <div className={styles.sheet}>
        <BackOff
          {...backOffProps}
          ref={setRef}
          className={cnames(styles.sheetBody, { [styles.noTitle]: hideTitleBar })}
          hidden={!selfAccessible}
          onPoseComplete={(completedPose) => {
            if (completedPose === 'back') {
              // Hide this page from screen readers whilst it is backed off
              this.setState({ selfAccessible: false });
            }

            if (completedPose === 'forward') {
              // Scroll all child pages back to top
              Object.values(this.localRefs).forEach((node) => {
                node.scrollTo(0, 0);
              });

              // Hide all child pages from being tabbed to / screen read
              this.setState({ accessibleChild: '' });
            }
          }}
        >
          { typeof children === 'function' ? children({ openSheet: this.openSheet, goBack }) : children }
        </BackOff>
        {
          !hideTitleBar && (
            <BackOff
              {...backOffProps}
              className={styles.titleBarArea}
              hidden={!selfAccessible}
            >
              <div style={{ position: 'sticky' }}>
                <TitleBar
                  leftAction={
                    parentSheet && (
                      <Button
                        onClick={goBack}
                        size={constants.SMALL}
                        iconBefore={<ChevronLeftIcon />}
                      >
                        {parentSheet.length > 15 ? intl.formatMessage(messages.back) : parentSheet }
                      </Button>
                    )
                  }
                  title={title}
                  rightAction={rightAction}
                />
              </div>
            </BackOff>
          )
        }
        {
          sheets && (
            Object.entries(sheets).map(([sheetId, sheet]) => {
              return (
                <SheetTransition
                  initialPose="closed"
                  pose={sheetId === activeChild ? 'open' : 'closed'}
                  className={styles.sheetContainer}
                  withParent={false}
                  hidden={sheetId !== accessibleChild}
                  key={`Sheet_${sheetId}`}
                >
                  {React.cloneElement(sheet, {
                    parentSheet: title,
                    goBack: this.goBack,
                    hideTitleBar,
                    id: sheetId,
                    setRef: (node) => { this.localRefs[sheetId] = node; },
                    rightAction,
                  })}
                </SheetTransition>
              );
            })
          )
        }
      </div>
    );
  }
}

Sheet.propTypes = {
  /**
    * The content displayed in this Sheet
    */
  children: PropTypes.oneOfType([
    PropTypes.node,
    PropTypes.func,
  ]).isRequired,
  /**
    * The sub-sheets that this sheet could navigate to
    */
  sheets: PropTypes.shape({}),
  /**
    * The title of this Sheet
    */
  title: PropTypes.string,
  /**
    * Private
    */
  id: PropTypes.string,
  /**
    * Private
    */
  parentSheet: PropTypes.string,
  /**
    * Private
    */
  goBack: PropTypes.func,
  /**
    * Private
    */
  hideTitleBar: PropTypes.bool,
  /**
    * Private
    */
  setRef: PropTypes.func,
  /**
    * Private
    */
  rightAction: PropTypes.node,
  /**
    * Private
    */
};

Sheet.defaultProps = {
  sheets: {},
  title: '',
  id: '',
  parentSheet: '',
  goBack: () => {},
  hideTitleBar: false,
  setRef: () => {},
  rightAction: null,
};

Sheet.displayName = 'Sheet';

/* eslint-disable react/prop-types */
const TitleBar = ({ title, leftAction, rightAction }) => (
  <AnimatedTitleBar>
    <AnimatedTitle key={title} className={styles.titleBar}>
      <div className={styles.titleBarAction}>{leftAction}</div>
      <div className={styles.titleBarTitle}>
        <div className={styles.titleBarTitleText}>{title}</div>
      </div>
      <div className={styles.titleBarAction}>{rightAction}</div>
    </AnimatedTitle>
  </AnimatedTitleBar>
);
/* eslint-enable react/prop-types */

const Sheets = props => <div className={styles.sheets}><Sheet {...props} /></div>;

Sheets.propTypes = {
  /**
    * The content displayed in the base sheet of this Sheets
    */
  children: PropTypes.oneOfType([
    PropTypes.node,
    PropTypes.func,
  ]).isRequired,
  /**
    * The sub-sheets that this Sheets could navigate to
    */
  sheets: PropTypes.shape({}),
  /**
    * The title of this Sheet
    */
  title: PropTypes.string,
  /**
    * Private
    */
  id: PropTypes.string,
  /**
    * Private
    */
  parentSheet: PropTypes.string,
  /**
    * Private
    */
  goBack: PropTypes.func,
  /**
    * When true, hide the title bar and it's navigation
    */
  hideTitleBar: PropTypes.bool,
  /**
    * Private
    */
  setRef: PropTypes.func,
  /**
    * A React component to be displayed as the right hand title bar action
    */
  rightAction: PropTypes.node,
};

Sheets.defaultProps = Sheet.defaultProps;

Sheets.displayName = 'Sheets';

const SheetsWithIntl = injectIntl(Sheets);
const SheetWithIntl = injectIntl(Sheet);

SheetsWithIntl.displayName = 'Sheets';
SheetWithIntl.displayName = 'Sheet';

export default SheetsWithIntl;
export { SheetWithIntl as Sheet };
