function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) { ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } } return n; }, _extends.apply(null, arguments); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) { o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) { if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } } return t; }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
import PropTypes from "prop-types";
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(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0) { ; } } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * The OpenSearch Contributors require contributions made to
 * this file be licensed under the Apache-2.0 license or a
 * compatible open source license.
 *
 * Modifications Copyright OpenSearch Contributors. See
 * GitHub history for details.
 */

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import React, { Fragment, useEffect, useState } from 'react';
import classNames from 'classnames';
import { EuiI18n } from '../i18n';
import { EuiInnerText } from '../inner_text';
import { EuiLink } from '../link';
import { EuiPopover } from '../popover';
import { EuiIcon } from '../icon';
import { throttle } from '../../services';
import { getBreakpoint } from '../../services/breakpoint';
/* Try to fit breadcrumbs with at least 160px into the width of each of the BREAKPOINTS
 *    1. put aside 275px for the last breadcrumb and possible loss due to layout
 *    2. provide at least 160px for each remaining breadcrumb
 *
 *    numberOfBreadcrumbs = (breakpointWidth - 275) / 160 + 1
 */
var responsiveDefault = {
  xs: 1,
  // Show only one
  s: 2,
  //  (575 - 275) / 160 + 1 = 2.88
  m: 4,
  //  (768 - 275) / 160 + 1 = 4.08
  l: 5,
  //  (992 - 275) / 160 + 1 = 5.48
  xl: 6,
  // (1200 - 275) / 160 + 1 = 6.78
  xxl: 9,
  // (1680 - 275) / 160 + 1 = 9.78
  xxxl: 11 // (1920 - 275) / 160 + 1 = 11.28
};
var limitBreadcrumbs = function limitBreadcrumbs(breadcrumbs, max, allBreadcrumbs) {
  var breadcrumbsAtStart = [];
  var breadcrumbsAtEnd = [];
  var limit = Math.min(max, breadcrumbs.length);
  var start = Math.floor(limit / 2);
  var overflowBreadcrumbs = allBreadcrumbs.slice(start, start + breadcrumbs.length - limit);
  for (var i = 0; i < limit; i++) {
    // We'll alternate with displaying breadcrumbs at the end and at the start, but be biased
    // towards breadcrumbs the end so that if max is an odd number, we'll have one more
    // breadcrumb visible at the end than at the beginning.
    var isEven = i % 2 === 0;

    // We're picking breadcrumbs from the front AND the back, so we treat each iteration as a
    // half-iteration.
    var normalizedIndex = Math.floor(i * 0.5);
    var indexOfBreadcrumb = isEven ? breadcrumbs.length - 1 - normalizedIndex : normalizedIndex;
    var breadcrumb = breadcrumbs[indexOfBreadcrumb];
    if (isEven) {
      breadcrumbsAtEnd.unshift(breadcrumb);
    } else {
      breadcrumbsAtStart.push(breadcrumb);
    }
  }
  var EuiBreadcrumbCollapsed = function EuiBreadcrumbCollapsed() {
    var _useState = useState(false),
      _useState2 = _slicedToArray(_useState, 2),
      isPopoverOpen = _useState2[0],
      setIsPopoverOpen = _useState2[1];
    var ellipsisButton = /*#__PURE__*/React.createElement(EuiI18n, {
      token: "euiBreadcrumbs.collapsedBadge.ariaLabel",
      default: "Show collapsed breadcrumbs"
    }, function (ariaLabel) {
      return /*#__PURE__*/React.createElement(EuiLink, {
        className: "euiBreadcrumb__collapsedLink",
        color: "subdued",
        "aria-label": ariaLabel,
        title: ariaLabel,
        onClick: function onClick() {
          return setIsPopoverOpen(!isPopoverOpen);
        }
      }, "\u2026 ", /*#__PURE__*/React.createElement(EuiIcon, {
        type: "arrowDown",
        size: "s"
      }));
    });
    return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
      className: "euiBreadcrumbWrapper euiBreadcrumbWrapper--collapsed"
    }, /*#__PURE__*/React.createElement(EuiPopover, {
      className: "euiBreadcrumb euiBreadcrumb--collapsed",
      button: ellipsisButton,
      isOpen: isPopoverOpen,
      closePopover: function closePopover() {
        return setIsPopoverOpen(false);
      }
    }, /*#__PURE__*/React.createElement(EuiBreadcrumbs, {
      className: "euiBreadcrumbs__inPopover",
      breadcrumbs: overflowBreadcrumbs,
      responsive: false,
      truncate: false,
      max: 0
    }))));
  };
  if (max < breadcrumbs.length) {
    breadcrumbsAtStart.push(/*#__PURE__*/React.createElement(EuiBreadcrumbCollapsed, {
      key: "collapsed"
    }));
  }
  return [].concat(breadcrumbsAtStart, breadcrumbsAtEnd);
};
export var EuiBreadcrumbs = function EuiBreadcrumbs(_ref) {
  var breadcrumbs = _ref.breadcrumbs,
    className = _ref.className,
    _ref$responsive = _ref.responsive,
    responsive = _ref$responsive === void 0 ? responsiveDefault : _ref$responsive,
    _ref$truncate = _ref.truncate,
    truncate = _ref$truncate === void 0 ? true : _ref$truncate,
    _ref$max = _ref.max,
    max = _ref$max === void 0 ? 5 : _ref$max,
    rest = _objectWithoutProperties(_ref, ["breadcrumbs", "className", "responsive", "truncate", "max"]);
  // Use the default object if they simply passed `true` for responsive
  var responsiveObject = _typeof(responsive) === 'object' ? responsive : responsiveDefault;
  var allowedBreakpoints = responsive ? Object.keys(responsiveObject) : undefined;
  var _useState3 = useState(getBreakpoint(typeof window === 'undefined' ? -Infinity : window.innerWidth, undefined, allowedBreakpoints)),
    _useState4 = _slicedToArray(_useState3, 2),
    currentBreakpoint = _useState4[0],
    setCurrentBreakpoint = _useState4[1];
  var functionToCallOnWindowResize = throttle(function () {
    var newBreakpoint = getBreakpoint(window.innerWidth, undefined, allowedBreakpoints);
    if (newBreakpoint !== currentBreakpoint) {
      setCurrentBreakpoint(newBreakpoint);
    }
    // reacts every 50ms to resize changes and always gets the final update
  }, 50);

  // Add window resize handlers
  useEffect(function () {
    window.addEventListener('resize', functionToCallOnWindowResize);
    return function () {
      window.removeEventListener('resize', functionToCallOnWindowResize);
    };
  }, [responsive, responsiveObject, functionToCallOnWindowResize]);
  var isInPopover = className === 'euiBreadcrumbs__inPopover';
  var breadcrumbElements = breadcrumbs.map(function (breadcrumb, index) {
    var text = breadcrumb.text,
      href = breadcrumb.href,
      onClick = breadcrumb.onClick,
      truncate = breadcrumb.truncate,
      breadcrumbClassName = breadcrumb.className,
      breadcrumbRest = _objectWithoutProperties(breadcrumb, ["text", "href", "onClick", "truncate", "className"]);
    var isFirstBreadcrumb = index === 0;
    var isLastBreadcrumb = index === breadcrumbs.length - 1;
    var breadcrumbWrapperClasses = classNames('euiBreadcrumbWrapper', {
      'euiBreadcrumbWrapper--first': isFirstBreadcrumb,
      'euiBreadcrumbWrapper--last': isLastBreadcrumb,
      'euiBreadcrumbWrapper--truncate': truncate
    });
    var breadcrumbClasses = classNames('euiBreadcrumb', breadcrumbClassName, {
      'euiBreadcrumb--last': isLastBreadcrumb,
      'euiBreadcrumb--truncate': truncate
    });
    var link = !href && !onClick ? /*#__PURE__*/React.createElement(EuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement("span", _extends({
        ref: ref,
        className: breadcrumbClasses,
        title: innerText,
        "aria-current": isLastBreadcrumb && !isInPopover ? 'page' : 'false'
      }, breadcrumbRest), text);
    }) : /*#__PURE__*/React.createElement(EuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement(EuiLink, _extends({
        ref: ref,
        color: isLastBreadcrumb && !isInPopover ? 'text' : 'subdued',
        onClick: onClick,
        href: href,
        className: breadcrumbClasses,
        title: innerText
      }, breadcrumbRest), text);
    });
    var breadcrumbWallClasses = classNames('euiBreadcrumbWall', {
      'euiBreadcrumbWall--single': isFirstBreadcrumb && isLastBreadcrumb
    });
    var wrapper = /*#__PURE__*/React.createElement("div", {
      className: breadcrumbWrapperClasses
    }, link);
    var wall = isFirstBreadcrumb ? /*#__PURE__*/React.createElement("div", {
      className: breadcrumbWallClasses
    }, wrapper) : wrapper;
    return /*#__PURE__*/React.createElement(Fragment, {
      key: index
    }, wall);
  });

  // The max property collapses any breadcrumbs past the max quantity.
  // This is the same behavior we want for responsiveness.
  // So calculate the max value based on the combination of `max` and `responsive`

  // First, calculate the responsive max value
  var responsiveMax = responsive && responsiveObject[currentBreakpoint] || null;

  // Second, if both max and responsiveMax are set, use the smaller of the two. Otherwise, use the one that is set.
  var calculatedMax = max && responsiveMax ? Math.min(max, responsiveMax) : max || responsiveMax;
  var limitedBreadcrumbs = calculatedMax ? limitBreadcrumbs(breadcrumbElements, calculatedMax, breadcrumbs) : breadcrumbElements;
  var classes = classNames('euiBreadcrumbs', className, {
    'euiBreadcrumbs--truncate': truncate
  });
  return /*#__PURE__*/React.createElement("nav", _extends({
    "aria-label": "breadcrumb",
    className: classes
  }, rest), limitedBreadcrumbs);
};

