"use strict";

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

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

var _Button = _interopRequireDefault(require("../Button/Button"));

var _Ellipses = _interopRequireDefault(require("./Ellipses"));

var _Page = _interopRequireDefault(require("./Page"));

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

var _classnames = _interopRequireDefault(require("classnames"));

var _Icons = require("../Icons");

var _i18n = require("../i18n");

var _excluded = ["ariaLabel", "className", "compact", "currentPage", "renderHref", "onPageChange", "isNavigationHidden", "startLabelText", "startAriaLabel", "endLabelText", "endAriaLabel", "totalPages"];

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

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

// Determines number of pages visible to either side of active page.
var overflow = 1; // Determines total number of visible pages without Ellipses.

var maxVisiblePages = 7;

function paginationBuilder(page, pages) {
  var paginationRange = [];
  var start = page - overflow;
  var end = page + overflow;
  var availableSlots = maxVisiblePages - 2;
  /**
   * If the current page is < `maxVisiblePages`,
   * add 1 - 5 pages.
   */

  if (page < availableSlots) {
    start = 1;
    end = availableSlots;
  }
  /**
   * If the current page equals `pages` - 1,
   * make sure `start` begins one page earlier.
   */


  if (page === pages - 2) {
    start -= 1;
    end += 1;
  }
  /**
   * If `end` page is two from the end,
   * make sure the last page shows instead of ellipsis.
   */


  if (end === pages - 2) {
    end += 1;
  }
  /**
   * If `end` > `pages`,
   * add last pages to `paginationRange[]`.
   */


  if (end >= pages) {
    start = pages - (availableSlots - 1);
    end = pages;
  }
  /**
   * If `pages` is 5 or fewer,
   * all pages added to `paginationRange[]`
   */


  if (pages <= maxVisiblePages) {
    start = 1;
    end = pages;
  }

  for (var i = start; i <= end; i++) {
    paginationRange.push(i);
  }

  return paginationRange;
}

