"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.DocExplorer = void 0;

require("../css/doc-explorer.css");

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _graphql = require("graphql");

var _FieldDoc = _interopRequireDefault(require("./DocExplorer/FieldDoc"));

var _SchemaDoc = _interopRequireDefault(require("./DocExplorer/SchemaDoc"));

var _SearchBox = _interopRequireDefault(require("./DocExplorer/SearchBox"));

var _SearchResults = _interopRequireDefault(require("./DocExplorer/SearchResults"));

var _TypeDoc = _interopRequireDefault(require("./DocExplorer/TypeDoc"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const initialNav = {
  name: 'Schema',
  title: 'Documentation Explorer'
};
/**
 * DocExplorer
 *
 * Shows documentations for GraphQL definitions from the schema.
 *
 * Props:
 *
 *   - schema: A required GraphQLSchema instance that provides GraphQL document
 *     definitions.
 *
 * Children:
 *
 *   - Any provided children will be positioned in the right-hand-side of the
 *     top bar. Typically this will be a "close" button for temporary explorer.
 *
 */

class DocExplorer extends _react.default.Component {
  constructor() {
    super();

    _defineProperty(this, "handleNavBackClick", () => {
      if (this.state.navStack.length > 1) {
        this.setState({
          navStack: this.state.navStack.slice(0, -1)
        });
      }
    });

    _defineProperty(this, "handleClickTypeOrField", typeOrField => {
      this.showDoc(typeOrField);
    });

    _defineProperty(this, "handleSearch", value => {
      this.showSearch(value);
    });

    this.state = {
      navStack: [initialNav]
    };
  }

  shouldComponentUpdate(nextProps, nextState) {
    return this.props.schema !== nextProps.schema || this.state.navStack !== nextState.navStack;
  }

  render() {
    const schema = this.props.schema;
    const navStack = this.state.navStack;
    const navItem = navStack[navStack.length - 1];
    let content;

    if (schema === undefined) {
      // Schema is undefined when it is being loaded via introspection.
      content = _react.default.createElement("div", {
        className: "spinner-container"
      }, _react.default.createElement("div", {
        className: "spinner"
      }));
    } else if (!schema) {
      // Schema is null when it explicitly does not exist, typically due to
      // an error during introspection.
      content = _react.default.createElement("div", {
        className: "error-container"
      }, 'No Schema Available');
    } else if (navItem.search) {
      content = _react.default.createElement(_SearchResults.default, {
        searchValue: navItem.search,
        withinType: navItem.def,
        schema: schema,
        onClickType: this.handleClickTypeOrField,
        onClickField: this.handleClickTypeOrField
      });
    } else if (navStack.length === 1) {
      content = _react.default.createElement(_SchemaDoc.default, {
        schema: schema,
        onClickType: this.handleClickTypeOrField
      });
    } else if ((0, _graphql.isType)(navItem.def)) {
      content = _react.default.createElement(_TypeDoc.default, {
        schema: schema,
        type: navItem.def,
        onClickType: this.handleClickTypeOrField,
        onClickField: this.handleClickTypeOrField
      });
    } else {
      content = _react.default.createElement(_FieldDoc.default, {
        field: navItem.def,
        onClickType: this.handleClickTypeOrField
      });
    }

    const shouldSearchBoxAppear = navStack.length === 1 || (0, _graphql.isType)(navItem.def) && navItem.def.getFields;
    let prevName;

    if (navStack.length > 1) {
      prevName = navStack[navStack.length - 2].name;
    }

    return _react.default.createElement("section", {
      className: "doc-explorer",
      key: navItem.name,
      "aria-label": "Documentation Explorer"
    }, _react.default.createElement("div", {
      className: "doc-explorer-title-bar"
    }, prevName && _react.default.createElement("button", {
      className: "doc-explorer-back",
      onClick: this.handleNavBackClick,
      "aria-label": `Go back to ${prevName}`
    }, prevName), _react.default.createElement("div", {
      className: "doc-explorer-title"
    }, navItem.title || navItem.name), _react.default.createElement("div", {
      className: "doc-explorer-rhs"
    }, this.props.children)), _react.default.createElement("div", {
      className: "doc-explorer-contents"
    }, shouldSearchBoxAppear && _react.default.createElement(_SearchBox.default, {
      value: navItem.search,
      placeholder: `Search ${navItem.name}...`,
      onSearch: this.handleSearch
    }), content));
  } // Public API


  showDoc(typeOrField) {
    const navStack = this.state.navStack;
    const topNav = navStack[navStack.length - 1];

    if (topNav.def !== typeOrField) {
      this.setState({
        navStack: navStack.concat([{
          name: typeOrField.name,
          def: typeOrField
        }])
      });
    }
  } // Public API


  showDocForReference(reference) {
    if (reference.kind === 'Type') {
      this.showDoc(reference.type);
    } else if (reference.kind === 'Field') {
      this.showDoc(reference.field);
    } else if (reference.kind === 'Argument' && reference.field) {
      this.showDoc(reference.field);
    } else if (reference.kind === 'EnumValue' && reference.type) {
      this.showDoc(reference.type);
    }
  } // Public API


  showSearch(search) {
    const navStack = this.state.navStack.slice();
    const topNav = navStack[navStack.length - 1];
    navStack[navStack.length - 1] = { ...topNav,
      search
    };
    this.setState({
      navStack
    });
  }

  reset() {
    this.setState({
      navStack: [initialNav]
    });
  }

}

exports.DocExplorer = DocExplorer;

_defineProperty(DocExplorer, "propTypes", {
  schema: _propTypes.default.instanceOf(_graphql.GraphQLSchema)
});