// @deprecated This component has never been exported out the component's folder
EuiBreadcrumbs.propTypes = {
  className: PropTypes.string,
  "aria-label": PropTypes.string,
  "data-test-subj": PropTypes.string,
  /**
     * Hides extra (above the max) breadcrumbs under a collapsed item as the window gets smaller.
     * Pass a custom #EuiBreadcrumbResponsiveMaxCount object to change the number of breadcrumbs to show at the particular breakpoints.
     * Omitting or passing a `0` value will show all breadcrumbs.
     *
     * Pass `false` to turn this behavior off.
     *
     * Default: `{ xs: 1, s: 2, m: 4 }`
     */
  responsive: PropTypes.oneOfType([PropTypes.bool.isRequired, PropTypes.any.isRequired]),
  /**
     * Forces all breadcrumbs to single line and
     * truncates each breadcrumb to a particular width,
     * except for the last item
     */
  truncate: PropTypes.bool,
  /**
     * Collapses the inner items past the maximum set here
     * into a single ellipses item
     */
  max: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.oneOf([null])]),
  /**
     * The array of individual #EuiBreadcrumb items
     */
  breadcrumbs: PropTypes.arrayOf(PropTypes.shape({
    className: PropTypes.string,
    "aria-label": PropTypes.string,
    "data-test-subj": PropTypes.string,
    /**
       * Visible label of the breadcrumb
       */
    text: PropTypes.node.isRequired,
    href: PropTypes.string,
    onClick: PropTypes.func,
    /**
       * Force a max-width on the breadcrumb text
       */
    truncate: PropTypes.bool
  }).isRequired).isRequired
};
export var EuiBreadcrumbsSimplified = function EuiBreadcrumbsSimplified(_ref2) {
  var breadcrumbs = _ref2.breadcrumbs,
    className = _ref2.className,
    _ref2$responsive = _ref2.responsive,
    responsive = _ref2$responsive === void 0 ? responsiveDefault : _ref2$responsive,
    _ref2$truncate = _ref2.truncate,
    truncate = _ref2$truncate === void 0 ? true : _ref2$truncate,
    _ref2$max = _ref2.max,
    max = _ref2$max === void 0 ? 5 : _ref2$max,
    rest = _objectWithoutProperties(_ref2, ["breadcrumbs", "className", "responsive", "truncate", "max"]);
  var _useState5 = useState(getBreakpoint(typeof window === 'undefined' ? -Infinity : window.innerWidth)),
    _useState6 = _slicedToArray(_useState5, 2),
    currentBreakpoint = _useState6[0],
    setCurrentBreakpoint = _useState6[1];
  var functionToCallOnWindowResize = throttle(function () {
    var newBreakpoint = getBreakpoint(window.innerWidth);
    if (newBreakpoint !== currentBreakpoint) {
      setCurrentBreakpoint(newBreakpoint);
    }
    // reacts every 50ms to resize changes and always gets the final update
  }, 50);

  // Add window resize handlers
  useEffect(function () {
    window.addEventListener('resize', functionToCallOnWindowResize);
    return function () {
      window.removeEventListener('resize', functionToCallOnWindowResize);
    };
  }, [responsive, functionToCallOnWindowResize]);
  var breadcrumbElements = breadcrumbs.map(function (breadcrumb, index) {
    var text = breadcrumb.text,
      href = breadcrumb.href,
      onClick = breadcrumb.onClick,
      truncate = breadcrumb.truncate,
      breadcrumbClassName = breadcrumb.className,
      breadcrumbRest = _objectWithoutProperties(breadcrumb, ["text", "href", "onClick", "truncate", "className"]);
    var isFirstBreadcrumb = index === 0;
    var isLastBreadcrumb = index === breadcrumbs.length - 1;
    var breadcrumbWrapperClasses = classNames('euiBreadcrumbWrapper', {
      'euiBreadcrumbWrapper--first': isFirstBreadcrumb,
      'euiBreadcrumbWrapper--last': isLastBreadcrumb,
      'euiBreadcrumbWrapper--truncate': truncate
    });
    var breadcrumbClasses = classNames('euiBreadcrumb', breadcrumbClassName, {
      'euiBreadcrumb--last': isLastBreadcrumb,
      'euiBreadcrumb--truncate': truncate
    });
    var link = !href && !onClick ? /*#__PURE__*/React.createElement(EuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement("span", _extends({
        ref: ref,
        className: breadcrumbClasses,
        title: innerText,
        "aria-current": isLastBreadcrumb ? 'page' : 'false'
      }, breadcrumbRest), text);
    }) : /*#__PURE__*/React.createElement(EuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement(EuiLink, _extends({
        ref: ref,
        color: isLastBreadcrumb ? 'text' : 'subdued',
        onClick: onClick,
        href: href,
        className: breadcrumbClasses,
        title: innerText
      }, breadcrumbRest), text);
    });
    var breadcrumbWallClasses = classNames('euiBreadcrumbWall', {
      'euiBreadcrumbWall--single': isFirstBreadcrumb && isLastBreadcrumb
    });
    var wrapper = /*#__PURE__*/React.createElement("div", {
      className: breadcrumbWrapperClasses
    }, link);
    var wall = isFirstBreadcrumb ? /*#__PURE__*/React.createElement("div", {
      className: breadcrumbWallClasses
    }, wrapper) : wrapper;
    return /*#__PURE__*/React.createElement(Fragment, {
      key: index
    }, wall);
  });

  // Use the default object if they simply passed `true` for responsive
  var responsiveObject = _typeof(responsive) === 'object' ? responsive : responsiveDefault;

  // The max property collapses any breadcrumbs past the max quantity.
  // This is the same behavior we want for responsiveness.
  // So calculate the max value based on the combination of `max` and `responsive`

  // First, calculate the responsive max value
  var responsiveMax = responsive && responsiveObject[currentBreakpoint] ? responsiveObject[currentBreakpoint] : null;

  // Second, if both max and responsiveMax are set, use the smaller of the two. Otherwise, use the one that is set.
  var calculatedMax = max && responsiveMax ? Math.min(max, responsiveMax) : max || responsiveMax;
  var limitedBreadcrumbs = calculatedMax ? limitBreadcrumbs(breadcrumbElements, calculatedMax, breadcrumbs) : breadcrumbElements;
  var classes = classNames('euiBreadcrumbs', className, {
    'euiBreadcrumbs--truncate': truncate
  });
  return /*#__PURE__*/React.createElement("nav", _extends({
    "aria-label": "breadcrumb",
    className: classes
  }, rest), limitedBreadcrumbs);
};
EuiBreadcrumbsSimplified.propTypes = {
  className: PropTypes.string,
  "aria-label": PropTypes.string,
  "data-test-subj": PropTypes.string,
  /**
     * Hides extra (above the max) breadcrumbs under a collapsed item as the window gets smaller.
     * Pass a custom #EuiBreadcrumbResponsiveMaxCount object to change the number of breadcrumbs to show at the particular breakpoints.
     * Omitting or passing a `0` value will show all breadcrumbs.
     *
     * Pass `false` to turn this behavior off.
     *
     * Default: `{ xs: 1, s: 2, m: 4 }`
     */
  responsive: PropTypes.oneOfType([PropTypes.bool.isRequired, PropTypes.any.isRequired]),
  /**
     * Forces all breadcrumbs to single line and
     * truncates each breadcrumb to a particular width,
     * except for the last item
     */
  truncate: PropTypes.bool,
  /**
     * Collapses the inner items past the maximum set here
     * into a single ellipses item
     */
  max: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.oneOf([null])]),
  /**
     * The array of individual #EuiBreadcrumb items
     */
  breadcrumbs: PropTypes.arrayOf(PropTypes.shape({
    className: PropTypes.string,
    "aria-label": PropTypes.string,
    "data-test-subj": PropTypes.string,
    /**
       * Visible label of the breadcrumb
       */
    text: PropTypes.node.isRequired,
    href: PropTypes.string,
    onClick: PropTypes.func,
    /**
       * Force a max-width on the breadcrumb text
       */
    truncate: PropTypes.bool
  }).isRequired).isRequired
};