function Pagination(_ref) {
  var ariaLabel = _ref.ariaLabel,
      className = _ref.className,
      compact = _ref.compact,
      currentPage = _ref.currentPage,
      renderHref = _ref.renderHref,
      onPageChange = _ref.onPageChange,
      isNavigationHidden = _ref.isNavigationHidden,
      startLabelText = _ref.startLabelText,
      startAriaLabel = _ref.startAriaLabel,
      endLabelText = _ref.endLabelText,
      endAriaLabel = _ref.endAriaLabel,
      totalPages = _ref.totalPages,
      rest = _objectWithoutProperties(_ref, _excluded);

  var classes = (0, _classnames.default)('ds-c-pagination', className);
  /**
   * `useState` and `useEffect` determine if
   * mobile layout of component is rendered.
   */

  var _React$useState = _react.default.useState(false),
      _React$useState2 = _slicedToArray(_React$useState, 2),
      isMobile = _React$useState2[0],
      setIsMobile = _React$useState2[1];

  _react.default.useEffect(function () {
    if (window) {
      // Mobile media query derived from: https://design.cms.gov/guidelines/responsive/
      var media = window.matchMedia('(max-width: 543px)');

      if (media.matches !== isMobile) {
        setIsMobile(media.matches);
      }

      var listener = function listener() {
        setIsMobile(media.matches);
      };

      media.addEventListener('change', listener);
      return function () {
        return media.removeEventListener('change', listener);
      };
    } else {
      setIsMobile(true);
    }
  }, [isMobile]);

  var pageChange = _react.default.useCallback(function (page) {
    return function (evt) {
      return onPageChange(evt, page);
    };
  }, [onPageChange]);

  var pages = [];
  /**
   * If `compact` or `isMobile` is true,
   * don't run code to populate `pages[]`.
   */

  if (!compact || !isMobile) {
    var pageRange = paginationBuilder(currentPage, totalPages);

    if (pageRange[0] >= 2) {
      /**
       * If `pageRange` begins with a page of 2 or greater,
       * begin Pagination with Page 1
       */
      pages.push( /*#__PURE__*/_react.default.createElement(_Page.default, {
        href: renderHref(1),
        key: "page-1",
        index: 1,
        isActive: currentPage === 1,
        onPageChange: pageChange(1)
      }));
      /**
       * If `pageRange` doesn't equal 2, second Pagination element is Ellipses,
       * otherwise page count continues.
       */

      if (pageRange[0] !== 2) {
        pages.push( /*#__PURE__*/_react.default.createElement(_Ellipses.default, {
          key: "ellipses-1"
        }));
      }
    }
    /**
     * Renders all Page components in range (3 pages) to Pagination component.
     */


    pageRange.map(function (page) {
      pages.push( /*#__PURE__*/_react.default.createElement(_Page.default, {
        href: renderHref(page),
        key: "page-".concat(page),
        index: page,
        isActive: currentPage === page,
        onPageChange: pageChange(page)
      }));
    });
    /**
     * Defines if/when the Ellipses component appears
     * at the end of the Pagination component -
     * as long as there are fewer than 7 pages.
     */

    if (currentPage <= totalPages - 3 && totalPages > maxVisiblePages) {
      if (currentPage < totalPages - 3) {
        pages.push( /*#__PURE__*/_react.default.createElement(_Ellipses.default, {
          key: "ellipses-2"
        }));
      }

      pages.push( /*#__PURE__*/_react.default.createElement(_Page.default, {
        href: renderHref(totalPages),
        key: "page-".concat(totalPages),
        index: totalPages,
        isActive: currentPage === totalPages,
        onPageChange: pageChange(totalPages)
      }));
    }
  }

  var startIcon = /*#__PURE__*/_react.default.createElement(_Icons.ArrowIcon, {
    direction: "left",
    className: "ds-c-pagination__nav--image"
  });

  var endIcon = /*#__PURE__*/_react.default.createElement(_Icons.ArrowIcon, {
    direction: "right",
    className: "ds-c-pagination__nav--image"
  });

  return /*#__PURE__*/_react.default.createElement("nav", _extends({
    className: classes,
    "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : (0, _i18n.t)('pagination.ariaLabel')
  }, rest), currentPage === 1 ? /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav ds-c-pagination__nav--disabled",
    style: {
      visibility: isNavigationHidden ? 'hidden' : 'visible'
    },
    "aria-hidden": isNavigationHidden
  }, /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav--img-container ds-c-pagination__nav--img-container-previous"
  }, startIcon), startLabelText !== null && startLabelText !== void 0 ? startLabelText : (0, _i18n.t)('pagination.startLabelText')) : /*#__PURE__*/_react.default.createElement(_Button.default, {
    variation: "ghost",
    href: renderHref(currentPage - 1),
    onClick: pageChange(currentPage - 1),
    "aria-label": startAriaLabel !== null && startAriaLabel !== void 0 ? startAriaLabel : (0, _i18n.t)('pagination.startAriaLabel'),
    className: "ds-c-pagination__nav"
  }, /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav--img-container ds-c-pagination__nav--img-container-previous"
  }, startIcon), startLabelText !== null && startLabelText !== void 0 ? startLabelText : (0, _i18n.t)('pagination.startLabelText')), isMobile || compact ? /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__page-count",
    dangerouslySetInnerHTML: {
      __html: (0, _i18n.t)('pagination.pageXOfY', {
        number: "<strong>".concat(currentPage, "</strong>"),
        total: "<strong>".concat(totalPages, "</strong>")
      })
    }
  }) : /*#__PURE__*/_react.default.createElement("ul", null, pages), currentPage === totalPages ? /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav ds-c-pagination__nav--disabled",
    style: {
      visibility: isNavigationHidden ? 'hidden' : 'visible'
    },
    "aria-hidden": isNavigationHidden
  }, endLabelText !== null && endLabelText !== void 0 ? endLabelText : (0, _i18n.t)('pagination.endLabelText'), /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav--img-container ds-c-pagination__nav--img-container-next"
  }, endIcon)) : /*#__PURE__*/_react.default.createElement(_Button.default, {
    variation: "ghost",
    href: renderHref(currentPage + 1),
    onClick: pageChange(currentPage + 1),
    "aria-label": endAriaLabel !== null && endAriaLabel !== void 0 ? endAriaLabel : (0, _i18n.t)('pagination.endAriaLabel'),
    className: "ds-c-pagination__nav"
  }, endLabelText !== null && endLabelText !== void 0 ? endLabelText : (0, _i18n.t)('pagination.endLabelText'), /*#__PURE__*/_react.default.createElement("span", {
    className: "ds-c-pagination__nav--img-container ds-c-pagination__nav--img-container-next"
  }, endIcon)));
}

Pagination.propTypes = {
  /**
     * Defines `aria-label` on wrapping Pagination element. Since this exists on a `<nav>` element, the word "navigation" should be omitted from this label. Optional.
     */
  ariaLabel: _propTypes.default.string,

  /**
     * Class to be applied to parent `<nav>` element of Pagination component. Optional.
     */
  className: _propTypes.default.string,

  /**
     * Renders compact layout. Optional.
     */
  compact: _propTypes.default.bool,

  /**
     * Defines active page in Pagination. Optional.
     */
  currentPage: _propTypes.default.number,

  /**
     * Determines if navigation is hidden when current page is the first or last of Pagination page set. Optional.
     */
  isNavigationHidden: _propTypes.default.bool,

  /**
     * A callback function used to handle state changes.
     */
  onPageChange: _propTypes.default.func.isRequired,

  /**
     * Defines application-specific routing in url for links.
     */
  renderHref: _propTypes.default.func.isRequired,

  /**
     * Sets custom label on start navigation. Added for language support. Optional.
     */
  startLabelText: _propTypes.default.string,

  /**
     * Sets custom ARIA label on start navigation. Added for language support. Label structure should be the equivalent of: Previous Page. Optional.
     */
  startAriaLabel: _propTypes.default.string,

  /**
     * Sets custom label on end navigation. Added for language support. Optional.
     */
  endLabelText: _propTypes.default.string,

  /**
     * Sets custom ARIA label on end navigation. Added for language support. Label structure should be the equivalent of: Next Page. Optional.
     */
  endAriaLabel: _propTypes.default.string,

  /**
     * Sets total number of pages in Pagination component.
     */
  totalPages: _propTypes.default.number.isRequired
};
Pagination.defaultProps = {
  compact: false,
  currentPage: 1,
  isNavigationHidden: false
};
var _default = Pagination;
exports.default = _default;